Viewing face normals of a mesh

<?xml encoding=”UTF-8″>By Balaji Ramamoorthy

Recently I had a drawing sent over by a developer which had a SubDMesh that was created through code using vertex and face information. In such meshes, the normals of the faces would depend on the order of vertices while defining the face vertices, so wanted to check if the normals were all ok.

Just in case you would like to view the normals for a mesh, here is the code snippet to show the normals of the facets. This blog post by my colleague Adam Nagy draws the edges of the mesh which formed the basis for this code snippet. 

 Acad::ErrorStatus es;
 
 ads_name name;
 AcGePoint3d pt;
  
 <span>int</span><span>  ret = acedEntSel(</span>
 _T(<span>"\nSelect a SubD Mesh: "</span><span> ), name, asDblArray(pt));</span>
  
 <span>if</span><span>  (ret != RTNORM)</span>
 <span>{</span>
 	acutPrintf(_T(<span>"\nNothing selected"</span><span> ));</span>
 	<span>return</span><span> ;</span>
 <span>}</span>
  
 AcDbObjectId id;
 acdbGetObjectId(id, name);
  
 <span>if</span><span>  (id.objectClass() != AcDbSubDMesh::desc())</span>
 <span>{</span>
 	acutPrintf(
 		_T(<span>"\nSelected entity is not a SubD Mesh"</span><span> ));</span>
 	<span>return</span><span> ;</span>
 <span>}</span>
 
 AcDbObjectPointer<AcDbSubDMesh> mesh(
 					id, AcDb::kForRead);
  
 AcDbFullSubentPathArray subentPaths;
 es = mesh->getSubentPath(-1,
 		kFaceSubentType, subentPaths);
 
 AcGePoint3dArray vertices;
 es = mesh->getSubDividedVertices(vertices);
  
 AcArray<Adesk::Int32> faceInfo;
 es = mesh->getSubDividedFaceArray(faceInfo);
 
 <span>// The content of the faces list is like so:</span><span> </span>
 <span>// [number of vertices of next face],</span><span> </span>
 <span>// <vertexIndex1, vertexIndex2, etc>,</span><span> </span>
 <span>// e.g. [4], <1, 2, 3, 4>, [3], <1, 2, 3>, etc</span><span> </span>
  
 AcDbDatabase * pDb =
 acdbHostApplicationServices()->workingDatabase();
 AcDbBlockTableRecordPointer
 ms(ACDB_MODEL_SPACE, pDb, AcDb::kForWrite);
  
 AcDbVoidPtrArray lineArray;
 <span>int</span><span>  face = 0;</span>
 <span>int</span><span>  numVerticesInFace = 0;</span>
 <span>for</span><span>  (<span>int</span><span>  i = 0; i < faceInfo.length(); </span></span>
 	i += numVerticesInFace + 1, face++)
 <span>{</span>
 	numVerticesInFace = faceInfo.at(i);
 
 	AcGePlane facePlane;
 	es = mesh->getFacePlane(
 		subentPaths.at(face).subentId(), 
 		facePlane);
 
 	AcGeBoundBlock3d boundBox;
 	<span>for</span><span>  (<span>int</span><span>  j = 0; j < numVerticesInFace; j++)</span></span>
 	<span>{</span>
 		AcGePoint3d pt1 =
 		vertices.at(faceInfo.at(i + j + 1));
 		AcGePoint3d pt2 =
 		vertices.at(
 		faceInfo.at(i + ((j + 1) % numVerticesInFace) + 1));
  
 		<span>if</span><span> (j == 0)</span>
 			boundBox.set(pt1, pt2);
 		<span>else</span><span> </span>
 		<span>{</span>
 			boundBox.extend(pt1);
 			boundBox.extend(pt2);
 		<span>}</span>
 				
 		<span>// If the edges are also required</span><span> </span>
 		<span>//AcDbObjectPointer<AcDbLine> line;</span><span> </span>
 		<span>//line.create();</span><span> </span>
 		<span>//line->setStartPoint(pt1);</span><span> </span>
 		<span>//line->setEndPoint(pt2);</span><span> </span>
 		<span>//ms->appendAcDbEntity(line);</span><span> </span>
 	<span>}</span>
 
 	AcGePoint3d minPt;
 	AcGePoint3d maxPt;
 	boundBox.getMinMaxPoints(minPt, maxPt);
 	AcGeVector3d normalLen = maxPt - minPt;
 
 	AcGeVector3d normal = facePlane.normal();
 					
 	<span>// Arrow</span><span> </span>
 	AcDbLine *pArrow = <span>new</span><span>  AcDbLine;</span>
 	pArrow->setColorIndex(2);
 
 	AcGePoint3d sp = minPt + normalLen * 0.5;
 	pArrow->setStartPoint(sp);
 
 	AcGePoint3d ep = sp 
 		+ normal.normalize() * normalLen.length();
 	pArrow->setEndPoint(ep);
 
 	ms->appendAcDbEntity(pArrow);
 	pArrow->close();
 
 	<span>// Arrow head</span><span> </span>
 	<span>double</span><span>  arrowLen = normalLen.length() * 0.2;</span>
 	AcDb3dSolid *pArrowHead = <span>new</span><span>  AcDb3dSolid;</span>
 	es = pArrowHead->createFrustum(
 		arrowLen, 
 		arrowLen / 3.0, 
 		arrowLen / 3.0, 
 		0.0);
 			
 	AcGeVector3d zd = (ep - sp).normalize();
 	AcGeVector3d yd = zd.perpVector().normalize();
 	AcGeVector3d xd = yd.crossProduct(zd).normalize();
 	AcGeMatrix3d mat;
 	mat.setCoordSystem(ep, xd, yd, zd);
 	pArrowHead->transformBy(mat);
 			
 	ms->appendAcDbEntity(pArrowHead);
 	pArrowHead->close();
 <span>}</span>
 

Here is a screenshot of the normals for a simple box mesh :

Normals


Comments

One response to “Viewing face normals of a mesh”

  1. I am not familiar with the command mesh , here I can learn a lot about it.Thanks .

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading