vrshoot

diff libs/assimp/TriangulateProcess.cpp @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libs/assimp/TriangulateProcess.cpp	Sat Feb 01 19:58:19 2014 +0200
     1.3 @@ -0,0 +1,527 @@
     1.4 +/*
     1.5 +---------------------------------------------------------------------------
     1.6 +Open Asset Import Library (assimp)
     1.7 +---------------------------------------------------------------------------
     1.8 +
     1.9 +Copyright (c) 2006-2012, assimp team
    1.10 +
    1.11 +All rights reserved.
    1.12 +
    1.13 +Redistribution and use of this software in source and binary forms, 
    1.14 +with or without modification, are permitted provided that the following 
    1.15 +conditions are met:
    1.16 +
    1.17 +* Redistributions of source code must retain the above
    1.18 +  copyright notice, this list of conditions and the
    1.19 +  following disclaimer.
    1.20 +
    1.21 +* Redistributions in binary form must reproduce the above
    1.22 +  copyright notice, this list of conditions and the
    1.23 +  following disclaimer in the documentation and/or other
    1.24 +  materials provided with the distribution.
    1.25 +
    1.26 +* Neither the name of the assimp team, nor the names of its
    1.27 +  contributors may be used to endorse or promote products
    1.28 +  derived from this software without specific prior
    1.29 +  written permission of the assimp team.
    1.30 +
    1.31 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    1.32 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    1.33 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.34 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    1.35 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.36 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    1.37 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.38 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
    1.39 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    1.40 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    1.41 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.42 +---------------------------------------------------------------------------
    1.43 +*/
    1.44 +
    1.45 +/** @file  TriangulateProcess.cpp
    1.46 + *  @brief Implementation of the post processing step to split up
    1.47 + *    all faces with more than three indices into triangles.
    1.48 + *
    1.49 + *
    1.50 + *  The triangulation algorithm will handle concave or convex polygons.
    1.51 + *  Self-intersecting or non-planar polygons are not rejected, but
    1.52 + *  they're probably not triangulated correctly.
    1.53 + *
    1.54 + * DEBUG SWITCHES - do not enable any of them in release builds:
    1.55 + *
    1.56 + * AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
    1.57 + *   - generates vertex colors to represent the face winding order.
    1.58 + *     the first vertex of a polygon becomes red, the last blue.
    1.59 + * AI_BUILD_TRIANGULATE_DEBUG_POLYS
    1.60 + *   - dump all polygons and their triangulation sequences to
    1.61 + *     a file
    1.62 + */
    1.63 +
    1.64 +#include "AssimpPCH.h"
    1.65 +
    1.66 +#ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS
    1.67 +#include "TriangulateProcess.h"
    1.68 +#include "ProcessHelper.h"
    1.69 +#include "PolyTools.h"
    1.70 +
    1.71 +//#define AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
    1.72 +//#define AI_BUILD_TRIANGULATE_DEBUG_POLYS
    1.73 +
    1.74 +#define POLY_GRID_Y 40
    1.75 +#define POLY_GRID_X 70
    1.76 +#define POLY_GRID_XPAD 20
    1.77 +#define POLY_OUTPUT_FILE "assimp_polygons_debug.txt"
    1.78 +
    1.79 +using namespace Assimp;
    1.80 +
    1.81 +// ------------------------------------------------------------------------------------------------
    1.82 +// Constructor to be privately used by Importer
    1.83 +TriangulateProcess::TriangulateProcess()
    1.84 +{
    1.85 +	// nothing to do here
    1.86 +}
    1.87 +
    1.88 +// ------------------------------------------------------------------------------------------------
    1.89 +// Destructor, private as well
    1.90 +TriangulateProcess::~TriangulateProcess()
    1.91 +{
    1.92 +	// nothing to do here
    1.93 +}
    1.94 +
    1.95 +// ------------------------------------------------------------------------------------------------
    1.96 +// Returns whether the processing step is present in the given flag field.
    1.97 +bool TriangulateProcess::IsActive( unsigned int pFlags) const
    1.98 +{
    1.99 +	return (pFlags & aiProcess_Triangulate) != 0;
   1.100 +}
   1.101 +
   1.102 +// ------------------------------------------------------------------------------------------------
   1.103 +// Executes the post processing step on the given imported data.
   1.104 +void TriangulateProcess::Execute( aiScene* pScene)
   1.105 +{
   1.106 +	DefaultLogger::get()->debug("TriangulateProcess begin");
   1.107 +
   1.108 +	bool bHas = false;
   1.109 +	for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
   1.110 +	{
   1.111 +		if(	TriangulateMesh( pScene->mMeshes[a]))
   1.112 +			bHas = true;
   1.113 +	}
   1.114 +	if (bHas)DefaultLogger::get()->info ("TriangulateProcess finished. All polygons have been triangulated.");
   1.115 +	else     DefaultLogger::get()->debug("TriangulateProcess finished. There was nothing to be done.");
   1.116 +}
   1.117 +
   1.118 +
   1.119 +// ------------------------------------------------------------------------------------------------
   1.120 +// Triangulates the given mesh.
   1.121 +bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
   1.122 +{
   1.123 +	// Now we have aiMesh::mPrimitiveTypes, so this is only here for test cases
   1.124 +	if (!pMesh->mPrimitiveTypes)	{
   1.125 +		bool bNeed = false;
   1.126 +
   1.127 +		for( unsigned int a = 0; a < pMesh->mNumFaces; a++)	{
   1.128 +			const aiFace& face = pMesh->mFaces[a];
   1.129 +
   1.130 +			if( face.mNumIndices != 3)	{
   1.131 +				bNeed = true;
   1.132 +			}
   1.133 +		}
   1.134 +		if (!bNeed)
   1.135 +			return false;
   1.136 +	}
   1.137 +	else if (!(pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) {
   1.138 +		return false;
   1.139 +	}
   1.140 +
   1.141 +	// Find out how many output faces we'll get
   1.142 +	unsigned int numOut = 0, max_out = 0;
   1.143 +	bool get_normals = true;
   1.144 +	for( unsigned int a = 0; a < pMesh->mNumFaces; a++)	{
   1.145 +		aiFace& face = pMesh->mFaces[a];
   1.146 +		if (face.mNumIndices <= 4) {
   1.147 +			get_normals = false;
   1.148 +		}
   1.149 +		if( face.mNumIndices <= 3) {
   1.150 +			numOut++;
   1.151 +
   1.152 +		}	
   1.153 +		else {
   1.154 +			numOut += face.mNumIndices-2;
   1.155 +			max_out = std::max(max_out,face.mNumIndices);
   1.156 +		}
   1.157 +	}
   1.158 +
   1.159 +	// Just another check whether aiMesh::mPrimitiveTypes is correct
   1.160 +	assert(numOut != pMesh->mNumFaces);
   1.161 +
   1.162 +	aiVector3D* nor_out = NULL;
   1.163 +
   1.164 +	// if we don't have normals yet, but expect them to be a cheap side
   1.165 +	// product of triangulation anyway, allocate storage for them.
   1.166 +	if (!pMesh->mNormals && get_normals) {
   1.167 +		// XXX need a mechanism to inform the GenVertexNormals process to treat these normals as preprocessed per-face normals
   1.168 +	//	nor_out = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
   1.169 +	}
   1.170 +
   1.171 +	// the output mesh will contain triangles, but no polys anymore
   1.172 +	pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
   1.173 +	pMesh->mPrimitiveTypes &= ~aiPrimitiveType_POLYGON;
   1.174 +
   1.175 +	aiFace* out = new aiFace[numOut](), *curOut = out;
   1.176 +	std::vector<aiVector3D> temp_verts3d(max_out+2); /* temporary storage for vertices */
   1.177 +	std::vector<aiVector2D> temp_verts(max_out+2);
   1.178 +
   1.179 +	// Apply vertex colors to represent the face winding?
   1.180 +#ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
   1.181 +	if (!pMesh->mColors[0])
   1.182 +		pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices];
   1.183 +	else
   1.184 +		new(pMesh->mColors[0]) aiColor4D[pMesh->mNumVertices];
   1.185 +
   1.186 +	aiColor4D* clr = pMesh->mColors[0];
   1.187 +#endif
   1.188 +
   1.189 +	
   1.190 +#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
   1.191 +	FILE* fout = fopen(POLY_OUTPUT_FILE,"a");
   1.192 +#endif
   1.193 +
   1.194 +	const aiVector3D* verts = pMesh->mVertices;
   1.195 +
   1.196 +	// use boost::scoped_array to avoid slow std::vector<bool> specialiations
   1.197 +	boost::scoped_array<bool> done(new bool[max_out]); 
   1.198 +	for( unsigned int a = 0; a < pMesh->mNumFaces; a++)	{
   1.199 +		aiFace& face = pMesh->mFaces[a];
   1.200 +
   1.201 +		unsigned int* idx = face.mIndices;
   1.202 +		int num = (int)face.mNumIndices, ear = 0, tmp, prev = num-1, next = 0, max = num;
   1.203 +
   1.204 +		// Apply vertex colors to represent the face winding?
   1.205 +#ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
   1.206 +		for (unsigned int i = 0; i < face.mNumIndices; ++i) {
   1.207 +			aiColor4D& c = clr[idx[i]];
   1.208 +			c.r = (i+1) / (float)max;
   1.209 +			c.b = 1.f - c.r;
   1.210 +		}
   1.211 +#endif
   1.212 +
   1.213 +		aiFace* const last_face = curOut; 
   1.214 +
   1.215 +		// if it's a simple point,line or triangle: just copy it
   1.216 +		if( face.mNumIndices <= 3)
   1.217 +		{
   1.218 +			aiFace& nface = *curOut++;
   1.219 +			nface.mNumIndices = face.mNumIndices;
   1.220 +			nface.mIndices    = face.mIndices;
   1.221 +
   1.222 +			face.mIndices = NULL;
   1.223 +			continue;
   1.224 +		}  
   1.225 +		// optimized code for quadrilaterals
   1.226 +		else if ( face.mNumIndices == 4) {
   1.227 +
   1.228 +			// quads can have at maximum one concave vertex. Determine
   1.229 +			// this vertex (if it exists) and start tri-fanning from
   1.230 +			// it. 
   1.231 +			unsigned int start_vertex = 0;
   1.232 +			for (unsigned int i = 0; i < 4; ++i) {
   1.233 +				const aiVector3D& v0 = verts[face.mIndices[(i+3) % 4]];
   1.234 +				const aiVector3D& v1 = verts[face.mIndices[(i+2) % 4]];
   1.235 +				const aiVector3D& v2 = verts[face.mIndices[(i+1) % 4]];
   1.236 +
   1.237 +				const aiVector3D& v = verts[face.mIndices[i]];
   1.238 +
   1.239 +				aiVector3D left = (v0-v); 
   1.240 +				aiVector3D diag = (v1-v); 
   1.241 +				aiVector3D right = (v2-v); 
   1.242 +
   1.243 +				left.Normalize();
   1.244 +				diag.Normalize();
   1.245 +				right.Normalize();
   1.246 +
   1.247 +				const float angle = acos(left*diag) + acos(right*diag);
   1.248 +				if (angle > AI_MATH_PI_F) {
   1.249 +					// this is the concave point
   1.250 +					start_vertex = i;
   1.251 +					break;
   1.252 +				}
   1.253 +			}
   1.254 +
   1.255 +			const unsigned int temp[] = {face.mIndices[0], face.mIndices[1], face.mIndices[2], face.mIndices[3]};
   1.256 +	
   1.257 +			aiFace& nface = *curOut++;
   1.258 +			nface.mNumIndices = 3;
   1.259 +			nface.mIndices = face.mIndices;
   1.260 +
   1.261 +			nface.mIndices[0] = temp[start_vertex];
   1.262 +			nface.mIndices[1] = temp[(start_vertex + 1) % 4];
   1.263 +			nface.mIndices[2] = temp[(start_vertex + 2) % 4];
   1.264 +
   1.265 +			aiFace& sface = *curOut++;
   1.266 +			sface.mNumIndices = 3;
   1.267 +			sface.mIndices = new unsigned int[3];
   1.268 +
   1.269 +			sface.mIndices[0] = temp[start_vertex];
   1.270 +			sface.mIndices[1] = temp[(start_vertex + 2) % 4];
   1.271 +			sface.mIndices[2] = temp[(start_vertex + 3) % 4];
   1.272 +		
   1.273 +			// prevent double deletion of the indices field
   1.274 +			face.mIndices = NULL;
   1.275 +			continue;
   1.276 +		} 
   1.277 +		else
   1.278 +		{
   1.279 +			// A polygon with more than 3 vertices can be either concave or convex.
   1.280 +			// Usually everything we're getting is convex and we could easily
   1.281 +			// triangulate by trifanning. However, LightWave is probably the only
   1.282 +			// modeling suite to make extensive use of highly concave, monster polygons ...
   1.283 +			// so we need to apply the full 'ear cutting' algorithm to get it right.
   1.284 +
   1.285 +			// RERQUIREMENT: polygon is expected to be simple and *nearly* planar.
   1.286 +			// We project it onto a plane to get a 2d triangle.
   1.287 +
   1.288 +			// Collect all vertices of of the polygon.
   1.289 +			for (tmp = 0; tmp < max; ++tmp) {
   1.290 +				temp_verts3d[tmp] = verts[idx[tmp]];
   1.291 +			}
   1.292 +
   1.293 +			// Get newell normal of the polygon. Store it for future use if it's a polygon-only mesh
   1.294 +			aiVector3D n;
   1.295 +			NewellNormal<3,3,3>(n,max,&temp_verts3d.front().x,&temp_verts3d.front().y,&temp_verts3d.front().z);
   1.296 +			if (nor_out) {
   1.297 +				 for (tmp = 0; tmp < max; ++tmp)
   1.298 +					 nor_out[idx[tmp]] = n;
   1.299 +			}
   1.300 +
   1.301 +			// Select largest normal coordinate to ignore for projection
   1.302 +			const float ax = (n.x>0 ? n.x : -n.x);    
   1.303 +			const float ay = (n.y>0 ? n.y : -n.y);   
   1.304 +			const float az = (n.z>0 ? n.z : -n.z);    
   1.305 +
   1.306 +			unsigned int ac = 0, bc = 1; /* no z coord. projection to xy */
   1.307 +			float inv = n.z;
   1.308 +			if (ax > ay) {
   1.309 +				if (ax > az) { /* no x coord. projection to yz */
   1.310 +					ac = 1; bc = 2;
   1.311 +					inv = n.x;
   1.312 +				}
   1.313 +			}
   1.314 +			else if (ay > az) { /* no y coord. projection to zy */
   1.315 +				ac = 2; bc = 0;
   1.316 +				inv = n.y;
   1.317 +			}
   1.318 +
   1.319 +			// Swap projection axes to take the negated projection vector into account
   1.320 +			if (inv < 0.f) {
   1.321 +				std::swap(ac,bc);
   1.322 +			}
   1.323 +
   1.324 +			for (tmp =0; tmp < max; ++tmp) {
   1.325 +				temp_verts[tmp].x = verts[idx[tmp]][ac];
   1.326 +				temp_verts[tmp].y = verts[idx[tmp]][bc];
   1.327 +				done[tmp] = false;	
   1.328 +			}
   1.329 +
   1.330 +			
   1.331 +#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
   1.332 +			// plot the plane onto which we mapped the polygon to a 2D ASCII pic
   1.333 +			aiVector2D bmin,bmax;
   1.334 +			ArrayBounds(&temp_verts[0],max,bmin,bmax);
   1.335 +
   1.336 +			char grid[POLY_GRID_Y][POLY_GRID_X+POLY_GRID_XPAD];
   1.337 +			std::fill_n((char*)grid,POLY_GRID_Y*(POLY_GRID_X+POLY_GRID_XPAD),' ');
   1.338 +
   1.339 +			for (int i =0; i < max; ++i) {
   1.340 +				const aiVector2D& v = (temp_verts[i] - bmin) / (bmax-bmin);
   1.341 +				const size_t x = static_cast<size_t>(v.x*(POLY_GRID_X-1)), y = static_cast<size_t>(v.y*(POLY_GRID_Y-1));
   1.342 +				char* loc = grid[y]+x;
   1.343 +				if (grid[y][x] != ' ') {
   1.344 +					for(;*loc != ' '; ++loc);
   1.345 +					*loc++ = '_';
   1.346 +				}
   1.347 +				*(loc+sprintf(loc,"%i",i)) = ' ';
   1.348 +			}
   1.349 +			
   1.350 +
   1.351 +			for(size_t y = 0; y < POLY_GRID_Y; ++y) {
   1.352 +				grid[y][POLY_GRID_X+POLY_GRID_XPAD-1] = '\0';
   1.353 +				fprintf(fout,"%s\n",grid[y]);
   1.354 +			}
   1.355 +
   1.356 +			fprintf(fout,"\ntriangulation sequence: ");
   1.357 +#endif
   1.358 +
   1.359 +			//
   1.360 +			// FIXME: currently this is the slow O(kn) variant with a worst case
   1.361 +			// complexity of O(n^2) (I think). Can be done in O(n).
   1.362 +			while (num > 3)	{
   1.363 +
   1.364 +				// Find the next ear of the polygon
   1.365 +				int num_found = 0;
   1.366 +				for (ear = next;;prev = ear,ear = next) {
   1.367 +				
   1.368 +					// break after we looped two times without a positive match
   1.369 +					for (next=ear+1;done[(next>=max?next=0:next)];++next);
   1.370 +					if (next < ear) {
   1.371 +						if (++num_found == 2) {
   1.372 +							break;
   1.373 +						}
   1.374 +					}
   1.375 +					const aiVector2D* pnt1 = &temp_verts[ear], 
   1.376 +						*pnt0 = &temp_verts[prev], 
   1.377 +						*pnt2 = &temp_verts[next];
   1.378 +			
   1.379 +					// Must be a convex point. Assuming ccw winding, it must be on the right of the line between p-1 and p+1.
   1.380 +					if (OnLeftSideOfLine2D(*pnt0,*pnt2,*pnt1)) {
   1.381 +						continue;
   1.382 +					}
   1.383 +
   1.384 +					// and no other point may be contained in this triangle
   1.385 +					for ( tmp = 0; tmp < max; ++tmp) {
   1.386 +
   1.387 +						// We need to compare the actual values because it's possible that multiple indexes in 
   1.388 +						// the polygon are referring to the same position. concave_polygon.obj is a sample
   1.389 +						//
   1.390 +						// FIXME: Use 'epsiloned' comparisons instead? Due to numeric inaccuracies in
   1.391 +						// PointInTriangle() I'm guessing that it's actually possible to construct
   1.392 +						// input data that would cause us to end up with no ears. The problem is,
   1.393 +						// which epsilon? If we chose a too large value, we'd get wrong results
   1.394 +						const aiVector2D& vtmp = temp_verts[tmp]; 
   1.395 +						if ( vtmp != *pnt1 && vtmp != *pnt2 && vtmp != *pnt0 && PointInTriangle2D(*pnt0,*pnt1,*pnt2,vtmp)) {
   1.396 +							break;		
   1.397 +						}
   1.398 +					}
   1.399 +					if (tmp != max) {
   1.400 +						continue;
   1.401 +					}
   1.402 +
   1.403 +					// this vertex is an ear
   1.404 +					break;
   1.405 +				}
   1.406 +				if (num_found == 2) {
   1.407 +					
   1.408 +					// Due to the 'two ear theorem', every simple polygon with more than three points must
   1.409 +					// have 2 'ears'. Here's definitely someting wrong ... but we don't give up yet.
   1.410 +					//
   1.411 +
   1.412 +					// Instead we're continuting with the standard trifanning algorithm which we'd
   1.413 +					// use if we had only convex polygons. That's life.
   1.414 +					DefaultLogger::get()->error("Failed to triangulate polygon (no ear found). Probably not a simple polygon?");
   1.415 +					
   1.416 +
   1.417 +#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
   1.418 +					fprintf(fout,"critical error here, no ear found! ");
   1.419 +#endif
   1.420 +					num = 0;
   1.421 +					break;
   1.422 +
   1.423 +					curOut -= (max-num); /* undo all previous work */
   1.424 +					for (tmp = 0; tmp < max-2; ++tmp) {
   1.425 +						aiFace& nface = *curOut++;
   1.426 +
   1.427 +						nface.mNumIndices = 3;
   1.428 +						if (!nface.mIndices)
   1.429 +							nface.mIndices = new unsigned int[3];
   1.430 +
   1.431 +						nface.mIndices[0] = 0;
   1.432 +						nface.mIndices[1] = tmp+1;
   1.433 +						nface.mIndices[2] = tmp+2;
   1.434 +
   1.435 +					}
   1.436 +					num = 0;
   1.437 +					break;
   1.438 +				}
   1.439 +
   1.440 +				aiFace& nface = *curOut++;
   1.441 +				nface.mNumIndices = 3;
   1.442 +
   1.443 +				if (!nface.mIndices) {
   1.444 +					nface.mIndices = new unsigned int[3];
   1.445 +				}
   1.446 +
   1.447 +				// setup indices for the new triangle ...
   1.448 +				nface.mIndices[0] = prev;
   1.449 +				nface.mIndices[1] = ear;
   1.450 +				nface.mIndices[2] = next;
   1.451 +
   1.452 +				// exclude the ear from most further processing
   1.453 +				done[ear] = true;
   1.454 +				--num;
   1.455 +			}
   1.456 +			if (num > 0) {
   1.457 +				// We have three indices forming the last 'ear' remaining. Collect them.
   1.458 +				aiFace& nface = *curOut++;
   1.459 +				nface.mNumIndices = 3;
   1.460 +				if (!nface.mIndices) {
   1.461 +					nface.mIndices = new unsigned int[3];
   1.462 +				}
   1.463 +
   1.464 +				for (tmp = 0; done[tmp]; ++tmp);
   1.465 +				nface.mIndices[0] = tmp;
   1.466 +
   1.467 +				for (++tmp; done[tmp]; ++tmp);
   1.468 +				nface.mIndices[1] = tmp;
   1.469 +
   1.470 +				for (++tmp; done[tmp]; ++tmp);
   1.471 +				nface.mIndices[2] = tmp;
   1.472 +
   1.473 +			}
   1.474 +		}
   1.475 +
   1.476 +#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
   1.477 +		
   1.478 +		for(aiFace* f = last_face; f != curOut; ++f) {
   1.479 +			unsigned int* i = f->mIndices;
   1.480 +			fprintf(fout," (%i %i %i)",i[0],i[1],i[2]);
   1.481 +		}
   1.482 +
   1.483 +		fprintf(fout,"\n*********************************************************************\n");
   1.484 +		fflush(fout);
   1.485 +		
   1.486 +#endif
   1.487 +
   1.488 +		for(aiFace* f = last_face; f != curOut; ) {
   1.489 +			unsigned int* i = f->mIndices;
   1.490 +
   1.491 +			//  drop dumb 0-area triangles
   1.492 +			if (fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) {
   1.493 +				DefaultLogger::get()->debug("Dropping triangle with area 0");
   1.494 +				--curOut;
   1.495 +
   1.496 +				delete[] f->mIndices;
   1.497 +				f->mIndices = NULL;
   1.498 +
   1.499 +				for(aiFace* ff = f; ff != curOut; ++ff) {
   1.500 +					ff->mNumIndices = (ff+1)->mNumIndices;
   1.501 +					ff->mIndices = (ff+1)->mIndices;
   1.502 +					(ff+1)->mIndices = NULL;
   1.503 +				}
   1.504 +				continue;
   1.505 +			}
   1.506 +
   1.507 +			i[0] = idx[i[0]];
   1.508 +			i[1] = idx[i[1]];
   1.509 +			i[2] = idx[i[2]];
   1.510 +			++f;
   1.511 +		}
   1.512 +
   1.513 +		delete[] face.mIndices;
   1.514 +		face.mIndices = NULL; 
   1.515 +	}
   1.516 +
   1.517 +#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
   1.518 +	fclose(fout);
   1.519 +#endif
   1.520 +
   1.521 +	// kill the old faces
   1.522 +	delete [] pMesh->mFaces;
   1.523 +
   1.524 +	// ... and store the new ones
   1.525 +	pMesh->mFaces    = out;
   1.526 +	pMesh->mNumFaces = (unsigned int)(curOut-out); /* not necessarily equal to numOut */
   1.527 +	return true;
   1.528 +}
   1.529 +
   1.530 +#endif // !! ASSIMP_BUILD_NO_TRIANGULATE_PROCESS