From 9c1306a95a1686d58534c3d7b4a1e25fc6f04680 Mon Sep 17 00:00:00 2001 From: aramis_acg Date: Fri, 9 Jul 2010 16:44:13 +0000 Subject: [PATCH] Skip ear cutting algorithm for quadrilaterals, makes triangulation MUCH, MUCH faster (100x) for models composed of quadrilaterals (i.e. Blender, Terragen). git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@773 67173fc5-114c-0410-ac8e-9d2fd5bffc1f --- code/TriangulateProcess.cpp | 33 ++++++++++++++++++++++++++------- doc/dox.h | 27 ++++++++++++++++++--------- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/code/TriangulateProcess.cpp b/code/TriangulateProcess.cpp index a5fee2c42..9e2c70b01 100644 --- a/code/TriangulateProcess.cpp +++ b/code/TriangulateProcess.cpp @@ -205,19 +205,33 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) } #endif - // if it's a simple primitive, just copy it + // if it's a simple point,line or triangle: just copy it if( face.mNumIndices <= 3) { aiFace& nface = *curOut++; nface.mNumIndices = face.mNumIndices; nface.mIndices = face.mIndices; } + // quadrilaterals can't have ears. trifanning will always work + else if ( face.mNumIndices == 4) { + aiFace& nface = *curOut++; + nface.mNumIndices = 3; + nface.mIndices = face.mIndices; + + aiFace& sface = *curOut++; + sface.mNumIndices = 3; + sface.mIndices = new unsigned int[3]; + + sface.mIndices[0] = face.mIndices[0]; + sface.mIndices[1] = face.mIndices[2]; + sface.mIndices[2] = face.mIndices[3]; + } else { // A polygon with more than 3 vertices can be either concave or convex. // Usually everything we're getting is convex and we could easily // triangulate by trifanning. However, LightWave is probably the only - // modeller making extensive use of highly concave monster polygons ... + // modeller to make extensive use of highly concave monster polygons ... // so we need to apply the full 'ear cutting' algorithm. // RERQUIREMENT: polygon is expected to be simple and *nearly* planar. @@ -226,8 +240,9 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) // Collect all vertices of of the polygon. aiVector3D* verts = pMesh->mVertices; - for (tmp = 0; tmp < max; ++tmp) + for (tmp = 0; tmp < max; ++tmp) { temp_verts[tmp] = verts[idx[tmp]]; + } // Get newell normal of the polygon. Store it for future use if it's a polygon-only mesh aiVector3D n; @@ -278,16 +293,18 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) // break after we looped two times without a positive match for (next=ear+1;done[(next>max-1?next=0:next)];++next); if (next < ear) { - if (++num_found == 2) + if (++num_found == 2) { break; + } } const aiVector2D* pnt1 = (const aiVector2D*)&temp_verts[ear], *pnt0 = (const aiVector2D*)&temp_verts[prev], *pnt2 = (const aiVector2D*)&temp_verts[next]; // Must be a convex point. Assuming ccw winding, it must be on the right of the line between p-1 and p+1. - if (OnLeftSideOfLine (*pnt0,*pnt2,*pnt1)) + if (OnLeftSideOfLine (*pnt0,*pnt2,*pnt1)) { continue; + } // and no other point may be contained in this triangle for ( tmp = 0; tmp < max; ++tmp) { @@ -304,8 +321,9 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) break; } - if (tmp != max) + if (tmp != max) { continue; + } // this vertex is an ear break; @@ -339,8 +357,9 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) aiFace& nface = *curOut++; nface.mNumIndices = 3; - if (!nface.mIndices) + if (!nface.mIndices) { nface.mIndices = new unsigned int[3]; + } // setup indices for the new triangle ... nface.mIndices[0] = idx[prev]; diff --git a/doc/dox.h b/doc/dox.h index 9e1c29b6b..dbc88692b 100644 --- a/doc/dox.h +++ b/doc/dox.h @@ -1469,7 +1469,8 @@ A sample report looks like this (some unrelated log messages omitted, grouped en @verbatim Debug, T5488: START `total` Info, T5488: Found a matching importer for this file format - + + Debug, T5488: START `import` Info, T5488: BlendModifier: Applied the `Subdivision` modifier to `OBMonkey` Debug, T5488: END `import`, dt= 3.516 s @@ -1478,43 +1479,51 @@ Debug, T5488: END `import`, dt= 3.516 s Debug, T5488: START `preprocess` Debug, T5488: END `preprocess`, dt= 0.001 s Info, T5488: Entering post processing pipeline - + + Debug, T5488: START `postprocess` Debug, T5488: RemoveRedundantMatsProcess begin Debug, T5488: RemoveRedundantMatsProcess finished Debug, T5488: END `postprocess`, dt= 0.001 s - + + Debug, T5488: START `postprocess` Debug, T5488: TriangulateProcess begin Info, T5488: TriangulateProcess finished. All polygons have been triangulated. Debug, T5488: END `postprocess`, dt= 3.415 s - + + Debug, T5488: START `postprocess` Debug, T5488: SortByPTypeProcess begin Info, T5488: Points: 0, Lines: 0, Triangles: 1, Polygons: 0 (Meshes, X = removed) -Debug, T5488: SortByPTypeProcess finished +Debug, T5488: SortByPTypeProcess finished + Debug, T5488: START `postprocess` Debug, T5488: JoinVerticesProcess begin Debug, T5488: Mesh 0 (unnamed) | Verts in: 503808 out: 126345 | ~74.922 Info, T5488: JoinVerticesProcess finished | Verts in: 503808 out: 126345 | ~74.9 -Debug, T5488: END `postprocess`, dt= 2.052 s +Debug, T5488: END `postprocess`, dt= 2.052 s + Debug, T5488: START `postprocess` Debug, T5488: FlipWindingOrderProcess begin Debug, T5488: FlipWindingOrderProcess finished Debug, T5488: END `postprocess`, dt= 0.006 s - + + Debug, T5488: START `postprocess` Debug, T5488: LimitBoneWeightsProcess begin Debug, T5488: LimitBoneWeightsProcess end Debug, T5488: END `postprocess`, dt= 0.001 s - + + Debug, T5488: START `postprocess` Debug, T5488: ImproveCacheLocalityProcess begin Debug, T5488: Mesh 0 | ACMR in: 0.851622 out: 0.718139 | ~15.7 Info, T5488: Cache relevant are 1 meshes (251904 faces). Average output ACMR is 0.718139 Debug, T5488: ImproveCacheLocalityProcess finished. Debug, T5488: END `postprocess`, dt= 1.903 s - + + Info, T5488: Leaving post processing pipeline Debug, T5488: END `total`, dt= 11.269 s @endverbatim