vrshoot

annotate libs/assimp/TriangulateProcess.cpp @ 1:e7ca128b8713

looks nice :)
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 02 Feb 2014 00:35:22 +0200
parents
children
rev   line source
nuclear@0 1 /*
nuclear@0 2 ---------------------------------------------------------------------------
nuclear@0 3 Open Asset Import Library (assimp)
nuclear@0 4 ---------------------------------------------------------------------------
nuclear@0 5
nuclear@0 6 Copyright (c) 2006-2012, assimp team
nuclear@0 7
nuclear@0 8 All rights reserved.
nuclear@0 9
nuclear@0 10 Redistribution and use of this software in source and binary forms,
nuclear@0 11 with or without modification, are permitted provided that the following
nuclear@0 12 conditions are met:
nuclear@0 13
nuclear@0 14 * Redistributions of source code must retain the above
nuclear@0 15 copyright notice, this list of conditions and the
nuclear@0 16 following disclaimer.
nuclear@0 17
nuclear@0 18 * Redistributions in binary form must reproduce the above
nuclear@0 19 copyright notice, this list of conditions and the
nuclear@0 20 following disclaimer in the documentation and/or other
nuclear@0 21 materials provided with the distribution.
nuclear@0 22
nuclear@0 23 * Neither the name of the assimp team, nor the names of its
nuclear@0 24 contributors may be used to endorse or promote products
nuclear@0 25 derived from this software without specific prior
nuclear@0 26 written permission of the assimp team.
nuclear@0 27
nuclear@0 28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
nuclear@0 29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
nuclear@0 30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
nuclear@0 31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
nuclear@0 32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
nuclear@0 33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
nuclear@0 34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
nuclear@0 35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
nuclear@0 36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
nuclear@0 37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
nuclear@0 38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
nuclear@0 39 ---------------------------------------------------------------------------
nuclear@0 40 */
nuclear@0 41
nuclear@0 42 /** @file TriangulateProcess.cpp
nuclear@0 43 * @brief Implementation of the post processing step to split up
nuclear@0 44 * all faces with more than three indices into triangles.
nuclear@0 45 *
nuclear@0 46 *
nuclear@0 47 * The triangulation algorithm will handle concave or convex polygons.
nuclear@0 48 * Self-intersecting or non-planar polygons are not rejected, but
nuclear@0 49 * they're probably not triangulated correctly.
nuclear@0 50 *
nuclear@0 51 * DEBUG SWITCHES - do not enable any of them in release builds:
nuclear@0 52 *
nuclear@0 53 * AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
nuclear@0 54 * - generates vertex colors to represent the face winding order.
nuclear@0 55 * the first vertex of a polygon becomes red, the last blue.
nuclear@0 56 * AI_BUILD_TRIANGULATE_DEBUG_POLYS
nuclear@0 57 * - dump all polygons and their triangulation sequences to
nuclear@0 58 * a file
nuclear@0 59 */
nuclear@0 60
nuclear@0 61 #include "AssimpPCH.h"
nuclear@0 62
nuclear@0 63 #ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS
nuclear@0 64 #include "TriangulateProcess.h"
nuclear@0 65 #include "ProcessHelper.h"
nuclear@0 66 #include "PolyTools.h"
nuclear@0 67
nuclear@0 68 //#define AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
nuclear@0 69 //#define AI_BUILD_TRIANGULATE_DEBUG_POLYS
nuclear@0 70
nuclear@0 71 #define POLY_GRID_Y 40
nuclear@0 72 #define POLY_GRID_X 70
nuclear@0 73 #define POLY_GRID_XPAD 20
nuclear@0 74 #define POLY_OUTPUT_FILE "assimp_polygons_debug.txt"
nuclear@0 75
nuclear@0 76 using namespace Assimp;
nuclear@0 77
nuclear@0 78 // ------------------------------------------------------------------------------------------------
nuclear@0 79 // Constructor to be privately used by Importer
nuclear@0 80 TriangulateProcess::TriangulateProcess()
nuclear@0 81 {
nuclear@0 82 // nothing to do here
nuclear@0 83 }
nuclear@0 84
nuclear@0 85 // ------------------------------------------------------------------------------------------------
nuclear@0 86 // Destructor, private as well
nuclear@0 87 TriangulateProcess::~TriangulateProcess()
nuclear@0 88 {
nuclear@0 89 // nothing to do here
nuclear@0 90 }
nuclear@0 91
nuclear@0 92 // ------------------------------------------------------------------------------------------------
nuclear@0 93 // Returns whether the processing step is present in the given flag field.
nuclear@0 94 bool TriangulateProcess::IsActive( unsigned int pFlags) const
nuclear@0 95 {
nuclear@0 96 return (pFlags & aiProcess_Triangulate) != 0;
nuclear@0 97 }
nuclear@0 98
nuclear@0 99 // ------------------------------------------------------------------------------------------------
nuclear@0 100 // Executes the post processing step on the given imported data.
nuclear@0 101 void TriangulateProcess::Execute( aiScene* pScene)
nuclear@0 102 {
nuclear@0 103 DefaultLogger::get()->debug("TriangulateProcess begin");
nuclear@0 104
nuclear@0 105 bool bHas = false;
nuclear@0 106 for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
nuclear@0 107 {
nuclear@0 108 if( TriangulateMesh( pScene->mMeshes[a]))
nuclear@0 109 bHas = true;
nuclear@0 110 }
nuclear@0 111 if (bHas)DefaultLogger::get()->info ("TriangulateProcess finished. All polygons have been triangulated.");
nuclear@0 112 else DefaultLogger::get()->debug("TriangulateProcess finished. There was nothing to be done.");
nuclear@0 113 }
nuclear@0 114
nuclear@0 115
nuclear@0 116 // ------------------------------------------------------------------------------------------------
nuclear@0 117 // Triangulates the given mesh.
nuclear@0 118 bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
nuclear@0 119 {
nuclear@0 120 // Now we have aiMesh::mPrimitiveTypes, so this is only here for test cases
nuclear@0 121 if (!pMesh->mPrimitiveTypes) {
nuclear@0 122 bool bNeed = false;
nuclear@0 123
nuclear@0 124 for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
nuclear@0 125 const aiFace& face = pMesh->mFaces[a];
nuclear@0 126
nuclear@0 127 if( face.mNumIndices != 3) {
nuclear@0 128 bNeed = true;
nuclear@0 129 }
nuclear@0 130 }
nuclear@0 131 if (!bNeed)
nuclear@0 132 return false;
nuclear@0 133 }
nuclear@0 134 else if (!(pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) {
nuclear@0 135 return false;
nuclear@0 136 }
nuclear@0 137
nuclear@0 138 // Find out how many output faces we'll get
nuclear@0 139 unsigned int numOut = 0, max_out = 0;
nuclear@0 140 bool get_normals = true;
nuclear@0 141 for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
nuclear@0 142 aiFace& face = pMesh->mFaces[a];
nuclear@0 143 if (face.mNumIndices <= 4) {
nuclear@0 144 get_normals = false;
nuclear@0 145 }
nuclear@0 146 if( face.mNumIndices <= 3) {
nuclear@0 147 numOut++;
nuclear@0 148
nuclear@0 149 }
nuclear@0 150 else {
nuclear@0 151 numOut += face.mNumIndices-2;
nuclear@0 152 max_out = std::max(max_out,face.mNumIndices);
nuclear@0 153 }
nuclear@0 154 }
nuclear@0 155
nuclear@0 156 // Just another check whether aiMesh::mPrimitiveTypes is correct
nuclear@0 157 assert(numOut != pMesh->mNumFaces);
nuclear@0 158
nuclear@0 159 aiVector3D* nor_out = NULL;
nuclear@0 160
nuclear@0 161 // if we don't have normals yet, but expect them to be a cheap side
nuclear@0 162 // product of triangulation anyway, allocate storage for them.
nuclear@0 163 if (!pMesh->mNormals && get_normals) {
nuclear@0 164 // XXX need a mechanism to inform the GenVertexNormals process to treat these normals as preprocessed per-face normals
nuclear@0 165 // nor_out = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
nuclear@0 166 }
nuclear@0 167
nuclear@0 168 // the output mesh will contain triangles, but no polys anymore
nuclear@0 169 pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
nuclear@0 170 pMesh->mPrimitiveTypes &= ~aiPrimitiveType_POLYGON;
nuclear@0 171
nuclear@0 172 aiFace* out = new aiFace[numOut](), *curOut = out;
nuclear@0 173 std::vector<aiVector3D> temp_verts3d(max_out+2); /* temporary storage for vertices */
nuclear@0 174 std::vector<aiVector2D> temp_verts(max_out+2);
nuclear@0 175
nuclear@0 176 // Apply vertex colors to represent the face winding?
nuclear@0 177 #ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
nuclear@0 178 if (!pMesh->mColors[0])
nuclear@0 179 pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices];
nuclear@0 180 else
nuclear@0 181 new(pMesh->mColors[0]) aiColor4D[pMesh->mNumVertices];
nuclear@0 182
nuclear@0 183 aiColor4D* clr = pMesh->mColors[0];
nuclear@0 184 #endif
nuclear@0 185
nuclear@0 186
nuclear@0 187 #ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
nuclear@0 188 FILE* fout = fopen(POLY_OUTPUT_FILE,"a");
nuclear@0 189 #endif
nuclear@0 190
nuclear@0 191 const aiVector3D* verts = pMesh->mVertices;
nuclear@0 192
nuclear@0 193 // use boost::scoped_array to avoid slow std::vector<bool> specialiations
nuclear@0 194 boost::scoped_array<bool> done(new bool[max_out]);
nuclear@0 195 for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
nuclear@0 196 aiFace& face = pMesh->mFaces[a];
nuclear@0 197
nuclear@0 198 unsigned int* idx = face.mIndices;
nuclear@0 199 int num = (int)face.mNumIndices, ear = 0, tmp, prev = num-1, next = 0, max = num;
nuclear@0 200
nuclear@0 201 // Apply vertex colors to represent the face winding?
nuclear@0 202 #ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
nuclear@0 203 for (unsigned int i = 0; i < face.mNumIndices; ++i) {
nuclear@0 204 aiColor4D& c = clr[idx[i]];
nuclear@0 205 c.r = (i+1) / (float)max;
nuclear@0 206 c.b = 1.f - c.r;
nuclear@0 207 }
nuclear@0 208 #endif
nuclear@0 209
nuclear@0 210 aiFace* const last_face = curOut;
nuclear@0 211
nuclear@0 212 // if it's a simple point,line or triangle: just copy it
nuclear@0 213 if( face.mNumIndices <= 3)
nuclear@0 214 {
nuclear@0 215 aiFace& nface = *curOut++;
nuclear@0 216 nface.mNumIndices = face.mNumIndices;
nuclear@0 217 nface.mIndices = face.mIndices;
nuclear@0 218
nuclear@0 219 face.mIndices = NULL;
nuclear@0 220 continue;
nuclear@0 221 }
nuclear@0 222 // optimized code for quadrilaterals
nuclear@0 223 else if ( face.mNumIndices == 4) {
nuclear@0 224
nuclear@0 225 // quads can have at maximum one concave vertex. Determine
nuclear@0 226 // this vertex (if it exists) and start tri-fanning from
nuclear@0 227 // it.
nuclear@0 228 unsigned int start_vertex = 0;
nuclear@0 229 for (unsigned int i = 0; i < 4; ++i) {
nuclear@0 230 const aiVector3D& v0 = verts[face.mIndices[(i+3) % 4]];
nuclear@0 231 const aiVector3D& v1 = verts[face.mIndices[(i+2) % 4]];
nuclear@0 232 const aiVector3D& v2 = verts[face.mIndices[(i+1) % 4]];
nuclear@0 233
nuclear@0 234 const aiVector3D& v = verts[face.mIndices[i]];
nuclear@0 235
nuclear@0 236 aiVector3D left = (v0-v);
nuclear@0 237 aiVector3D diag = (v1-v);
nuclear@0 238 aiVector3D right = (v2-v);
nuclear@0 239
nuclear@0 240 left.Normalize();
nuclear@0 241 diag.Normalize();
nuclear@0 242 right.Normalize();
nuclear@0 243
nuclear@0 244 const float angle = acos(left*diag) + acos(right*diag);
nuclear@0 245 if (angle > AI_MATH_PI_F) {
nuclear@0 246 // this is the concave point
nuclear@0 247 start_vertex = i;
nuclear@0 248 break;
nuclear@0 249 }
nuclear@0 250 }
nuclear@0 251
nuclear@0 252 const unsigned int temp[] = {face.mIndices[0], face.mIndices[1], face.mIndices[2], face.mIndices[3]};
nuclear@0 253
nuclear@0 254 aiFace& nface = *curOut++;
nuclear@0 255 nface.mNumIndices = 3;
nuclear@0 256 nface.mIndices = face.mIndices;
nuclear@0 257
nuclear@0 258 nface.mIndices[0] = temp[start_vertex];
nuclear@0 259 nface.mIndices[1] = temp[(start_vertex + 1) % 4];
nuclear@0 260 nface.mIndices[2] = temp[(start_vertex + 2) % 4];
nuclear@0 261
nuclear@0 262 aiFace& sface = *curOut++;
nuclear@0 263 sface.mNumIndices = 3;
nuclear@0 264 sface.mIndices = new unsigned int[3];
nuclear@0 265
nuclear@0 266 sface.mIndices[0] = temp[start_vertex];
nuclear@0 267 sface.mIndices[1] = temp[(start_vertex + 2) % 4];
nuclear@0 268 sface.mIndices[2] = temp[(start_vertex + 3) % 4];
nuclear@0 269
nuclear@0 270 // prevent double deletion of the indices field
nuclear@0 271 face.mIndices = NULL;
nuclear@0 272 continue;
nuclear@0 273 }
nuclear@0 274 else
nuclear@0 275 {
nuclear@0 276 // A polygon with more than 3 vertices can be either concave or convex.
nuclear@0 277 // Usually everything we're getting is convex and we could easily
nuclear@0 278 // triangulate by trifanning. However, LightWave is probably the only
nuclear@0 279 // modeling suite to make extensive use of highly concave, monster polygons ...
nuclear@0 280 // so we need to apply the full 'ear cutting' algorithm to get it right.
nuclear@0 281
nuclear@0 282 // RERQUIREMENT: polygon is expected to be simple and *nearly* planar.
nuclear@0 283 // We project it onto a plane to get a 2d triangle.
nuclear@0 284
nuclear@0 285 // Collect all vertices of of the polygon.
nuclear@0 286 for (tmp = 0; tmp < max; ++tmp) {
nuclear@0 287 temp_verts3d[tmp] = verts[idx[tmp]];
nuclear@0 288 }
nuclear@0 289
nuclear@0 290 // Get newell normal of the polygon. Store it for future use if it's a polygon-only mesh
nuclear@0 291 aiVector3D n;
nuclear@0 292 NewellNormal<3,3,3>(n,max,&temp_verts3d.front().x,&temp_verts3d.front().y,&temp_verts3d.front().z);
nuclear@0 293 if (nor_out) {
nuclear@0 294 for (tmp = 0; tmp < max; ++tmp)
nuclear@0 295 nor_out[idx[tmp]] = n;
nuclear@0 296 }
nuclear@0 297
nuclear@0 298 // Select largest normal coordinate to ignore for projection
nuclear@0 299 const float ax = (n.x>0 ? n.x : -n.x);
nuclear@0 300 const float ay = (n.y>0 ? n.y : -n.y);
nuclear@0 301 const float az = (n.z>0 ? n.z : -n.z);
nuclear@0 302
nuclear@0 303 unsigned int ac = 0, bc = 1; /* no z coord. projection to xy */
nuclear@0 304 float inv = n.z;
nuclear@0 305 if (ax > ay) {
nuclear@0 306 if (ax > az) { /* no x coord. projection to yz */
nuclear@0 307 ac = 1; bc = 2;
nuclear@0 308 inv = n.x;
nuclear@0 309 }
nuclear@0 310 }
nuclear@0 311 else if (ay > az) { /* no y coord. projection to zy */
nuclear@0 312 ac = 2; bc = 0;
nuclear@0 313 inv = n.y;
nuclear@0 314 }
nuclear@0 315
nuclear@0 316 // Swap projection axes to take the negated projection vector into account
nuclear@0 317 if (inv < 0.f) {
nuclear@0 318 std::swap(ac,bc);
nuclear@0 319 }
nuclear@0 320
nuclear@0 321 for (tmp =0; tmp < max; ++tmp) {
nuclear@0 322 temp_verts[tmp].x = verts[idx[tmp]][ac];
nuclear@0 323 temp_verts[tmp].y = verts[idx[tmp]][bc];
nuclear@0 324 done[tmp] = false;
nuclear@0 325 }
nuclear@0 326
nuclear@0 327
nuclear@0 328 #ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
nuclear@0 329 // plot the plane onto which we mapped the polygon to a 2D ASCII pic
nuclear@0 330 aiVector2D bmin,bmax;
nuclear@0 331 ArrayBounds(&temp_verts[0],max,bmin,bmax);
nuclear@0 332
nuclear@0 333 char grid[POLY_GRID_Y][POLY_GRID_X+POLY_GRID_XPAD];
nuclear@0 334 std::fill_n((char*)grid,POLY_GRID_Y*(POLY_GRID_X+POLY_GRID_XPAD),' ');
nuclear@0 335
nuclear@0 336 for (int i =0; i < max; ++i) {
nuclear@0 337 const aiVector2D& v = (temp_verts[i] - bmin) / (bmax-bmin);
nuclear@0 338 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));
nuclear@0 339 char* loc = grid[y]+x;
nuclear@0 340 if (grid[y][x] != ' ') {
nuclear@0 341 for(;*loc != ' '; ++loc);
nuclear@0 342 *loc++ = '_';
nuclear@0 343 }
nuclear@0 344 *(loc+sprintf(loc,"%i",i)) = ' ';
nuclear@0 345 }
nuclear@0 346
nuclear@0 347
nuclear@0 348 for(size_t y = 0; y < POLY_GRID_Y; ++y) {
nuclear@0 349 grid[y][POLY_GRID_X+POLY_GRID_XPAD-1] = '\0';
nuclear@0 350 fprintf(fout,"%s\n",grid[y]);
nuclear@0 351 }
nuclear@0 352
nuclear@0 353 fprintf(fout,"\ntriangulation sequence: ");
nuclear@0 354 #endif
nuclear@0 355
nuclear@0 356 //
nuclear@0 357 // FIXME: currently this is the slow O(kn) variant with a worst case
nuclear@0 358 // complexity of O(n^2) (I think). Can be done in O(n).
nuclear@0 359 while (num > 3) {
nuclear@0 360
nuclear@0 361 // Find the next ear of the polygon
nuclear@0 362 int num_found = 0;
nuclear@0 363 for (ear = next;;prev = ear,ear = next) {
nuclear@0 364
nuclear@0 365 // break after we looped two times without a positive match
nuclear@0 366 for (next=ear+1;done[(next>=max?next=0:next)];++next);
nuclear@0 367 if (next < ear) {
nuclear@0 368 if (++num_found == 2) {
nuclear@0 369 break;
nuclear@0 370 }
nuclear@0 371 }
nuclear@0 372 const aiVector2D* pnt1 = &temp_verts[ear],
nuclear@0 373 *pnt0 = &temp_verts[prev],
nuclear@0 374 *pnt2 = &temp_verts[next];
nuclear@0 375
nuclear@0 376 // Must be a convex point. Assuming ccw winding, it must be on the right of the line between p-1 and p+1.
nuclear@0 377 if (OnLeftSideOfLine2D(*pnt0,*pnt2,*pnt1)) {
nuclear@0 378 continue;
nuclear@0 379 }
nuclear@0 380
nuclear@0 381 // and no other point may be contained in this triangle
nuclear@0 382 for ( tmp = 0; tmp < max; ++tmp) {
nuclear@0 383
nuclear@0 384 // We need to compare the actual values because it's possible that multiple indexes in
nuclear@0 385 // the polygon are referring to the same position. concave_polygon.obj is a sample
nuclear@0 386 //
nuclear@0 387 // FIXME: Use 'epsiloned' comparisons instead? Due to numeric inaccuracies in
nuclear@0 388 // PointInTriangle() I'm guessing that it's actually possible to construct
nuclear@0 389 // input data that would cause us to end up with no ears. The problem is,
nuclear@0 390 // which epsilon? If we chose a too large value, we'd get wrong results
nuclear@0 391 const aiVector2D& vtmp = temp_verts[tmp];
nuclear@0 392 if ( vtmp != *pnt1 && vtmp != *pnt2 && vtmp != *pnt0 && PointInTriangle2D(*pnt0,*pnt1,*pnt2,vtmp)) {
nuclear@0 393 break;
nuclear@0 394 }
nuclear@0 395 }
nuclear@0 396 if (tmp != max) {
nuclear@0 397 continue;
nuclear@0 398 }
nuclear@0 399
nuclear@0 400 // this vertex is an ear
nuclear@0 401 break;
nuclear@0 402 }
nuclear@0 403 if (num_found == 2) {
nuclear@0 404
nuclear@0 405 // Due to the 'two ear theorem', every simple polygon with more than three points must
nuclear@0 406 // have 2 'ears'. Here's definitely someting wrong ... but we don't give up yet.
nuclear@0 407 //
nuclear@0 408
nuclear@0 409 // Instead we're continuting with the standard trifanning algorithm which we'd
nuclear@0 410 // use if we had only convex polygons. That's life.
nuclear@0 411 DefaultLogger::get()->error("Failed to triangulate polygon (no ear found). Probably not a simple polygon?");
nuclear@0 412
nuclear@0 413
nuclear@0 414 #ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
nuclear@0 415 fprintf(fout,"critical error here, no ear found! ");
nuclear@0 416 #endif
nuclear@0 417 num = 0;
nuclear@0 418 break;
nuclear@0 419
nuclear@0 420 curOut -= (max-num); /* undo all previous work */
nuclear@0 421 for (tmp = 0; tmp < max-2; ++tmp) {
nuclear@0 422 aiFace& nface = *curOut++;
nuclear@0 423
nuclear@0 424 nface.mNumIndices = 3;
nuclear@0 425 if (!nface.mIndices)
nuclear@0 426 nface.mIndices = new unsigned int[3];
nuclear@0 427
nuclear@0 428 nface.mIndices[0] = 0;
nuclear@0 429 nface.mIndices[1] = tmp+1;
nuclear@0 430 nface.mIndices[2] = tmp+2;
nuclear@0 431
nuclear@0 432 }
nuclear@0 433 num = 0;
nuclear@0 434 break;
nuclear@0 435 }
nuclear@0 436
nuclear@0 437 aiFace& nface = *curOut++;
nuclear@0 438 nface.mNumIndices = 3;
nuclear@0 439
nuclear@0 440 if (!nface.mIndices) {
nuclear@0 441 nface.mIndices = new unsigned int[3];
nuclear@0 442 }
nuclear@0 443
nuclear@0 444 // setup indices for the new triangle ...
nuclear@0 445 nface.mIndices[0] = prev;
nuclear@0 446 nface.mIndices[1] = ear;
nuclear@0 447 nface.mIndices[2] = next;
nuclear@0 448
nuclear@0 449 // exclude the ear from most further processing
nuclear@0 450 done[ear] = true;
nuclear@0 451 --num;
nuclear@0 452 }
nuclear@0 453 if (num > 0) {
nuclear@0 454 // We have three indices forming the last 'ear' remaining. Collect them.
nuclear@0 455 aiFace& nface = *curOut++;
nuclear@0 456 nface.mNumIndices = 3;
nuclear@0 457 if (!nface.mIndices) {
nuclear@0 458 nface.mIndices = new unsigned int[3];
nuclear@0 459 }
nuclear@0 460
nuclear@0 461 for (tmp = 0; done[tmp]; ++tmp);
nuclear@0 462 nface.mIndices[0] = tmp;
nuclear@0 463
nuclear@0 464 for (++tmp; done[tmp]; ++tmp);
nuclear@0 465 nface.mIndices[1] = tmp;
nuclear@0 466
nuclear@0 467 for (++tmp; done[tmp]; ++tmp);
nuclear@0 468 nface.mIndices[2] = tmp;
nuclear@0 469
nuclear@0 470 }
nuclear@0 471 }
nuclear@0 472
nuclear@0 473 #ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
nuclear@0 474
nuclear@0 475 for(aiFace* f = last_face; f != curOut; ++f) {
nuclear@0 476 unsigned int* i = f->mIndices;
nuclear@0 477 fprintf(fout," (%i %i %i)",i[0],i[1],i[2]);
nuclear@0 478 }
nuclear@0 479
nuclear@0 480 fprintf(fout,"\n*********************************************************************\n");
nuclear@0 481 fflush(fout);
nuclear@0 482
nuclear@0 483 #endif
nuclear@0 484
nuclear@0 485 for(aiFace* f = last_face; f != curOut; ) {
nuclear@0 486 unsigned int* i = f->mIndices;
nuclear@0 487
nuclear@0 488 // drop dumb 0-area triangles
nuclear@0 489 if (fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) {
nuclear@0 490 DefaultLogger::get()->debug("Dropping triangle with area 0");
nuclear@0 491 --curOut;
nuclear@0 492
nuclear@0 493 delete[] f->mIndices;
nuclear@0 494 f->mIndices = NULL;
nuclear@0 495
nuclear@0 496 for(aiFace* ff = f; ff != curOut; ++ff) {
nuclear@0 497 ff->mNumIndices = (ff+1)->mNumIndices;
nuclear@0 498 ff->mIndices = (ff+1)->mIndices;
nuclear@0 499 (ff+1)->mIndices = NULL;
nuclear@0 500 }
nuclear@0 501 continue;
nuclear@0 502 }
nuclear@0 503
nuclear@0 504 i[0] = idx[i[0]];
nuclear@0 505 i[1] = idx[i[1]];
nuclear@0 506 i[2] = idx[i[2]];
nuclear@0 507 ++f;
nuclear@0 508 }
nuclear@0 509
nuclear@0 510 delete[] face.mIndices;
nuclear@0 511 face.mIndices = NULL;
nuclear@0 512 }
nuclear@0 513
nuclear@0 514 #ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
nuclear@0 515 fclose(fout);
nuclear@0 516 #endif
nuclear@0 517
nuclear@0 518 // kill the old faces
nuclear@0 519 delete [] pMesh->mFaces;
nuclear@0 520
nuclear@0 521 // ... and store the new ones
nuclear@0 522 pMesh->mFaces = out;
nuclear@0 523 pMesh->mNumFaces = (unsigned int)(curOut-out); /* not necessarily equal to numOut */
nuclear@0 524 return true;
nuclear@0 525 }
nuclear@0 526
nuclear@0 527 #endif // !! ASSIMP_BUILD_NO_TRIANGULATE_PROCESS