Notifications
Clear all

[Closed] Extrude Faces?

How can I extrude faces in the 3dsmax SDK?

In maxscript, I would do (just as an example):


 obj = box()
 convertToMesh obj
 meshop.extrudeFaces obj #{1..obj.faces.count} 5.0 -1.0
 

in C++, the mesh.extrudeFaces method only takes a single parameter, a boolean. The descriptions states it extrudes the selected faces.


pubic : void Mesh::ExtrudeFaces(BOOL doFace = 1)
* Extrudes the selected faces.  Not that this is just a topological change.  The new extruded faces do not change position but are left on top of the original faces.
\param doFace
if TRUE the faces are extruded.  if FALSE then the selected edges are extruded.
File: mesh.h

Therefore, how can I “select” the faces I want to extrude prior to calling this method?

Thanks!

9 Replies

Therefore, how can I “select” the faces I want to extrude prior to calling this method?

the extrudefaces method creates all new geometry needed to create the extrude but doesn’t do any of the actual shifting of the verts.
So this is how I would probably do it where faces is a bitarray of the faces you want to extrude or use a MeshDelta object

mesh->faceSel = faces;
   mesh->ExtrudeFaces();
   int nVerts=mesh->getNumVerts();
   if (nVerts != 0) 
   {
   // collect the verts in the "extruded" faces
   	BitArray verts (nVerts);
   	for (int i = 0; i < mesh->getNumFaces(); ++i) 
      {
   		if (!mesh->faceSel[i]) continue;
   		Face *f = &mesh->faces[i];
   		for (int j = 0; j < 3; j++) verts.Set(f->v[j]);
   	}
// do the shift
   	 for (int i = 0; i < mesh->nVerts; ++i) 
   	  {
   		   if(verts [ i])
   		   {
   			   // compute the shift.... for each vert
   		   }
   	  }
   }

Hello,

How would I get the BitArray of the faces I would like to extrude?

For example in maxscript:
faces = #{1…10}

Thanks!

how do you know which faces you want to extrude ? from the current selection, an array of face indices, all the faces of a material id, or a smoothing group etc.

Sorry, I mean, how would I go about creating the BitArray of face indices by range. In maxscript you do:

#{startIndice..endIndice}

For instance, let’s say I wanted to convert #{5…15) to C++
Would it be something like this?


BitArray faces(10);
faces.shift(RIGHT_BITSHIFT, 5);

How do I do this in C++:

mesh.faceSel = #{5…15} // Specify a range of face indices to select

That is my question. Sorry if I’m not making any sense. I’m a noob at the SDK but not at maxscript. Thanks for your help.

i’ve played a lot with c++ bitarrays… the simplest, fastest, and universal way to get/set bits is a simple iteration:

BitArray bits(count);
for (int k=start; k < count && k <= end; k++) bits.Set(k);

where bit index is zero based instead of mxs

i don’t have my pro computer around… but i remember that my extrude faces code i stole from meshop.cpp example in max sdk and it works for me

Thank you Denis. It’s working now

from fextrude.cpp in the modifiers project in the samples

if (os->obj->IsSubClassOf(triObjectClassID)) {
		TriObject *tobj = (TriObject*)os->obj;
		Mesh &mesh = tobj->GetMesh();
		Interval iv = FOREVER;
		float a, s;
		Point3 pt, center;
		int c;
		
		pblock->GetValue(PB_AMOUNT,t,a,iv);
		pblock->GetValue(PB_SCALE,t,s,iv);
		pblock->GetValue(PB_CENTER,t,c,iv);
		base->GetValue(t,&pt,iv,CTRL_ABSOLUTE);		

		// Extrude the faces -- this just creates the new faces
		mesh.ExtrudeFaces();

		// Build normals of selected faces only		
		Tab<Point3> normals;
		if (!c) {
			normals.SetCount(mesh.getNumVerts());
			for (int i=0; i<mesh.getNumVerts(); i++) {
				normals[i] = Point3(0,0,0);
				}
			for (int i=0; i<mesh.getNumFaces(); i++) {
				if (mesh.faceSel[i]) {
					Point3 norm = 
						(mesh.verts[mesh.faces[i].v[1]]-mesh.verts[mesh.faces[i].v[0]]) ^
						(mesh.verts[mesh.faces[i].v[2]]-mesh.verts[mesh.faces[i].v[1]]);
					for (int j=0; j<3; j++) {				
						normals[mesh.faces[i].v[j]] += norm;
						}
					}
				}			
			for (int i=0; i<mesh.getNumVerts(); i++) {
				normals[i] = Normalize(normals[i]);
				}
		} else {
			// Compute the center point			
			base->GetValue(t,¢er,iv,CTRL_ABSOLUTE);			
			}

		// Mark vertices used by selected faces
		BitArray sel;
		sel.SetSize(mesh.getNumVerts());
		for (int i=0; i<mesh.getNumFaces(); i++) {
			if (mesh.faceSel[i]) {
				for (int j=0; j<3; j++) sel.Set(mesh.faces[i].v[j],TRUE);
				}
			}

		// Move selected verts
		for (int i=0; i<mesh.getNumVerts(); i++) {
			if (sel[i]) {
				if (!c) {
					mesh.verts[i] += normals[i]*a;
				} else {
					Point3 vect = Normalize((mesh.verts[i] * (*mc.tm))
						- center);
					mesh.verts[i] += vect*a;
					}
				}
			}
		
		// Scale verts
		if (s!=100.0f) {
			s /= 100.0f;

			AdjEdgeList ae(mesh);
			AdjFaceList af(mesh,ae);
			FaceClusterList clust(mesh.faceSel,af);
			
			// Make sure each vertex is only scaled once.
			BitArray done;
			done.SetSize(mesh.getNumVerts());

			// scale each cluster independently
			for (int i=0; (DWORD)i<clust.count; i++) {
				// First determine cluster center
				Point3 cent(0,0,0);
				int ct=0;
				for (int j=0; j<mesh.getNumFaces(); j++) {
					if (clust[j]==(DWORD)i) {
						for (int k=0; k<3; k++) {
							cent += mesh.verts[mesh.faces[j].v[k]];
							ct++;
							}
						}
					}
				if (ct) cent /= float(ct);

				// Now scale the cluster about its center
				for (int j=0; j<mesh.getNumFaces(); j++) {
					if (clust[j]==(DWORD)i) {
						for (int k=0; k<3; k++) {
							int index = mesh.faces[j].v[k]; 
							if (done[index]) continue;
							done.Set(index);
							mesh.verts[index] = 
								(mesh.verts[index]-cent)*s + cent;							
							}
						}
					}
				}
			}
		
		mesh.InvalidateTopologyCache ();
		os->obj->UpdateValidity(GEOM_CHAN_NUM,iv);		
		}