MNMesh Notes on Debugging
See Also: Class MNMesh.
MNDebugPrint:
Please familiarize yourself with the new MNDebugPrint methods in MNVert, MNEdge, MNFace, MNMesh, and MNMeshBorder. These functions print out detailed ASCII summaries of the component or mesh, which can be an invaluable aid in tracking bugs. Also, during your debugging phase, frequent calls to MNMesh::CheckAllData can be very useful. But, since the MNDebugPrint and CheckAllData functions are highly time intensive and serve no useful purpose for a released plug-in, you should check to remove them all before release.
As an example, here is the MNMesh::MNDebugPrint output from a standard 3ds max box, after applying MakePolyMesh. Mapping coordinates, vertex colors, and face triangulation may also be included.
MNMesh Debug Output: 8 verts, 12 edges, 6 faces
Vertex 0:( -17.185, -26.798, 0.000) Edges:(0 3 9 ) Faces:(0 2 5 )
Vertex 1:( 17.185, -26.798, 0.000) Edges:(2 3 8 ) Faces:(0 2 3 )
Vertex 2:( -17.185, 26.798, 0.000) Edges:(0 1 11 ) Faces:(0 4 5 )
Vertex 3:( 17.185, 26.798, 0.000) Edges:(1 2 10 ) Faces:(0 3 4 )
Vertex 4:( -17.185, -26.798, 24.984) Edges:(4 7 9 ) Faces:(1 2 5 )
Vertex 5:( 17.185, -26.798, 24.984) Edges:(4 5 8 ) Faces:(1 2 3 )
Vertex 6:( -17.185, 26.798, 24.984) Edges:(6 7 11 ) Faces:(1 4 5 )
Vertex 7:( 17.185, 26.798, 24.984) Edges:(5 6 10 ) Faces:(1 3 4 )
Edge 0: verts(0 2), face 0, rev-face 5
Edge 1: verts(2 3), face 0, rev-face 4
Edge 2: verts(3 1), face 0, rev-face 3
Edge 3: verts(1 0), face 0, rev-face 2
Edge 4: verts(4 5), face 1, rev-face 2
Edge 5: verts(5 7), face 1, rev-face 3
Edge 6: verts(7 6), face 1, rev-face 4
Edge 7: verts(6 4), face 1, rev-face 5
Edge 8: verts(1 5), face 2, rev-face 3
Edge 9: verts(4 0), face 2, rev-face 5
Edge 10: verts(3 7), face 3, rev-face 4
Edge 11: verts(2 6), face 4, rev-face 5
Face 0: verts(0 2 3 1 ) edges(0v 1v 2v 3v )
Face 1: verts(4 5 7 6 ) edges(4v 5v 6v 7v )
Face 2: verts(0 1 5 4 ) edges(3v 8v 4v 9v )
Face 3: verts(1 3 7 5 ) edges(2v 10v 5v 8v )
Face 4: verts(3 2 6 7 ) edges(1v 11v 6v 10v )
Face 5: verts(2 0 4 6 ) edges(0v 9v 7v 11v )
Assertion failures:
MNMeshes have a complex, interlinked topology. Without frequent assertions, a mistake in one part of the code can result in a failure much further down the line. Since an assertion failure in itself provides little diagnostic information, each AF in MNMath.dll is accompanied by a DebugPrint message giving more information about the problem. If this information does not immediately lead to a solution, try using assert (CheckAllData()) between each of your MNMesh operations.
If you call an MNMesh function that produces an inexplicable error after your MNMesh has successfully had all its data checked with MNMesh::CheckAllData, please contact SDK support.
To give a simple example, suppose you had an application which created an MNMesh from a Mesh, made it into a polygonal mesh, split a single face, and returned.
SplitUp(Mesh & mesh) {
MNMesh mm(mesh);
mm.MakePolyMesh();
mm.SplitTriEdge(0, .5f);
mm.OutToTri(mesh);
}
You try it out on a geosphere, and it works fine. But then you try it out on a box, and for some reason you get an assertion failure somewhere in the MNMath.dll source. By running 3ds max under the debugger, you can reproduce the error. If you check the Debug output in Visual Studio, you’ll find the message:
MNMesh::SplitTriEdge error: edge’s face 1(0) not a triangle.
So you check with the documentation and realize that SplitTriEdge is an edge-splitting function that only works on triangulated meshes. To do the same thing to a PolyMesh, you need to use one of the variants of SplitEdge. So you can fix your code by either removing mm.MakePolyMesh(), triangulating with a call to mm.Triangulate(), or just calling mm.SplitEdge (0, .5f) instead of SplitTriEdge.
Imagine a more complicated case: in the middle of a series of complex MNMesh modifications made by your program, you need to recompute the triangulation of one of the higher-degree faces with a call to MNMesh::RetriangulateFace. For some reason, this generates an assertion failure. Checking the Debug output, you find the cryptic message:
MNMesh::RetriangulateFace internal error.
This could mean one of two things. First of all, the MNMesh could have had some of its data scrambled before the call to RetriangulateFace. You can check this by adding an assert (mm.CheckAllData ()), where mm is your MNMesh, immediately before the call to RetriangulateFace. CheckAllData performs a time-intensive series of checks on the mesh structure, checking each mesh component against the components it’s supposed to be linked to, checking that nothing references a dead component, and so on. If any errors are found, the check will fail, and CheckAllData will print diagnostic information to the Debug output.
If CheckAllData gives your mesh a clean bill of health, but you’re still getting an "internal error", or just an "error" with no further info, you may have found a bug. Please contact SDK support.