Changeset 980 for GTP/trunk/Lib/Geom/shared/GTGeometry/src
- Timestamp:
- 05/24/06 10:47:49 (19 years ago)
- Location:
- GTP/trunk/Lib/Geom/shared/GTGeometry/src
- Files:
-
- 1 deleted
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
GTP/trunk/Lib/Geom/shared/GTGeometry/src/GeoMesh.cpp
r891 r980 4 4 using namespace std; 5 5 6 //---------------------------------------------------------------------------- 6 //--------------------------------------------------------------------------- 7 // Cosntructor. 8 //--------------------------------------------------------------------------- 7 9 Mesh::Mesh(): 8 mVertexBuffer(0), mSubMeshCount(0), mSubMesh(0) 9 { 10 } 11 10 mVertexBuffer(0), mSubMeshCount(0), mSubMesh(0), hasSkeleton(false) 11 { 12 mMeshBounds.maxX = 0.0; 13 mMeshBounds.maxY = 0.0; 14 mMeshBounds.maxZ = 0.0; 15 mMeshBounds.minX = 0.0; 16 mMeshBounds.minY = 0.0; 17 mMeshBounds.minZ = 0.0; 18 mMeshBounds.scaleFactor = 0.0; 19 } 20 21 //--------------------------------------------------------------------------- 22 // Destroyer. 23 //--------------------------------------------------------------------------- 12 24 Mesh::~Mesh() 13 25 { … … 17 29 18 30 31 //--------------------------------------------------------------------------- 32 // Copy constructor. 33 //--------------------------------------------------------------------------- 19 34 Mesh::Mesh(const Mesh &objmesh) 20 35 { 21 36 // constructor copia 22 mVertexBuffer=new VertexBuffer(); 23 mSubMeshCount=objmesh.mSubMeshCount; 24 mSubMesh = new Geometry::SubMesh[objmesh.mSubMeshCount]; 25 for(size_t i=0;i<objmesh.mSubMeshCount;i++) 26 { 27 mSubMesh[i].mSharedVertexBuffer=false; 28 mSubMesh[i].mVertexBuffer = new Geometry::VertexBuffer(); 29 mSubMesh[i].mVertexBuffer->mPosition = new Geometry::Vector3[objmesh.mSubMesh[i].mVertexBuffer->mVertexCount]; 30 mSubMesh[i].mVertexBuffer->mNormal = new Geometry::Vector3[objmesh.mSubMesh[i].mVertexBuffer->mVertexCount]; 31 mSubMesh[i].mVertexBuffer->mTexCoords = new Geometry::Vector2[objmesh.mSubMesh[i].mVertexBuffer->mVertexCount]; 32 mSubMesh[i].mVertexBuffer->mVertexCount = objmesh.mSubMesh[i].mVertexBuffer->mVertexCount; 33 mSubMesh[i].mVertexBuffer->mVertexInfo = objmesh.mSubMesh[i].mVertexBuffer->mVertexInfo; 34 mSubMesh[i].mType = objmesh.mSubMesh[i].mType; 35 36 // De momento con esto se parte de un geomesh con vértices compartidos y se obtiene un geomesh sin vértices 37 // compartidos. Los vértices se replican en cada uno de los submeshes. 38 // HAY QUE CAMBIARLO. 39 if(objmesh.mSubMesh[i].mSharedVertexBuffer == true) 40 { 41 for(size_t s=0;s<objmesh.mSubMesh[i].mVertexBuffer->mVertexCount;s++) 42 { 43 //Copiamos mPosition 44 if (objmesh.mSubMesh[i].mVertexBuffer->mVertexInfo & Geometry::VERTEX_POSITION) 37 mVertexBuffer = new VertexBuffer(); 38 mSubMeshCount = objmesh.mSubMeshCount; 39 mSubMesh = new SubMesh[objmesh.mSubMeshCount]; 40 41 // Fill up bounding box settings. 42 mMeshBounds.maxX = objmesh.mMeshBounds.maxX; 43 mMeshBounds.maxY = objmesh.mMeshBounds.maxY; 44 mMeshBounds.maxZ = objmesh.mMeshBounds.maxZ; 45 mMeshBounds.minX = objmesh.mMeshBounds.minX; 46 mMeshBounds.minY = objmesh.mMeshBounds.minY; 47 mMeshBounds.minZ = objmesh.mMeshBounds.minZ; 48 mMeshBounds.radius = objmesh.mMeshBounds.radius; 49 mMeshBounds.scaleFactor = objmesh.mMeshBounds.scaleFactor; 50 51 // For each submesh. 52 for(size_t i = 0; i < objmesh.mSubMeshCount; i++) 53 { 54 mSubMesh[i].mSharedVertexBuffer = false; 55 mSubMesh[i].mVertexBuffer = new VertexBuffer(); 56 mSubMesh[i].mVertexBuffer->mPosition = new Vector3[objmesh.mSubMesh[i].mVertexBuffer->mVertexCount]; 57 mSubMesh[i].mVertexBuffer->mNormal = new Vector3[objmesh.mSubMesh[i].mVertexBuffer->mVertexCount]; 58 mSubMesh[i].mVertexBuffer->mTexCoords = new Vector2[objmesh.mSubMesh[i].mVertexBuffer->mVertexCount]; 59 mSubMesh[i].mVertexBuffer->mVertexCount = objmesh.mSubMesh[i].mVertexBuffer->mVertexCount; 60 mSubMesh[i].mVertexBuffer->mVertexInfo = objmesh.mSubMesh[i].mVertexBuffer->mVertexInfo; 61 mSubMesh[i].mType = objmesh.mSubMesh[i].mType; 62 strcpy(mSubMesh[i].mMaterialName,objmesh.mSubMesh[i].mMaterialName); 63 64 if(objmesh.mSubMesh[i].mSharedVertexBuffer) 65 { 66 for(size_t s = 0; 67 s<objmesh.mSubMesh[i].mVertexBuffer->mVertexCount; 68 s++) 69 { 70 // Copy mPosition. 71 if (objmesh.mSubMesh[i].mVertexBuffer->mVertexInfo & VERTEX_POSITION) 45 72 { 46 73 mSubMesh[i].mVertexBuffer->mPosition[s].x = objmesh.mVertexBuffer->mPosition[s].x; … … 48 75 mSubMesh[i].mVertexBuffer->mPosition[s].z = objmesh.mVertexBuffer->mPosition[s].z; 49 76 } 50 //Copiamos mNormal 51 if (objmesh.mSubMesh[i].mVertexBuffer->mVertexInfo & Geometry::VERTEX_NORMAL) 77 78 // Copy mNormal. 79 if (objmesh.mSubMesh[i].mVertexBuffer->mVertexInfo & VERTEX_NORMAL) 52 80 { 53 81 mSubMesh[i].mVertexBuffer->mNormal[s].x = objmesh.mVertexBuffer->mNormal[s].x; … … 56 84 } 57 85 58 // Copiamos mTexCoords59 if (objmesh.mSubMesh[i].mVertexBuffer->mVertexInfo & Geometry::VERTEX_TEXCOORDS)86 // Copy mTexCoords. 87 if (objmesh.mSubMesh[i].mVertexBuffer->mVertexInfo & VERTEX_TEXCOORDS) 60 88 { 61 89 mSubMesh[i].mVertexBuffer->mTexCoords[s].x = objmesh.mVertexBuffer->mTexCoords[s].x; … … 67 95 else 68 96 { 69 for(size_t s =0;s<objmesh.mSubMesh[i].mVertexBuffer->mVertexCount;s++)70 { 71 // Copiamos mPosition72 if (objmesh.mSubMesh[i].mVertexBuffer->mVertexInfo & Geometry::VERTEX_POSITION)97 for(size_t s = 0; s < objmesh.mSubMesh[i].mVertexBuffer->mVertexCount; s++) 98 { 99 // Copy mPosition. 100 if (objmesh.mSubMesh[i].mVertexBuffer->mVertexInfo & VERTEX_POSITION) 73 101 { 74 102 mSubMesh[i].mVertexBuffer->mPosition[s].x = objmesh.mSubMesh[i].mVertexBuffer->mPosition[s].x; … … 76 104 mSubMesh[i].mVertexBuffer->mPosition[s].z = objmesh.mSubMesh[i].mVertexBuffer->mPosition[s].z; 77 105 } 106 78 107 //Copiamos mNormal 79 if (objmesh.mSubMesh[i].mVertexBuffer->mVertexInfo & Geometry::VERTEX_NORMAL)108 if (objmesh.mSubMesh[i].mVertexBuffer->mVertexInfo & VERTEX_NORMAL) 80 109 { 81 110 mSubMesh[i].mVertexBuffer->mNormal[s].x = objmesh.mSubMesh[i].mVertexBuffer->mNormal[s].x; … … 85 114 86 115 //Copiamos mTexCoords 87 if (objmesh.mSubMesh[i].mVertexBuffer->mVertexInfo & Geometry::VERTEX_TEXCOORDS)116 if (objmesh.mSubMesh[i].mVertexBuffer->mVertexInfo & VERTEX_TEXCOORDS) 88 117 { 89 118 mSubMesh[i].mVertexBuffer->mTexCoords[s].x = objmesh.mSubMesh[i].mVertexBuffer->mTexCoords[s].x; … … 93 122 94 123 } 95 // Copiar los indices 96 mSubMesh[i].mIndexCount=objmesh.mSubMesh[i].mIndexCount; 97 mSubMesh[i].mIndex = new Index[mSubMesh[i].mIndexCount]; 98 memcpy(mSubMesh[i].mIndex,objmesh.mSubMesh[i].mIndex,objmesh.mSubMesh[i].mIndexCount*sizeof(Geometry::Index)); 99 100 // Copiar las tiras 101 // TENER EN CUENTA SI ES UN MESH DE TIRAS O LISTA DE TRIANGULOS 102 __w64 int Desp=0; // desplazamiento entre posiciones de memoria. 124 125 // Copy indices. 126 mSubMesh[i].mIndexCount = objmesh.mSubMesh[i].mIndexCount; 127 mSubMesh[i].mIndex = new Index[mSubMesh[i].mIndexCount]; 128 129 memcpy(mSubMesh[i].mIndex,objmesh.mSubMesh[i].mIndex,objmesh.mSubMesh[i].mIndexCount*sizeof(Index)); 130 131 // Copy strips. 132 __w64 int offset = 0; // offset between memory positions. 103 133 mSubMesh[i].mStripCount=objmesh.mSubMesh[i].mStripCount; 104 134 if (objmesh.mSubMesh[i].mStripCount>0) … … 106 136 mSubMesh[i].mStrip = new Index*[objmesh.mSubMesh[i].mStripCount]; 107 137 108 Desp= &(mSubMesh[i].mIndex[0]) - &(objmesh.mSubMesh[i].mIndex[0]); 109 for (size_t j=0;j<objmesh.mSubMesh[i].mStripCount;j++) 110 { 111 mSubMesh[i].mStrip[j]=objmesh.mSubMesh[i].mStrip[j] + Desp; 112 } 113 } 114 } 115 } 116 138 offset = &(mSubMesh[i].mIndex[0]) - &(objmesh.mSubMesh[i].mIndex[0]); 139 for (size_t j=0;j<objmesh.mSubMesh[i].mStripCount;j++) 140 { 141 mSubMesh[i].mStrip[j]=objmesh.mSubMesh[i].mStrip[j] + offset; 142 } 143 } 144 145 // Copy submesh bones. 146 if (!objmesh.mSubMesh[i].mBones.empty()) 147 { 148 for (int j = 0; j < objmesh.mSubMesh[i].mBones.size(); j++) 149 { 150 mSubMesh[i].mBones.push_back(objmesh.mSubMesh[i].mBones[j]); 151 } 152 } 153 } 154 155 // Copy skeleton name. 156 if (objmesh.hasSkeleton) 157 { 158 hasSkeleton = true; 159 160 strcpy(mSkeletonName,objmesh.mSkeletonName); 161 } 162 163 // Copy mesh bones. 164 if (!objmesh.mBones.empty()) 165 { 166 for (int j = 0; j < objmesh.mBones.size(); j++) 167 { 168 mBones.push_back(objmesh.mBones[j]); 169 } 170 } 171 172 } 173 174 //--------------------------------------------------------------------------- 175 // Assignment operator. 176 //--------------------------------------------------------------------------- 117 177 Mesh &Mesh::operator =(const Geometry::Mesh &objmesh) 118 178 { … … 122 182 mSubMeshCount = objmesh.mSubMeshCount; 123 183 mSubMesh = new Geometry::SubMesh[objmesh.mSubMeshCount]; 124 184 185 // Fill up bounding box settings. 186 mMeshBounds.maxX = objmesh.mMeshBounds.maxX; 187 mMeshBounds.maxY = objmesh.mMeshBounds.maxY; 188 mMeshBounds.maxZ = objmesh.mMeshBounds.maxZ; 189 mMeshBounds.minX = objmesh.mMeshBounds.minX; 190 mMeshBounds.minY = objmesh.mMeshBounds.minY; 191 mMeshBounds.minZ = objmesh.mMeshBounds.minZ; 192 mMeshBounds.radius = objmesh.mMeshBounds.radius; 193 mMeshBounds.scaleFactor = objmesh.mMeshBounds.scaleFactor; 194 195 // For each submesh. 125 196 for(size_t i = 0; i < objmesh.mSubMeshCount; i++) 126 197 { 127 // Debug.128 /*129 cout << "VertexCount["130 << i131 << "]: "132 << objmesh.mSubMesh[i].mVertexBuffer->mVertexCount133 << endl;134 */135 //--------------------------------------------------------------------------------------------136 137 198 mSubMesh[i].mSharedVertexBuffer = objmesh.mSubMesh[i].mSharedVertexBuffer; //.false; 138 199 mSubMesh[i].mVertexBuffer = new Geometry::VertexBuffer(); … … 142 203 mSubMesh[i].mVertexBuffer->mVertexCount = objmesh.mSubMesh[i].mVertexBuffer->mVertexCount; 143 204 mSubMesh[i].mVertexBuffer->mVertexInfo = objmesh.mSubMesh[i].mVertexBuffer->mVertexInfo; 144 mSubMesh[i].mType = objmesh.mSubMesh[i].mType; 205 mSubMesh[i].mType = objmesh.mSubMesh[i].mType; 206 strcpy(mSubMesh[i].mMaterialName,objmesh.mSubMesh[i].mMaterialName); 145 207 146 208 if (objmesh.mSubMesh[i].mSharedVertexBuffer && !copiados) … … 179 241 mSubMesh[i].mIndex = new Index[mSubMesh[i].mIndexCount]; 180 242 181 memcpy(mSubMesh[i].mIndex,objmesh.mSubMesh[i].mIndex,objmesh.mSubMesh[i].mIndexCount*sizeof(Geometry::Index)); 243 memcpy( mSubMesh[i].mIndex, 244 objmesh.mSubMesh[i].mIndex, 245 objmesh.mSubMesh[i].mIndexCount*sizeof(Geometry::Index)); 182 246 183 247 // Copiar las tiras 184 __w64 Desp= 0; // desplazamiento entre posiciones de memoria.248 __w64 offset = 0; // desplazamiento entre posiciones de memoria. 185 249 mSubMesh[i].mStripCount = objmesh.mSubMesh[i].mStripCount; 186 250 … … 188 252 { 189 253 mSubMesh[i].mStrip = new Index*[objmesh.mSubMesh[i].mStripCount]; 190 Desp= &(mSubMesh[i].mIndex[0]) - &(objmesh.mSubMesh[i].mIndex[0]);254 offset = &(mSubMesh[i].mIndex[0]) - &(objmesh.mSubMesh[i].mIndex[0]); 191 255 192 256 for (size_t j = 0; j < objmesh.mSubMesh[i].mStripCount; j++) 193 257 { 194 mSubMesh[i].mStrip[j] = objmesh.mSubMesh[i].mStrip[j] + Desp; 195 } 196 } 197 198 //OSCAR 199 //Copio los bones 258 mSubMesh[i].mStrip[j] = objmesh.mSubMesh[i].mStrip[j] + offset; 259 } 260 } 261 262 // Copy submesh bones. 200 263 if (!objmesh.mSubMesh[i].mBones.empty()) 201 264 { … … 207 270 } 208 271 209 //OSCAR 210 //Copio el nombre del esqueleto 272 // Copy skeleton name. 211 273 if (objmesh.hasSkeleton) 212 274 { … … 216 278 } 217 279 218 //OSCAR 219 //Copio los bones 280 // Copy mesh bones. 220 281 if (!objmesh.mBones.empty()) 221 282 { … … 229 290 } 230 291 292 //--------------------------------------------------------------------------- 293 // Load mesh. 294 //--------------------------------------------------------------------------- 231 295 void Mesh::Load(Serializer &s) 232 296 { … … 256 320 } 257 321 322 //--------------------------------------------------------------------------- 323 // Save mesh. 324 //--------------------------------------------------------------------------- 258 325 void Mesh::Save(Serializer &s) 259 326 { … … 271 338 } 272 339 273 // 26-12-2005 340 //--------------------------------------------------------------------------- 341 // Export to obj mesh. 342 //--------------------------------------------------------------------------- 274 343 void Mesh::exportToOBJ(char *nomfich) 275 344 { … … 279 348 obj << "begin" << std::endl; 280 349 // Vértices 281 for (size_t i=0; i <this->mSubMeshCount; i++)282 { 283 for (size_t j=0; j <this->mSubMesh[i].mVertexBuffer->mVertexCount; j++)350 for (size_t i=0; i < mSubMeshCount; i++) 351 { 352 for (size_t j=0; j < mSubMesh[i].mVertexBuffer->mVertexCount; j++) 284 353 { 285 obj << "v " << this->mSubMesh[i].mVertexBuffer->mPosition[j].x << " " <<286 this->mSubMesh[i].mVertexBuffer->mPosition[j].y << " " <<287 this->mSubMesh[i].mVertexBuffer->mPosition[j].z << " " << std::endl;354 obj << "v " << mSubMesh[i].mVertexBuffer->mPosition[j].x << " " << 355 mSubMesh[i].mVertexBuffer->mPosition[j].y << " " << 356 mSubMesh[i].mVertexBuffer->mPosition[j].z << " " << std::endl; 288 357 } 289 358 } … … 291 360 292 361 // Caras 293 for (size_t i=0; i <this->mSubMeshCount; i++)294 { 295 for (size_t j=0; j <this->mSubMesh[i].mIndexCount; j=j+3)362 for (size_t i=0; i < mSubMeshCount; i++) 363 { 364 for (size_t j=0; j < mSubMesh[i].mIndexCount; j=j+3) 296 365 { 297 obj << "f " << this->mSubMesh[i].mIndex[j]+1 << " " <<298 this->mSubMesh[i].mIndex[j+1]+1 << " " <<299 this->mSubMesh[i].mIndex[j+2]+1 << std::endl;366 obj << "f " << mSubMesh[i].mIndex[j]+1 << " " << 367 mSubMesh[i].mIndex[j+1]+1 << " " << 368 mSubMesh[i].mIndex[j+2]+1 << std::endl; 300 369 } 301 370 } … … 305 374 } 306 375 307 // 26-12-2005 308 Geometry::Mesh *Mesh::toSharedVertex() 376 //--------------------------------------------------------------------------- 377 // Transform to shared vertex mesh. 378 //--------------------------------------------------------------------------- 379 Mesh *Mesh::toSharedVertex() 309 380 { 310 381 311 382 // Move all vertex to the shared vertex buffer. 312 Geometry::Mesh *mesh = new Geometry::Mesh();313 314 if ( this->mSubMesh[0].mSharedVertexBuffer)383 Mesh *mesh = new Mesh(); 384 385 if (mSubMesh[0].mSharedVertexBuffer) 315 386 { 316 387 *mesh = *this; 388 317 389 return mesh; 318 390 } 319 391 320 mesh->mVertexBuffer=new VertexBuffer(); 321 mesh->mSubMeshCount = this->mSubMeshCount; 392 mesh->mVertexBuffer = new VertexBuffer(); 393 mesh->mSubMeshCount = mSubMeshCount; 394 322 395 // Reserva memoria para los submeshes 323 mesh->mSubMesh = new Geometry::SubMesh[this->mSubMeshCount]; 324 325 // construcción de los submeshes 326 long int acumVerts=0; 327 for (size_t i=0; i<mesh->mSubMeshCount; i++) 328 { 329 mesh->mSubMesh[i].mSharedVertexBuffer=true; 330 mesh->mSubMesh[i].mVertexBuffer=mesh->mVertexBuffer; 331 mesh->mSubMesh[i].mStripCount=0; 332 mesh->mSubMesh[i].mStrip=NULL; 333 396 mesh->mSubMesh = new SubMesh[mSubMeshCount]; 397 398 // Fill up bounding box settings. 399 mesh->mMeshBounds.maxX = mMeshBounds.maxX; 400 mesh->mMeshBounds.maxY = mMeshBounds.maxY; 401 mesh->mMeshBounds.maxZ = mMeshBounds.maxZ; 402 mesh->mMeshBounds.minX = mMeshBounds.minX; 403 mesh->mMeshBounds.minY = mMeshBounds.minY; 404 mesh->mMeshBounds.minZ = mMeshBounds.minZ; 405 mesh->mMeshBounds.radius = mMeshBounds.radius; 406 mesh->mMeshBounds.scaleFactor = mMeshBounds.scaleFactor; 407 408 // construcción de los submeshes 409 long int acumVerts = 0; 410 411 for (size_t i = 0; i < mesh->mSubMeshCount; i++) 412 { 413 mesh->mSubMesh[i].mSharedVertexBuffer = true; 414 mesh->mSubMesh[i].mVertexBuffer = mesh->mVertexBuffer; 415 mesh->mSubMesh[i].mStripCount = 0; 416 mesh->mSubMesh[i].mStrip = NULL; 417 mesh->mSubMesh[i].mType = mSubMesh[i].mType; 418 419 strcpy(mesh->mSubMesh[i].mMaterialName,mSubMesh[i].mMaterialName); 420 334 421 // copiar los índices 335 mesh->mSubMesh[i].mIndexCount =this->mSubMesh[i].mIndexCount;336 mesh->mSubMesh[i].mIndex =new Geometry::Index[this->mSubMesh[i].mIndexCount];337 338 for (size_t j =0; j< this->mSubMesh[i].mIndexCount; j++)422 mesh->mSubMesh[i].mIndexCount = mSubMesh[i].mIndexCount; 423 mesh->mSubMesh[i].mIndex = new Index[mSubMesh[i].mIndexCount]; 424 425 for (size_t j = 0; j < mSubMesh[i].mIndexCount; j++) 339 426 { 340 mesh->mSubMesh[i].mIndex[j] = this->mSubMesh[i].mIndex[j]+acumVerts;341 } 342 343 acumVerts += this->mSubMesh[i].mVertexBuffer->mVertexCount;427 mesh->mSubMesh[i].mIndex[j] = mSubMesh[i].mIndex[j]+acumVerts; 428 } 429 430 acumVerts += mSubMesh[i].mVertexBuffer->mVertexCount; 344 431 345 432 // Copiar las tiras 346 int Desp=0; // desplazamiento entre posiciones de memoria. 347 mesh->mSubMesh[i].mStripCount=this->mSubMesh[i].mStripCount; 348 if (this->mSubMesh[i].mStripCount>0) 349 { 350 mesh->mSubMesh[i].mStrip = new Index*[this->mSubMesh[i].mStripCount]; 351 352 Desp= &(mesh->mSubMesh[i].mIndex[0]) - &(this->mSubMesh[i].mIndex[0]); 353 for (size_t j=0;j<this->mSubMesh[i].mStripCount;j++) 354 { 355 mesh->mSubMesh[i].mStrip[j]=this->mSubMesh[i].mStrip[j] + Desp; 356 } 357 } 358 } 359 360 mesh->mVertexBuffer->mVertexCount=acumVerts; 361 mesh->mVertexBuffer->mVertexInfo=this->mSubMesh[0].mVertexBuffer->mVertexInfo; 362 mesh->mVertexBuffer->mPosition=new Geometry::Vector3[mesh->mVertexBuffer->mVertexCount]; 363 mesh->mVertexBuffer->mNormal=new Geometry::Vector3[mesh->mVertexBuffer->mVertexCount]; 364 mesh->mVertexBuffer->mTexCoords=new Geometry::Vector2[mesh->mVertexBuffer->mVertexCount]; 365 433 int offset = 0; // desplazamiento entre posiciones de memoria. 434 435 mesh->mSubMesh[i].mStripCount = mSubMesh[i].mStripCount; 436 437 if (mSubMesh[i].mStripCount > 0) 438 { 439 mesh->mSubMesh[i].mStrip = new Index*[mSubMesh[i].mStripCount]; 440 441 offset = &(mesh->mSubMesh[i].mIndex[0]) - &(mSubMesh[i].mIndex[0]); 442 443 for (size_t j = 0; j < mSubMesh[i].mStripCount; j++) 444 { 445 mesh->mSubMesh[i].mStrip[j] = mSubMesh[i].mStrip[j] + offset; 446 } 447 } 448 } 449 450 mesh->mVertexBuffer->mVertexCount = acumVerts; 451 mesh->mVertexBuffer->mVertexInfo = mSubMesh[0].mVertexBuffer->mVertexInfo; 452 453 mesh->mVertexBuffer->mPosition = new Vector3[mesh->mVertexBuffer->mVertexCount]; 454 mesh->mVertexBuffer->mNormal = new Vector3[mesh->mVertexBuffer->mVertexCount]; 455 mesh->mVertexBuffer->mTexCoords = new Vector2[mesh->mVertexBuffer->mVertexCount]; 456 366 457 // copiar los vértices 367 acumVerts=0; 368 size_t newIndex; 369 for (size_t i=0; i<this->mSubMeshCount; i++) 370 { 371 for(size_t j=0;j<this->mSubMesh[i].mVertexBuffer->mVertexCount;j++) 372 { 373 newIndex=acumVerts+j; 374 mesh->mVertexBuffer->mPosition[newIndex].x=this->mSubMesh[i].mVertexBuffer->mPosition[j].x; 375 mesh->mVertexBuffer->mPosition[newIndex].y=this->mSubMesh[i].mVertexBuffer->mPosition[j].y; 376 mesh->mVertexBuffer->mPosition[newIndex].z=this->mSubMesh[i].mVertexBuffer->mPosition[j].z; 377 378 mesh->mVertexBuffer->mNormal[newIndex].x=this->mSubMesh[i].mVertexBuffer->mNormal[j].x; 379 mesh->mVertexBuffer->mNormal[newIndex].y=this->mSubMesh[i].mVertexBuffer->mNormal[j].y; 380 mesh->mVertexBuffer->mNormal[newIndex].z=this->mSubMesh[i].mVertexBuffer->mNormal[j].z; 381 382 mesh->mVertexBuffer->mTexCoords[newIndex].x=this->mSubMesh[i].mVertexBuffer->mTexCoords[j].x; 383 mesh->mVertexBuffer->mTexCoords[newIndex].y=this->mSubMesh[i].mVertexBuffer->mTexCoords[j].y; 384 } 385 acumVerts+=this->mSubMesh[i].mVertexBuffer->mVertexCount; 458 acumVerts = 0; 459 460 size_t newIndex; 461 462 for (size_t i = 0; i < mSubMeshCount; i++) 463 { 464 for(size_t j = 0; j < mSubMesh[i].mVertexBuffer->mVertexCount; j++) 465 { 466 newIndex = acumVerts + j; 467 468 mesh->mVertexBuffer-> 469 mPosition[newIndex].x = mSubMesh[i].mVertexBuffer-> 470 mPosition[j].x; 471 472 mesh->mVertexBuffer-> 473 mPosition[newIndex].y = mSubMesh[i].mVertexBuffer-> 474 mPosition[j].y; 475 476 mesh->mVertexBuffer-> 477 mPosition[newIndex].z = mSubMesh[i].mVertexBuffer-> 478 mPosition[j].z; 479 480 mesh->mVertexBuffer-> 481 mNormal[newIndex].x = mSubMesh[i].mVertexBuffer-> 482 mNormal[j].x; 483 484 mesh->mVertexBuffer-> 485 mNormal[newIndex].y = mSubMesh[i].mVertexBuffer-> 486 mNormal[j].y; 487 488 mesh->mVertexBuffer-> 489 mNormal[newIndex].z = mSubMesh[i].mVertexBuffer-> 490 mNormal[j].z; 491 492 mesh->mVertexBuffer-> 493 mTexCoords[newIndex].x = mSubMesh[i].mVertexBuffer-> 494 mTexCoords[j].x; 495 496 mesh->mVertexBuffer-> 497 mTexCoords[newIndex].y = mSubMesh[i].mVertexBuffer-> 498 mTexCoords[j].y; 499 } 500 501 acumVerts += mSubMesh[i].mVertexBuffer->mVertexCount; 386 502 } 387 503 -
GTP/trunk/Lib/Geom/shared/GTGeometry/src/GeoMeshSimplifier.cpp
r891 r980 8 8 using namespace std; 9 9 10 MeshSimplifier::MeshSimplifier( const Geometry::Mesh *m, 11 Geometry::TIPOFUNC upb) 10 //////////////////////////////////////////////////////////////////////////// 11 // // 12 // MeshSimplifier class // 13 // // 14 //////////////////////////////////////////////////////////////////////////// 15 16 //--------------------------------------------------------------------------- 17 // MeshSimplifier constructor. 18 //--------------------------------------------------------------------------- 19 MeshSimplifier::MeshSimplifier( const Mesh *m, 20 TIPOFUNC upb) 12 21 { 13 22 objmesh = m; 14 m eshsalida= NULL;23 mGeoMesh = NULL; 15 24 msimpsequence = NULL; 16 25 indexMeshLeaves = -1; … … 20 29 } 21 30 31 //--------------------------------------------------------------------------- 32 // MeshSimplifier destroyer. 33 //--------------------------------------------------------------------------- 22 34 MeshSimplifier::~MeshSimplifier() 23 35 { … … 25 37 } 26 38 39 //--------------------------------------------------------------------------- 27 40 // Returns the simplified mesh. 28 Geometry::Mesh *MeshSimplifier::GetMesh () 29 { 30 return meshsalida; 31 } 32 33 void MeshSimplifier::setMeshLeaves(Geometry::Index index) 41 //--------------------------------------------------------------------------- 42 Mesh * MeshSimplifier::GetMesh() 43 { 44 return mGeoMesh; 45 } 46 47 //--------------------------------------------------------------------------- 48 // Set submesh leaves 49 //--------------------------------------------------------------------------- 50 void MeshSimplifier::setMeshLeaves(Index index) 34 51 { 35 52 indexMeshLeaves = index; 36 53 } 37 54 55 //--------------------------------------------------------------------------- 38 56 // Returns the simplification sequence for general meshes. 39 Geometry::MeshSimplificationSequence *MeshSimplifier::GetSimplificationSequence() 57 //--------------------------------------------------------------------------- 58 MeshSimplificationSequence *MeshSimplifier::GetSimplificationSequence() 40 59 { 41 60 return msimpsequence; 42 61 } 43 62 44 GeometryBasedSimplifier::GeometryBasedSimplifier (const Geometry::Mesh *m, 45 Geometry::TIPOFUNC upb) 46 :MeshSimplifier(m,upb) 47 { 48 } 49 63 //////////////////////////////////////////////////////////////////////////// 64 // // 65 // GeometryBasedSimplifier class // 66 // // 67 //////////////////////////////////////////////////////////////////////////// 68 69 //--------------------------------------------------------------------------- 70 //--------------------------------------------------------------------------- 71 GeometryBasedSimplifier::GeometryBasedSimplifier( const Mesh *m, 72 TIPOFUNC upb) 73 :MeshSimplifier(m,upb) 74 { 75 } 76 77 //--------------------------------------------------------------------------- 78 //--------------------------------------------------------------------------- 50 79 GeometryBasedSimplifier::~GeometryBasedSimplifier() 51 80 { 52 81 } 53 82 83 //--------------------------------------------------------------------------- 54 84 // Starts the simplification process. Receives as a parameter the LOD factor in a range of [0,1]. Implements the Simplifier::Simplify method to perform an image based simplification. 55 void GeometryBasedSimplifier::Simplify (Geometry::Real paramlod) 85 //--------------------------------------------------------------------------- 86 void GeometryBasedSimplifier::Simplify(Real paramlod) 56 87 { 57 88 SimplificationMethod *m_qslim = new SimplificationMethod(objmesh); … … 59 90 m_qslim->setMeshLeaves(indexMeshLeaves); 60 91 61 msimpsequence = m_qslim->Decimate(paramlod,&meshsalida,0,mUPB); 92 msimpsequence = m_qslim->Decimate(paramlod,0,mUPB); 93 94 mGeoMesh = m_qslim->GetMesh(); 62 95 63 96 delete m_qslim; 64 97 } 65 98 99 //--------------------------------------------------------------------------- 66 100 // Starts the simplification process. Receives as a parameter the number of vertices of the resulting mesh. Implements the Simplifier::Simplify method to perform an image based simplification. 67 void GeometryBasedSimplifier::Simplify (Geometry::uint32 numvertices) 101 //--------------------------------------------------------------------------- 102 void GeometryBasedSimplifier::Simplify(uint32 numvertices) 68 103 { 69 104 SimplificationMethod *m_qslim = new SimplificationMethod(objmesh); … … 71 106 m_qslim->setMeshLeaves(indexMeshLeaves); 72 107 73 msimpsequence = m_qslim->Decimate((float)numvertices,&meshsalida,1,mUPB); 108 msimpsequence = m_qslim->Decimate((float)numvertices,1,mUPB); 109 110 mGeoMesh = m_qslim->GetMesh(); 74 111 75 112 delete m_qslim; 76 113 } 77 114 115 //////////////////////////////////////////////////////////////////////////// 116 // // 117 // ViewPointDrivenSimplifier class // 118 // // 119 //////////////////////////////////////////////////////////////////////////// 120 121 //--------------------------------------------------------------------------- 122 /// Class constructor. Will call Simplifier class constructor. 123 //--------------------------------------------------------------------------- 124 ViewPointDrivenSimplifier::ViewPointDrivenSimplifier( const Mesh *m, 125 TIPOFUNC upb) 126 :MeshSimplifier(m,upb) 127 { 128 //char s[MAX_CHAR]; 129 130 // Set progress update function 131 VMI::mUPB = upb; 132 133 VMI::width = 256; 134 VMI::height = 256; 135 136 VMI::bEnableOffScreen = GL_TRUE; 137 VMI::bBeQuiet = GL_FALSE; 138 VMI::bSaveLog = GL_FALSE; 139 VMI::bLoadCamerasFromFile = GL_FALSE; 140 141 VMI::cameraType = 1; 142 VMI::radius = 1.3; 143 VMI::fov = 60.0; 144 145 printf("w: %d h: %d\n", VMI::width, VMI::height); 146 147 printf( "t: %d c: %d o: %d r: %f\n", 148 VMI::numDemandedTriangles, 149 VMI::cameraType, 150 VMI::bEnableOffScreen, 151 VMI::radius); 152 153 154 mGeoMesh = new Mesh(); 155 156 *mGeoMesh = *m; 157 158 // Transform NoSV Mesh to a SV Mesh. 159 mGeoMesh = mGeoMesh->toSharedVertex(); 160 161 // Loads the vmi mesh structure for a geometry mesh given. 162 VMI::mesh = initMeshStructure(mGeoMesh); 163 164 //VMI::printMesh(mesh); 165 //getchar(); 166 167 // Get a filename without extension 168 //strncpy(VMI::filename, argv[argc - 1], strlen(argv[argc - 1]) - 4); 169 170 //glutInit(&argc, argv); 171 glutInitDisplayMode(GLUT_DEPTH | GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA); /* RGB and Alpha */ 172 glutInitWindowSize(VMI::width, VMI::height); 173 glutInitWindowPosition(100, 100); 174 175 //#ifdef KL // Kullback-Leibler 176 // sprintf(s, "VKL - [%s]", argv[argc-1]); 177 //#endif 178 //#ifdef MI // Mutual Information 179 // sprintf(s, "VMI - [%s]", argv[argc-1]); 180 //#endif 181 //#ifdef HE // Hellinger 182 // sprintf(s, "VHE - [%s]", argv[argc-1]); 183 //#endif 184 //#ifdef CS // Chi-Square 185 // sprintf(s, "VCS - [%s]", argv[argc-1]); 186 //#endif 187 188 VMI::vmiWin = glutCreateWindow("VMI"/*s*/); 189 190 glewInit(); 191 192 VMI::init(); 193 194 if (VMI::bLoadCamerasFromFile == GL_FALSE) 195 { 196 switch (VMI::cameraType) 197 { 198 case 0: 199 VMI::cameras = VMI::setCameras(VMI::radius, OCTAHEDRON, &VMI::numCameras); 200 printf("Number of cameras: %d\n", OCTAHEDRON); 201 break; 202 case 1: 203 VMI:: cameras = VMI::setCameras(VMI::radius, ICOSAHEDRON, &VMI::numCameras); 204 printf("Number of cameras: %d\n", ICOSAHEDRON); 205 break; 206 case 2: 207 VMI::cameras = VMI::setCameras(VMI::radius, DODECAHEDRON, &VMI::numCameras); 208 printf("Number of cameras: %d\n", DODECAHEDRON); 209 break; 210 default: 211 break; 212 } 213 } 214 else 215 { 216 // Loads a cameras file 217 //sprintf(s,"%s.cam", VMI::filename); 218 219 //VMI::cameras = VMI::loadCameras(VMI::radius, s, &VMI::numCameras); 220 //getchar(); 221 } 222 223 VMI::histogram = VMI::initHistogram( VMI::mesh->currentNumTriangles, 224 VMI::numCameras); 225 226 VMI::initialIs = VMI::initIs(VMI::numCameras); 227 228 } 229 230 //--------------------------------------------------------------------------- 231 /// Class destructor. 232 //--------------------------------------------------------------------------- 233 ViewPointDrivenSimplifier::~ViewPointDrivenSimplifier(void) 234 { 235 // Free memory 236 VMI::freeMemory(); 237 } 238 239 /// Copy constructor 240 //ViewPointDrivenSimplifier(const ViewPointDrivenSimplifier&); 241 242 /// Assignment operator 243 //ViewPointDrivenSimplifier& operator =(const ViewPointDrivenSimplifier&); 244 245 /// Starts the simplification process. Receives as a parameter the LOD factor in a range of [0,1]. Implements the Simplifier::Simplify method to perform an image based simplification. 246 void ViewPointDrivenSimplifier::Simplify(Real percent) 247 { 248 // TODO: parametros libreria globales 249 250 251 VMI::numDemandedTriangles = (int)(VMI::mesh->numTriangles * percent); 252 253 if ((VMI::numDemandedTriangles == 0) 254 || 255 (VMI::numDemandedTriangles >= VMI::mesh->currentNumTriangles)) 256 { 257 printf("Illegal number of triangles.\n"); 258 } 259 260 VMI::display(); 261 262 // Load a geometry mesh for vmi mesh. 263 loadMesh(); 264 } 265 266 //--------------------------------------------------------------------------- 267 /// Starts the simplification process. Receives as a parameter the number of vertices of the resulting mesh. Implements the Simplifier::Simplify method to perform an image based simplification. 268 //--------------------------------------------------------------------------- 269 void ViewPointDrivenSimplifier::Simplify(uint32 numVertices) 270 { 271 float percent; 272 273 percent = (numVertices * 100.0) / VMI::mesh->numVertices; 274 275 VMI::numDemandedTriangles = (int)(VMI::mesh->numTriangles * (percent / 100)); 276 277 if ((VMI::numDemandedTriangles == 0) 278 || 279 (VMI::numDemandedTriangles >= VMI::mesh->currentNumTriangles)) 280 { 281 printf("Illegal number of triangles.\n"); 282 } 283 284 VMI::display(); 285 286 // Load a geometry mesh for vmi mesh. 287 loadMesh(); 288 289 } 290 291 // Returns the simplified mesh. 292 //Mesh * ViewPointDrivenSimplifier::GetMesh() 293 //{ 294 // return mGeoMesh; 295 //} 296 297 //--------------------------------------------------------------------------- 298 // Init vmi mesh structure for a geometry mesh given. 299 //--------------------------------------------------------------------------- 300 VMI::Mesh * ViewPointDrivenSimplifier::initMeshStructure(Mesh *geoMesh) 301 { 302 GLuint i, j, v1, v2, v3, n, e, t; 303 VMI::Mesh *vmi_mesh; 304 SubMesh *geosubmesh; 305 VertexBuffer *vertex_buffer; 306 int mesh_index_count; 307 int index; 308 309 // Reallocate memory for vmi mesh object. 310 vmi_mesh = (VMI::Mesh *)malloc(sizeof(VMI::Mesh)); 311 312 if (vmi_mesh == NULL) 313 { 314 fprintf(stderr, "Error allocating memory\n"); 315 exit(1); 316 } 317 318 // Shared vertex buffer. 319 vertex_buffer = geoMesh->mVertexBuffer; 320 321 // Reallocate memory for vertices of mesh. 322 vmi_mesh->vertices = (VMI::Vertex *)malloc(sizeof(VMI::Vertex) 323 * 324 vertex_buffer->mVertexCount); 325 326 if (vmi_mesh->vertices == NULL) 327 { 328 fprintf(stderr, "Error allocating memory\n"); 329 exit(1); 330 } 331 332 // Initialize mesh index count. 333 mesh_index_count = 0; 334 335 for (int submesh = 0; submesh < mGeoMesh->mSubMeshCount; submesh++) 336 { 337 mesh_index_count += mGeoMesh->mSubMesh[submesh].mIndexCount; 338 } 339 340 // Reallocate memory for indices. 341 vmi_mesh->triangles = (VMI::Triangle *)malloc(sizeof(VMI::Triangle) 342 * 343 (mesh_index_count / 3)); 344 345 if (vmi_mesh->triangles == NULL) 346 { 347 fprintf(stderr, "Error allocating memory\n"); 348 exit(1); 349 } 350 351 printf("Adding vertices..."); 352 353 // Fill up vertices. 354 for (i = 0; i < vertex_buffer->mVertexCount; i++) 355 { 356 // Vertices start at 0. 357 vmi_mesh->vertices[i].x = vertex_buffer->mPosition[i].x; 358 vmi_mesh->vertices[i].y = vertex_buffer->mPosition[i].y; 359 vmi_mesh->vertices[i].z = vertex_buffer->mPosition[i].z; 360 361 vmi_mesh->vertices[i].numTriangles = 0; 362 vmi_mesh->vertices[i].triangles = NULL; 363 vmi_mesh->vertices[i].enable = GL_TRUE; 364 } 365 366 printf("Ok\n"); 367 vmi_mesh->numVertices = vertex_buffer->mVertexCount; 368 vmi_mesh->currentNumVertices = vertex_buffer->mVertexCount; 369 370 // Fill up triangles. 371 printf("Adding triangles..."); 372 373 // Initialize index of triangle. 374 index = 0; 375 376 // For each submesh. 377 for (int submesh = 0; submesh < mGeoMesh->mSubMeshCount; submesh++) 378 { 379 // Gets actual submesh. 380 geosubmesh = &mGeoMesh->mSubMesh[submesh]; 381 382 for (i = 0; i < (geosubmesh->mIndexCount / 3); i++) 383 { 384 vmi_mesh->triangles[index].id = index; 385 vmi_mesh->triangles[index].submesh = submesh; 386 vmi_mesh->triangles[index].indices[0] = geosubmesh->mIndex[(3 * i)]; 387 vmi_mesh->triangles[index].indices[1] = geosubmesh->mIndex[(3 * i) + 1]; 388 vmi_mesh->triangles[index].indices[2] = geosubmesh->mIndex[(3 * i) + 2]; 389 390 vmi_mesh->triangles[index].area = computeTriangleArea(vmi_mesh->vertices, 391 &vmi_mesh->triangles[index]); 392 //printf("\n%d a: %f",index , vmi_mesh->triangles[index].area); 393 computeTriangleNormal(vmi_mesh->vertices, &vmi_mesh->triangles[index]); 394 395 vmi_mesh->triangles[index].saliency = 0.0; 396 397 vmi_mesh->triangles[index].enable = GL_TRUE; 398 399 for (j = 0; j < 3; j++) 400 { 401 // Adding triangle index adjacent to 3 vertices 402 v1 = vmi_mesh->triangles[index].indices[j]; 403 404 // Reallocate memory for the new adjacent triangle 405 vmi_mesh->vertices[v1].triangles = (GLuint *)realloc(vmi_mesh->vertices[v1].triangles, (vmi_mesh->vertices[v1].numTriangles + 1) * sizeof(GLuint)); 406 VMI::addItem((int *)vmi_mesh->vertices[v1].triangles, (int *)&vmi_mesh->vertices[v1].numTriangles, index); 407 } 408 409 // Increments triangle count. 410 index++; 411 } 412 } 413 414 //printf("\n"); 415 printf("Ok\n"); 416 417 vmi_mesh->numTriangles = mesh_index_count / 3; 418 vmi_mesh->currentNumTriangles = mesh_index_count / 3; 419 420 printf("Num Triangles: %d\n",vmi_mesh->numTriangles); 421 422 // E = 3 T / 2 423 vmi_mesh->edges = (VMI::Edge *)malloc(sizeof(VMI::Edge) 424 * 425 vmi_mesh->numTriangles * 3); 426 427 if (vmi_mesh->edges == NULL) 428 { 429 fprintf(stderr, "Error allocating memory\n"); 430 exit(1); 431 } 432 433 // Init edges 434 for (i=0; i<vmi_mesh->numTriangles * 3; i++) 435 { 436 vmi_mesh->edges[i].triangles = NULL; 437 vmi_mesh->edges[i].numTriangles = 0; 438 } 439 440 printf("Adding edges..."); 441 n = 0; 442 443 for (i=0; i<vmi_mesh->numTriangles; i++) 444 { 445 t = 0; 446 v1 = vmi_mesh->triangles[i].indices[0]; 447 v2 = vmi_mesh->triangles[i].indices[1]; 448 v3 = vmi_mesh->triangles[i].indices[2]; 449 450 if ((e = findEdge(vmi_mesh->edges, n, v1, v2)) == -1) 451 { 452 vmi_mesh->edges[n].u = v1; 453 vmi_mesh->edges[n].v = v2; 454 vmi_mesh->edges[n].enable = GL_TRUE; 455 456 // Reallocate memory for the new adjacent triangle 457 vmi_mesh->edges[n].triangles = (GLuint *)realloc(vmi_mesh->edges[n].triangles, (vmi_mesh->edges[n].numTriangles + 1) * sizeof(GLuint)); 458 // Adding triangle i adjacent to edge n 459 VMI::addItem((int *)vmi_mesh->edges[n].triangles, (int *)&vmi_mesh->edges[n].numTriangles, i); 460 //printf("n:%d i:%d\n", n, i); 461 462 // Adding edge n adjacent to triangle i 463 VMI::addItem((int *)vmi_mesh->triangles[i].edges, (int *)&t, n); 464 n++; 465 } 466 else 467 { 468 // Reallocate memory for the new adjacent triangle. 469 vmi_mesh->edges[e].triangles = (GLuint *)realloc(vmi_mesh->edges[e].triangles, (vmi_mesh->edges[e].numTriangles + 1) * sizeof(GLuint)); 470 // Adding triangle i adjacent to edge e 471 VMI::addItem((int *)vmi_mesh->edges[e].triangles, (int *)&vmi_mesh->edges[e].numTriangles, i); 472 //printf("n:%d i:%d\n", e, i); 473 474 // Adding edge e adjacent to triangle i 475 VMI::addItem((int *)vmi_mesh->triangles[i].edges, (int *)&t, e); 476 } 477 if ((e = findEdge(vmi_mesh->edges, n, v2, v3)) == -1) 478 { 479 vmi_mesh->edges[n].u = v2; 480 vmi_mesh->edges[n].v = v3; 481 vmi_mesh->edges[n].enable = GL_TRUE; 482 483 // Reallocate memory for the new adjacent triangle 484 vmi_mesh->edges[n].triangles = (GLuint *)realloc(vmi_mesh->edges[n].triangles, (vmi_mesh->edges[n].numTriangles + 1) * sizeof(GLuint)); 485 // Adding triangle i adjacent to edge n 486 VMI::addItem((int *)vmi_mesh->edges[n].triangles, (int *)&vmi_mesh->edges[n].numTriangles, i); 487 //printf("n:%d i:%d\n", n, i); 488 489 // Adding edge n adjacent to triangle i 490 VMI::addItem((int *)vmi_mesh->triangles[i].edges, (int *)&t, n); 491 n++; 492 } 493 else 494 { 495 // Reallocate memory for the new adjacent triangle 496 vmi_mesh->edges[e].triangles = (GLuint *)realloc(vmi_mesh->edges[e].triangles, (vmi_mesh->edges[e].numTriangles + 1) * sizeof(GLuint)); 497 // Adding triangle i adjacent to edge e 498 VMI::addItem((int *)vmi_mesh->edges[e].triangles, (int *)&vmi_mesh->edges[e].numTriangles, i); 499 //printf("n:%d i:%d\n", e, i); 500 501 // Adding edge e adjacent to triangle i 502 VMI::addItem((int *)vmi_mesh->triangles[i].edges, (int *)&t, e); 503 } 504 505 if ((e = findEdge(vmi_mesh->edges, n, v3, v1)) == -1) 506 { 507 vmi_mesh->edges[n].u = v3; 508 vmi_mesh->edges[n].v = v1; 509 vmi_mesh->edges[n].enable = GL_TRUE; 510 511 // Reallocate memory for the new adjacent triangle 512 vmi_mesh->edges[n].triangles = (GLuint *)realloc(vmi_mesh->edges[n].triangles, (vmi_mesh->edges[n].numTriangles + 1) * sizeof(GLuint)); 513 // Adding triangle i adjacent to edge n 514 VMI::addItem((int *)vmi_mesh->edges[n].triangles, (int *)&vmi_mesh->edges[n].numTriangles, i); 515 //printf("n:%d i:%d\n", n, i); 516 517 // Adding edge n adjacent to triangle i 518 VMI::addItem((int *)vmi_mesh->triangles[i].edges, (int *)&t, n); 519 n++; 520 } 521 else 522 { 523 // Reallocate memory for the new adjacent triangle 524 vmi_mesh->edges[e].triangles = (GLuint *)realloc(vmi_mesh->edges[e].triangles, (vmi_mesh->edges[e].numTriangles + 1) * sizeof(GLuint)); 525 // Adding triangle i adjacent to edge e 526 VMI::addItem((int *)vmi_mesh->edges[e].triangles, (int *)&vmi_mesh->edges[e].numTriangles, i); 527 //printf("n:%d i:%d\n", e, i); 528 529 // Adding edge e adjacent to triangle i 530 VMI::addItem((int *)vmi_mesh->triangles[i].edges, (int *)&t, e); 531 } 532 } 533 534 printf("Ok\n"); 535 vmi_mesh->numEdges = n; 536 537 return vmi_mesh; 538 } 539 540 //--------------------------------------------------------------------------- 541 // Gets the geometry mesh of a the vmi mesh given. 542 //--------------------------------------------------------------------------- 543 void ViewPointDrivenSimplifier::loadMesh() 544 { 545 int num_indices; 546 SubMesh *geosubmesh; 547 VertexBuffer *vertex_buffer; 548 549 // Gets old vertex buffer. 550 vertex_buffer = mGeoMesh->mVertexBuffer; 551 552 // Initialize auxiliar vertex buffer. 553 mVB = new VertexBuffer(); 554 555 mVB->mPosition = new Vector3[VMI::mesh->currentNumVertices]; 556 mVB->mNormal = new Vector3[VMI::mesh->currentNumVertices]; 557 mVB->mTexCoords = new Vector2[VMI::mesh->currentNumVertices]; 558 559 mVB->mVertexInfo = vertex_buffer->mVertexInfo; 560 561 // For each submesh. 562 for (int submesh = 0; submesh < mGeoMesh->mSubMeshCount; submesh++) 563 { 564 geosubmesh = &mGeoMesh->mSubMesh[submesh]; 565 566 delete []geosubmesh->mIndex; 567 568 // Initialize submesh index count; 569 num_indices = 0; 570 571 // For each triangle. 572 for (int i = 0; i < VMI::mesh->numTriangles; i++) 573 { 574 // If is enable and of the current submesh. 575 if ((VMI::mesh->triangles[i].enable) 576 && 577 (VMI::mesh->triangles[i].submesh == submesh)) 578 { 579 // Increments submesh index count. 580 num_indices += 3; 581 } 582 } 583 584 geosubmesh->mIndexCount = num_indices; 585 586 geosubmesh->mIndex = new Index[geosubmesh->mIndexCount]; 587 588 // Initialize number of indices. 589 num_indices = 0; 590 591 // Fill up indices. 592 for (int i = 0; i < VMI::mesh->numTriangles; i++) 593 { 594 if ((VMI::mesh->triangles[i].enable) 595 && 596 (VMI::mesh->triangles[i].submesh == submesh)) 597 { 598 geosubmesh->mIndex[num_indices++] = VMI::mesh->triangles[i].indices[0]; 599 geosubmesh->mIndex[num_indices++] = VMI::mesh->triangles[i].indices[1]; 600 geosubmesh->mIndex[num_indices++] = VMI::mesh->triangles[i].indices[2]; 601 } 602 } 603 604 // For each index. 605 for (int i = 0; i < geosubmesh->mIndexCount; i++) 606 { 607 findVertex(submesh,i); 608 } 609 610 geosubmesh->mVertexBuffer = mVB; 611 } 612 613 delete vertex_buffer; 614 615 mGeoMesh->mVertexBuffer = mVB; 616 617 } 618 619 //--------------------------------------------------------------------------- 620 // Find vertex in auxiliar vertex buffer. 621 //--------------------------------------------------------------------------- 622 void ViewPointDrivenSimplifier::findVertex(size_t submesh, size_t elem) 623 { 624 bool found; 625 int index; 626 int i; 627 int new_elem; 628 VertexBuffer *vertex_buffer; 629 630 found = false; 631 632 // Shared vertex buffer. 633 vertex_buffer = mGeoMesh->mVertexBuffer; 634 635 index = mGeoMesh->mSubMesh[submesh].mIndex[elem]; 636 637 i = 0; 638 639 while (!found && (i < mVB->mVertexCount)) 640 { 641 if ((VMI::mesh->vertices[index].x == mVB->mPosition[i].x) 642 && 643 (VMI::mesh->vertices[index].y == mVB->mPosition[i].y) 644 && 645 (VMI::mesh->vertices[index].z == mVB->mPosition[i].z)) 646 { 647 found = true; 648 649 // Update index. 650 mGeoMesh->mSubMesh[submesh].mIndex[elem] = i; 651 } 652 653 // Increments index. 654 i++; 655 } 656 657 if (!found) 658 { 659 // Last element. 660 new_elem = mVB->mVertexCount; 661 662 // Add to last. 663 mVB->mPosition[new_elem].x = VMI::mesh->vertices[index].x; 664 mVB->mPosition[new_elem].y = VMI::mesh->vertices[index].y; 665 mVB->mPosition[new_elem].z = VMI::mesh->vertices[index].z; 666 667 mVB->mNormal[new_elem].x = vertex_buffer->mNormal[index].x; 668 mVB->mNormal[new_elem].y = vertex_buffer->mNormal[index].y; 669 mVB->mNormal[new_elem].z = vertex_buffer->mNormal[index].z; 670 671 mVB->mTexCoords[new_elem].x = vertex_buffer->mTexCoords[index].x; 672 mVB->mTexCoords[new_elem].y = vertex_buffer->mTexCoords[index].y; 673 674 // Update index. 675 mGeoMesh->mSubMesh[submesh].mIndex[elem] = new_elem; 676 677 // Increments vertex count. 678 mVB->mVertexCount++; 679 } 680 } 681 -
GTP/trunk/Lib/Geom/shared/GTGeometry/src/GeoMeshStripifier.cpp
r891 r980 8 8 * 9 9 * @file GeoMeshStripifier.cpp 10 *===========================================================================*/10 /*===========================================================================*/ 11 11 12 12 #include "GeoMeshStripifier.h" 13 #include "tri_stripper.h"14 13 15 14 using namespace Geometry; 16 15 using namespace std; 17 using namespace triangle_stripper; 16 17 //----------------------------------------------------------------------------- 18 // Private. 19 //----------------------------------------------------------------------------- 20 21 /// InitList: 22 BOOL CustomStripifier::InitList(PLISTHEAD LHead) 23 { 24 if (LHead == NULL) 25 { 26 return FALSE; 27 } 28 29 LHead->LHeaders[LISTHEAD] = LHead->LHeaders[LISTTAIL] = NULL; 30 LHead->NumList = 0; 31 32 return TRUE; 33 } 34 35 /// AddHead: 36 BOOL CustomStripifier::AddHead(PLISTHEAD LHead, PLISTINFO LInfo) 37 { 38 if (LHead == NULL || LInfo == NULL) 39 { 40 return(FALSE); 41 } 42 43 if (EMPTYLIST(LHead)) 44 { 45 LHead->LHeaders[LISTTAIL] = LInfo; 46 } 47 else 48 { 49 LHead->LHeaders[LISTHEAD]->ListNode.Previous = (void *) LInfo; 50 } 51 52 LInfo->ListNode.Next = (void *) LHead->LHeaders[LISTHEAD]; 53 LHead->LHeaders[LISTHEAD] = LInfo; 54 LInfo->ListNode.Previous = NULL; 55 LHead->NumList++; 56 57 return(TRUE); 58 } 59 60 /// AddTail 61 BOOL CustomStripifier::AddTail(PLISTHEAD LHead, PLISTINFO LInfo) 62 { 63 if (LHead == NULL || LInfo == NULL) 64 { 65 return FALSE; 66 } 67 68 if (EMPTYLIST(LHead)) 69 { 70 LHead->LHeaders[LISTHEAD] = LInfo; 71 } 72 else 73 { 74 LHead->LHeaders[LISTTAIL]->ListNode.Next = (void *) LInfo; 75 } 76 77 LInfo->ListNode.Previous = (void *) LHead->LHeaders[LISTTAIL]; 78 LHead->LHeaders[LISTTAIL] = LInfo; 79 LInfo->ListNode.Next = NULL; 80 LHead->NumList++; 81 82 return TRUE; 83 } 84 85 /// InsertNode 86 BOOL CustomStripifier::InsertNode( PLISTHEAD LHead, int nPos, PLISTINFO LInfo ) 87 { 88 PLISTINFO add_node; 89 90 if ( LHead == NULL || LInfo == NULL || nPos > NumOnList( LHead ) ) 91 { 92 return FALSE; 93 } 94 95 if ( nPos == 0 ) 96 { 97 AddHead( LHead, LInfo ); 98 } 99 else if ( nPos == NumOnList( LHead ) ) 100 { 101 AddTail( LHead, LInfo ); 102 } 103 else 104 { 105 if ( (add_node = PeekList( LHead, LISTHEAD, nPos - 1 )) == NULL ) 106 { 107 return FALSE; 108 } 109 110 ((PLISTINFO)add_node->ListNode.Next)->ListNode.Previous = LInfo; 111 112 LInfo->ListNode.Next = add_node->ListNode.Next; 113 LInfo->ListNode.Previous = add_node; 114 add_node->ListNode.Next = LInfo; 115 LHead->NumList++; 116 } 117 118 return TRUE; 119 } 120 121 /// RemHead: 122 PLISTINFO CustomStripifier::RemHead(PLISTHEAD LHead) 123 { 124 PLISTINFO t, t1; 125 126 if ( LHead == NULL || EMPTYLIST(LHead) ) 127 { 128 return NULL; 129 } 130 131 t = LHead->LHeaders[LISTHEAD]; 132 LHead->LHeaders[LISTHEAD] = (PLISTINFO) t->ListNode.Next; 133 134 if (LHead->LHeaders[LISTHEAD] != NULL) 135 { 136 t1 = (PLISTINFO) t->ListNode.Next; 137 t1->ListNode.Previous = NULL; 138 } 139 else 140 { 141 LHead->LHeaders[LISTTAIL] = NULL; 142 } 143 144 LHead->NumList--; 145 146 return t; 147 } 148 149 /// RemTail: 150 PLISTINFO CustomStripifier::RemTail(PLISTHEAD LHead) 151 { 152 PLISTINFO t, t1; 153 154 if ( LHead == NULL || EMPTYLIST(LHead) ) 155 { 156 return NULL; 157 } 158 159 t = LHead->LHeaders[LISTTAIL]; 160 LHead->LHeaders[LISTTAIL] = (PLISTINFO) t->ListNode.Previous; 161 162 if (LHead->LHeaders[LISTTAIL] != NULL) 163 { 164 t1 = (PLISTINFO) t->ListNode.Previous; 165 t1->ListNode.Next = NULL; 166 } 167 else 168 { 169 LHead->LHeaders[LISTHEAD] = NULL; 170 } 171 172 LHead->NumList--; 173 174 return t; 175 } 176 177 /// PeekList: 178 PLISTINFO CustomStripifier::PeekList(PLISTHEAD LHead, int wch, int index ) 179 { 180 PLISTINFO t; 181 182 if (LHead == NULL) 183 { 184 return NULL; 185 } 186 187 if ( (t = LHead->LHeaders[wch]) == NULL ) 188 { 189 return NULL; 190 } 191 192 for (; t != NULL && index > 0; index-- ) 193 { 194 t = (wch == LISTHEAD) ? (PLISTINFO) t->ListNode.Next 195 : (PLISTINFO) t->ListNode.Previous; 196 } 197 198 return t; 199 } 200 201 /// RemoveList: 202 PLISTINFO CustomStripifier::RemoveList(PLISTHEAD LHead, PLISTINFO LInfo ) 203 { 204 PLISTINFO t; 205 PLISTINFO t1; 206 207 t = LInfo; 208 209 if (LHead == NULL) 210 { 211 return NULL; 212 } 213 214 if (LHead->LHeaders[LISTHEAD] == t) 215 { 216 t = (PLISTINFO) RemHead(LHead); 217 } 218 else if (LHead->LHeaders[LISTTAIL] == t) 219 { 220 t = (PLISTINFO) RemTail(LHead); 221 } 222 else 223 { 224 t1 = (PLISTINFO) t->ListNode.Previous; 225 t1->ListNode.Next = t->ListNode.Next; 226 t1 = (PLISTINFO) t->ListNode.Next; 227 t1->ListNode.Previous = t->ListNode.Previous; 228 LHead->NumList--; 229 } 230 231 return t; 232 } 233 234 /// SearchList: 235 /// Try to find a specific node in the queue whose key matches with 236 /// searching key. Return the pointer to that node if found, return NULL 237 /// otherwise 238 /// @param lpHashTbl => a far pointer to the hash table. 239 /// @param lpKey => a far poniter to searching key. 240 /// @param CompareCallBack => comparision function. 241 /// @return a far pointer to the node to be found. 242 PLISTINFO CustomStripifier::SearchList( 243 PLISTHEAD listHead, 244 PVOID lpSKey, 245 int (* CompareCallBack) ( PVOID, PVOID ) ) 246 { 247 PLISTINFO list_info; 248 249 list_info = PeekList( listHead, LISTHEAD, 0); 250 251 while ( list_info != NULL ) 252 { 253 if ( CompareCallBack( list_info, lpSKey ) ) 254 { 255 break; 256 } 257 258 list_info = (PLISTINFO) GetNextNode( list_info ); 259 } 260 261 return list_info; 262 } 263 264 /// init_vert_norms: 265 void CustomStripifier::init_vert_norms(int num_vert) 266 { 267 /* Initialize vertex/normal array to have all zeros to 268 start with. 269 */ 270 register int x; 271 272 for (x = 0; x < num_vert; x++) 273 { 274 *(vert_norms + x) = 0; 275 } 276 } 277 278 /// init_vert_texture: 279 void CustomStripifier::init_vert_texture(int num_vert) 280 { 281 /* Initialize vertex/normal array to have all zeros to 282 start with. 283 */ 284 register int x; 285 286 for (x = 0; x < num_vert; x++) 287 { 288 *(vert_texture + x) = 0; 289 } 290 } 291 292 /// InitVertexTable: 293 BOOL CustomStripifier::InitVertexTable( int size ) 294 { 295 register int index; 296 297 /* Initialize the face table */ 298 Vertices = (ListHead**) malloc(sizeof(ListHead*) * size ); 299 300 if (Vertices) 301 { 302 for (index = 0; index < size; index++) 303 { 304 Vertices[index] = NULL; 305 } 306 307 return TRUE; 308 309 } 310 311 return FALSE; 312 } 313 314 /// InitFaceTable: 315 BOOL CustomStripifier::InitFaceTable( int size ) 316 { 317 register int index; 318 319 /* Initialize the face table */ 320 PolFaces = (ListHead**) malloc(sizeof(ListHead*) * size); 321 322 if (PolFaces) 323 { 324 for (index = 0; index < size; index++) 325 { 326 PolFaces[index] = NULL; 327 } 328 329 return TRUE; 330 } 331 332 return FALSE; 333 } 334 335 /// InitEdgeTable: 336 BOOL CustomStripifier::InitEdgeTable( int size ) 337 { 338 register int index; 339 340 /* Initialize the edge table */ 341 PolEdges = (ListHead**) malloc(sizeof(ListHead*) * size ); 342 343 if (PolEdges) 344 { 345 for (index=0; index < size; index++) 346 { 347 PolEdges[index] = NULL; 348 } 349 350 return TRUE; 351 } 352 353 return FALSE; 354 } 355 356 /// InitStripTable: 357 void CustomStripifier::InitStripTable( ) 358 { 359 360 PLISTHEAD list_head; 361 362 /* Initialize the strip table */ 363 list_head = (PLISTHEAD) malloc(sizeof(ListHead)); 364 365 if (list_head) 366 { 367 InitList(list_head); 368 369 strips[0] = list_head; 370 } 371 else 372 { 373 printf("Out of memory !\n"); 374 375 exit(0); 376 } 377 378 } 379 380 /// Init_Table_SGI: 381 void CustomStripifier::Init_Table_SGI(int numFaces) 382 { 383 PLISTHEAD list_head; 384 int max_adj = 60; 385 register int x; 386 387 /* This routine will initialize the table that will 388 have the faces sorted by the number of adjacent polygons 389 to it. 390 */ 391 392 for (x=0; x< max_adj; x++) 393 { 394 /* We are allowing the max number of sides of a polygon 395 to be max_adj. 396 */ 397 list_head = (PLISTHEAD) malloc(sizeof(ListHead)); 398 399 if (list_head) 400 { 401 InitList(list_head); 402 403 array[x] = list_head; 404 } 405 else 406 { 407 printf("Out of memory !\n"); 408 exit(0); 409 } 410 } 411 412 if (face_array != NULL) /* It seems this function is called more than */ 413 { 414 free(face_array); /* once so we'll free up the old stuff */ 415 } 416 417 face_array = (P_FACE_ADJACENCIES) malloc (sizeof(FACE_ADJACENCIES) * numFaces); 418 419 if (face_array == NULL) 420 { 421 printf("Out of memory !!\n"); 422 exit(0); 423 } 424 425 } 426 427 /// BuildVertexTable: 428 void CustomStripifier::BuildVertexTable(int size) 429 { 430 register int index; 431 PLISTHEAD list_head; 432 433 for (index = 0; index < size; index++) 434 { 435 list_head = (PLISTHEAD) malloc(sizeof(ListHead)); 436 437 if (list_head) 438 { 439 InitList(list_head); 440 441 Vertices[index] = list_head; 442 } 443 else 444 { 445 return; 446 } 447 448 } 449 } 450 451 /// BuildFaceTable: 452 void CustomStripifier::BuildFaceTable( int size ) 453 { 454 register int index; 455 PLISTHEAD list_head; 456 457 for (index = 0; index < size; index++) 458 { 459 list_head = (PLISTHEAD) malloc(sizeof(ListHead)); 460 461 if (list_head) 462 { 463 InitList(list_head); 464 465 PolFaces[index] = list_head; 466 } 467 else 468 { 469 return; 470 } 471 } 472 } 473 474 /// BuildEdgeTable: 475 void CustomStripifier::BuildEdgeTable( int size ) 476 { 477 register int index; 478 PLISTHEAD list_head; 479 480 for (index = 0; index < size; index++) 481 { 482 list_head = (PLISTHEAD) malloc(sizeof(ListHead)); 483 484 if (list_head) 485 { 486 InitList(list_head); 487 488 PolEdges[index] = list_head; 489 } 490 else 491 { 492 return; 493 } 494 } 495 } 496 497 /// Start_Vertex_Struct: 498 void CustomStripifier::Start_Vertex_Struct(int numVerts) 499 { 500 if (InitVertexTable(numVerts)) 501 { 502 BuildVertexTable(numVerts); 503 } 504 } 505 506 /// Start_Face_Struct: 507 void CustomStripifier::Start_Face_Struct(int numFaces) 508 { 509 if (InitFaceTable(numFaces)) 510 { 511 BuildFaceTable(numFaces); 512 } 513 } 514 515 /// Start_Edge_Struct: 516 void CustomStripifier::Start_Edge_Struct(int numVerts) 517 { 518 if (InitEdgeTable(numVerts)) 519 { 520 BuildEdgeTable(numVerts); 521 } 522 } 523 524 /// switch_lower: 525 void CustomStripifier::switch_lower (int *x, int *y) 526 { 527 register int temp; 528 529 /* Put lower value in x */ 530 if (*y < *x) 531 { 532 temp = *x; 533 *x = *y; 534 *y = temp; 535 } 536 } 537 538 /// member: 539 BOOL CustomStripifier::member(int x , int id1, int id2, int id3) 540 { 541 /* Is x in the triangle specified by id1,id2,id3 */ 542 if ((x != id1) && (x != id2) && (x != id3)) 543 { 544 return FALSE; 545 } 546 547 return TRUE; 548 } 549 550 /// Exist: 551 BOOL CustomStripifier::Exist(int faceId, int id1, int id2) 552 { 553 /* Does the edge specified by id1 and id2 exist in this 554 face currently? Maybe we deleted in partial triangulation 555 */ 556 ListHead *list_head; 557 PF_FACES temp; 558 register int x,size; 559 BOOL a = FALSE; 560 BOOL b = FALSE; 561 562 list_head = PolFaces[faceId]; 563 564 temp = (PF_FACES) PeekList(list_head, LISTHEAD, 0); 565 size = temp->nPolSize; 566 567 for (x=0; x<size; x++) 568 { 569 if (*(temp->pPolygon+x) == id1) 570 { 571 a = TRUE; 572 } 573 574 if (*(temp->pPolygon+x) == id2) 575 { 576 b = TRUE; 577 } 578 579 if (a && b) 580 { 581 return TRUE; 582 } 583 } 584 585 return FALSE; 586 } 587 588 /// Different: 589 int CustomStripifier::Different(int id1,int id2,int id3,int id4,int id5, int id6, int *x, int *y) 590 { 591 /* Find the vertex in the first 3 numbers that does not exist in 592 the last three numbers 593 */ 594 if ((id1 != id4) && (id1 != id5) && (id1 != id6)) 595 { 596 *x = id2; 597 *y = id3; 598 return id1; 599 } 600 if ((id2 != id4) && (id2 != id5) && (id2 != id6)) 601 { 602 *x = id1; 603 *y = id3; 604 return id2; 605 } 606 if ((id3 != id4) && (id3 != id5) && (id3 != id6)) 607 { 608 *x = id1; 609 *y = id2; 610 return id3; 611 } 612 613 /* Because there are degeneracies in the data, this might occur */ 614 *x = id5; 615 *y = id6; 616 return id4; 617 } 618 619 /// Return_Other: 620 int CustomStripifier::Return_Other(int *index,int e1,int e2) 621 { 622 /* We have a triangle and want to know the third vertex of it */ 623 register int x; 624 625 for (x=0;x<3;x++) 626 { 627 if ((*(index+x) != e1) && (*(index+x) != e2)) 628 return *(index+x); 629 } 630 /* If there is a degenerate triangle return arbitrary */ 631 return e1; 632 } 633 634 /// Get_Other_Vertex: 635 int CustomStripifier::Get_Other_Vertex(int id1,int id2,int id3,int *index) 636 { 637 /* We have a list index of 4 numbers and we wish to 638 return the number that is not id1,id2 or id3 639 */ 640 register int x; 641 642 for (x=0; x<4; x++) 643 { 644 if ((*(index+x) != id1) && (*(index+x) != id2) && 645 (*(index+x) != id3)) 646 return *(index+x); 647 } 648 /* If there is some sort of degeneracy this might occur, 649 return arbitrary 650 */ 651 if (x==4) 652 return id1; 653 } 654 655 /// Done: 656 PLISTINFO CustomStripifier::Done(int face_id, int *bucket) 657 { 658 /* Check to see whether the polygon with face_id was used 659 already, return NULL if it was, otherwise return a pointer to the face. 660 */ 661 662 PLISTINFO lpListInfo; 663 664 lpListInfo = (PLISTINFO) face_array[face_id].pfNode; 665 if (lpListInfo != NULL) { 666 *bucket = face_array[face_id].bucket; 667 return lpListInfo; 668 } 669 else 670 return lpListInfo; 671 } 672 673 /// First_Edge: 674 void CustomStripifier::First_Edge(int *id1,int *id2, int *id3) 675 { 676 /* Get the first triangle in the strip we just found, we will use this to 677 try to extend backwards in the strip 678 */ 679 680 ListHead *pListHead; 681 register int num; 682 P_STRIPS temp1,temp2,temp3; 683 684 pListHead = strips[0]; 685 num = NumOnList(pListHead); 686 687 /* Did not have a strip */ 688 if (num < 3) 689 return; 690 691 temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 0); 692 temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 1); 693 temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 2); 694 *id1 = temp1->face_id; 695 *id2 = temp2->face_id; 696 *id3 = temp3->face_id; 697 698 } 699 700 /// Last_Edge: 701 void CustomStripifier::Last_Edge(int *id1, int *id2, int *id3, BOOL save) 702 { 703 /* We need the last edge that we had */ 704 static int v1, v2, v3; 705 706 if (save) 707 { 708 v1 = *id1; 709 v2 = *id2; 710 v3 = *id3; 711 } 712 else 713 { 714 *id1 = v1; 715 *id2 = v2; 716 *id3 = v3; 717 } 718 } 719 720 /// find_triangle_orientation: 721 void CustomStripifier::find_triangle_orientation(int vertex1,int vertex2,int vertex3, 722 int *original_vertex) 723 { 724 int vertices,index; 725 PF_VERTICES verts; 726 727 /* Search through face to match orignal vertices */ 728 729 /* Start with vertex1's Vertices struct */ 730 verts = (PF_VERTICES) PeekList(Vertices[vertex1-1],LISTHEAD,0); 731 do { 732 index = 0; 733 for (vertices = 0; vertices < verts->face->nOrgSize;vertices++) { 734 if (vertex1 == verts->face->pPolygon[vertices]+1 || 735 vertex2 == verts->face->pPolygon[vertices]+1 || 736 vertex3 == verts->face->pPolygon[vertices]+1 ) 737 original_vertex[index++] = verts->face->pPolygon[vertices]+1; 738 if (index == 3) 739 break; 740 } 741 if (index == 3) 742 break; 743 } while ((verts = (PF_VERTICES) GetNextNode(verts)) != NULL); 744 745 if (index != 3) { 746 /* Search vertex2's Vertices struct */ 747 verts = (PF_VERTICES) PeekList(Vertices[vertex2-1],LISTHEAD,0); 748 do { 749 index = 0; 750 for (vertices = 0; vertices < verts->face->nOrgSize;vertices++) { 751 if (vertex1 == verts->face->pPolygon[vertices]+1 || 752 vertex2 == verts->face->pPolygon[vertices]+1 || 753 vertex3 == verts->face->pPolygon[vertices]+1 ) 754 original_vertex[index++] = verts->face->pPolygon[vertices]+1; 755 if (index == 3) 756 break; 757 } 758 if (index == 3) 759 break; 760 } while ((verts = (PF_VERTICES) GetNextNode(verts)) != NULL); 761 } 762 763 if (index != 3) { 764 /* Search vertex3's Vertices struct */ 765 verts = (PF_VERTICES) PeekList(Vertices[vertex3-1],LISTHEAD,0); 766 do { 767 index = 0; 768 for (vertices = 0; vertices < verts->face->nOrgSize;vertices++) { 769 if (vertex1 == verts->face->pPolygon[vertices]+1 || 770 vertex2 == verts->face->pPolygon[vertices]+1 || 771 vertex3 == verts->face->pPolygon[vertices]+1 ) 772 original_vertex[index++] = verts->face->pPolygon[vertices]+1; 773 if (index == 3) 774 break; 775 } 776 if (index == 3) 777 break; 778 } while ((verts = (PF_VERTICES) GetNextNode(verts)) != NULL); 779 } 780 781 /* if (index !=3 ) 782 printf("Warning: Didn't find a triangle for %d %d %d\n", 783 vertex1,vertex2,vertex3); 784 */ 785 } 786 787 /// preserve_strip_orientation_with_normal: 788 void CustomStripifier::preserve_strip_orientation_with_normal(FILE *output, int vertex1, int normal1, int vertex2, int normal2, int vertex3, int normal3) 789 { 790 int original_vertex[3]; 791 792 find_triangle_orientation(vertex1,vertex2,vertex3, original_vertex); 793 794 if ( ( original_vertex[0] == vertex3 && original_vertex[1] == vertex2 && original_vertex[2] == vertex1) || 795 ( original_vertex[0] == vertex2 && original_vertex[1] == vertex1 && original_vertex[2] == vertex3 ) || 796 ( original_vertex[0] == vertex1 && original_vertex[1] == vertex3 && original_vertex[2] == vertex2 )) { 797 // New Triangle is in an opposite orientation. Add vertex2 to correct it 798 fprintf(output," %d//%d",vertex2,normal2); 799 } 800 801 } 802 803 /// preserve_strip_orientation_with_texture: 804 void CustomStripifier::preserve_strip_orientation_with_texture(FILE *output, 805 int vertex1, int texture1, 806 int vertex2, int texture2, 807 int vertex3, int texture3) 808 { 809 int original_vertex[3]; 810 811 find_triangle_orientation(vertex1,vertex2,vertex3, 812 original_vertex); 813 814 if ( ( original_vertex[0] == vertex3 && 815 original_vertex[1] == vertex2 && 816 original_vertex[2] == vertex1 ) || 817 ( original_vertex[0] == vertex2 && 818 original_vertex[1] == vertex1 && 819 original_vertex[2] == vertex3 ) || 820 ( original_vertex[0] == vertex1 && 821 original_vertex[1] == vertex3 && 822 original_vertex[2] == vertex2 ) ) { 823 /* New Triangle is in an opposite orientation */ 824 /* Add vertex2 to correct it */ 825 fprintf(output," %d/%d",vertex2,texture2); 826 } 827 } 828 829 /// preserve_strip_orientation_with_texture_and_normal: 830 void CustomStripifier::preserve_strip_orientation_with_texture_and_normal(FILE *output, 831 int vertex1, int texture1, int normal1, 832 int vertex2, int texture2, int normal2, 833 int vertex3, int texture3, int normal3) 834 { 835 int original_vertex[3]; 836 837 find_triangle_orientation(vertex1,vertex2,vertex3, 838 original_vertex); 839 840 if ( ( original_vertex[0] == vertex3 && 841 original_vertex[1] == vertex2 && 842 original_vertex[2] == vertex1 ) || 843 ( original_vertex[0] == vertex2 && 844 original_vertex[1] == vertex1 && 845 original_vertex[2] == vertex3 ) || 846 ( original_vertex[0] == vertex1 && 847 original_vertex[1] == vertex3 && 848 original_vertex[2] == vertex2 ) ) { 849 /* New Triangle is in an opposite orientation */ 850 /* Add vertex2 to correct it */ 851 fprintf(output," %d/%d/%d",vertex2,texture2,normal2); 852 } 853 } 854 855 /// preserve_strip_orientation: 856 void CustomStripifier::preserve_strip_orientation(FILE *output,int vertex1, int vertex2,int vertex3) 857 { 858 int original_vertex[3]; 859 860 find_triangle_orientation(vertex1,vertex2,vertex3, 861 original_vertex); 862 863 if ( ( original_vertex[0] == vertex3 && 864 original_vertex[1] == vertex2 && 865 original_vertex[2] == vertex1 ) || 866 ( original_vertex[0] == vertex2 && 867 original_vertex[1] == vertex1 && 868 original_vertex[2] == vertex3 ) || 869 ( original_vertex[0] == vertex1 && 870 original_vertex[1] == vertex3 && 871 original_vertex[2] == vertex2 )) { 872 /* New Triangle is in an opposite orientation */ 873 /* Add vertex2 to correct it */ 874 fprintf(output," %d",vertex2); 875 mi_vector[num_tiras].push_back(vertex2-1); 876 } 877 } 878 879 /// Output_TriEx: 880 void CustomStripifier::Output_TriEx(int id1, int id2, int id3, FILE *output, 881 int flag, int where) 882 { 883 /* We will save everything into a list, rather than output at once, 884 as was done in the old routine. This way for future modifications 885 we can change the strips later on if we want to. 886 */ 887 888 int swap,temp1,temp2,temp3; 889 static int total=0; 890 static int tri=0; 891 static int strips = 0; 892 static int cost = 0; 893 894 if (flag == -20) 895 { 896 cost = cost + where+total+tri+strips+strips; 897 printf("We will need to send %d vertices to the renderer\n",cost); 898 total = 0; 899 tri = 0; 900 strips = 0; 901 return ; 902 } 903 904 905 if (flag == -10) 906 /* We are finished, now is time to output the triangle list 907 */ 908 { 909 fprintf(output,"\nt"); 910 mi_vector_tipo nada; 911 mi_vector.push_back(nada); 912 num_tiras++; 913 tri = tri + Finished(&swap,output,1); 914 total = total + swap; 915 strips++; 916 /*printf("There are %d swaps %d tri %d strips\n",total,tri,strips);*/ 917 } 918 else 919 { 920 Last_Edge(&temp1,&temp2,&temp3,0); 921 Add_Id_Strips(id1,where); 922 Add_Id_Strips(id2,where); 923 Add_Id_Strips(id3,where); 924 Last_Edge(&id1,&id2,&id3,1); 925 } 926 } 927 928 /// Extend_BackwardsEx: 929 void CustomStripifier::Extend_BackwardsEx(int face_id, FILE *output, int *ties, 930 int tie, int triangulate, 931 int swaps,int *next_id) 932 { 933 /* We just made a strip, now we are going to see if we can extend 934 backwards from the starting face, which had 2 or more adjacencies 935 to start with. 936 */ 937 938 int bucket,next_face,num,x,y,z,c,max,f; 939 ListHead *pListFace; 940 PF_FACES face; 941 P_ADJACENCIES temp; 942 943 /* Get the first triangle that we have saved the the strip data 944 structure, so we can see if there are any polygons adjacent 945 to this edge or a neighboring one 946 */ 947 First_Edge(&x,&y,&z); 948 949 pListFace = PolFaces[face_id]; 950 face = (PF_FACES) PeekList(pListFace,LISTHEAD,0); 951 952 num = face->nPolSize; 953 954 /* Go through the edges to see if there is an adjacency 955 with a vertex in common to the first triangle that was 956 outputted in the strip. (maybe edge was deleted....) 957 */ 958 for (c=0; c<num ; c++) 959 { 960 961 if ( (c != (num-1)) && 962 (( (*(face->pPolygon+c) == x) && (*(face->pPolygon+c+1) == y)) || 963 (*(face->pPolygon+c) == y) && (*(face->pPolygon+c+1) == x))) 964 { 965 /* Input edge is still there see if there is an adjacency */ 966 next_face = Find_Face(face_id, x, y, &bucket); 967 if (next_face == -1) 968 /* Could not find a face adjacent to the edge */ 969 break; 970 pListFace = array[bucket]; 971 max = NumOnList(pListFace); 972 for (f=0;;f++) 973 { 974 temp = (P_ADJACENCIES) PeekList(pListFace,LISTHEAD,f); 975 if (temp->face_id == next_face) 976 { 977 Last_Edge(&z,&y,&x,1); 978 Polygon_OutputEx(temp,temp->face_id,bucket,pListFace, 979 output,ties,tie,triangulate, 980 swaps,next_id,0); 981 return; 982 } 983 984 if (temp == NULL) 985 { 986 printf("Error in the new buckets%d %d %d\n",bucket,max,0); 987 exit(0); 988 } 989 } 990 991 } 992 else if ( (c == (num -1)) && 993 ( ((*(face->pPolygon) == x) && (*(face->pPolygon+num-1) == y)) || 994 (*(face->pPolygon) == y) && (*(face->pPolygon+num-1) == x))) 995 { 996 next_face = Find_Face(face_id,x,y,&bucket); 997 if (next_face == -1) 998 /* Could not find a face adjacent to the edge */ 999 break; 1000 pListFace = array[bucket]; 1001 max = NumOnList(pListFace); 1002 for (f=0;;f++) 1003 { 1004 temp = (P_ADJACENCIES) PeekList(pListFace,LISTHEAD,f); 1005 if (temp->face_id == next_face) 1006 { 1007 Last_Edge(&z,&y,&x,1); 1008 Polygon_OutputEx(temp,temp->face_id,bucket,pListFace, 1009 output,ties,tie,triangulate, 1010 swaps,next_id,0); 1011 return; 1012 } 1013 1014 if (temp == NULL) 1015 { 1016 printf("Error in the new buckets%d %d %d\n",bucket,max,0); 1017 exit(0); 1018 } 1019 } 1020 } 1021 } 1022 } 1023 1024 /// Polygon_OutputEx: 1025 void CustomStripifier::Polygon_OutputEx(P_ADJACENCIES temp,int face_id,int bucket, 1026 ListHead *pListHead, FILE *output, 1027 int *ties, int tie, 1028 int triangulate, int swaps, 1029 int *next_id, int where) 1030 { 1031 ListHead *pListFace; 1032 PF_FACES face; 1033 static BOOL begin = TRUE; 1034 int old_face,next_face_id,next_bucket,e1,e2,e3,other1,other2,other3; 1035 P_ADJACENCIES lpListInfo; 1036 1037 /* We have a polygon to output, the id is face id, and the number 1038 of adjacent polygons to it is bucket. 1039 */ 1040 1041 Last_Edge(&e1,&e2,&e3,0); 1042 1043 /* Get the polygon with id face_id */ 1044 pListFace = PolFaces[face_id]; 1045 face = (PF_FACES) PeekList(pListFace,LISTHEAD,0); 1046 1047 if (face->nPolSize == 3) 1048 { 1049 /* It is already a triangle */ 1050 if (bucket == 0) 1051 { 1052 /* It is not adjacent to anything so we do not have to 1053 worry about the order of the sides or updating adjacencies 1054 */ 1055 1056 Last_Edge(&e1,&e2,&e3,0); 1057 next_face_id = Different(*(face->pPolygon),*(face->pPolygon+1), 1058 *(face->pPolygon+2), 1059 e1,e2,e3,&other1,&other2); 1060 /* No input edge, at the start */ 1061 if ((e2 ==0) && (e3 == 0)) 1062 { 1063 e2 = other1; 1064 e3 = other2; 1065 } 1066 1067 Output_TriEx(e2,e3,next_face_id,NULL,begin,where); 1068 if (face_array[temp->face_id].head == pListHead) 1069 face_array[temp->face_id].pfNode = NULL; 1070 RemoveList(pListHead,(PLISTINFO) temp); 1071 /* We will be at the beginning of the next strip. */ 1072 begin = TRUE; 1073 } 1074 /* It is a triangle with adjacencies. This means that we 1075 have to: 1076 1. Update the adjacencies in the list, because we are 1077 using this polygon and it will be deleted. 1078 2. Get the next polygon. 1079 */ 1080 else 1081 { 1082 /* Return the face_id of the next polygon we will be using, 1083 while updating the adjacency list by decrementing the 1084 adjacencies of everything adjacent to the current triangle. 1085 */ 1086 1087 next_face_id = Update_AdjacenciesEx(face_id,&next_bucket, &e1,&e2,ties); 1088 old_face = next_face_id; 1089 1090 /* Break the tie, if there was one */ 1091 if (tie != FIRST) 1092 old_face = Get_Next_Face(tie,face_id,triangulate); 1093 1094 if (next_face_id == -1) 1095 { 1096 Polygon_OutputEx(temp,face_id,0,pListHead,output,ties,tie, 1097 triangulate,swaps,next_id,where); 1098 return; 1099 } 1100 1101 1102 /* We are using a different face */ 1103 if ((tie != FIRST) && (old_face != next_face_id) && (swaps == ON)) 1104 { 1105 next_face_id = old_face; 1106 /* Get the new output edge, since e1 and e2 are for the 1107 original next face that we got. 1108 */ 1109 e3 = Get_EdgeEx(&e1,&e2,face->pPolygon,next_face_id, 1110 face->nPolSize,0,0); 1111 } 1112 1113 /* Find the other vertex to transmit in the triangle */ 1114 e3 = Return_Other(face->pPolygon,e1,e2); 1115 Last_Edge(&other1,&other2,&other3,0); 1116 1117 if ((other1 != 0) && (other2 != 0)) 1118 { 1119 /* See which vertex in the output edge is not in the input edge */ 1120 if ((e1 != other2) && (e1 != other3)) 1121 e3 = e1; 1122 else if ((e2 != other2) && (e2 != other3)) 1123 e3 = e2; 1124 /* can happen with > 2 polys on an edge but won't 1125 form a good strip so stop the strip here 1126 */ 1127 else 1128 { 1129 Polygon_OutputEx(temp,face_id,0,pListHead,output, 1130 ties,tie,triangulate,swaps,next_id,where); 1131 return; 1132 } 1133 1134 /* See which vertex of the input edge is not in the output edge */ 1135 if ((other2 != e1) && (other2 != e2)) 1136 { 1137 other1 = other2; 1138 other2 = other3; 1139 } 1140 else if ((other3 != e1) && (other3 != e2)) 1141 other1 = other3; 1142 else 1143 { 1144 /* Degenerate triangle just return*/ 1145 Output_TriEx(other1,other2,e3,NULL,begin,where); 1146 if (face_array[temp->face_id].head == pListHead) 1147 face_array[temp->face_id].pfNode = NULL; 1148 RemoveList(pListHead,(PLISTINFO) temp); 1149 begin = FALSE; 1150 return; 1151 } 1152 1153 } 1154 1155 /* There was not an input edge, we are the first triangle in a strip */ 1156 else 1157 { 1158 /* Find the correct order to transmit the triangle, what is 1159 the output edge that we want ? 1160 */ 1161 other1 = e3; 1162 e3 = e2; 1163 other2 = e1; 1164 } 1165 1166 /* At this point the adjacencies have been updated and we 1167 have the next polygon id 1168 */ 1169 Output_TriEx(other1,other2,e3,NULL,begin,where); 1170 if (face_array[temp->face_id].head == pListHead) 1171 face_array[temp->face_id].pfNode = NULL; 1172 RemoveList(pListHead,(PLISTINFO) temp); 1173 begin = FALSE; 1174 1175 if (Done(next_face_id,&next_bucket) == NULL) 1176 return; 1177 1178 pListHead = array[next_bucket]; 1179 lpListInfo = face_array[next_face_id].pfNode; 1180 if (lpListInfo == NULL) 1181 { 1182 printf("There is an error finding the next polygon3 %d\n", 1183 next_face_id); 1184 exit(0); 1185 } 1186 Polygon_OutputEx(lpListInfo,next_face_id,next_bucket, 1187 pListHead, output,ties,tie, 1188 triangulate,swaps,next_id,where); 1189 1190 } 1191 } 1192 1193 else 1194 { 1195 /* It is not a triangle, we have to triangulate it . 1196 Since it is not adjacent to anything we can triangulate it 1197 blindly 1198 */ 1199 if (bucket == 0) 1200 { 1201 /* Check to see if there is not an input edge */ 1202 Last_Edge(&other1,&other2,&other3,0); 1203 if ((other1 == 0) && (other2 ==0)) 1204 Blind_TriangulateEx(face->nPolSize,face->pPolygon, 1205 TRUE,where); 1206 else 1207 Blind_TriangulateEx(face->nPolSize,face->pPolygon, 1208 FALSE,where); 1209 1210 if (face_array[temp->face_id].head == pListHead) 1211 face_array[temp->face_id].pfNode = NULL; 1212 RemoveList(pListHead,(PLISTINFO) temp); 1213 /* We will be at the beginning of the next strip. */ 1214 begin = TRUE; 1215 } 1216 1217 /* If we have specified PARTIAL triangulation then 1218 we will go to special routines that will break the 1219 polygon and update the data structure. Else everything 1220 below will simply triangulate the whole polygon 1221 */ 1222 else if (triangulate == PARTIAL) 1223 { 1224 1225 /* Return the face_id of the next polygon we will be using, 1226 */ 1227 next_face_id = Min_Face_AdjEx(face_id,&next_bucket,ties); 1228 1229 1230 /* Don't do it partially, because we can go inside and get 1231 less adjacencies, for a quad we can do the whole thing. 1232 */ 1233 if ((face_id == next_face_id) && (face->nPolSize == 4) && (swaps == ON)) 1234 { 1235 next_face_id = Update_AdjacenciesEx(face_id, &next_bucket, 1236 &e1,&e2,ties); 1237 if (next_face_id == -1) 1238 { 1239 /* There is no sequential face to go to, end the strip */ 1240 Polygon_OutputEx(temp,face_id,0,pListHead,output, 1241 ties,tie,triangulate,swaps,next_id,where); 1242 return; 1243 } 1244 1245 /* Break the tie, if there was one */ 1246 if (tie != FIRST) 1247 next_face_id = Get_Next_Face(tie,face_id,triangulate); 1248 Non_Blind_TriangulateEx(face->nPolSize,face->pPolygon, 1249 output,next_face_id,face_id,where); 1250 1251 if (face_array[temp->face_id].head == pListHead) 1252 face_array[temp->face_id].pfNode = NULL; 1253 RemoveList(pListHead,(PLISTINFO) temp); 1254 } 1255 1256 /* Was not a quad but we still do not want to do it partially for 1257 now, since we want to only do one triangle at a time 1258 */ 1259 else if ((face_id == next_face_id) && (swaps == ON)) 1260 Inside_Polygon(face->nPolSize,face->pPolygon, 1261 face_id,pListHead,where); 1262 1263 else 1264 { 1265 if ((tie != FIRST) && (swaps == ON)) 1266 next_face_id = Get_Next_Face(tie,face_id,triangulate); 1267 Partial_Triangulate(face->nPolSize,face->pPolygon, 1268 output,next_face_id,face_id,next_id, 1269 pListHead,temp,where); 1270 /* Check the next bucket again ,maybe it changed 1271 We calculated one less, but that might not be the case 1272 */ 1273 } 1274 1275 if (Done(next_face_id,&next_bucket) == NULL) 1276 { 1277 /* Check to see if there is not an input edge */ 1278 Last_Edge(&other1,&other2,&other3,0); 1279 if ((other1 == 0) && (other2 ==0)) 1280 Blind_TriangulateEx(face->nPolSize,face->pPolygon, 1281 TRUE,where); 1282 else 1283 Blind_TriangulateEx(face->nPolSize,face->pPolygon, 1284 FALSE,where); 1285 1286 if (Done(face_id,&bucket) != NULL) 1287 { 1288 pListHead = array[bucket]; 1289 lpListInfo = face_array[face_id].pfNode; 1290 if (face_array[temp->face_id].head == pListHead) 1291 face_array[lpListInfo->face_id].pfNode = NULL; 1292 RemoveList(pListHead,(PLISTINFO)lpListInfo); 1293 } 1294 begin = TRUE; 1295 return; 1296 } 1297 1298 begin = FALSE; 1299 pListHead = array[next_bucket]; 1300 lpListInfo = face_array[next_face_id].pfNode; 1301 if (lpListInfo == NULL) 1302 { 1303 printf("There is an error finding the next polygon1 %d %d\n", 1304 next_face_id,next_bucket); 1305 exit(0); 1306 } 1307 Polygon_OutputEx(lpListInfo,next_face_id,next_bucket, 1308 pListHead, output,ties,tie, 1309 triangulate,swaps,next_id,where); 1310 } 1311 1312 1313 else 1314 { 1315 /* WHOLE triangulation */ 1316 /* It is not a triangle and has adjacencies. 1317 This means that we have to: 1318 1. TriangulateEx this polygon, not blindly because 1319 we have an edge that we want to come out on, that 1320 is the edge that is adjacent to a polygon with the 1321 least number of adjacencies. Also we must come in 1322 on the last seen edge. 1323 2. Update the adjacencies in the list, because we are 1324 using this polygon . 1325 3. Get the next polygon. 1326 */ 1327 /* Return the face_id of the next polygon we will be using, 1328 while updating the adjacency list by decrementing the 1329 adjacencies of everything adjacent to the current polygon. 1330 */ 1331 1332 next_face_id = Update_AdjacenciesEx(face_id,&next_bucket, &e1,&e2,ties); 1333 1334 if (Done(next_face_id,&next_bucket) == NULL) 1335 { 1336 Polygon_OutputEx(temp,face_id,0,pListHead,output,ties,tie, 1337 triangulate,swaps,next_id,where); 1338 /* Because maybe there was more than 2 polygons on the edge */ 1339 return; 1340 } 1341 1342 /* Break the tie, if there was one */ 1343 else if (tie != FIRST) 1344 next_face_id = Get_Next_Face(tie,face_id,triangulate); 1345 1346 Non_Blind_TriangulateEx(face->nPolSize,face->pPolygon, 1347 output,next_face_id,face_id,where); 1348 1349 if (face_array[temp->face_id].head == pListHead) 1350 face_array[temp->face_id].pfNode = NULL; 1351 RemoveList(pListHead,(PLISTINFO) temp); 1352 begin = FALSE; 1353 pListHead = array[next_bucket]; 1354 lpListInfo = face_array[next_face_id].pfNode; 1355 1356 if (lpListInfo == NULL) 1357 { 1358 printf("There is an error finding the next polygon2 %d %d\n", 1359 next_face_id,next_bucket); 1360 exit(0); 1361 } 1362 Polygon_OutputEx(lpListInfo,next_face_id,next_bucket, 1363 pListHead, output,ties,tie, 1364 triangulate,swaps,next_id,where); 1365 } 1366 1367 } 1368 Last_Edge(&e1,&e2,&e3,0); 1369 } 1370 1371 /// Adjacent: 1372 int CustomStripifier::Adjacent(int id2,int id1, int *list, int size) 1373 { 1374 /* Return the vertex that is adjacent to id1, 1375 but is not id2, in the list of integers. 1376 */ 1377 1378 register int x=0; 1379 1380 while (x < size) 1381 { 1382 if (*(list+x) == id1) 1383 { 1384 if ((x != (size -1)) && (x != 0)) 1385 { 1386 if ( *(list+x+1) != id2) 1387 return *(list+x+1); 1388 else 1389 return *(list+x-1); 1390 } 1391 else if (x == (size -1)) 1392 { 1393 if (*(list) != id2) 1394 return *(list); 1395 else 1396 return *(list+x-1); 1397 } 1398 else 1399 { 1400 if (*(list+size-1) != id2) 1401 return *(list+size-1); 1402 else 1403 return *(list+x+1); 1404 } 1405 } 1406 x++; 1407 } 1408 /* if there are degeneracies */ 1409 return id1; 1410 } 1411 1412 /// Rearrange_Index: 1413 void CustomStripifier::Rearrange_Index(int *index, int size) 1414 { 1415 /* If we are in the middle of a strip we must find the 1416 edge to start on, which is the last edge that we had 1417 transmitted. 1418 */ 1419 int x,f,y,e1,e2,e3; 1420 register int increment = 1; 1421 int *temp; 1422 1423 /* Find where the input edge is in the input list */ 1424 Last_Edge(&e1,&e2,&e3,0); 1425 for (y = 0; y < size; y++) 1426 { 1427 if (*(index+y) == e2) 1428 { 1429 if ((y != (size - 1)) && (*(index+y+1) == e3)) 1430 break; 1431 else if ((y == (size - 1)) && (*(index) == e3)) 1432 break; 1433 else if ((y != 0) && (*(index+y-1) == e3)) 1434 { 1435 increment = -1; 1436 break; 1437 } 1438 else if ((y==0) && (*(index+size-1) == e3)) 1439 { 1440 increment = -1; 1441 break; 1442 } 1443 } 1444 if (*(index+y) == e3) 1445 { 1446 if ((y != (size - 1)) && (*(index+y+1) == e2)) 1447 break; 1448 else if ((y == (size - 1)) && (*(index) == e2)) 1449 break; 1450 else if ((y != 0) && (*(index+y-1) == e2)) 1451 { 1452 increment = -1; 1453 break; 1454 } 1455 else if ((y==0) && (*(index+size-1) == e2)) 1456 { 1457 increment = -1; 1458 break; 1459 } 1460 } 1461 /* Edge is not here, we are at the beginning */ 1462 if ((y == (size-1)) && (increment != -1)) 1463 return; 1464 } 1465 1466 /* Now put the list into a new list, starting with the 1467 input edge. Increment tells us whether we have to go 1468 forward or backward. 1469 */ 1470 /* Was in good position already */ 1471 if ((y == 0) && (increment == 1)) 1472 return; 1473 1474 temp = (int *) malloc(sizeof(int) * size); 1475 memcpy(temp,index,sizeof(int)*size); 1476 1477 if (increment == 1) 1478 { 1479 x=0; 1480 for (f = y ; f< size; f++) 1481 { 1482 *(index+x) = *(temp+f); 1483 x++; 1484 } 1485 /* Finish the rest of the list */ 1486 for(f = 0; f < y ; f++) 1487 { 1488 *(index+x) = *(temp+f); 1489 x++; 1490 } 1491 } 1492 else 1493 { 1494 x=0; 1495 for (f = y ; f >= 0; f--) 1496 { 1497 *(index+x) = *(temp+f); 1498 x++; 1499 } 1500 /* Finish the rest of the list */ 1501 for(f = (size - 1); f > y ; f--) 1502 { 1503 *(index+x) = *(temp+f); 1504 x++; 1505 } 1506 } 1507 } 1508 1509 /// Delete_From_List: 1510 void CustomStripifier::Delete_From_List(int id,int *list, int *size) 1511 { 1512 /* Delete the occurence of id in the list. 1513 (list has size size) 1514 */ 1515 1516 int *temp; 1517 register int x,y=0; 1518 1519 temp = (int *) malloc(sizeof(int) * (*size)); 1520 for (x=0; x<(*size); x++) 1521 { 1522 if (*(list+x) != id) 1523 { 1524 *(temp+y) = *(list+x); 1525 y++; 1526 } 1527 } 1528 *(temp+y) = -1; 1529 *size = *size - (*size - y - 1); 1530 memcpy(list,temp,sizeof(int)*(*size)); 1531 } 1532 1533 /// Build_SGI_Table: 1534 void CustomStripifier::Build_SGI_Table(int num_faces) 1535 { 1536 /* Build a table that has the polygons sorted by the 1537 number of adjacent polygons. 1538 */ 1539 int x,y,size,tally=0; 1540 ListHead *pListHead; 1541 PF_FACES temp = NULL; 1542 1543 /* For each face....*/ 1544 for (x=0;x < num_faces;x++) 1545 { 1546 pListHead = PolFaces[x]; 1547 temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); 1548 /* Check each edge of the face and tally the number of adjacent 1549 polygons to this face. 1550 */ 1551 if ( temp != NULL ) 1552 { 1553 /* Size of the polygon */ 1554 size = temp->nPolSize; 1555 if (size != 1) 1556 { 1557 for (y = 0; y< size; y++) 1558 { 1559 if (y != (size-1)) 1560 tally += Num_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1)); 1561 else 1562 tally+= Num_Adj(*(temp->pPolygon),*(temp->pPolygon+(size-1))); 1563 } 1564 1565 /* Tally is the number of polygons that is adjacent to 1566 the current polygon. 1567 */ 1568 /* Now put the face in the proper bucket depending on tally. */ 1569 Add_Sgi_Adj(tally,x); 1570 temp = NULL; 1571 tally=0; 1572 } 1573 } 1574 } 1575 } 1576 1577 /// Triangulate_Quad: 1578 void CustomStripifier::Triangulate_Quad(int out_edge1,int out_edge2,int in_edge1, 1579 int in_edge2,int size,int *index, 1580 int reversed,int where) 1581 { 1582 int vertex4,vertex5; 1583 1584 /* This routine will nonblindly triangulate a quad, meaning 1585 that there is a definite input and a definite output 1586 edge that we must adhere to. Reversed will tell the orientation 1587 of the input edge. (Reversed is -1 is we do not have an input 1588 edge, in other words we are at the beginning of a strip.) 1589 Out_edge* is the output edge, and in_edge* is the input edge. 1590 Index are the edges of the polygon 1591 and size is the size of the polygon. Begin is whether we are 1592 at the start of a new strip. 1593 */ 1594 1595 /* If we do not have an input edge, then we can make our input 1596 edge whatever we like, therefore it will be easier to come 1597 out on the output edge. 1598 */ 1599 if (reversed == -1) 1600 { 1601 vertex4 = Adjacent(out_edge1,out_edge2,index,size); 1602 vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index); 1603 Output_Tri(vertex5,vertex4,out_edge1,where); 1604 Output_Tri(vertex4,out_edge1,out_edge2,where); 1605 return; 1606 } 1607 1608 /* These are the 5 cases that we can have for the output edge */ 1609 1610 /* Are they consecutive so that we form a triangle to 1611 peel off, but cannot use the whole quad? 1612 */ 1613 1614 if (in_edge2 == out_edge1) 1615 { 1616 /* Output the triangle that comes out the correct 1617 edge last. First output the triangle that comes out 1618 the wrong edge. 1619 */ 1620 vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index); 1621 Output_Tri(in_edge1,in_edge2,vertex4,where); 1622 Output_Tri(vertex4,in_edge2,out_edge2,where); 1623 return; 1624 } 1625 /* The next case is where it is impossible to come out the 1626 edge that we want. So we will have to start a new strip to 1627 come out on that edge. We will output the one triangle 1628 that we can, and then start the new strip with the triangle 1629 that comes out on the edge that we want to come out on. 1630 */ 1631 else if (in_edge1 == out_edge1) 1632 { 1633 /* We want to output the first triangle (whose output 1634 edge is not the one that we want. 1635 We have to find the vertex that we need, which is 1636 the other vertex which we do not have. 1637 */ 1638 vertex4 = Get_Other_Vertex(in_edge2,in_edge1,out_edge2,index); 1639 Output_Tri(in_edge2,in_edge1,vertex4,where); 1640 Output_Tri(vertex4,in_edge1,out_edge2,where); 1641 return; 1642 } 1643 1644 /* Consecutive cases again, but with the output edge reversed */ 1645 else if (in_edge1 == out_edge2) 1646 { 1647 vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index); 1648 Output_Tri(in_edge2,in_edge1,vertex4,where); 1649 Output_Tri(vertex4,in_edge1,out_edge1,where); 1650 return; 1651 } 1652 else if (in_edge2 == out_edge2) 1653 { 1654 vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index); 1655 Output_Tri(in_edge1,in_edge2,vertex4,where); 1656 Output_Tri(vertex4,in_edge2,out_edge1,where); 1657 return; 1658 } 1659 1660 /* The final case is where we want to come out the opposite 1661 edge. 1662 */ 1663 else 1664 { 1665 if( ((!reversed) && 1666 (out_edge1 == (Adjacent(in_edge1,in_edge2,index,size)))) || 1667 ((reversed) && 1668 (out_edge2 == (Adjacent(in_edge2,in_edge1,index,size))))) 1669 { 1670 /* We need to know the orientation of the input 1671 edge, so we know which way to put the diagonal. 1672 And also the output edge, so that we triangulate 1673 correctly. 1674 */ 1675 Output_Tri(in_edge1,in_edge2,out_edge2,where); 1676 Output_Tri(in_edge2,out_edge2,out_edge1,where); 1677 } 1678 else 1679 { 1680 /* Input and output orientation was reversed, so diagonal will 1681 be reversed from above. 1682 */ 1683 Output_Tri(in_edge1,in_edge2,out_edge1,where); 1684 Output_Tri(in_edge2,out_edge1,out_edge2,where); 1685 } 1686 return; 1687 } 1688 } 1689 1690 /// Triangulate_Polygon: 1691 void CustomStripifier::Triangulate_Polygon( int out_edge1,int out_edge2, 1692 int in_edge1, int in_edge2, 1693 int size, int *index, 1694 FILE *output, int reversed, 1695 int face_id, int where, 1696 int color1, int color2, 1697 int color3) 1698 { 1699 /* We have a polygon that we need to nonblindly triangulate. 1700 We will recursively try to triangulate it, until we are left 1701 with a polygon of size 4, which can use the quad routine 1702 from above. We will be taking off a triangle at a time 1703 and outputting it. We will have 3 cases similar to the 1704 cases for the quad above. The inputs to this routine 1705 are the same as for the quad routine. 1706 */ 1707 1708 int vertex4; 1709 int *temp; 1710 1711 1712 /* Since we are calling this recursively, we have to check whether 1713 we are down to the case of the quad. 1714 */ 1715 1716 if (size == 4) 1717 { 1718 Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size, 1719 index,reversed,where); 1720 return; 1721 } 1722 1723 1724 1725 /* We do not have a specified input edge, and therefore we 1726 can make it anything we like, as long as we still come out 1727 the output edge that we want. 1728 */ 1729 if (reversed == -1) 1730 { 1731 /* Get the vertex for the last triangle, which is 1732 the one coming out the output edge, before we do 1733 any deletions to the list. We will be doing this 1734 bottom up. 1735 */ 1736 vertex4 = Adjacent(out_edge1,out_edge2,index,size); 1737 temp = (int *) malloc(sizeof(int) * size); 1738 memcpy(temp,index,sizeof(int)*size); 1739 Delete_From_List(out_edge2,index,&size); 1740 Triangulate_Polygon(out_edge1,vertex4,in_edge2, 1741 vertex4,size-1,index,output,reversed,face_id, 1742 where,color1,color2,color3); 1743 memcpy(index,temp,sizeof(int)*size); 1744 /* Lastly do the triangle that comes out the output 1745 edge. 1746 */ 1747 Output_Tri(vertex4,out_edge1,out_edge2,where); 1748 return; 1749 } 1750 1751 /* These are the 5 cases that we can have for the output edge */ 1752 1753 /* Are they consecutive so that we form a triangle to 1754 peel off that comes out the correct output edge, 1755 but we cannot use the whole polygon? 1756 */ 1757 if (in_edge2 == out_edge1) 1758 { 1759 /* Output the triangle that comes out the correct 1760 edge last. First recursively do the rest of the 1761 polygon. 1762 */ 1763 /* Do the rest of the polygon without the triangle. 1764 We will be doing a fan triangulation. 1765 */ 1766 /* Get the vertex adjacent to in_edge1, but is not 1767 in_edge2. 1768 */ 1769 vertex4 = Adjacent(in_edge2,in_edge1,index,size); 1770 Output_Tri(in_edge1,in_edge2,vertex4,where); 1771 /* Create a new edgelist without the triangle that 1772 was just outputted. 1773 */ 1774 temp = (int *) malloc(sizeof(int) * size); 1775 memcpy(temp,index,sizeof(int)*size); 1776 Delete_From_List(in_edge1,index,&size); 1777 Triangulate_Polygon(out_edge1,out_edge2,in_edge2, 1778 vertex4,size-1,index,output,!reversed,face_id, 1779 where,color1,color2,color3); 1780 memcpy(index,temp,sizeof(int)*size); 1781 return; 1782 } 1783 1784 /* Next case is where it is again consecutive, but the triangle 1785 formed by the consecutive edges do not come out of the 1786 correct output edge. For this case, we can not do much to 1787 keep it sequential. Try and do the fan. 1788 */ 1789 else if (in_edge1 == out_edge1) 1790 { 1791 /* Get vertex adjacent to in_edge2, but is not in_edge1 */ 1792 vertex4 = Adjacent(in_edge1,in_edge2,index,size); 1793 Output_Tri(in_edge1,in_edge2,vertex4,where); 1794 /* Since that triangle goes out of the polygon (the 1795 output edge of it), we can make our new input edge 1796 anything we like, so we will try to make it good for 1797 the strip. (This will be like starting a new strip, 1798 all so that we can go out the correct output edge.) 1799 */ 1800 temp = (int *) malloc(sizeof(int) * size); 1801 memcpy(temp,index,sizeof(int)*size); 1802 Delete_From_List(in_edge2,index,&size); 1803 Triangulate_Polygon(out_edge1,out_edge2,in_edge1, 1804 vertex4,size-1,index,output,reversed,face_id, 1805 where,color1,color2,color3); 1806 memcpy(index,temp,sizeof(int)*size); 1807 return; 1808 } 1809 /* Consecutive cases again, but with the output edge reversed */ 1810 else if (in_edge1 == out_edge2) 1811 { 1812 /* Get vertex adjacent to in_edge2, but is not in_edge1 */ 1813 vertex4 = Adjacent(in_edge1,in_edge2,index,size); 1814 Output_Tri(in_edge2,in_edge1,vertex4,where); 1815 temp = (int *) malloc(sizeof(int) * size); 1816 memcpy(temp,index,sizeof(int)*size); 1817 Delete_From_List(in_edge2,index,&size); 1818 Triangulate_Polygon(out_edge1,out_edge2,in_edge1, 1819 vertex4,size-1,index,output,reversed,face_id, 1820 where,color1,color2,color3); 1821 memcpy(index,temp,sizeof(int)*size); 1822 return; 1823 } 1824 else if (in_edge2 == out_edge2) 1825 { 1826 /* Get vertex adjacent to in_edge2, but is not in_edge1 */ 1827 vertex4 = Adjacent(in_edge2,in_edge1,index,size); 1828 Output_Tri(in_edge1,in_edge2,vertex4,where); 1829 temp = (int *) malloc(sizeof(int) * size); 1830 memcpy(temp,index,sizeof(int)*size); 1831 Delete_From_List(in_edge1,index,&size); 1832 Triangulate_Polygon(out_edge1,out_edge2,vertex4, 1833 in_edge2,size-1,index,output,reversed,face_id, 1834 where,color1,color2,color3); 1835 memcpy(index,temp,sizeof(int)*size); 1836 return; 1837 } 1838 1839 /* Else the edge is not consecutive, and it is sufficiently 1840 far away, for us not to make a conclusion at this time. 1841 So we can take off a triangle and recursively call this 1842 function. 1843 */ 1844 else 1845 { 1846 vertex4 = Adjacent(in_edge2,in_edge1,index,size); 1847 Output_Tri(in_edge1,in_edge2,vertex4,where); 1848 temp = (int *) malloc(sizeof(int) * size); 1849 memcpy(temp,index,sizeof(int)*size); 1850 Delete_From_List(in_edge1,index,&size); 1851 Triangulate_Polygon(out_edge1,out_edge2,in_edge2, 1852 vertex4,size-1,index,output,!reversed,face_id, 1853 where,color1,color2,color3); 1854 memcpy(index,temp,sizeof(int)*size); 1855 return; 1856 } 1857 } 1858 1859 /// Triangulate: 1860 void CustomStripifier::Triangulate(int out_edge1,int out_edge2,int in_edge1, 1861 int in_edge2,int size,int *index, 1862 FILE *output,int reversed,int face_id, int where, 1863 int color1, int color2,int color3) 1864 { 1865 /* We have the info we need to triangulate a polygon */ 1866 1867 if (size == 4) 1868 Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size, 1869 index,reversed,where); 1870 else 1871 Triangulate_Polygon(out_edge1,out_edge2,in_edge1,in_edge2,size, 1872 index,output,reversed,face_id,where,color1,color2,color3); 1873 } 1874 1875 /// Non_Blind_Triangulate: 1876 void CustomStripifier::Non_Blind_Triangulate(int size,int *index, 1877 FILE *output,int next_face_id,int face_id,int where, 1878 int color1,int color2,int color3) 1879 { 1880 int id1,id2,id3; 1881 int nedge1,nedge2; 1882 int reversed; 1883 /* We have a polygon that has to be triangulated and we cannot 1884 do it blindly, ie we will try to come out on the edge that 1885 has the least number of adjacencies 1886 */ 1887 1888 Last_Edge(&id1,&id2,&id3,0); 1889 /* Find the edge that is adjacent to the new face , 1890 also return whether the orientation is reversed in the 1891 face of the input edge, which is id2 and id3. 1892 */ 1893 if (next_face_id == -1) 1894 { 1895 printf("The face is -1 and the size is %d\n",size); 1896 exit(0); 1897 } 1898 1899 reversed = Get_Edge(&nedge1,&nedge2,index,next_face_id,size,id2,id3); 1900 /* Do the triangulation */ 1901 1902 /* If reversed is -1, the input edge is not in the polygon, 1903 therefore we can have the input edge to be anything we like, 1904 since we are at the beginning of a strip 1905 */ 1906 Triangulate(nedge1,nedge2,id2,id3,size,index,output,reversed, 1907 face_id, where,color1,color2,color3); 1908 } 1909 1910 /// Blind_Triangulate: 1911 void CustomStripifier::Blind_Triangulate(int size, int *index, BOOL begin, int where) 1912 { 1913 /* save sides in temp array, we need it so we know 1914 about swaps. 1915 */ 1916 int mode, decreasing,increasing,e1,e2,e3; 1917 1918 /* Rearrange the index list so that the input edge is first 1919 */ 1920 if (!begin) 1921 Rearrange_Index(index,size); 1922 1923 /* We are given a polygon of more than 3 sides 1924 and want to triangulate it. We will output the 1925 triangles to the output file. 1926 */ 1927 1928 /* Find where the input edge is in the input list */ 1929 Last_Edge(&e1,&e2,&e3,0); 1930 if (( (!begin) && (*(index) == e2) ) || (begin)) 1931 { 1932 Output_Tri(*(index+0),*(index+1),*(index+size-1),where); 1933 /* If we have a quad, (chances are yes), then we know that 1934 we can just add one diagonal and be done. (divide the 1935 quad into 2 triangles. 1936 */ 1937 if (size == 4) 1938 { 1939 Output_Tri(*(index+1),*(index+size-1),*(index+2),where); 1940 return; 1941 } 1942 increasing = 1; 1943 mode = 1; 1944 1945 } 1946 else if (!begin) 1947 { 1948 Output_Tri(*(index+1),*(index+0),*(index+size-1),where); 1949 if (size == 4) 1950 { 1951 Output_Tri(*(index+0),*(index+size-1),*(index+2),where); 1952 return; 1953 } 1954 Output_Tri(*(index+0),*(index+size-1),*(index+2),where); 1955 increasing = 2; 1956 mode = 0; 1957 } 1958 if (size != 4) 1959 { 1960 /* We do not have a quad, we have something bigger. */ 1961 decreasing = size - 1; 1962 do 1963 { 1964 /* Will be alternating diagonals, so we will be increasing 1965 and decreasing around the polygon. 1966 */ 1967 if (mode) 1968 { 1969 Output_Tri(*(index+increasing),*(index+decreasing), 1970 *(index+increasing+1),where); 1971 increasing++; 1972 } 1973 else 1974 { 1975 Output_Tri(*(index+decreasing),*(index+increasing), 1976 *(index+decreasing-1),where); 1977 decreasing--; 1978 } 1979 mode = !mode; 1980 } while ((decreasing - increasing) >= 2); 1981 1982 } 1983 } 1984 1985 /// Get_Edge: 1986 int CustomStripifier::Get_Edge(int *edge1,int *edge2,int *index,int face_id, 1987 int size, int id1, int id2) 1988 { 1989 /* Put the edge that is adjacent to face_id into edge1 1990 and edge2. For each edge see if it is adjacent to 1991 face_id. Id1 and id2 is the input edge, so see if 1992 the orientation is reversed, and save it in reversed. 1993 */ 1994 register int x; 1995 int reversed = -1; 1996 BOOL set = FALSE; 1997 1998 for (x=0; x< size; x++) 1999 { 2000 if (x == (size-1)) 2001 { 2002 if ((*(index) == id1) && (*(index+size-1)==id2)) 2003 { 2004 if (set) 2005 return 1; 2006 reversed = 1; 2007 } 2008 else if ((*(index) == id2) && (*(index+size-1)==id1)) 2009 { 2010 if (set) 2011 return 0; 2012 reversed = 0; 2013 } 2014 2015 if (Look_Up(*(index),*(index+size-1),face_id)) 2016 { 2017 if ( (out1 != -1) && 2018 ( (out1 == *(index)) || 2019 (out1 == *(index+size-1)) ) && 2020 ( (out2 == *(index)) || 2021 (out2 == *(index+size-1)) )) 2022 { 2023 set = TRUE; 2024 *edge1 = *(index); 2025 *edge2 = *(index+size-1); 2026 } 2027 else if (out1 == -1) 2028 { 2029 set = TRUE; 2030 *edge1 = *(index); 2031 *edge2 = *(index+size-1); 2032 } 2033 if ((reversed != -1) && (set)) 2034 return reversed; 2035 } 2036 } 2037 else 2038 { 2039 if ((*(index+x) == id1) && (*(index+x+1)==id2)) 2040 { 2041 if (set) 2042 return 0; 2043 reversed = 0; 2044 } 2045 else if ((*(index+x) == id2) && (*(index+x+1)==id1)) 2046 { 2047 if (set) 2048 return 1; 2049 reversed = 1; 2050 } 2051 2052 if (Look_Up(*(index+x),*(index+x+1),face_id)) 2053 { 2054 if ( (out1 != -1) && 2055 ( (out1 == *(index+x)) || 2056 (out1 == *(index+x+1)) ) && 2057 ((out2 == *(index+x)) || 2058 (out2 == *(index+x+1)))) 2059 { 2060 set = TRUE; 2061 *edge1 = *(index+x); 2062 *edge2 = *(index+x+1); 2063 } 2064 else if (out1 == -1) 2065 { 2066 set = TRUE; 2067 *edge1 = *(index+x); 2068 *edge2 = *(index+x + 1); 2069 } 2070 if ((reversed != -1) && (set)) 2071 return reversed; 2072 } 2073 } 2074 } 2075 if ((x == size) && (reversed != -1)) 2076 { 2077 /* Could not find the output edge */ 2078 printf("Error in the Lookup %d %d %d %d %d %d %d %d\n", 2079 face_id,id1,id2,reversed,*edge1,*edge2,out1,out2); 2080 exit(0); 2081 } 2082 return reversed; 2083 } 2084 2085 /// Udate_Face: 2086 void CustomStripifier::Update_Face(int *next_bucket, int *min_face, int face_id, int *e1, 2087 int *e2,int temp1,int temp2,int *ties) 2088 { 2089 /* We have a face id that needs to be decremented. 2090 We have to determine where it is in the structure, 2091 so that we can decrement it. 2092 */ 2093 /* The number of adjacencies may have changed, so to locate 2094 it may be a little tricky. However we know that the number 2095 of adjacencies is less than or equal to the original number 2096 of adjacencies, 2097 */ 2098 int y,size; 2099 ListHead *pListHead; 2100 PF_FACES temp = NULL; 2101 PLISTINFO lpListInfo; 2102 static int each_poly = 0; 2103 BOOL there = FALSE; 2104 2105 pListHead = PolFaces[face_id]; 2106 temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); 2107 /* Check each edge of the face and tally the number of adjacent 2108 polygons to this face. 2109 */ 2110 if ( temp != NULL ) 2111 { 2112 /* Size of the polygon */ 2113 size = temp->nPolSize; 2114 /* We did it already */ 2115 if (size == 1) 2116 return; 2117 for (y = 0; y< size; y++) 2118 { 2119 /* If we are doing partial triangulation, we must check 2120 to see whether the edge is still there in the polygon, 2121 since we might have done a portion of the polygon 2122 and saved the rest for later. 2123 */ 2124 if (y != (size-1)) 2125 { 2126 if( ((temp1 == *(temp->pPolygon+y)) && 2127 (temp2 ==*(temp->pPolygon+y+1))) || 2128 ((temp2 == *(temp->pPolygon+y)) && 2129 (temp1 ==*(temp->pPolygon+y+1)))) 2130 /* edge is still there we are ok */ 2131 there = TRUE; 2132 } 2133 else 2134 { 2135 if( ((temp1 == *(temp->pPolygon)) && 2136 (temp2 == *(temp->pPolygon+size-1))) || 2137 ((temp2 == *(temp->pPolygon)) && 2138 (temp1 ==*(temp->pPolygon+size-1)))) 2139 /* edge is still there we are ok */ 2140 there = TRUE; 2141 } 2142 } 2143 2144 if (!there) 2145 /* Original edge was already used, we cannot use this polygon */ 2146 return; 2147 2148 /* We have a starting point to start our search to locate 2149 this polygon. 2150 */ 2151 2152 /* Check to see if this polygon was done */ 2153 lpListInfo = Done(face_id,&y); 2154 2155 if (lpListInfo == NULL) 2156 return; 2157 2158 /* Was not done, but there is an error in the adjacency calculations */ 2159 if (y == 0) 2160 { 2161 printf("There is an error in finding the adjacencies\n"); 2162 exit(0); 2163 } 2164 2165 /* Now put the face in the proper bucket depending on tally. */ 2166 /* First add it to the new bucket, then remove it from the old */ 2167 Add_Sgi_Adj(y-1,face_id); 2168 RemoveList(array[y],lpListInfo); 2169 2170 /* Save it if it was the smallest seen so far since then 2171 it will be the next face 2172 Here we will have different options depending on 2173 what we want for resolving ties: 2174 1) First one we see we will use 2175 2) Random resolving 2176 3) Look ahead 2177 4) Alternating direction 2178 */ 2179 /* At a new strip */ 2180 if (*next_bucket == 60) 2181 *ties = *ties + each_poly; 2182 /* Have a tie */ 2183 if (*next_bucket == (y-1)) 2184 { 2185 Add_Ties(face_id); 2186 each_poly++; 2187 } 2188 /* At a new minimum */ 2189 if (*next_bucket > (y-1)) 2190 { 2191 *next_bucket = y-1; 2192 *min_face = face_id; 2193 *e1 = temp1; 2194 *e2 = temp2; 2195 each_poly = 0; 2196 Clear_Ties(); 2197 Add_Ties(face_id); 2198 } 2199 } 2200 } 2201 2202 /// Delete_Adj: 2203 void CustomStripifier::Delete_Adj(int id1, int id2,int *next_bucket,int *min_face, 2204 int current_face,int *e1,int *e2,int *ties) 2205 { 2206 /* Find the face that is adjacent to the edge and is not the 2207 current face. Delete one adjacency from it. Save the min 2208 adjacency seen so far. 2209 */ 2210 register int count=0; 2211 PF_EDGES temp = NULL; 2212 ListHead *pListHead; 2213 int next_face; 2214 2215 /* Always want smaller id first */ 2216 switch_lower(&id1,&id2); 2217 2218 pListHead = PolEdges[id1]; 2219 temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); 2220 if (temp == NULL) 2221 /* It could be a new edge that we created. So we can 2222 exit, since there is not a face adjacent to it. 2223 */ 2224 return; 2225 while (temp->edge[0] != id2) 2226 { 2227 count++; 2228 temp = ( PF_EDGES )GetNextNode(temp); 2229 2230 if (temp == NULL) 2231 /* Was a new edge that was created and therefore 2232 does not have anything adjacent to it 2233 */ 2234 return; 2235 } 2236 /* Was not adjacent to anything else except itself */ 2237 if (temp->edge[2] == -1) 2238 return; 2239 2240 /* Was adjacent to something */ 2241 else 2242 { 2243 if (temp->edge[2] == current_face) 2244 next_face = temp->edge[1]; 2245 else 2246 next_face = temp->edge[2]; 2247 } 2248 /* We have the other face adjacent to this edge, it is 2249 next_face. Now we need to decrement this faces' adjacencies. 2250 */ 2251 Update_Face(next_bucket, min_face, next_face,e1,e2,id1,id2,ties); 2252 } 2253 2254 /// Update_Adjacencies: 2255 int CustomStripifier::Update_Adjacencies(int face_id, int *next_bucket, int *e1, int *e2, 2256 int *ties) 2257 { 2258 /* Give the face with id face_id, we want to decrement 2259 all the faces that are adjacent to it, since we will 2260 be deleting face_id from the data structure. 2261 We will return the face that has the least number 2262 of adjacencies. 2263 */ 2264 PF_FACES temp = NULL; 2265 ListHead *pListHead; 2266 int size,y,min_face = -1; 2267 2268 *next_bucket = 60; 2269 pListHead = PolFaces[face_id]; 2270 temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); 2271 2272 if ( temp == NULL ) 2273 { 2274 printf("The face was already deleted, there is an error\n"); 2275 exit(0); 2276 } 2277 2278 /* Size of the polygon */ 2279 size = temp->nPolSize; 2280 for (y = 0; y< size; y++) 2281 { 2282 if (y != (size-1)) 2283 Delete_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1), 2284 next_bucket,&min_face,face_id,e1,e2,ties); 2285 else 2286 Delete_Adj(*(temp->pPolygon),*(temp->pPolygon+(size-1)), 2287 next_bucket,&min_face,face_id,e1,e2,ties); 2288 } 2289 return (min_face); 2290 } 2291 2292 /// Old_Adj: 2293 int CustomStripifier::Old_Adj(int face_id) 2294 { 2295 /* Find the bucket that the face_id is currently in, 2296 because maybe we will be deleting it. 2297 */ 2298 PF_FACES temp = NULL; 2299 ListHead *pListHead; 2300 int y; 2301 2302 pListHead = PolFaces[face_id]; 2303 temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); 2304 if ( temp == NULL ) 2305 { 2306 printf("The face was already deleted, there is an error\n"); 2307 exit(0); 2308 } 2309 2310 if (Done(face_id,&y) == NULL) 2311 { 2312 printf("There is an error in finding the face\n"); 2313 exit(0); 2314 } 2315 return y; 2316 } 2317 2318 /// Number_Adj: 2319 int CustomStripifier::Number_Adj(int id1, int id2, int curr_id) 2320 { 2321 /* Given edge whose endpoints are specified by id1 and id2, 2322 determine how many polygons share this edge and return that 2323 number minus one (since we do not want to include the polygon 2324 that the caller has already). 2325 */ 2326 2327 int size,y,count=0; 2328 PF_EDGES temp = NULL; 2329 PF_FACES temp2 = NULL; 2330 ListHead *pListHead; 2331 BOOL there= FALSE; 2332 2333 /* Always want smaller id first */ 2334 switch_lower(&id1,&id2); 2335 2336 pListHead = PolEdges[id1]; 2337 temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); 2338 if (temp == NULL) 2339 /* new edge that was created might not be here */ 2340 return 0; 2341 while (temp->edge[0] != id2) 2342 { 2343 count++; 2344 temp = ( PF_EDGES )GetNextNode(temp); 2345 2346 if (temp == NULL) 2347 /* This edge was not there in the original, which 2348 mean that we created it in the partial triangulation. 2349 So it is adjacent to nothing. 2350 */ 2351 return 0; 2352 } 2353 /* Was not adjacent to anything else except itself */ 2354 if (temp->edge[2] == -1) 2355 return 0; 2356 else 2357 { 2358 /* It was adjacent to another polygon, but maybe we did this 2359 polygon already, and it was done partially so that this edge 2360 could have been done 2361 */ 2362 if (curr_id != temp->edge[1]) 2363 { 2364 /* Did we use this polygon already?and it was deleted 2365 completely from the structure 2366 */ 2367 pListHead = PolFaces[temp->edge[1]]; 2368 temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); 2369 if (Done(temp->edge[1],&size) == NULL) 2370 return 0; 2371 } 2372 else 2373 { 2374 pListHead = PolFaces[temp->edge[2]]; 2375 temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); 2376 if (Done(temp->edge[2],&size)== NULL) 2377 return 0; 2378 } 2379 2380 /* Now we have to check whether it was partially done, before 2381 we can say definitely if it is adjacent. 2382 Check each edge of the face and tally the number of adjacent 2383 polygons to this face. 2384 */ 2385 if ( temp2 != NULL ) 2386 { 2387 /* Size of the polygon */ 2388 size = temp2->nPolSize; 2389 for (y = 0; y< size; y++) 2390 { 2391 /* If we are doing partial triangulation, we must check 2392 to see whether the edge is still there in the polygon, 2393 since we might have done a portion of the polygon 2394 and saved the rest for later. 2395 */ 2396 if (y != (size-1)) 2397 { 2398 if(((id1 == *(temp2->pPolygon+y)) && 2399 (id2 ==*(temp2->pPolygon+y+1))) || 2400 ((id2 == *(temp2->pPolygon+y)) && 2401 (id1 ==*(temp2->pPolygon+y+1)))) 2402 /* edge is still there we are ok */ 2403 there = TRUE; 2404 } 2405 else 2406 { 2407 if(((id1 == *(temp2->pPolygon)) && 2408 (id2 == *(temp2->pPolygon+size-1))) || 2409 ((id2 == *(temp2->pPolygon)) && 2410 (id1 ==*(temp2->pPolygon+size-1)))) 2411 /* edge is still there we are ok */ 2412 there = TRUE; 2413 } 2414 } 2415 } 2416 2417 if (there ) 2418 return 1; 2419 return 0; 2420 } 2421 } 2422 2423 /// Min_Adj: 2424 int CustomStripifier::Min_Adj(int id) 2425 { 2426 /* Used for the lookahead to break ties. It will 2427 return the minimum adjacency found at this face. 2428 */ 2429 int y,numverts,t,x=60; 2430 PF_FACES temp=NULL; 2431 ListHead *pListHead; 2432 2433 /* If polygon was used then we can't use this face */ 2434 if (Done(id,&y) == NULL) 2435 return 60; 2436 2437 /* It was not used already */ 2438 pListHead = PolFaces[id]; 2439 temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); 2440 if ( temp != NULL ) 2441 { 2442 numverts = temp->nPolSize; 2443 for (y = 0; y< numverts; y++) 2444 { 2445 if (y != (numverts-1)) 2446 t = Number_Adj(*(temp->pPolygon+y),*(temp->pPolygon+y+1),id); 2447 else 2448 t = Number_Adj(*(temp->pPolygon),*(temp->pPolygon+(numverts-1)),id); 2449 if (t < x) 2450 x = t; 2451 } 2452 } 2453 if (x == -1) 2454 { 2455 printf("Error in the look\n"); 2456 exit(0); 2457 } 2458 return x; 2459 } 2460 2461 /// Edje_Least: 2462 void CustomStripifier::Edge_Least(int *index,int *new1,int *new2,int face_id,int size) 2463 { 2464 /* We had a polygon without an input edge and now we re going to pick one 2465 of the edges with the least number of adjacencies to be the input 2466 edge 2467 */ 2468 register int x,value,smallest=60; 2469 2470 for (x = 0; x<size; x++) 2471 { 2472 if (x != (size -1) ) 2473 value = Number_Adj(*(index+x),*(index+x+1),face_id); 2474 else 2475 value = Number_Adj(*(index),*(index+size-1),face_id); 2476 if (value < smallest) 2477 { 2478 smallest = value; 2479 if (x != (size -1)) 2480 { 2481 *new1 = *(index+x); 2482 *new2 = *(index+x+1); 2483 } 2484 else 2485 { 2486 *new1 = *(index); 2487 *new2 = *(index+size-1); 2488 } 2489 } 2490 } 2491 if ((smallest == 60) || (smallest < 0)) 2492 { 2493 printf("There is an error in getting the least edge\n"); 2494 exit(0); 2495 } 2496 } 2497 2498 /// Check_In_Polygon: 2499 void CustomStripifier::Check_In_Polygon(int face_id, int *min, int size) 2500 { 2501 /* Check to see the adjacencies by going into a polygon that has 2502 greater than 4 sides. 2503 */ 2504 2505 ListHead *pListHead; 2506 PF_FACES temp; 2507 int y,id1,id2,id3,x=0,z=0; 2508 int saved[2]; 2509 int big_saved[60]; 2510 2511 pListHead = PolFaces[face_id]; 2512 temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); 2513 2514 /* Get the input edge that we came in on */ 2515 Last_Edge(&id1,&id2,&id3,0); 2516 2517 /* Find the number of adjacencies to the edges that are adjacent 2518 to the input edge. 2519 */ 2520 for (y=0; y< size; y++) 2521 { 2522 if (y != (size-1)) 2523 { 2524 if (((*(temp->pPolygon+y) == id2) && (*(temp->pPolygon+y+1) != id3)) 2525 || ((*(temp->pPolygon+y) == id3) && (*(temp->pPolygon+y+1) != id2))) 2526 { 2527 saved[x++] = Number_Adj(*(temp->pPolygon+y), 2528 *(temp->pPolygon+y+1),face_id); 2529 big_saved[z++] = saved[x-1]; 2530 } 2531 else 2532 big_saved[z++] = Number_Adj(*(temp->pPolygon+y), 2533 *(temp->pPolygon+y+1),face_id); 2534 } 2535 else 2536 { 2537 if (((*(temp->pPolygon) == id2) && 2538 (*(temp->pPolygon+size-1) != id3)) || 2539 ((*(temp->pPolygon) == id3) && 2540 (*(temp->pPolygon+size-1) != id2))) 2541 { 2542 saved[x++] = Number_Adj(*(temp->pPolygon), 2543 *(temp->pPolygon+size-1),face_id); 2544 big_saved[z++] = saved[x-1]; 2545 } 2546 else 2547 big_saved[z++] = Number_Adj(*(temp->pPolygon), 2548 *(temp->pPolygon+size-1),face_id); 2549 } 2550 } 2551 /* There was an input edge */ 2552 if (x == 2) 2553 { 2554 if (saved[0] < saved[1]) 2555 /* Count the polygon that we will be cutting as another adjacency*/ 2556 *min = saved[0] + 1; 2557 else 2558 *min = saved[1] + 1; 2559 } 2560 /* There was not an input edge */ 2561 else 2562 { 2563 if (z != size) 2564 { 2565 printf("There is an error with the z %d %d\n",size,z); 2566 exit(0); 2567 } 2568 *min = 60; 2569 for (x = 0; x < size; x++) 2570 { 2571 if (*min > big_saved[x]) 2572 *min = big_saved[x]; 2573 } 2574 } 2575 } 2576 2577 /// New_Face: 2578 void CustomStripifier::New_Face (int face_id, int v1, int v2, int v3) 2579 { 2580 /* We want to change the face that was face_id, we will 2581 change it to a triangle, since the rest of the polygon 2582 was already outputtted 2583 */ 2584 ListHead *pListHead; 2585 PF_FACES temp = NULL; 2586 2587 pListHead = PolFaces[face_id]; 2588 temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0); 2589 /* Check each edge of the face and tally the number of adjacent 2590 polygons to this face. 2591 */ 2592 if ( temp != NULL ) 2593 { 2594 /* Size of the polygon */ 2595 if (temp->nPolSize != 4) 2596 { 2597 printf("There is a miscalculation in the partial\n"); 2598 exit (0); 2599 } 2600 temp->nPolSize = 3; 2601 *(temp->pPolygon) = v1; 2602 *(temp->pPolygon+1) = v2; 2603 *(temp->pPolygon+2) = v3; 2604 } 2605 } 2606 2607 /// New_Size_Face: 2608 void CustomStripifier::New_Size_Face(int face_id) 2609 { 2610 /* We want to change the face that was face_id, we will 2611 change it to a triangle, since the rest of the polygon 2612 was already outputtted 2613 */ 2614 ListHead *pListHead; 2615 PF_FACES temp = NULL; 2616 2617 pListHead = PolFaces[face_id]; 2618 temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); 2619 /* Check each edge of the face and tally the number of adjacent 2620 polygons to this face. 2621 */ 2622 if ( temp != NULL ) 2623 (temp->nPolSize)--; 2624 else 2625 printf("There is an error in updating the size\n"); 2626 } 2627 2628 /// Check_In_Quad: 2629 void CustomStripifier::Check_In_Quad(int face_id,int *min) 2630 { 2631 /* Check to see what the adjacencies are for the polygons that 2632 are inside the quad, ie the 2 triangles that we can form. 2633 */ 2634 ListHead *pListHead; 2635 int y,id1,id2,id3,x=0; 2636 int saved[4]; 2637 PF_FACES temp; 2638 register int size = 4; 2639 2640 pListHead = PolFaces[face_id]; 2641 temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); 2642 2643 /* Get the input edge that we came in on */ 2644 Last_Edge(&id1,&id2,&id3,0); 2645 2646 /* Now find the adjacencies for the inside triangles */ 2647 for (y = 0; y< size; y++) 2648 { 2649 /* Will not do this if the edge is the input edge */ 2650 if (y != (size-1)) 2651 { 2652 if ((((*(temp->pPolygon+y) == id2) && 2653 (*(temp->pPolygon+y+1) == id3))) || 2654 (((*(temp->pPolygon+y) == id3) && 2655 (*(temp->pPolygon+y+1) == id2)))) 2656 saved[x++] = -1; 2657 else 2658 { 2659 if (x == 4) 2660 { 2661 printf("There is an error in the check in quad \n"); 2662 exit(0); 2663 } 2664 /* Save the number of Adjacent Polygons to this edge */ 2665 saved[x++] = Number_Adj(*(temp->pPolygon+y), 2666 *(temp->pPolygon+y+1),face_id); 2667 } 2668 } 2669 else if ((((*(temp->pPolygon) == id2) && 2670 (*(temp->pPolygon+size-1) == id3))) || 2671 (((*(temp->pPolygon) == id3) && 2672 (*(temp->pPolygon+size-1) == id2))) ) 2673 saved[x++] = -1; 2674 else 2675 { 2676 if (x == 4) 2677 { 2678 printf("There is an error in the check in quad \n"); 2679 exit(0); 2680 } 2681 /* Save the number of Adjacent Polygons to this edge */ 2682 saved[x++] = Number_Adj(*(temp->pPolygon), 2683 *(temp->pPolygon+size-1),face_id); 2684 2685 } 2686 } 2687 if (x != 4) 2688 { 2689 printf("Did not enter all the values %d \n",x); 2690 exit(0); 2691 } 2692 2693 *min = 10; 2694 for (x=0; x<4; x++) 2695 { 2696 if (x!= 3) 2697 { 2698 if ((saved[x] != -1) && (saved[x+1] != -1) && 2699 ((saved[x] + saved[x+1]) < *min)) 2700 *min = saved[x] + saved[x+1]; 2701 } 2702 else 2703 { 2704 if ((saved[0] != -1) && (saved[x] != -1) && 2705 ((saved[x] + saved[0]) < *min)) 2706 *min = saved[0] + saved[x]; 2707 } 2708 } 2709 } 2710 2711 /// Get_Output_Edge: 2712 int CustomStripifier::Get_Output_Edge(int face_id, int size, int *index,int id2,int id3) 2713 { 2714 /* Return the vertex adjacent to either input1 or input2 that 2715 is adjacent to the least number of polygons on the edge that 2716 is shared with either input1 or input2. 2717 */ 2718 register int x=0,y; 2719 int saved[2]; 2720 int edges[2][1]; 2721 2722 for (y = 0; y < size; y++) 2723 { 2724 if (y != (size-1)) 2725 { 2726 if (((*(index+y) == id2) && (*(index+y+1) != id3)) 2727 || ((*(index+y) == id3) && (*(index+y+1) != id2))) 2728 { 2729 saved[x++] = Number_Adj(*(index+y),*(index+y+1),face_id); 2730 edges[x-1][0] = *(index+y+1); 2731 } 2732 else if (y != 0) 2733 { 2734 if (( (*(index+y) == id2) && (*(index+y-1) != id3) ) || 2735 ( (*(index+y) == id3) && (*(index+y-1) != id2)) ) 2736 { 2737 saved[x++] = Number_Adj(*(index+y),*(index+y-1),face_id); 2738 edges[x-1][0] = *(index+y-1); 2739 } 2740 } 2741 else if (y == 0) 2742 { 2743 if (( (*(index) == id2) && (*(index+size-1) != id3) ) || 2744 ( (*(index) == id3) && (*(index+size-1) != id2)) ) 2745 { 2746 saved[x++] = Number_Adj(*(index),*(index+size-1),face_id); 2747 edges[x-1][0] = *(index+size-1); 2748 } 2749 } 2750 2751 } 2752 else 2753 { 2754 if (((*(index+size-1) == id2) && (*(index) != id3)) 2755 || ((*(index+size-1) == id3) && (*(index) != id2))) 2756 { 2757 saved[x++] = Number_Adj(*(index),*(index+size-1),face_id); 2758 edges[x-1][0] = *(index); 2759 } 2760 2761 if (( (*(index+size-1) == id2) && (*(index+y-1) != id3) ) || 2762 ( (*(index+size-1) == id3) && (*(index+y-1) != id2)) ) 2763 { 2764 saved[x++] = Number_Adj(*(index+size-1),*(index+y-1),face_id); 2765 edges[x-1][0] = *(index+y-1); 2766 } 2767 } 2768 } 2769 if ((x != 2)) 2770 { 2771 printf("There is an error in getting the input edge %d \n",x); 2772 exit(0); 2773 } 2774 if (saved[0] < saved[1]) 2775 return edges[0][0]; 2776 else 2777 return edges[1][0]; 2778 2779 } 2780 2781 /// Get_Input_Edge: 2782 void CustomStripifier::Get_Input_Edge(int *index,int id1,int id2,int id3, 2783 int *new1,int *new2,int size,int face_id) 2784 { 2785 /* We had a polygon without an input edge and now we are going to pick one 2786 as the input edge. The last triangle was id1,id2,id3, we will try to 2787 get an edge to have something in common with one of those vertices, 2788 otherwise we will pick the edge with the least number of adjacencies. 2789 */ 2790 2791 register int x; 2792 int saved[3]; 2793 2794 saved[0] = -1; 2795 saved[1] = -1; 2796 saved[2] = -1; 2797 2798 /* Go through the edges to see if there is one in common with one 2799 of the vertices of the last triangle that we had, preferably id2 or 2800 id3 since those are the last 2 things in the stack of size 2. 2801 */ 2802 for (x=0; x< size; x++) 2803 { 2804 if (*(index+x) == id1) 2805 { 2806 if (x != (size-1)) 2807 saved[0] = *(index+x+1); 2808 else 2809 saved[0] = *(index); 2810 } 2811 2812 if (*(index+x) == id2) 2813 { 2814 if (x != (size-1)) 2815 saved[1] = *(index+x+1); 2816 else 2817 saved[1] = *(index); 2818 } 2819 2820 if (*(index+x) == id3) 2821 { 2822 if (x != (size -1)) 2823 saved[2] = *(index+x+1); 2824 else 2825 saved[2] = *(index); 2826 } 2827 } 2828 /* Now see what we saved */ 2829 if (saved[2] != -1) 2830 { 2831 *new1 = id3; 2832 *new2 = saved[2]; 2833 return; 2834 } 2835 else if (saved[1] != -1) 2836 { 2837 *new1 = id2; 2838 *new2 = saved[1]; 2839 return; 2840 } 2841 else if (saved[0] != -1) 2842 { 2843 *new1 = id1; 2844 *new2 = saved[0]; 2845 return; 2846 } 2847 /* We did not find anything so get the edge with the 2848 least number of adjacencies 2849 */ 2850 Edge_Least(index,new1,new2,face_id,size); 2851 2852 } 2853 2854 /// Find_Face: 2855 int CustomStripifier::Find_Face(int current_face, int id1, int id2, int *bucket) 2856 { 2857 /* Find the face that is adjacent to the edge and is not the 2858 current face. 2859 */ 2860 register int size,y,count=0; 2861 PF_EDGES temp = NULL; 2862 PF_FACES temp2 = NULL; 2863 ListHead *pListHead; 2864 int next_face; 2865 BOOL there = FALSE; 2866 2867 2868 /* Always want smaller id first */ 2869 switch_lower(&id1,&id2); 2870 2871 pListHead = PolEdges[id1]; 2872 temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); 2873 /* The input edge was a new edge */ 2874 if (temp == NULL) 2875 return -1; 2876 2877 while (temp->edge[0] != id2) 2878 { 2879 count++; 2880 temp = ( PF_EDGES )GetNextNode(temp); 2881 2882 /* The input edge was a new edge */ 2883 if (temp == NULL) 2884 return -1; 2885 } 2886 /* Was not adjacent to anything else except itself */ 2887 if (temp->edge[2] == -1) 2888 return -1; 2889 else 2890 { 2891 if (temp->edge[2] == current_face) 2892 next_face = temp->edge[1]; 2893 else 2894 next_face = temp->edge[2]; 2895 } 2896 /* We have the other face adjacent to this edge, it is 2897 next_face. 2898 */ 2899 pListHead = PolFaces[next_face]; 2900 temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); 2901 2902 /* See if the face was already deleted, and where 2903 it is if it was not 2904 */ 2905 2906 if (Done(next_face,bucket) == NULL) 2907 return -1; 2908 2909 /* Make sure the edge is still in this polygon, and that it is not 2910 done 2911 */ 2912 /* Size of the polygon */ 2913 size = temp2->nPolSize; 2914 for (y = 0; y< size; y++) 2915 { 2916 /* Make sure that the edge is still in the 2917 polygon and was not deleted, because if the edge was 2918 deleted, then we used it already. 2919 */ 2920 if (y != (size-1)) 2921 { 2922 if( ((id1 == *(temp2->pPolygon+y)) && (id2 ==*(temp2->pPolygon+y+1))) 2923 || ((id2 == *(temp2->pPolygon+y)) && (id1 ==*(temp2->pPolygon+y+1)))) 2924 /* edge is still there we are ok */ 2925 there = TRUE; 2926 } 2927 else 2928 { 2929 if(((id1 == *(temp2->pPolygon)) && (id2 ==*(temp2->pPolygon+size-1))) || 2930 ((id2 == *(temp2->pPolygon)) && (id1 ==*(temp2->pPolygon+size-1)))) 2931 /* edge is still there we are ok */ 2932 there = TRUE; 2933 } 2934 } 2935 2936 if (!there) 2937 /* Edge already used and deleted from the polygon*/ 2938 return -1; 2939 else 2940 return next_face; 2941 } 2942 2943 /// Look_Up: 2944 BOOL CustomStripifier::Look_Up(int id1,int id2,int face_id) 2945 { 2946 /* See if the endpoints of the edge specified by id1 and id2 2947 are adjacent to the face with face_id 2948 */ 2949 register int count = 0; 2950 PF_EDGES temp = NULL; 2951 ListHead *pListHead; 2952 2953 /* Always want smaller id first */ 2954 switch_lower(&id1,&id2); 2955 2956 pListHead = PolEdges[id1]; 2957 temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); 2958 if (temp == NULL) 2959 /* Was a new edge that we created */ 2960 return 0; 2961 2962 while (temp->edge[0] != id2) 2963 { 2964 count++; 2965 temp = ( PF_EDGES )GetNextNode(temp); 2966 2967 if (temp == NULL) 2968 /* Was a new edge that we created */ 2969 return 0; 2970 } 2971 /* Was not adjacent to anything else except itself */ 2972 if ((temp->edge[2] == face_id) || (temp->edge[1] == face_id)) 2973 { 2974 /* Edge was adjacent to face, make sure that edge is 2975 still there 2976 */ 2977 if (Exist(face_id,id1,id2)) 2978 return 1; 2979 else 2980 return 0; 2981 } 2982 else 2983 return 0; 2984 } 2985 2986 /// Add_Id_Strips: 2987 void CustomStripifier::Add_Id_Strips(int id, int where) 2988 { 2989 /* Just save the triangle for later */ 2990 P_STRIPS pfNode; 2991 2992 pfNode = (P_STRIPS) malloc(sizeof(Strips) ); 2993 if ( pfNode ) 2994 { 2995 pfNode->face_id = id; 2996 if (where == 1) 2997 AddTail(strips[0],(PLISTINFO) pfNode); 2998 /* We are backtracking in the strip */ 2999 else 3000 AddHead(strips[0],(PLISTINFO) pfNode); 3001 } 3002 else 3003 { 3004 printf("There is not enough memory to allocate for the strips\n"); 3005 exit(0); 3006 } 3007 } 3008 3009 /// Num_Adj: 3010 int CustomStripifier::Num_Adj(int id1, int id2) 3011 { 3012 /* Given edge whose endpoints are specified by id1 and id2, 3013 determine how many polygons share this edge and return that 3014 number minus one (since we do not want to include the polygon 3015 that the caller has already). 3016 */ 3017 3018 PF_EDGES temp = NULL; 3019 ListHead *pListHead; 3020 register count=-1; 3021 3022 /* Always want smaller id first */ 3023 switch_lower(&id1,&id2); 3024 3025 pListHead = PolEdges[id1]; 3026 temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); 3027 if (temp == NULL) 3028 { 3029 printf("There is an error in the creation of the table \n"); 3030 exit(0); 3031 } 3032 while (temp->edge[0] != id2) 3033 { 3034 count++; 3035 temp = ( PF_EDGES )GetNextNode(temp); 3036 3037 if (temp == NULL) 3038 { 3039 printf("There is an error in the creation of the table\n"); 3040 exit(0); 3041 } 3042 } 3043 /* Was not adjacent to anything else except itself */ 3044 if (temp->edge[2] == -1) 3045 return 0; 3046 return 1; 3047 } 3048 3049 /// Add_Sgi_Adj: 3050 void CustomStripifier::Add_Sgi_Adj(int bucket,int face_id) 3051 { 3052 /* This routine will add the face to the proper bucket, 3053 depending on how many faces are adjacent to it (what the 3054 value bucket should be). 3055 */ 3056 P_ADJACENCIES pfNode; 3057 3058 pfNode = (P_ADJACENCIES) malloc(sizeof(ADJACENCIES) ); 3059 if ( pfNode ) 3060 { 3061 pfNode->face_id = face_id; 3062 AddHead(array[bucket],(PLISTINFO) pfNode); 3063 face_array[face_id].bucket = bucket; 3064 face_array[face_id].pfNode = pfNode; 3065 face_array[face_id].head = array[bucket]; 3066 } 3067 else 3068 { 3069 printf("Out of memory for the SGI adj list!\n"); 3070 exit(0); 3071 } 3072 } 3073 3074 /// Find_Adjacencies: 3075 void CustomStripifier::Find_Adjacencies(int num_faces) 3076 { 3077 register int x,y; 3078 register int numverts; 3079 PF_FACES temp =NULL; 3080 ListHead* pListHead; 3081 3082 /* Fill in the adjacencies data structure for all the faces */ 3083 for (x=0;x<num_faces;x++) 3084 { 3085 pListHead = PolFaces[x]; 3086 temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); 3087 if ( temp != NULL ) 3088 { 3089 numverts = temp->nPolSize; 3090 if (numverts != 1) 3091 { 3092 for (y = 0; y< numverts; y++) 3093 { 3094 if (y != (numverts-1)) 3095 Add_AdjEdge(*(temp->pPolygon+y), 3096 *(temp->pPolygon+y+1),x,y); 3097 3098 else 3099 Add_AdjEdge(*(temp->pPolygon), 3100 *(temp->pPolygon+(numverts-1)),x,numverts-1); 3101 3102 } 3103 } 3104 temp = NULL; 3105 } 3106 } 3107 } 3108 3109 /// Clear_Ties: 3110 void CustomStripifier::Clear_Ties() 3111 { 3112 /* Clear the buffer, because we do not have the tie 3113 any more that we had before */ 3114 last = 0; 3115 } 3116 3117 /// Add_Ties: 3118 void CustomStripifier::Add_Ties(int id) 3119 { 3120 /* We have a tie to add to the buffer */ 3121 ties_array[last++] = id; 3122 } 3123 3124 /// Alternate_Tie: 3125 int CustomStripifier::Alternate_Tie() 3126 { 3127 /* Alternate in what we choose to break the tie 3128 We are just alternating between the first and 3129 second thing that we found 3130 */ 3131 static int x = 0; 3132 register int t; 3133 3134 t = ties_array[x]; 3135 x++; 3136 if (x == 2) 3137 x = 0; 3138 return t; 3139 } 3140 3141 /// Random_Tie: 3142 int CustomStripifier::Random_Tie() 3143 { 3144 /* Randomly choose the next face with which 3145 to break the tie 3146 */ 3147 register int num; 3148 3149 num = rand(); 3150 while (num >= last) 3151 num = num/20; 3152 return (ties_array[num]); 3153 } 3154 3155 /// Look_Ahead: 3156 int CustomStripifier::Look_Ahead(int id) 3157 { 3158 /* Look ahead at this face and save the minimum 3159 adjacency of all the faces that are adjacent to 3160 this face. 3161 */ 3162 return Min_Adj(id); 3163 } 3164 3165 /// Random_Look: 3166 int CustomStripifier::Random_Look(int id[],int count) 3167 { 3168 /* We had a tie within a tie in the lookahead, 3169 break it randomly 3170 */ 3171 register int num; 3172 3173 num = rand(); 3174 while (num >= count) 3175 num = num/20; 3176 return (id[num]); 3177 } 3178 3179 /// Look_Ahead_Tie: 3180 int CustomStripifier::Look_Ahead_Tie() 3181 { 3182 /* Look ahead and find the face to go to that 3183 will give the least number of adjacencies 3184 */ 3185 int id[60],t,x,f=0,min = 60; 3186 3187 for (x = 0; x < last; x++) 3188 { 3189 t = Look_Ahead(ties_array[x]); 3190 /* We have a tie */ 3191 if (t == min) 3192 id[f++] = ties_array[x]; 3193 if (t < min) 3194 { 3195 f = 0; 3196 min = t; 3197 id[f++] = ties_array[x]; 3198 } 3199 } 3200 /* No tie within the tie */ 3201 if ( f == 1) 3202 return id[0]; 3203 /* Or ties, but we are at the end of strips */ 3204 if (min == 0) 3205 return id[0]; 3206 return (Random_Look(id,f)); 3207 } 3208 3209 /// Sequential_Tri: 3210 int CustomStripifier::Sequential_Tri(int *index) 3211 { 3212 /* We have a triangle and need to break the ties at it. 3213 We will choose the edge that is sequential. There 3214 is definitely one since we know we have a triangle 3215 and that there is a tie and there are only 2 edges 3216 for the tie. 3217 */ 3218 int reversed,e1,e2,e3,output1,output2,output3,output4; 3219 3220 /* e2 and e3 are the input edge to the triangle */ 3221 Last_Edge(&e1,&e2,&e3,0); 3222 3223 if ((e2 == 0) && (e3 == 0)) 3224 /* Starting the strip, don't need to do this */ 3225 return ties_array[0]; 3226 3227 /* For the 2 ties find the edge adjacent to face id */ 3228 reversed = Get_EdgeEx(&output1,&output2,index,ties_array[0],3,0,0); 3229 reversed = Get_EdgeEx(&output3,&output4,index,ties_array[1],3,0,0); 3230 3231 if ((output1 == e3) || (output2 == e3)) 3232 return ties_array[0]; 3233 if ((output3 == e3) || (output4 == e3)) 3234 return ties_array[1]; 3235 printf("There is an error trying to break sequential triangle \n"); 3236 } 3237 3238 /// Sequential_Quad: 3239 int CustomStripifier::Sequential_Quad(int *index, int triangulate) 3240 { 3241 /* We have a quad that need to break its ties, we will try 3242 and choose a side that is sequential, otherwise use lookahead 3243 */ 3244 int reversed,output1,output2,x,e1,e2,e3; 3245 3246 /* e2 and e3 are the input edge to the quad */ 3247 Last_Edge(&e1,&e2,&e3,0); 3248 3249 /* No input edge */ 3250 if ((e2 == 0) && (e3 == 0)) 3251 return ties_array[0]; 3252 3253 /* Go through the ties and see if there is a sequential one */ 3254 for (x = 0; x < last; x++) 3255 { 3256 reversed = Get_EdgeEx(&output1,&output2,index,ties_array[x],4,0,0); 3257 /* Partial and whole triangulation will have different requirements */ 3258 if (((output1 == e3) || (output2 == e3)) && (triangulate == PARTIAL)) 3259 return ties_array[x]; 3260 if (((output1 != e3) && (output1 != e2) && 3261 (output2 != e3) && (output2 != e2))) 3262 return ties_array[x]; 3263 } 3264 /* There was not a tie that was sequential */ 3265 return Look_Ahead_Tie(); 3266 } 3267 3268 /// Whole_Output: 3269 void CustomStripifier::Whole_Output(int in1, int *index, int size, int *out1, int *out2) 3270 { 3271 /* Used to sequentially break ties in the whole triangulation for polygons 3272 greater than 4 sides. We will find the output edge that is good 3273 for sequential triangulation. 3274 */ 3275 3276 int half; 3277 3278 /* Put the input edge first in the list */ 3279 Rearrange_IndexEx(index,size); 3280 3281 if (!(EVEN(size))) 3282 { 3283 if (*(index) == in1) 3284 half = size/2 ; 3285 else 3286 half = size/2 +1; 3287 } 3288 else 3289 half = size/2; 3290 3291 *out1 = *(index+half); 3292 *out2 = *(index+half+1); 3293 } 3294 3295 /// Sequential_Poly: 3296 int CustomStripifier::Sequential_Poly(int size, int *index, int triangulate) 3297 { 3298 /* We have a polygon of greater than 4 sides and wish to break the 3299 tie in the most sequential manner. 3300 */ 3301 3302 int x,reversed,output1,output2,e1,e2,e3,saved1=-1,saved2=-1,output3,output4; 3303 3304 /* e2 and e3 are the input edge to the quad */ 3305 Last_Edge(&e1,&e2,&e3,0); 3306 3307 /* If we are using whole, find the output edge that is sequential */ 3308 if (triangulate == WHOLE) 3309 Whole_Output(e2,index,size,&output3,&output4); 3310 3311 /* No input edge */ 3312 if ((e2 == 0) && (e3 == 0)) 3313 return ties_array[0]; 3314 3315 for (x = 0; x < last ; x++) 3316 { 3317 reversed = Get_EdgeEx(&output1,&output2,index,ties_array[x],size,0,0); 3318 /* Partial that can be removed in just one triangle */ 3319 if (((output1 == e3) || (output2 == e3)) && (triangulate == PARTIAL)) 3320 saved1 = ties_array[x]; 3321 /* Partial removed in more than one triangle */ 3322 if ((output1 != e3) && (output1 != e2) && 3323 (output2 != e3) && (output2 != e2) && 3324 (triangulate == PARTIAL) && (saved2 != -1)) 3325 saved2 = ties_array[x]; 3326 /* Whole is not so easy, since the whole polygon must be done. Given 3327 an input edge there is only one way to come out, approximately half 3328 way around the polygon. 3329 */ 3330 if (((output1 == output3) && (output2 == output4)) || 3331 ((output1 == output4) && (output2 == output3)) && 3332 (triangulate == WHOLE)) 3333 return ties_array[x]; 3334 } 3335 3336 if (saved1 != -1) 3337 return saved1; 3338 if (saved2 != -1) 3339 return saved2; 3340 3341 /* There was not a tie that was sequential */ 3342 return Look_Ahead_Tie(); 3343 } 3344 3345 /// Sequential_Tie: 3346 int CustomStripifier::Sequential_Tie(int face_id,int triangulate) 3347 { 3348 /* Break the tie by choosing the face that will 3349 not give us a swap and is sequential. If there 3350 is not one, then do the lookahead to break the 3351 tie. 3352 */ 3353 /* Separate into 3 cases for simplicity, if the current 3354 polygon has 3 sides, 4 sides or if the sides were 3355 greater. We can do the smaller cases faster, so that 3356 is why I separated the cases. 3357 */ 3358 3359 ListHead *pListFace; 3360 PF_FACES face; 3361 3362 /* Get the polygon with id face_id */ 3363 pListFace = PolFaces[face_id]; 3364 face = (PF_FACES) PeekList(pListFace,LISTHEAD,0); 3365 3366 if (face->nPolSize == 3) 3367 return(Sequential_Tri(face->pPolygon)); 3368 if (face->nPolSize == 4) 3369 return(Sequential_Quad(face->pPolygon,triangulate)); 3370 else 3371 return(Sequential_Poly(face->nPolSize,face->pPolygon,triangulate)); 3372 3373 } 3374 3375 /// Get_Next_Face: 3376 int CustomStripifier::Get_Next_Face(int t, int face_id, int triangulate) 3377 { 3378 /* Get the next face depending on what 3379 the user specified 3380 */ 3381 3382 /* Did not have a tie, don't do anything */ 3383 if (last == 1) 3384 return(ties_array[0]); 3385 if (t == RANDOM) 3386 return Random_Tie(); 3387 if (t == ALTERNA) 3388 return Alternate_Tie(); 3389 if (t == LOOK) 3390 return Look_Ahead_Tie(); 3391 if (t == SEQUENTIAL) 3392 return Sequential_Tie(face_id,triangulate); 3393 3394 printf("Illegal option specified for ties, using first \n"); 3395 return (ties_array[0]); 3396 } 3397 3398 /// new_vertex: 3399 BOOL CustomStripifier::new_vertex(double difference, int id1,int id2, 3400 struct vert_struct *n) 3401 { 3402 /* Is the difference between id1 and id2 (2 normal vertices that 3403 mapped to the same vertex) greater than the 3404 threshold that was specified? 3405 */ 3406 struct vert_struct *pn1,*pn2; 3407 double dot_product; 3408 double distance1, distance2,distance; 3409 double rad; 3410 char arg1[100]; 3411 char arg2[100]; 3412 3413 pn1 = n + id1; 3414 pn2 = n + id2; 3415 3416 dot_product = ((pn1->x) * (pn2->x)) + 3417 ((pn1->y) * (pn2->y)) + 3418 ((pn1->z) * (pn2->z)); 3419 /* Get the absolute value */ 3420 if (dot_product < 0) 3421 dot_product = dot_product * -1; 3422 3423 distance1 = sqrt( (pn1->x * pn1->x) + 3424 (pn1->y * pn1->y) + 3425 (pn1->z * pn1->z) ); 3426 distance2 = sqrt( (pn2->x * pn2->x) + 3427 (pn2->y * pn2->y) + 3428 (pn2->z * pn2->z) ); 3429 distance = distance1 * distance2; 3430 3431 rad = acos((double)dot_product/(double)distance); 3432 /* convert to degrees */ 3433 rad = (180 * rad)/GEO_PI; 3434 3435 if ( rad <= difference) 3436 return FALSE; 3437 3438 /* double checking because of imprecision with floating 3439 point acos function 3440 */ 3441 sprintf( arg1,"%.5f", rad ); 3442 sprintf( arg2,"%.5f", difference ); 3443 if ( strcmp( arg1, arg2 ) <=0 ) 3444 return( FALSE ); 3445 if ( rad <= difference) 3446 return FALSE; 3447 else 3448 return TRUE; 3449 } 3450 3451 /// Check_VN: 3452 BOOL CustomStripifier::Check_VN(int vertex,int normal, struct vert_added *added) 3453 { 3454 /* Check to see if we already added this vertex and normal */ 3455 register int x,n; 3456 3457 n = (added+vertex)->num; 3458 for (x = 0; x < n; x++) 3459 { 3460 if (*((added+vertex)->normal+x) == normal) 3461 return TRUE; 3462 } 3463 return FALSE; 3464 } 3465 3466 /// norm_array: 3467 BOOL CustomStripifier::norm_array(int id, int vertex, double normal_difference, 3468 struct vert_struct *n, int num_vert) 3469 { 3470 static int last; 3471 static struct vert_added *added; 3472 register int x; 3473 static BOOL first = TRUE; 3474 3475 if (first) 3476 { 3477 /* This is the first time that we are in here, so we will allocate 3478 a structure that will save the vertices that we added, so that we 3479 do not add the same thing twice 3480 */ 3481 first = FALSE; 3482 added = (struct vert_added *) malloc (sizeof (struct vert_added ) * num_vert); 3483 /* The number of vertices added for each vertex must be initialized to 3484 zero 3485 */ 3486 for (x = 0; x < num_vert; x++) 3487 (added+x)->num = 0; 3488 } 3489 3490 if (vertex) 3491 /* Set the pointer to the vertex, we will be calling again with the 3492 normal to fill it with 3493 */ 3494 last = id; 3495 else 3496 { 3497 /* Fill the pointer with the id of the normal */ 3498 if (*(vert_norms + last) == 0) 3499 *(vert_norms + last) = id; 3500 else if ((*(vert_norms + last) != id) && ((int)normal_difference != 360)) 3501 { 3502 /* difference is big enough, we need to create a new vertex */ 3503 if (new_vertex(normal_difference,id,*(vert_norms + last),n)) 3504 { 3505 /* First check to see if we added this vertex and normal already */ 3506 if (Check_VN(last,id,added)) 3507 return FALSE; 3508 /* OK, create the new vertex, and have its id = the number of 3509 vertices and its normal what we have here 3510 */ 3511 vert_norms = (int *)realloc(vert_norms, sizeof(int) * (num_vert + 1)); 3512 if (!vert_norms) 3513 { 3514 printf("Allocation error - aborting\n"); 3515 exit(1); 3516 } 3517 *(vert_norms + num_vert) = id; 3518 /* We created a new vertex, now put it in our added structure so 3519 we do not add the same thing twice 3520 */ 3521 (added+last)->num = (added+last)->num + 1; 3522 if ((added+last)->num == 1) 3523 { 3524 /* First time */ 3525 (added+last)->normal = (int *) malloc (sizeof (int ) * 1); 3526 *((added+last)->normal) = id; 3527 } 3528 else 3529 { 3530 /* Not the first time, reallocate space */ 3531 (added+last)->normal = (int *)realloc((added+last)->normal, sizeof(int) * (added+last)->num); 3532 *((added+last)->normal+((added+last)->num-1)) = id; 3533 } 3534 return TRUE; 3535 } 3536 } 3537 } 3538 return FALSE; 3539 } 3540 3541 /// add_texture: 3542 void CustomStripifier::add_texture(int id,BOOL vertex) 3543 { 3544 /* Save the texture with its vertex for future use when outputting */ 3545 static int last; 3546 3547 if (vertex) 3548 last = id; 3549 else 3550 *(vert_texture+last) = id; 3551 } 3552 3553 /// add_vert_id: 3554 int CustomStripifier::add_vert_id(int id, int index_count) 3555 { 3556 register int x; 3557 3558 // Test if degenerate, if so do not add degenerate vertex 3559 for (x = 1; x < index_count ; x++) 3560 { 3561 if (ids[x] == id) 3562 return 0; 3563 } 3564 ids[index_count] = id; 3565 3566 return 1; 3567 } 3568 3569 /// add_norm_id: 3570 void CustomStripifier::add_norm_id(int id, int index_count) 3571 { 3572 norms[index_count] = id; 3573 } 3574 3575 /// AddNewFace: 3576 void CustomStripifier::AddNewFace(int ids[MAX1], int vert_count, int face_id, int norms[MAX1]) 3577 { 3578 PF_FACES pfNode; 3579 PF_VERTICES pfVertNode; 3580 int *pTempInt; 3581 int *pnorms; 3582 F_EDGES **pTempVertptr; 3583 int *pTempmarked; 3584 int *pTempwalked; 3585 register int y; 3586 register int count = 0; 3587 3588 // Add a new face into our face data structure 3589 pfNode = (PF_FACES) malloc(sizeof(F_FACES)); 3590 3591 if (pfNode) 3592 { 3593 pfNode->pPolygon = (int*) malloc(sizeof(int) * (vert_count) ); 3594 pfNode->pNorms = (int*) malloc(sizeof(int) * (vert_count) ); 3595 3596 pfNode->VertandId = (F_EDGES**)malloc(sizeof(F_EDGES*) 3597 * 3598 (vert_count)); 3599 3600 pfNode->marked = (int*)malloc(sizeof(int) * (vert_count)); 3601 pfNode->walked = (int*)malloc(sizeof(int) * (vert_count)); 3602 } 3603 3604 pTempInt = pfNode->pPolygon; 3605 pnorms = pfNode->pNorms; 3606 pTempmarked = pfNode->marked; 3607 pTempwalked = pfNode->walked; 3608 pTempVertptr = pfNode->VertandId; 3609 pfNode->nPolSize = vert_count; 3610 pfNode->nOrgSize = vert_count; 3611 pfNode->seen = -1; 3612 pfNode->seen2 = -1; 3613 3614 for (y = 1; y <= vert_count; y++) 3615 { 3616 *(pTempInt + count) = ids[y]; 3617 *(pnorms + count) = norms[y]; 3618 *(pTempmarked + count) = FALSE; 3619 *(pTempwalked + count) = -1; 3620 *(pTempVertptr+count) = NULL; 3621 3622 count++; 3623 3624 /* Add this FaceNode to the Vertices Structure */ 3625 pfVertNode = (PF_VERTICES) malloc(sizeof(F_VERTICES)); 3626 pfVertNode->face = pfNode; 3627 3628 AddHead(Vertices[ids[y]],(PLISTINFO) pfVertNode); 3629 } 3630 3631 AddHead(PolFaces[face_id-1],(PLISTINFO) pfNode); 3632 3633 } 3634 3635 /// CopyFace: 3636 void CustomStripifier::CopyFace(int ids[MAX1], int vert_count, int face_id, int norms[MAX1]) 3637 { 3638 PF_FACES pfNode; 3639 int *pTempInt; 3640 int *pnorms; 3641 F_EDGES **pTempVertptr; 3642 int *pTempmarked; 3643 int *pTempwalked; 3644 register int y; 3645 register int count = 0; 3646 3647 /* Copy a face node into a new node, used after the global algorithm 3648 is run, so that we can save whatever is left into a new structure 3649 */ 3650 3651 pfNode = (PF_FACES) malloc(sizeof(F_FACES)); 3652 3653 if ( pfNode ) 3654 { 3655 pfNode->pPolygon = (int*) malloc( sizeof(int) 3656 * 3657 (vert_count)); 3658 3659 pfNode->pNorms = (int*) malloc( sizeof(int) 3660 * 3661 (vert_count)); 3662 3663 pfNode->VertandId = (F_EDGES**) malloc( sizeof(F_EDGES*) 3664 * 3665 (vert_count)); 3666 3667 pfNode->marked = (int*)malloc(sizeof(int) * (vert_count)); 3668 pfNode->walked = (int*)malloc(sizeof(int) * (vert_count)); 3669 } 3670 3671 pTempInt = pfNode->pPolygon; 3672 pnorms = pfNode->pNorms; 3673 pTempmarked = pfNode->marked; 3674 pTempwalked = pfNode->walked; 3675 pTempVertptr = pfNode->VertandId; 3676 pfNode->nPolSize = vert_count; 3677 pfNode->nOrgSize = vert_count; 3678 pfNode->seen = -1; 3679 pfNode->seen2 = -1; 3680 3681 for (y = 0; y < vert_count; y++) 3682 { 3683 *(pTempInt + count) = ids[y]; 3684 *(pnorms + count) = norms[y]; 3685 *(pTempmarked + count) = FALSE; 3686 *(pTempwalked + count) = -1; 3687 *(pTempVertptr+count) = NULL; 3688 3689 count++; 3690 } 3691 3692 AddHead(PolFaces[face_id-1],(PLISTINFO) pfNode); 3693 } 3694 3695 /// Add_AdjEdge: 3696 void CustomStripifier::Add_AdjEdge(int v1,int v2,int fnum,int index1 ) 3697 { 3698 PF_EDGES temp = NULL; 3699 PF_FACES temp2 = NULL; 3700 PF_EDGES pfNode; 3701 ListHead *pListHead; 3702 ListHead *pListFace; 3703 BOOL flag = TRUE; 3704 register int count = 0; 3705 register int t; 3706 register int v3 = -1; 3707 3708 if (v1 > v2) 3709 { 3710 t = v1; 3711 v1 = v2; 3712 v2 = t; 3713 } 3714 3715 pListFace = PolFaces[fnum]; 3716 temp2 = (PF_FACES) PeekList(pListFace,LISTHEAD,0); 3717 pListHead = PolEdges[v1]; 3718 temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); 3719 3720 if (temp == NULL) 3721 { 3722 flag = FALSE; 3723 } 3724 3725 count++; 3726 3727 while (flag) 3728 { 3729 if (v2 == temp->edge[0]) 3730 { 3731 /* If greater than 2 polygons adjacent to an edge, 3732 then we will only save the first 2 that we found. 3733 We will have a small performance hit, 3734 but this does not happen often. 3735 */ 3736 if (temp->edge[2] == -1) 3737 { 3738 temp->edge[2] = fnum; 3739 } 3740 else 3741 { 3742 v3 = temp->edge[2]; 3743 3744 // More than 3 edges are adjacent. 3745 // The mesh is not Manifold. 3746 mError = 1; 3747 } 3748 3749 flag = FALSE; 3750 } 3751 else 3752 { 3753 temp = ( PF_EDGES ) GetNextNode(temp); 3754 3755 count++; 3756 3757 if (temp == NULL) 3758 { 3759 flag = FALSE; 3760 } 3761 } 3762 } 3763 3764 /* Did not find it */ 3765 if (temp == NULL) 3766 { 3767 pfNode = (PF_EDGES) malloc(sizeof(F_EDGES)); 3768 3769 if (pfNode) 3770 { 3771 pfNode->edge[0] = v2; 3772 pfNode->edge[1] = fnum; 3773 pfNode->edge[2] = v3; 3774 3775 AddTail(PolEdges[v1], (PLISTINFO) pfNode); 3776 } 3777 else 3778 { 3779 printf("Out of memory!\n"); 3780 exit(1); 3781 } 3782 3783 *(temp2->VertandId+index1) = pfNode; 3784 } 3785 else 3786 { 3787 *(temp2->VertandId+index1) = temp; 3788 } 3789 } 3790 3791 /// power_10: 3792 int CustomStripifier::power_10(int power) 3793 { 3794 /* Raise 10 to the power */ 3795 register int i,p; 3796 3797 p = 1; 3798 for (i = 1; i <= power; ++i) 3799 p = p * 10; 3800 return p; 3801 } 3802 3803 /// power_negative: 3804 float CustomStripifier::power_negative(int power) 3805 { 3806 /* Raise 10 to the negative power */ 3807 3808 register int i; 3809 float p; 3810 3811 p = (float)1; 3812 for (i = 1; i<=power; i++) 3813 p = p * (float).1; 3814 return p; 3815 } 3816 3817 /// convert_array: 3818 float CustomStripifier::convert_array(int num[],int stack_size) 3819 { 3820 /* Convert an array of characters to an integer */ 3821 3822 register int counter,c; 3823 float temp =(float)0.0; 3824 3825 for (c=(stack_size-1), counter = 0; c>=0; c--, counter++) 3826 { 3827 if (num[c] == -1) 3828 /* We are at the decimal point, convert to decimal 3829 less than 1 3830 */ 3831 { 3832 counter = -1; 3833 temp = power_negative(stack_size - c - 1) * temp; 3834 } 3835 else 3836 temp += power_10(counter) * num[c]; 3837 } 3838 3839 return(temp); 3840 } 3841 3842 /// print_usage: 3843 void CustomStripifier::print_usage(void) 3844 { 3845 printf("Usage: stripe [abfglopqrw] file_name\n"); 3846 printf("Options:\n"); 3847 printf(" -b\tSpecifies that the input file is in binary\n"); 3848 printf(" -g\tFind triangle strips only within the groups specified in the data file\n"); 3849 printf(" -o\tTurn off orientation checking\n\n"); 3850 3851 printf("Tie Breaking:\n"); 3852 printf(" -a\tAlternate left-right direction in choosing next polygon\n"); 3853 printf(" -f\tChoose the first polygon that it found\n"); 3854 printf(" -l\tLook ahead one level in choosing the next polygon\n"); 3855 printf(" -q\tChoose the polygon which does not produce a swap\n"); 3856 printf(" -r\tRandomly choose the next polygon\n\n"); 3857 3858 printf("Triangulation:\n"); 3859 printf(" -p\tPartially triangulate faces\n"); 3860 printf(" -w\tFully triangluate faces\n"); 3861 } 3862 3863 /// get_options: 3864 float CustomStripifier::get_options(int argc, 3865 char **argv, 3866 int *f, 3867 int *t, 3868 int *tr, 3869 int *group, 3870 int *orientation) 3871 { 3872 char c; 3873 int count = 0; 3874 int buffer[MAX1]; 3875 int next = 0; 3876 /* tie variable */ 3877 enum tie_options tie = FIRST; 3878 /* triangulation variable */ 3879 enum triangulation_options triangulate = WHOLE; 3880 /* normal difference variable (in degrees) */ 3881 float norm_difference = (float)360.0; 3882 /* file-type variable */ 3883 enum file_options file_type = ASCII; 3884 3885 *orientation = 1; 3886 3887 /* User has the wrong number of options */ 3888 if ((argc > 6) || (argc < 2)) 3889 { 3890 print_usage(); 3891 exit(0); 3892 } 3893 3894 /* Interpret the options specified */ 3895 while (--argc > 0 && (*++argv)[0] == '-') 3896 { 3897 /* At the next option that was specified */ 3898 next = 1; 3899 while ((c = *++argv[0])) 3900 switch (c) 3901 { 3902 case 'f': 3903 /* Use the first polygon we see. */ 3904 tie = FIRST; 3905 break; 3906 3907 case 'r': 3908 /* Randomly choose the next polygon */ 3909 tie = RANDOM; 3910 break; 3911 3912 case 'a': 3913 /* Alternate direction in choosing the next polygon */ 3914 tie = ALTERNA; 3915 break; 3916 3917 case 'l': 3918 /* Use lookahead to choose the next polygon */ 3919 tie = LOOK; 3920 break; 3921 3922 case 'q': 3923 /* Try to reduce swaps */ 3924 tie = SEQUENTIAL; 3925 break; 3926 3927 case 'p': 3928 /* Use partial triangulation of polygons */ 3929 triangulate = PARTIAL; 3930 break; 3931 3932 case 'w': 3933 /* Use whole triangulation of polygons */ 3934 triangulate = WHOLE; 3935 break; 3936 3937 case 'b': 3938 /* Input file is in binary */ 3939 file_type = BINARY; 3940 break; 3941 3942 case 'g': 3943 /* Strips will be grouped according to the groups in 3944 the data file. We will have to restrict strips to be 3945 in the grouping of the data file. 3946 */ 3947 *group = 1; 3948 break; 3949 3950 case 'o': 3951 *orientation = 0; 3952 3953 /* Get each the value of the integer */ 3954 /* We have an integer */ 3955 default: 3956 if ((c >= '0') && (c <= '9')) 3957 { 3958 /* More than one normal difference specified, use the last one */ 3959 if (next == 1) 3960 { 3961 count = 0; 3962 next = 0; 3963 } 3964 buffer[count++] = ATOI(c); 3965 } 3966 /* At the decimal point */ 3967 else if (c == '.') 3968 { 3969 /* More than one normal difference specified, use the last one */ 3970 if (next == 1) 3971 { 3972 count = 0; 3973 next = 0; 3974 } 3975 buffer[count++] = -1; 3976 } 3977 else 3978 break; 3979 } 3980 } 3981 /* Convert the buffer of characters to a floating pt integer */ 3982 if (count != 0) 3983 norm_difference = convert_array(buffer,count); 3984 *f = file_type; 3985 *t = tie; 3986 *tr = triangulate; 3987 return norm_difference; 3988 } 3989 3990 /// AdjacentEx: 3991 int CustomStripifier::AdjacentEx(int id2,int id1, int *list, int size) 3992 { 3993 /* Return the vertex that is adjacent to id1, 3994 but is not id2, in the list of integers. 3995 */ 3996 3997 register int x=0; 3998 3999 while (x < size) 4000 { 4001 if (*(list+x) == id1) 4002 { 4003 if ((x != (size -1)) && (x != 0)) 4004 { 4005 if ( *(list+x+1) != id2) 4006 return *(list+x+1); 4007 else 4008 return *(list+x-1); 4009 } 4010 else if (x == (size -1)) 4011 { 4012 if (*(list) != id2) 4013 return *(list); 4014 else 4015 return *(list+x-1); 4016 } 4017 else 4018 { 4019 if (*(list+size-1) != id2) 4020 return *(list+size-1); 4021 else 4022 return *(list+x+1); 4023 } 4024 } 4025 x++; 4026 } 4027 printf("Error in the list\n"); 4028 exit(0); 4029 } 4030 4031 /// Delete_From_ListEx: 4032 void CustomStripifier::Delete_From_ListEx(int id,int *list, int size) 4033 { 4034 /* Delete the occurence of id in the list. 4035 (list has size size) 4036 */ 4037 4038 int *temp; 4039 register int x,y=0; 4040 4041 temp = (int *) malloc(sizeof(int) * size); 4042 for (x=0; x<size; x++) 4043 { 4044 if (*(list+x) != id) 4045 { 4046 *(temp+y) = *(list+x); 4047 y++; 4048 } 4049 } 4050 if(y != (size-1)) 4051 { 4052 printf("There is an error in the delete\n"); 4053 exit(0); 4054 } 4055 *(temp+size-1) = -1; 4056 memcpy(list,temp,sizeof(int)*size); 4057 4058 } 4059 4060 /// Triangulate_QuadEx: 4061 void CustomStripifier::Triangulate_QuadEx(int out_edge1,int out_edge2,int in_edge1, 4062 int in_edge2,int size,int *index, 4063 int reversed, 4064 int where) 4065 { 4066 int vertex4,vertex5; 4067 4068 /* This routine will nonblindly triangulate a quad, meaning 4069 that there is a definite input and a definite output 4070 edge that we must adhere to. Reversed will tell the orientation 4071 of the input edge. (Reversed is -1 is we do not have an input 4072 edge, in other words we are at the beginning of a strip.) 4073 Out_edge* is the output edge, and in_edge* is the input edge. 4074 Index are the edges of the polygon 4075 and size is the size of the polygon. Begin is whether we are 4076 at the start of a new strip. 4077 */ 4078 4079 /* If we do not have an input edge, then we can make our input 4080 edge whatever we like, therefore it will be easier to come 4081 out on the output edge. 4082 */ 4083 if (reversed == -1) 4084 { 4085 vertex4 = AdjacentEx(out_edge1,out_edge2,index,size); 4086 vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index); 4087 Output_TriEx(vertex5,vertex4,out_edge1,NULL,-1,where); 4088 Output_TriEx(vertex4,out_edge1,out_edge2,NULL,-1,where); 4089 return; 4090 } 4091 4092 /* These are the 5 cases that we can have for the output edge */ 4093 4094 /* Are they consecutive so that we form a triangle to 4095 peel off, but cannot use the whole quad? 4096 */ 4097 4098 if (in_edge2 == out_edge1) 4099 { 4100 /* Output the triangle that comes out the correct 4101 edge last. First output the triangle that comes out 4102 the wrong edge. 4103 */ 4104 vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index); 4105 Output_TriEx(in_edge1,in_edge2,vertex4,NULL,-1,where); 4106 Output_TriEx(vertex4,in_edge2,out_edge2,NULL,-1,where); 4107 return; 4108 } 4109 /* The next case is where it is impossible to come out the 4110 edge that we want. So we will have to start a new strip to 4111 come out on that edge. We will output the one triangle 4112 that we can, and then start the new strip with the triangle 4113 that comes out on the edge that we want to come out on. 4114 */ 4115 else if (in_edge1 == out_edge1) 4116 { 4117 /* We want to output the first triangle (whose output 4118 edge is not the one that we want. 4119 We have to find the vertex that we need, which is 4120 the other vertex which we do not have. 4121 */ 4122 vertex4 = Get_Other_Vertex(in_edge2,in_edge1,out_edge2,index); 4123 Output_TriEx(in_edge2,in_edge1,vertex4,NULL,-1,where); 4124 Output_TriEx(vertex4,in_edge1,out_edge2,NULL,-1,where); 4125 return; 4126 } 4127 4128 /* Consecutive cases again, but with the output edge reversed */ 4129 else if (in_edge1 == out_edge2) 4130 { 4131 vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index); 4132 Output_TriEx(in_edge2,in_edge1,vertex4,NULL,-1,where); 4133 Output_TriEx(vertex4,in_edge1,out_edge1,NULL,-1,where); 4134 return; 4135 } 4136 else if (in_edge2 == out_edge2) 4137 { 4138 vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index); 4139 Output_TriEx(in_edge1,in_edge2,vertex4,NULL,-1,where); 4140 Output_TriEx(vertex4,in_edge2,out_edge1,NULL,-1,where); 4141 return; 4142 } 4143 4144 /* The final case is where we want to come out the opposite edge.*/ 4145 else 4146 { 4147 if( ((!reversed) && 4148 (out_edge1 == (AdjacentEx(in_edge1,in_edge2,index,size)))) || 4149 ((reversed) && 4150 (out_edge2 == (AdjacentEx(in_edge2,in_edge1,index,size))))) 4151 { 4152 /* We need to know the orientation of the input 4153 edge, so we know which way to put the diagonal. 4154 And also the output edge, so that we triangulate correctly. 4155 */ 4156 Output_TriEx(in_edge1,in_edge2,out_edge2,NULL,-1,where); 4157 Output_TriEx(in_edge2,out_edge2,out_edge1,NULL,-1,where); 4158 } 4159 else 4160 { 4161 /* Input and output orientation was reversed, so diagonal will 4162 be reversed from above. 4163 */ 4164 Output_TriEx(in_edge1,in_edge2,out_edge1,NULL,-1,where); 4165 Output_TriEx(in_edge2,out_edge1,out_edge2,NULL,-1,where); 4166 } 4167 return; 4168 } 4169 } 4170 4171 /// Triangulate_PolygonEx: 4172 void CustomStripifier::Triangulate_PolygonEx( int out_edge1,int out_edge2, 4173 int in_edge1, int in_edge2, 4174 int size, int *index, 4175 FILE *fp, int reversed, 4176 int face_id, int where) 4177 { 4178 /* We have a polygon that we need to nonblindly triangulate. 4179 We will recursively try to triangulate it, until we are left 4180 with a polygon of size 4, which can use the quad routine 4181 from above. We will be taking off a triangle at a time 4182 and outputting it. We will have 3 cases similar to the 4183 cases for the quad above. The inputs to this routine 4184 are the same as for the quad routine. 4185 */ 4186 4187 int vertex4; 4188 int *temp; 4189 4190 4191 /* Since we are calling this recursively, we have to check whether 4192 we are down to the case of the quad. 4193 */ 4194 4195 if (size == 4) 4196 { 4197 Triangulate_QuadEx(out_edge1,out_edge2,in_edge1,in_edge2,size, 4198 index,reversed,where); 4199 return; 4200 } 4201 4202 4203 4204 /* We do not have a specified input edge, and therefore we 4205 can make it anything we like, as long as we still come out 4206 the output edge that we want. 4207 */ 4208 if (reversed == -1) 4209 { 4210 /* Get the vertex for the last triangle, which is 4211 the one coming out the output edge, before we do 4212 any deletions to the list. We will be doing this 4213 bottom up. 4214 */ 4215 vertex4 = AdjacentEx(out_edge1,out_edge2,index,size); 4216 temp = (int *) malloc(sizeof(int) * size); 4217 memcpy(temp,index,sizeof(int)*size); 4218 Delete_From_ListEx(out_edge2,index,size); 4219 Triangulate_PolygonEx(out_edge1,vertex4,in_edge2, 4220 vertex4,size-1,index, 4221 fp,reversed,face_id,where); 4222 memcpy(index,temp,sizeof(int)*size); 4223 /* Lastly do the triangle that comes out the output 4224 edge. 4225 */ 4226 Output_TriEx(vertex4,out_edge1,out_edge2,NULL,-1,where); 4227 return; 4228 } 4229 4230 /* These are the 5 cases that we can have for the output edge */ 4231 4232 /* Are they consecutive so that we form a triangle to 4233 peel off that comes out the correct output edge, 4234 but we cannot use the whole polygon? 4235 */ 4236 if (in_edge2 == out_edge1) 4237 { 4238 /* Output the triangle that comes out the correct 4239 edge last. First recursively do the rest of the 4240 polygon. 4241 */ 4242 /* Do the rest of the polygon without the triangle. 4243 We will be doing a fan triangulation. 4244 */ 4245 /* Get the vertex adjacent to in_edge1, but is not 4246 in_edge2. 4247 */ 4248 vertex4 = AdjacentEx(in_edge2,in_edge1,index,size); 4249 Output_TriEx(in_edge1,in_edge2,vertex4,NULL,-1,where); 4250 /* Create a new edgelist without the triangle that 4251 was just outputted. 4252 */ 4253 temp = (int *) malloc(sizeof(int) * size); 4254 memcpy(temp,index,sizeof(int)*size); 4255 Delete_From_ListEx(in_edge1,index,size); 4256 Triangulate_PolygonEx(out_edge1,out_edge2,in_edge2, 4257 vertex4,size-1,index,fp, 4258 !reversed,face_id,where); 4259 memcpy(index,temp,sizeof(int)*size); 4260 return; 4261 } 4262 4263 /* Next case is where it is again consecutive, but the triangle 4264 formed by the consecutive edges do not come out of the 4265 correct output edge. For this case, we can not do much to 4266 keep it sequential. Try and do the fan. 4267 */ 4268 else if (in_edge1 == out_edge1) 4269 { 4270 /* Get vertex adjacent to in_edge2, but is not in_edge1 */ 4271 vertex4 = AdjacentEx(in_edge1,in_edge2,index,size); 4272 Output_TriEx(in_edge1,in_edge2,vertex4,fp,-1,where); 4273 /* Since that triangle goes out of the polygon (the 4274 output edge of it), we can make our new input edge 4275 anything we like, so we will try to make it good for 4276 the strip. (This will be like starting a new strip, 4277 all so that we can go out the correct output edge.) 4278 */ 4279 temp = (int *) malloc(sizeof(int) * size); 4280 memcpy(temp,index,sizeof(int)*size); 4281 Delete_From_ListEx(in_edge2,index,size); 4282 Triangulate_PolygonEx(out_edge1,out_edge2,in_edge1, 4283 vertex4,size-1,index,fp, 4284 reversed,face_id,where); 4285 memcpy(index,temp,sizeof(int)*size); 4286 return; 4287 } 4288 /* Consecutive cases again, but with the output edge reversed */ 4289 else if (in_edge1 == out_edge2) 4290 { 4291 /* Get vertex adjacent to in_edge2, but is not in_edge1 */ 4292 vertex4 = AdjacentEx(in_edge1,in_edge2,index,size); 4293 Output_TriEx(in_edge2,in_edge1,vertex4,fp,-1,where); 4294 temp = (int *) malloc(sizeof(int) * size); 4295 memcpy(temp,index,sizeof(int)*size); 4296 Delete_From_ListEx(in_edge2,index,size); 4297 Triangulate_PolygonEx(out_edge1,out_edge2,in_edge1, 4298 vertex4,size-1,index,fp, 4299 reversed,face_id,where); 4300 memcpy(index,temp,sizeof(int)*size); 4301 return; 4302 } 4303 else if (in_edge2 == out_edge2) 4304 { 4305 /* Get vertex adjacent to in_edge2, but is not in_edge1 */ 4306 vertex4 = AdjacentEx(in_edge2,in_edge1,index,size); 4307 Output_TriEx(in_edge1,in_edge2,vertex4,fp,-1,where); 4308 temp = (int *) malloc(sizeof(int) * size); 4309 memcpy(temp,index,sizeof(int)*size); 4310 Delete_From_ListEx(in_edge1,index,size); 4311 Triangulate_PolygonEx(out_edge1,out_edge2,vertex4, 4312 in_edge2,size-1,index,fp, 4313 reversed,face_id,where); 4314 memcpy(index,temp,sizeof(int)*size); 4315 return; 4316 } 4317 4318 /* Else the edge is not consecutive, and it is sufficiently 4319 far away, for us not to make a conclusion at this time. 4320 So we can take off a triangle and recursively call this 4321 function. 4322 */ 4323 else 4324 { 4325 vertex4 = AdjacentEx(in_edge2,in_edge1,index,size); 4326 Output_TriEx(in_edge1,in_edge2,vertex4,fp,-1,where); 4327 temp = (int *) malloc(sizeof(int) * size); 4328 memcpy(temp,index,sizeof(int)*size); 4329 Delete_From_ListEx(in_edge1,index,size); 4330 Triangulate_PolygonEx(out_edge1,out_edge2,in_edge2, 4331 vertex4,size-1,index,fp, 4332 !reversed,face_id,where); 4333 memcpy(index,temp,sizeof(int)*size); 4334 return; 4335 } 4336 } 4337 4338 /// TriangulateEx: 4339 void CustomStripifier::TriangulateEx(int out_edge1,int out_edge2,int in_edge1, 4340 int in_edge2,int size,int *index, 4341 FILE *output,int reversed,int face_id, int where) 4342 { 4343 /* We have the info we need to triangulate a polygon */ 4344 4345 if (size == 4) 4346 Triangulate_QuadEx(out_edge1,out_edge2,in_edge1,in_edge2,size, 4347 index,reversed,where); 4348 else 4349 Triangulate_PolygonEx(out_edge1,out_edge2,in_edge1,in_edge2,size, 4350 index,output,reversed,face_id,where); 4351 } 4352 4353 /// Non_Blind_TriangulateEx: 4354 void CustomStripifier::Non_Blind_TriangulateEx(int size,int *index, 4355 FILE *output,int next_face_id,int face_id,int where) 4356 { 4357 int id1,id2,id3; 4358 int nedge1,nedge2; 4359 int reversed; 4360 /* We have a polygon that has to be triangulated and we cannot 4361 do it blindly, ie we will try to come out on the edge that 4362 has the least number of adjacencies 4363 */ 4364 4365 Last_Edge(&id1,&id2,&id3,0); 4366 /* Find the edge that is adjacent to the new face , 4367 also return whether the orientation is reversed in the 4368 face of the input edge, which is id2 and id3. 4369 */ 4370 if (next_face_id == -1) 4371 { 4372 printf("The face is -1 and the size is %d\n",size); 4373 exit(0); 4374 } 4375 4376 reversed = Get_EdgeEx(&nedge1,&nedge2,index,next_face_id,size,id2,id3); 4377 /* Do the triangulation */ 4378 4379 /* If reversed is -1, the input edge is not in the polygon, 4380 therefore we can have the input edge to be anything we like, 4381 since we are at the beginning of a strip 4382 */ 4383 TriangulateEx(nedge1,nedge2,id2,id3,size,index,output,reversed, 4384 face_id, where); 4385 } 4386 4387 /// Rearrange_IndexEx: 4388 void CustomStripifier::Rearrange_IndexEx(int *index, int size) 4389 { 4390 /* If we are in the middle of a strip we must find the 4391 edge to start on, which is the last edge that we had 4392 transmitted. 4393 */ 4394 int x,f,y,e1,e2,e3; 4395 int increment = 1; 4396 int *temp; 4397 4398 /* Find where the input edge is in the input list */ 4399 Last_Edge(&e1,&e2,&e3,0); 4400 for (y = 0; y < size; y++) 4401 { 4402 if (*(index+y) == e2) 4403 { 4404 if ((y != (size - 1)) && (*(index+y+1) == e3)) 4405 break; 4406 else if ((y == (size - 1)) && (*(index) == e3)) 4407 break; 4408 else if ((y != 0) && (*(index+y-1) == e3)) 4409 { 4410 increment = -1; 4411 break; 4412 } 4413 else if ((y==0) && (*(index+size-1) == e3)) 4414 { 4415 increment = -1; 4416 break; 4417 } 4418 } 4419 if (*(index+y) == e3) 4420 { 4421 if ((y != (size - 1)) && (*(index+y+1) == e2)) 4422 break; 4423 else if ((y == (size - 1)) && (*(index) == e2)) 4424 break; 4425 else if ((y != 0) && (*(index+y-1) == e2)) 4426 { 4427 increment = -1; 4428 break; 4429 } 4430 else if ((y==0) && (*(index+size-1) == e2)) 4431 { 4432 increment = -1; 4433 break; 4434 } 4435 } 4436 /* Edge is not here, we are at the beginning */ 4437 if ((y == (size-1)) && (increment != -1)) 4438 return; 4439 } 4440 4441 /* Now put the list into a new list, starting with the 4442 input edge. Increment tells us whether we have to go 4443 forward or backward. 4444 */ 4445 /* Was in good position already */ 4446 if ((y == 0) && (increment == 1)) 4447 return; 4448 4449 4450 temp = (int *) malloc(sizeof(int) * size); 4451 memcpy(temp,index,sizeof(int)*size); 4452 4453 if (increment == 1) 4454 { 4455 x=0; 4456 for (f = y ; f< size; f++) 4457 { 4458 *(index+x) = *(temp+f); 4459 x++; 4460 } 4461 /* Finish the rest of the list */ 4462 for(f = 0; f < y ; f++) 4463 { 4464 *(index+x) = *(temp+f); 4465 x++; 4466 } 4467 } 4468 else 4469 { 4470 x=0; 4471 for (f = y ; f >= 0; f--) 4472 { 4473 *(index+x) = *(temp+f); 4474 x++; 4475 } 4476 /* Finish the rest of the list */ 4477 for(f = (size - 1); f > y ; f--) 4478 { 4479 *(index+x) = *(temp+f); 4480 x++; 4481 } 4482 } 4483 } 4484 4485 /// Blind_TriangulateEx: 4486 void CustomStripifier::Blind_TriangulateEx(int size, int *index, 4487 BOOL begin, int where ) 4488 { 4489 /* save sides in temp array, we need it so we know 4490 about swaps. 4491 */ 4492 int mode, decreasing,increasing,e1,e2,e3; 4493 4494 /* Rearrange the index list so that the input edge is first 4495 */ 4496 if (!begin) 4497 Rearrange_IndexEx(index,size); 4498 4499 /* We are given a polygon of more than 3 sides 4500 and want to triangulate it. We will output the 4501 triangles to the output file. 4502 */ 4503 4504 /* Find where the input edge is in the input list */ 4505 Last_Edge(&e1,&e2,&e3,0); 4506 if (( (!begin) && (*(index) == e2) ) || (begin)) 4507 { 4508 Output_TriEx(*(index+0),*(index+1),*(index+size-1),NULL,-1,where); 4509 /* If we have a quad, (chances are yes), then we know that 4510 we can just add one diagonal and be done. (divide the 4511 quad into 2 triangles. 4512 */ 4513 if (size == 4) 4514 { 4515 Output_TriEx(*(index+1),*(index+size-1),*(index+2),NULL,-1,where); 4516 return; 4517 } 4518 increasing = 1; 4519 mode = 1; 4520 4521 } 4522 else if (!begin) 4523 { 4524 Output_TriEx(*(index+1),*(index+0),*(index+size-1),NULL,-1,where); 4525 if (size == 4) 4526 { 4527 Output_TriEx(*(index+0),*(index+size-1),*(index+2),NULL,-1,where); 4528 return; 4529 } 4530 Output_TriEx(*(index+0),*(index+size-1),*(index+2),NULL,-1,where); 4531 increasing = 2; 4532 mode = 0; 4533 } 4534 if (size != 4) 4535 { 4536 /* We do not have a quad, we have something bigger. */ 4537 decreasing = size - 1; 4538 4539 do 4540 { 4541 /* Will be alternating diagonals, so we will be increasing 4542 and decreasing around the polygon. 4543 */ 4544 if (mode) 4545 { 4546 Output_TriEx(*(index+increasing),*(index+decreasing), 4547 *(index+increasing+1),NULL,-1,where); 4548 increasing++; 4549 } 4550 else 4551 { 4552 Output_TriEx(*(index+decreasing),*(index+increasing), 4553 *(index+decreasing-1),NULL,-1,where); 4554 decreasing--; 4555 } 4556 mode = !mode; 4557 } while ((decreasing - increasing) >= 2); 4558 4559 } 4560 } 4561 4562 /// Get_EdgeEx: 4563 int CustomStripifier::Get_EdgeEx(int *edge1,int *edge2,int *index,int face_id, 4564 int size, int id1, int id2) 4565 { 4566 /* Put the edge that is adjacent to face_id into edge1 4567 and edge2. For each edge see if it is adjacent to 4568 face_id. Id1 and id2 is the input edge, so see if 4569 the orientation is reversed, and save it in reversed. 4570 */ 4571 int x; 4572 int reversed = -1; 4573 BOOL set = FALSE; 4574 4575 for (x=0; x< size; x++) 4576 { 4577 if (x == (size-1)) 4578 { 4579 if ((*(index) == id1) && (*(index+size-1)==id2)) 4580 { 4581 if (set) 4582 return 1; 4583 reversed = 1; 4584 } 4585 else if ((*(index) == id2) && (*(index+size-1)==id1)) 4586 { 4587 if (set) 4588 return 0; 4589 reversed = 0; 4590 } 4591 4592 if (Look_Up(*(index),*(index+size-1),face_id)) 4593 { 4594 if ( (out1Ex != -1) && 4595 ( (out1Ex == *(index)) || (out1Ex == *(index+size-1)) ) && 4596 ( (out2Ex == *(index)) || (out2Ex == *(index+size-1)) )) 4597 { 4598 set = TRUE; 4599 *edge1 = *(index); 4600 *edge2 = *(index+size-1); 4601 } 4602 else if (out1Ex == -1) 4603 { 4604 set = TRUE; 4605 *edge1 = *(index); 4606 *edge2 = *(index+size-1); 4607 } 4608 if ((reversed != -1) && (set)) 4609 return reversed; 4610 } 4611 } 4612 else 4613 { 4614 if ((*(index+x) == id1) && (*(index+x+1)==id2)) 4615 { 4616 if (set) 4617 return 0; 4618 reversed = 0; 4619 } 4620 else if ((*(index+x) == id2) && (*(index+x+1)==id1)) 4621 { 4622 if (set) 4623 return 1; 4624 reversed = 1; 4625 } 4626 4627 if (Look_Up(*(index+x),*(index+x+1),face_id)) 4628 { 4629 if ( (out1Ex != -1) && 4630 ( (out1Ex == *(index+x)) || (out1Ex == *(index+x+1)) ) && 4631 ((out2Ex == *(index+x)) || (out2Ex == *(index+x+1)))) 4632 { 4633 set = TRUE; 4634 *edge1 = *(index+x); 4635 *edge2 = *(index+x+1); 4636 } 4637 else if (out1Ex == -1) 4638 { 4639 set = TRUE; 4640 *edge1 = *(index+x); 4641 *edge2 = *(index+x + 1); 4642 } 4643 if ((reversed != -1) && (set)) 4644 return reversed; 4645 } 4646 } 4647 } 4648 if ((x == size) && (reversed != -1)) 4649 { 4650 /* Could not find the output edge */ 4651 printf("Error in the Lookup %d %d %d %d %d %d %d %d\n", 4652 face_id,id1,id2,reversed,*edge1,*edge2,out1Ex,out2Ex); 4653 exit(0); 4654 } 4655 return reversed; 4656 } 4657 4658 /// Update_FaceEx: 4659 void CustomStripifier::Update_FaceEx( int *next_bucket,int *min_face, 4660 int face_id, int *e1, 4661 int *e2,int temp1, 4662 int temp2,int *ties) 4663 { 4664 /* We have a face id that needs to be decremented. 4665 We have to determine where it is in the structure, 4666 so that we can decrement it. 4667 */ 4668 /* The number of adjacencies may have changed, so to locate 4669 it may be a little tricky. However we know that the number 4670 of adjacencies is less than or equal to the original number 4671 of adjacencies, 4672 */ 4673 int y,size; 4674 ListHead *pListHead; 4675 PF_FACES temp = NULL; 4676 PLISTINFO lpListInfo; 4677 static int each_poly = 0; 4678 BOOL there = FALSE; 4679 4680 pListHead = PolFaces[face_id]; 4681 temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); 4682 /* Check each edge of the face and tally the number of adjacent 4683 polygons to this face. 4684 */ 4685 if ( temp != NULL ) 4686 { 4687 /* Size of the polygon */ 4688 size = temp->nPolSize; 4689 for (y = 0; y< size; y++) 4690 { 4691 /* If we are doing partial triangulation, we must check 4692 to see whether the edge is still there in the polygon, 4693 since we might have done a portion of the polygon 4694 and saved the rest for later. 4695 */ 4696 if (y != (size-1)) 4697 { 4698 if( ((temp1 == *(temp->pPolygon+y)) && 4699 (temp2 ==*(temp->pPolygon+y+1))) || 4700 ((temp2 == *(temp->pPolygon+y)) && 4701 (temp1 ==*(temp->pPolygon+y+1)))) 4702 /* edge is still there we are ok */ 4703 there = TRUE; 4704 } 4705 else 4706 { 4707 if( ((temp1 == *(temp->pPolygon)) && 4708 (temp2 == *(temp->pPolygon+size-1))) || 4709 ((temp2 == *(temp->pPolygon)) && 4710 (temp1 ==*(temp->pPolygon+size-1)))) 4711 /* edge is still there we are ok */ 4712 there = TRUE; 4713 } 4714 } 4715 4716 if (!there) 4717 /* Original edge was already used, we cannot use this polygon */ 4718 return; 4719 4720 /* We have a starting point to start our search to locate 4721 this polygon. 4722 */ 4723 4724 /* Check to see if this polygon was done */ 4725 lpListInfo = Done(face_id,&y); 4726 4727 if (lpListInfo == NULL) 4728 return; 4729 4730 /* Was not done, but there is an error in the adjacency calculations */ 4731 /* If more than one edge is adj to it then maybe it was not updated */ 4732 if (y == 0) 4733 return; 4734 4735 /* Now put the face in the proper bucket depending on tally. */ 4736 /* First add it to the new bucket, then remove it from the old */ 4737 Add_Sgi_Adj(y-1,face_id); 4738 RemoveList(array[y],lpListInfo); 4739 4740 /* Save it if it was the smallest seen so far since then 4741 it will be the next face 4742 Here we will have different options depending on 4743 what we want for resolving ties: 4744 1) First one we see we will use 4745 2) Random resolving 4746 3) Look ahead 4747 4) Alternating direction 4748 */ 4749 /* At a new strip */ 4750 if (*next_bucket == 60) 4751 *ties = *ties + each_poly; 4752 /* Have a tie */ 4753 if (*next_bucket == (y-1)) 4754 { 4755 Add_Ties(face_id); 4756 each_poly++; 4757 } 4758 /* At a new minimum */ 4759 if (*next_bucket > (y-1)) 4760 { 4761 *next_bucket = y-1; 4762 *min_face = face_id; 4763 *e1 = temp1; 4764 *e2 = temp2; 4765 each_poly = 0; 4766 Clear_Ties(); 4767 Add_Ties(face_id); 4768 } 4769 } 4770 } 4771 4772 /// Delete_AdjEx: 4773 void CustomStripifier::Delete_AdjEx(int id1, int id2, 4774 int *next_bucket, int *min_face, 4775 int current_face, int *e1, 4776 int *e2, int *ties) 4777 { 4778 /* Find the face that is adjacent to the edge and is not the 4779 current face. Delete one adjacency from it. Save the min 4780 adjacency seen so far. 4781 */ 4782 register int count=0; 4783 PF_EDGES temp = NULL; 4784 ListHead *pListHead; 4785 int next_face; 4786 4787 /* Always want smaller id first */ 4788 switch_lower(&id1,&id2); 4789 4790 pListHead = PolEdges[id1]; 4791 temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); 4792 if (temp == NULL) 4793 /* It could be a new edge that we created. So we can 4794 exit, since there is not a face adjacent to it. 4795 */ 4796 return; 4797 while (temp->edge[0] != id2) 4798 { 4799 count++; 4800 temp = ( PF_EDGES )GetNextNode(temp); 4801 4802 if (temp == NULL) 4803 /* Was a new edge that was created and therefore 4804 does not have anything adjacent to it 4805 */ 4806 return; 4807 } 4808 /* Was not adjacent to anything else except itself */ 4809 if (temp->edge[2] == -1) 4810 return; 4811 4812 /* Was adjacent to something */ 4813 else 4814 { 4815 if (temp->edge[2] == current_face) 4816 next_face = temp->edge[1]; 4817 else 4818 next_face = temp->edge[2]; 4819 } 4820 /* We have the other face adjacent to this edge, it is 4821 next_face. Now we need to decrement this faces' adjacencies. 4822 */ 4823 Update_FaceEx(next_bucket, min_face, next_face,e1,e2,id1,id2,ties); 4824 } 4825 4826 /// Change_FaceEx: 4827 int CustomStripifier::Change_FaceEx(int face_id,int in1,int in2, 4828 ListHead *pListHead, BOOL no_check) 4829 { 4830 /* We are doing a partial triangulation and we need to 4831 put the new face of triangle into the correct bucket 4832 */ 4833 int input_adj,y; 4834 P_ADJACENCIES lpListInfo; 4835 4836 /* Find the old number of adjacencies to this face, 4837 so we know where to delete it from 4838 */ 4839 y = Old_Adj(face_id); 4840 pListHead = array[y]; 4841 lpListInfo = face_array[face_id].pfNode; 4842 4843 if (lpListInfo == NULL) 4844 { 4845 printf("There is an error finding the next polygon3 %d\n",face_id); 4846 exit(0); 4847 } 4848 4849 /* Do we need to change the adjacency? Maybe the edge on the triangle 4850 that was outputted was not adjacent to anything. We know if we 4851 have to check by "check". We came out on the output edge 4852 that we needed, then we know that the adjacencies will decrease 4853 by exactly one. 4854 */ 4855 if (!no_check) 4856 { 4857 input_adj = Number_Adj(in1,in2,face_id); 4858 /* If there weren't any then don't do anything */ 4859 if (input_adj == 0) 4860 return y; 4861 } 4862 4863 if (face_array[lpListInfo->face_id].head == pListHead) 4864 face_array[lpListInfo->face_id].pfNode = NULL; 4865 RemoveList(pListHead,(PLISTINFO)/*(temp*/lpListInfo); 4866 /* Before we had a quad with y adjacencies. The in edge 4867 did not have an adjacency, since it was just deleted, 4868 since we came in on it. The outedge must have an adjacency 4869 otherwise we would have a bucket 0, and would not be in this 4870 routine. Therefore the new adjacency must be y-1 4871 */ 4872 4873 Add_Sgi_Adj(y-1,face_id); 4874 return (y-1); 4875 } 4876 4877 /// Update_AdjacenciesEx: 4878 int CustomStripifier::Update_AdjacenciesEx(int face_id, int *next_bucket, int *e1, int *e2, 4879 int *ties) 4880 { 4881 /* Give the face with id face_id, we want to decrement 4882 all the faces that are adjacent to it, since we will 4883 be deleting face_id from the data structure. 4884 We will return the face that has the least number 4885 of adjacencies. 4886 */ 4887 PF_FACES temp = NULL; 4888 ListHead *pListHead; 4889 int size,y,min_face = -1; 4890 4891 *next_bucket = 60; 4892 pListHead = PolFaces[face_id]; 4893 temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); 4894 4895 if ( temp == NULL ) 4896 { 4897 printf("The face was already deleted, there is an error\n"); 4898 exit(0); 4899 } 4900 4901 /* Size of the polygon */ 4902 size = temp->nPolSize; 4903 for (y = 0; y< size; y++) 4904 { 4905 if (y != (size-1)) 4906 Delete_AdjEx(*(temp->pPolygon+y),*(temp->pPolygon+y+1), 4907 next_bucket,&min_face,face_id,e1,e2,ties); 4908 else 4909 Delete_AdjEx(*(temp->pPolygon),*(temp->pPolygon+(size-1)), 4910 next_bucket,&min_face,face_id,e1,e2,ties); 4911 } 4912 return (min_face); 4913 } 4914 4915 /// Find_Adj_TallyEx: 4916 void CustomStripifier::Find_Adj_TallyEx(int id1, int id2, 4917 int *next_bucket, int *min_face, 4918 int current_face, int *ties) 4919 { 4920 /* Find the face that is adjacent to the edge and is not the 4921 current face. Save the min adjacency seen so far. 4922 */ 4923 int size,each_poly=0,y,count=0; 4924 PF_EDGES temp = NULL; 4925 PF_FACES temp2 = NULL; 4926 ListHead *pListHead; 4927 int next_face; 4928 BOOL there = FALSE; 4929 4930 4931 /* Always want smaller id first */ 4932 switch_lower(&id1,&id2); 4933 4934 pListHead = PolEdges[id1]; 4935 temp = (PF_EDGES) PeekList(pListHead,LISTHEAD,count); 4936 if (temp == NULL) 4937 /* This was a new edge that was created, so it is 4938 adjacent to nothing. 4939 */ 4940 return; 4941 while (temp->edge[0] != id2) 4942 { 4943 count++; 4944 temp =( PF_EDGES ) GetNextNode(temp); 4945 4946 if (temp == NULL) 4947 /* This was a new edge that we created */ 4948 return; 4949 } 4950 /* Was not adjacent to anything else except itself */ 4951 if (temp->edge[2] == -1) 4952 return; 4953 else 4954 { 4955 if (temp->edge[2] == current_face) 4956 next_face = temp->edge[1]; 4957 else 4958 next_face = temp->edge[2]; 4959 } 4960 /* We have the other face adjacent to this edge, it is 4961 next_face. Find how many faces it is adjacent to. 4962 */ 4963 pListHead = PolFaces[next_face]; 4964 temp2 = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); 4965 /* Check each edge of the face and tally the number of adjacent 4966 polygons to this face. This will be the original number of 4967 polygons adjacent to this polygon, we must then see if this 4968 number has been decremented 4969 */ 4970 if ( temp2 != NULL ) 4971 { 4972 /* Size of the polygon */ 4973 size = temp2->nPolSize; 4974 for (y = 0; y< size; y++) 4975 { 4976 /* Make sure that the edge is still in the 4977 polygon and was not deleted, because if the edge was 4978 deleted, then we used it already. 4979 */ 4980 if (y != (size-1)) 4981 { 4982 if( ((id1 == *(temp2->pPolygon+y)) && 4983 (id2 ==*(temp2->pPolygon+y+1))) || 4984 ((id2 == *(temp2->pPolygon+y)) && 4985 (id1 ==*(temp2->pPolygon+y+1)))) 4986 /* edge is still there we are ok */ 4987 there = TRUE; 4988 } 4989 else 4990 { 4991 if( ((id1 == *(temp2->pPolygon)) && 4992 (id2 ==*(temp2->pPolygon+size-1))) || 4993 ((id2 == *(temp2->pPolygon)) && 4994 (id1 ==*(temp2->pPolygon+size-1)))) 4995 /* edge is still there we are ok */ 4996 there = TRUE; 4997 } 4998 } 4999 5000 if (!there) 5001 /* Edge already used and deleted from the polygon*/ 5002 return; 5003 5004 /* See if the face was already deleted, and where 5005 it is if it was not 5006 */ 5007 if (Done(next_face,&y) == NULL) 5008 return; 5009 5010 /* Save it if it was the smallest seen so far since then 5011 it will be the next face 5012 Here we will have different options depending on 5013 what we want for resolving ties: 5014 1) First one we see we will use 5015 2) Random resolving 5016 3) Look ahead 5017 4) Alternating direction 5018 */ 5019 5020 /* At a new strip */ 5021 if (*next_bucket == 60) 5022 *ties = *ties + each_poly; 5023 /* Have a tie */ 5024 if (*next_bucket == (y-1)) 5025 { 5026 Add_Ties(next_face); 5027 each_poly++; 5028 } 5029 /* At a new minimum */ 5030 if (*next_bucket > (y-1)) 5031 { 5032 *next_bucket = y-1; 5033 *min_face = next_face; 5034 each_poly = 0; 5035 Clear_Ties(); 5036 Add_Ties(next_face); 5037 } 5038 } 5039 } 5040 5041 /// Min_Face_AdjEx: 5042 int CustomStripifier::Min_Face_AdjEx(int face_id, int *next_bucket, int *ties) 5043 { 5044 /* Used for the Partial triangulation to find the next 5045 face. It will return the minimum adjacency face id 5046 found at this face. 5047 */ 5048 PF_FACES temp = NULL; 5049 ListHead *pListHead; 5050 int size,y,min_face,test_face; 5051 5052 *next_bucket = 60; 5053 pListHead = PolFaces[face_id]; 5054 temp = ( PF_FACES ) PeekList( pListHead, LISTHEAD, 0 ); 5055 5056 if ( temp == NULL ) 5057 { 5058 printf("The face was already deleted, there is an error\n"); 5059 exit(0); 5060 } 5061 5062 /* Size of the polygon */ 5063 size = temp->nPolSize; 5064 for (y = 0; y< size; y++) 5065 { 5066 if (y != (size-1)) 5067 Find_Adj_TallyEx(*(temp->pPolygon+y),*(temp->pPolygon+y+1), 5068 next_bucket,&min_face,face_id,ties); 5069 else 5070 Find_Adj_TallyEx(*(temp->pPolygon),*(temp->pPolygon+(size-1)), 5071 next_bucket,&min_face,face_id,ties); 5072 } 5073 /* Maybe we can do better by triangulating the face, because 5074 by triangulating the face we will go to a polygon of lesser 5075 adjacencies 5076 */ 5077 if (size == 4) 5078 { 5079 /* Checking for a quad whether to do the whole polygon will 5080 result in better performance because the triangles in the polygon 5081 have less adjacencies 5082 */ 5083 Check_In_Quad(face_id,&test_face); 5084 if (*next_bucket > test_face) 5085 /* We can do better by going through the polygon */ 5086 min_face = face_id; 5087 } 5088 5089 /* We have a polygon with greater than 4 sides, check to see if going 5090 inside is better than going outside the polygon for the output edge. 5091 */ 5092 else 5093 { 5094 Check_In_Polygon(face_id,&test_face,size); 5095 if (*next_bucket > test_face) 5096 /* We can do better by going through the polygon */ 5097 min_face = face_id; 5098 } 5099 5100 return (min_face); 5101 } 5102 5103 /// Find_StripsEx: 5104 void CustomStripifier::Find_StripsEx(FILE *output,int *ties, 5105 int tie, int triangulate, 5106 int swaps,int *next_id) 5107 { 5108 /* This routine will peel off the strips from the model */ 5109 5110 ListHead *pListHead; 5111 P_ADJACENCIES temp = NULL; 5112 register int max,bucket = 0; 5113 BOOL whole_flag = TRUE; 5114 int dummy = 0; 5115 int cont = 0; 5116 5117 /* Set the last known input edge to be null */ 5118 Last_Edge(&dummy,&dummy,&dummy,1); 5119 5120 /* Search for lowest adjacency polygon and output strips */ 5121 while (whole_flag) 5122 { 5123 bucket = -1; 5124 /* Search for polygons in increasing number of adjacencies */ 5125 while (bucket < 59) 5126 { 5127 bucket++; 5128 pListHead = array[bucket]; 5129 max = NumOnList(pListHead); 5130 if (max > 0) 5131 { 5132 temp = (P_ADJACENCIES) PeekList(pListHead,LISTHEAD,0); 5133 if (temp == NULL) 5134 { 5135 printf("Error in the buckets%d %d %d\n",bucket,max,0); 5136 exit(0); 5137 } 5138 5139 Polygon_OutputEx(temp,temp->face_id,bucket,pListHead, output,ties,tie,triangulate,swaps,next_id,1); 5140 /* Try to extend backwards, if the starting polygon in the 5141 strip had 2 or more adjacencies to begin with 5142 */ 5143 if (bucket >= 2) 5144 Extend_BackwardsEx(temp->face_id,output,ties,tie, triangulate,swaps,next_id); 5145 5146 break; 5147 } 5148 } 5149 /* Went through the whole structure, it is empty and we are done. 5150 */ 5151 if ((bucket == 59) && (max == 0)) 5152 whole_flag = FALSE; 5153 5154 /* We just finished a strip, send dummy data to signal the end 5155 of the strip so that we can output it. 5156 */ 5157 else 5158 { 5159 Output_TriEx(-1,-2,-3,output,-10,1); 5160 Last_Edge(&dummy,&dummy,&dummy,1); 5161 cont++; 5162 } 5163 } 5164 printf("We got %d strips\n",cont); 5165 } 5166 5167 /// SGI_Strip: 5168 void CustomStripifier::SGI_Strip(int num_faces, 5169 FILE *output, 5170 int ties, 5171 int triangulate) 5172 { 5173 int next_id = -1,t=0; 5174 5175 /* We are going to output and find triangle strips 5176 according the the method that SGI uses, ie always 5177 choosing as the next triangle in our strip the triangle 5178 that has the least number of adjacencies. We do not have 5179 all triangles and will be triangulating on the fly those 5180 polygons that have more than 3 sides. 5181 */ 5182 5183 /* Build a table that has all the polygons sorted by the number 5184 of polygons adjacent to it. 5185 */ 5186 /* Initialize it */ 5187 Init_Table_SGI(num_faces); 5188 /* Build it */ 5189 Build_SGI_Table(num_faces); 5190 5191 /* We will have a structure to hold all the strips, until 5192 outputted. 5193 */ 5194 InitStripTable(); 5195 /* Now we have the structure built to find the polygons according 5196 to the number of adjacencies. Now use the SGI Method to find 5197 strips according to the adjacencies 5198 */ 5199 5200 Find_StripsEx(output,&t,ties,triangulate,ON,&next_id); 5201 5202 } 5203 5204 /// P_Triangulate_Quad: 5205 void CustomStripifier::P_Triangulate_Quad(int out_edge1,int out_edge2, 5206 int in_edge1, int in_edge2, 5207 int size, int *index, 5208 int reversed, int face_id, 5209 ListHead *pListHead, 5210 P_ADJACENCIES temp, 5211 int where) 5212 { 5213 int vertex4,vertex5,dummy=60; 5214 5215 /* This routine will nonblindly triangulate a quad, meaning 5216 that there is a definite input and a definite output 5217 edge that we must adhere to. Reversed will tell the orientation 5218 of the input edge. (Reversed is -1 is we do not have an input 5219 edge, in other words we are at the beginning of a strip.) 5220 Out_edge* is the output edge, and in_edge* is the input edge. 5221 Index are the edges of the polygon 5222 and size is the size of the polygon. Begin is whether we are 5223 at the start of a new strip. 5224 Note that we will not necessarily triangulate the whole quad; 5225 maybe we will do half and leave the other half (a triangle) 5226 for later. 5227 */ 5228 5229 5230 /* If we do not have an input edge, then we can make our input 5231 edge whatever we like, therefore it will be easier to come 5232 out on the output edge. In this case the whole quad is done. 5233 */ 5234 if (reversed == -1) 5235 { 5236 vertex4 = AdjacentEx(out_edge1,out_edge2,index,size); 5237 vertex5 = Get_Other_Vertex(vertex4,out_edge1,out_edge2,index); 5238 Output_TriEx(vertex5,vertex4,out_edge1,NULL,-1,where); 5239 Output_TriEx(vertex4,out_edge1,out_edge2,NULL,-1,where); 5240 dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy); 5241 5242 if (face_array[temp->face_id].head == pListHead) 5243 face_array[temp->face_id].pfNode = NULL; 5244 RemoveList(pListHead,(PLISTINFO) temp); 5245 return; 5246 } 5247 5248 /* These are the 5 cases that we can have for the output edge */ 5249 5250 /* Are they consecutive so that we form a triangle to 5251 peel off, but cannot use the whole quad? 5252 */ 5253 5254 if (in_edge2 == out_edge1) 5255 { 5256 /* Output the triangle that comes out the correct 5257 edge. Save the other half for later. 5258 */ 5259 vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index); 5260 Output_TriEx(in_edge1,in_edge2,out_edge2,NULL,-1,where); 5261 /* Now we have a triangle used, and a triangle that is 5262 left for later. 5263 */ 5264 5265 /* Now delete the adjacencies by one for all the faces 5266 that are adjacent to the triangle that we just outputted. 5267 */ 5268 Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy, 5269 face_id,&dummy,&dummy,&dummy); 5270 Delete_AdjEx(out_edge2,in_edge2,&dummy,&dummy, 5271 face_id,&dummy,&dummy,&dummy); 5272 /* Put the new face in the proper bucket of adjacencies 5273 There are 2 edges that need to be checked for the triangle 5274 that was just outputted. For the output edge we definitely 5275 will be decreasing the adjacency, but we must check for the 5276 input edge. 5277 */ 5278 5279 dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE); 5280 dummy = Change_FaceEx(face_id,in_edge2,out_edge2,pListHead,TRUE); 5281 5282 /* Update the face data structure, by deleting the old 5283 face and putting in the triangle as the new face 5284 */ 5285 New_Face(face_id,in_edge1,out_edge2,vertex4); 5286 return; 5287 } 5288 else if (in_edge1 == out_edge1) 5289 { 5290 /* We want to output the first triangle (whose output 5291 edge is not the one that we want. 5292 We have to find the vertex that we need, which is 5293 the other vertex which we do not have. 5294 */ 5295 vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge2,index); 5296 Output_TriEx(in_edge2,in_edge1,out_edge2,NULL,-1,where); 5297 /* Now we have a triangle used, and a triangle that is 5298 left for later. 5299 */ 5300 5301 /* Now delete the adjacencies by one for all the faces 5302 that are adjacent to the triangle that we just outputted. 5303 */ 5304 Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, 5305 &dummy,&dummy,&dummy); 5306 Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 5307 face_id,&dummy,&dummy,&dummy); 5308 5309 /* Put the new face in the proper bucket of adjacencies */ 5310 dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE); 5311 dummy = Change_FaceEx(face_id,in_edge1,out_edge2,pListHead,TRUE); 5312 5313 /* Update the face data structure, by deleting the old 5314 face and putting in the triangle as the new face 5315 */ 5316 New_Face(face_id,in_edge2,out_edge2,vertex4); 5317 return; 5318 } 5319 5320 /* Consecutive cases again, but with the output edge reversed */ 5321 else if (in_edge1 == out_edge2) 5322 { 5323 vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index); 5324 Output_TriEx(in_edge2,in_edge1,out_edge1,NULL,-1,where); 5325 /* Now we have a triangle used, and a triangle that is 5326 left for later. 5327 */ 5328 5329 /* Now delete the adjacencies by one for all the faces 5330 that are adjacent to the triangle that we just outputted. 5331 */ 5332 Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, 5333 &dummy,&dummy,&dummy); 5334 Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 5335 face_id,&dummy,&dummy,&dummy); 5336 5337 /* Put the new face in the proper bucket of adjacencies */ 5338 dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE); 5339 dummy = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,TRUE); 5340 5341 /* Update the face data structure, by deleting the old 5342 face and putting in the triangle as the new face 5343 */ 5344 New_Face(face_id,in_edge2,out_edge1,vertex4); 5345 return; 5346 } 5347 else if (in_edge2 == out_edge2) 5348 { 5349 vertex4 = Get_Other_Vertex(in_edge1,in_edge2,out_edge1,index); 5350 Output_TriEx(in_edge1,in_edge2,out_edge1,NULL,-1,where); 5351 /* Now we have a triangle used, and a triangle that is 5352 left for later. 5353 */ 5354 /* Now delete the adjacencies by one for all the faces 5355 that are adjacent to the triangle that we just outputted. 5356 */ 5357 Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, 5358 &dummy,&dummy,&dummy); 5359 Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 5360 face_id,&dummy,&dummy,&dummy); 5361 5362 /* Put the new face in the proper bucket of adjacencies */ 5363 dummy = Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE); 5364 dummy = Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,TRUE); 5365 5366 /* Update the face data structure, by deleting the old 5367 face and putting in the triangle as the new face 5368 */ 5369 New_Face(face_id,in_edge1,out_edge1,vertex4); 5370 return; 5371 } 5372 5373 /* The final case is where we want to come out the opposite 5374 edge. 5375 */ 5376 else 5377 { 5378 if( ((!reversed) && 5379 (out_edge1 == (AdjacentEx(in_edge1,in_edge2,index,size)))) || 5380 ((reversed) && 5381 (out_edge2 == (AdjacentEx(in_edge2,in_edge1,index,size))))) 5382 { 5383 /* We need to know the orientation of the input 5384 edge, so we know which way to put the diagonal. 5385 And also the output edge, so that we triangulate 5386 correctly. Does not need partial. 5387 */ 5388 Output_TriEx(in_edge1,in_edge2,out_edge2,NULL,-1,where); 5389 Output_TriEx(in_edge2,out_edge2,out_edge1,NULL,-1,where); 5390 dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy); 5391 5392 if (face_array[temp->face_id].head == pListHead) 5393 face_array[temp->face_id].pfNode = NULL; 5394 RemoveList(pListHead,(PLISTINFO) temp); 5395 } 5396 else 5397 { 5398 /* Input and output orientation was reversed, so diagonal will 5399 be reversed from above. 5400 */ 5401 Output_TriEx(in_edge1,in_edge2,out_edge1,NULL,-1,where); 5402 Output_TriEx(in_edge2,out_edge1,out_edge2,NULL,-1,where); 5403 dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy); 5404 5405 if (face_array[temp->face_id].head == pListHead) 5406 face_array[temp->face_id].pfNode = NULL; 5407 RemoveList(pListHead,(PLISTINFO) temp); 5408 } 5409 return; 5410 } 5411 } 5412 5413 /// P_Triangulate_Polygon: 5414 void CustomStripifier::P_Triangulate_Polygon( int out_edge1,int out_edge2, 5415 int in_edge1, int in_edge2, 5416 int size, int *index, 5417 FILE *fp, int reversed, 5418 int face_id, int *next_id, 5419 ListHead *pListHead, 5420 P_ADJACENCIES temp2, 5421 int where) 5422 { 5423 /* We have a polygon greater than 4 sides, which we wish 5424 to partially triangulate 5425 */ 5426 int next_bucket,vertex4,dummy = 60; 5427 int *temp; 5428 5429 5430 /* Since we are calling this recursively, we have to check whether 5431 we are down to the case of the quad. 5432 */ 5433 if (size == 4) 5434 { 5435 P_Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size, 5436 index,reversed,face_id, 5437 pListHead,temp2,where); 5438 return; 5439 } 5440 5441 /* We do not have a specified input edge, and therefore we 5442 can make it anything we like, as long as we still come out 5443 the output edge that we want. 5444 */ 5445 if (reversed == -1) 5446 { 5447 /* Get the vertex for the last triangle, which is 5448 the one coming out the output edge, before we do 5449 any deletions to the list. We will be doing this 5450 bottom up. 5451 */ 5452 vertex4 = AdjacentEx(out_edge1,out_edge2,index,size); 5453 temp = (int *) malloc(sizeof(int) * size); 5454 memcpy(temp,index,sizeof(int)*size); 5455 Delete_From_ListEx(out_edge2,index,size); 5456 /* We do not have to partially triangulate, since 5457 we will do the whole thing, so use the whole routine 5458 */ 5459 Triangulate_PolygonEx(vertex4,out_edge1,in_edge2, 5460 vertex4,size-1,index,fp, 5461 reversed,face_id, 5462 where); 5463 memcpy(index,temp,sizeof(int)*size); 5464 /* Lastly do the triangle that comes out the output 5465 edge. 5466 */ 5467 Output_TriEx(vertex4,out_edge1,out_edge2,NULL,-1,where); 5468 /* We were able to do the whole polygon, now we 5469 can delete the whole thing from our data structure. 5470 */ 5471 dummy = Update_AdjacenciesEx(face_id, &dummy, &dummy,&dummy,&dummy); 5472 5473 if (face_array[temp2->face_id].head == pListHead) 5474 face_array[temp2->face_id].pfNode = NULL; 5475 RemoveList(pListHead,(PLISTINFO) temp2); 5476 return; 5477 } 5478 5479 /* These are the 5 cases that we can have for the output edge */ 5480 5481 /* Are they consecutive so that we form a triangle to 5482 peel off that comes out the correct output edge, 5483 but we cannot use the whole polygon? 5484 */ 5485 if (in_edge2 == out_edge1) 5486 { 5487 Output_TriEx(in_edge1,out_edge1,out_edge2,NULL,-1,where); 5488 5489 /* Now delete the adjacencies by one for all the faces 5490 that are adjacent to the triangle that we just outputted. 5491 */ 5492 Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, 5493 &dummy,&dummy,&dummy); 5494 Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 5495 face_id,&dummy,&dummy,&dummy); 5496 5497 /* Put the new face in the proper bucket of adjacencies */ 5498 next_bucket=Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE); 5499 next_bucket=Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,TRUE); 5500 5501 /* Create a new edgelist without the triangle that 5502 was just outputted. 5503 */ 5504 Delete_From_ListEx(in_edge2,index,size); 5505 /* Update the face data structure, by deleting the old 5506 face and putting in the polygon minus the triangle 5507 as the new face, here we will be decrementing the size 5508 by one. 5509 */ 5510 New_Size_Face(face_id); 5511 return; 5512 } 5513 5514 /* Next case is where it is again consecutive, but the triangle 5515 formed by the consecutive edges do not come out of the 5516 correct output edge. (the input edge will be reversed in 5517 the next triangle) 5518 */ 5519 else if (in_edge1 == out_edge1) 5520 { 5521 /* Get vertex adjacent to in_edge2, but is not in_edge1 */ 5522 Output_TriEx(in_edge2,in_edge1,out_edge2,NULL,-1,where); 5523 5524 /* Now delete the adjacencies by one for all the faces 5525 that are adjacent to the triangle that we just outputted. 5526 */ 5527 Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, 5528 &dummy,&dummy,&dummy); 5529 Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 5530 face_id,&dummy,&dummy,&dummy); 5531 5532 /* Put the new face in the proper bucket of adjacencies */ 5533 next_bucket=Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE); 5534 next_bucket=Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,TRUE); 5535 5536 /* Create a new edgelist without the triangle that 5537 was just outputted. 5538 */ 5539 Delete_From_ListEx(in_edge1,index,size); 5540 /* Update the face data structure, by deleting the old 5541 face and putting in the polygon minus the triangle 5542 as the new face, here we will be decrementing the size 5543 by one. 5544 */ 5545 New_Size_Face(face_id); 5546 return; 5547 } 5548 5549 /* Consecutive cases again, but with the output edge reversed */ 5550 else if (in_edge1 == out_edge2) 5551 { 5552 Output_TriEx(in_edge2,in_edge1,out_edge1,NULL,-1,where); 5553 5554 /* Now delete the adjacencies by one for all the faces 5555 that are adjacent to the triangle that we just outputted. 5556 */ 5557 Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, 5558 &dummy,&dummy,&dummy); 5559 Delete_AdjEx(out_edge1,out_edge2,&dummy,&dummy, 5560 face_id,&dummy,&dummy,&dummy); 5561 5562 /* Put the new face in the proper bucket of adjacencies */ 5563 next_bucket=Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE); 5564 next_bucket=Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,TRUE); 5565 5566 /* Create a new edgelist without the triangle that 5567 was just outputted. 5568 */ 5569 Delete_From_ListEx(in_edge1,index,size); 5570 /* Update the face data structure, by deleting the old 5571 face and putting in the polygon minus the triangle 5572 as the new face, here we will be decrementing the size 5573 by one. 5574 */ 5575 New_Size_Face(face_id); 5576 return; 5577 } 5578 else if (in_edge2 == out_edge2) 5579 { 5580 Output_TriEx(in_edge1,in_edge2,out_edge1,NULL,-1,where); 5581 5582 /* Now delete the adjacencies by one for all the faces 5583 that are adjacent to the triangle that we just outputted. 5584 */ 5585 Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, 5586 &dummy,&dummy,&dummy); 5587 Delete_AdjEx(out_edge2,out_edge1,&dummy,&dummy, 5588 face_id,&dummy,&dummy,&dummy); 5589 5590 /* Put the new face in the proper bucket of adjacencies */ 5591 next_bucket=Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE); 5592 next_bucket=Change_FaceEx(face_id,out_edge1,out_edge2,pListHead,TRUE); 5593 5594 /* Create a new edgelist without the triangle that 5595 was just outputted. 5596 */ 5597 Delete_From_ListEx(in_edge2,index,size); 5598 /* Update the face data structure, by deleting the old 5599 face and putting in the polygon minus the triangle 5600 as the new face, here we will be decrementing the size 5601 by one. 5602 */ 5603 New_Size_Face(face_id); 5604 return; 5605 } 5606 5607 /* Else the edge is not consecutive, and it is sufficiently 5608 far away, for us not to make a conclusion at this time. 5609 So we can take off a triangle and recursively call this 5610 function. 5611 */ 5612 else 5613 { 5614 if (!reversed) 5615 { 5616 vertex4 = AdjacentEx(in_edge2,in_edge1,index,size); 5617 Output_TriEx(in_edge1,in_edge2,vertex4,NULL,-1,where); 5618 5619 /* Now delete the adjacencies by one for all the faces 5620 that are adjacent to the triangle that we just outputted. 5621 */ 5622 Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, 5623 &dummy,&dummy,&dummy); 5624 Delete_AdjEx(in_edge1,vertex4,&dummy,&dummy, 5625 face_id,&dummy,&dummy,&dummy); 5626 5627 /* Put the new face in the proper bucket of adjacencies */ 5628 next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2, 5629 pListHead,FALSE); 5630 next_bucket = Change_FaceEx(face_id,in_edge1,vertex4, 5631 pListHead,FALSE); 5632 5633 /* Create a new edgelist without the triangle that 5634 was just outputted. 5635 */ 5636 Delete_From_ListEx(in_edge1,index,size); 5637 /* Update the face data structure, by deleting the old 5638 face and putting in the polygon minus the triangle 5639 as the new face, here we will be decrementing the size 5640 by one. 5641 */ 5642 New_Size_Face(face_id); 5643 5644 /* Save the info for the new bucket, we will need it on 5645 the next pass for the variables, pListHead and temp 5646 */ 5647 pListHead = array[next_bucket]; 5648 temp2 = face_array[face_id].pfNode; 5649 if (temp2 == NULL) 5650 { 5651 printf("There is an error finding the next polygon10\n", 5652 next_bucket,face_id); 5653 exit(0); 5654 } 5655 5656 P_Triangulate_Polygon(out_edge1,out_edge2,in_edge2, 5657 vertex4,size-1,index,fp,!reversed, 5658 face_id,next_id,pListHead,temp2,where); 5659 } 5660 else 5661 { 5662 vertex4 = AdjacentEx(in_edge1,in_edge2,index,size); 5663 Output_TriEx(in_edge2,in_edge1,vertex4,NULL,-1,where); 5664 5665 /* Now delete the adjacencies by one for all the faces 5666 that are adjacent to the triangle that we just outputted. 5667 */ 5668 Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, 5669 &dummy,&dummy,&dummy); 5670 Delete_AdjEx(in_edge2,vertex4,&dummy,&dummy, 5671 face_id,&dummy,&dummy,&dummy); 5672 5673 /* Put the new face in the proper bucket of adjacencies */ 5674 next_bucket = Change_FaceEx(face_id,in_edge1,in_edge2, 5675 pListHead,FALSE); 5676 next_bucket = Change_FaceEx(face_id,in_edge2,vertex4, 5677 pListHead,FALSE); 5678 5679 /* Create a new edgelist without the triangle that 5680 was just outputted. 5681 */ 5682 Delete_From_ListEx(in_edge2,index,size); 5683 5684 /* Update the face data structure, by deleting the old 5685 face and putting in the polygon minus the triangle 5686 as the new face, here we will be decrementing the size 5687 by one. 5688 */ 5689 New_Size_Face(face_id); 5690 5691 /* Save the info for the new bucket, we will need it on 5692 the next pass for the variables, pListHead and temp 5693 */ 5694 pListHead = array[next_bucket]; 5695 temp2 = face_array[face_id].pfNode; 5696 if (temp2 == NULL) 5697 { 5698 printf("There is an error finding the next polygon11 %d %d\n", 5699 face_id,next_bucket); 5700 exit(0); 5701 } 5702 5703 P_Triangulate_Polygon(out_edge1,out_edge2,vertex4, 5704 in_edge1,size-1,index,fp,!reversed, 5705 face_id,next_id,pListHead,temp2,where); 5706 } 5707 return; 5708 } 5709 } 5710 5711 /// P_Triangulate: 5712 void CustomStripifier::P_Triangulate( int out_edge1,int out_edge2,int in_edge1, 5713 int in_edge2, int size, int *index, 5714 FILE *output, int reversed, int face_id, 5715 int *next_id, ListHead *pListHead, 5716 P_ADJACENCIES temp,int where) 5717 { 5718 5719 if (size == 4) 5720 P_Triangulate_Quad(out_edge1,out_edge2,in_edge1,in_edge2,size, 5721 index,reversed,face_id, 5722 pListHead,temp,where); 5723 else 5724 P_Triangulate_Polygon(out_edge1,out_edge2,in_edge1,in_edge2,size, 5725 index,output,reversed,face_id,next_id, 5726 pListHead,temp,where); 5727 } 5728 5729 void CustomStripifier::Partial_Triangulate(int size,int *index, 5730 FILE *output,int next_face_id,int face_id, 5731 int *next_id,ListHead *pListHead, 5732 P_ADJACENCIES temp, int where) 5733 { 5734 int id1,id2,id3; 5735 int nedge1,nedge2; 5736 int reversed; 5737 5738 /* We have a polygon that has to be triangulated and we cannot 5739 do it blindly, ie we will try to come out on the edge that 5740 has the least number of adjacencies, But also we do not 5741 want to triangulate the whole polygon now, so that means 5742 we will output the least number of triangles that we can 5743 and then update the data structures, with the polygon 5744 that is left after we are done. 5745 */ 5746 Last_Edge(&id1,&id2,&id3,0); 5747 5748 /* Find the edge that is adjacent to the new face , 5749 also return whether the orientation is reversed in the 5750 face of the input edge, which is id2 and id3. 5751 */ 5752 reversed = Get_EdgeEx(&nedge1,&nedge2,index,next_face_id,size,id2,id3); 5753 5754 /* Input edge and output edge can be the same if there are more than 5755 one polygon on an edge 5756 */ 5757 if ( ((nedge1 == id2) && (nedge2 == id3)) || 5758 ((nedge1 == id3) && (nedge2 == id2)) ) 5759 /* Set output edge arbitrarily but when come out of here the 5760 next face will be on the old output edge (identical one) 5761 */ 5762 nedge2 = Return_Other(index,id2,id3); 5763 5764 /* Do the triangulation */ 5765 P_Triangulate(nedge1,nedge2,id2,id3,size,index,output,reversed, 5766 face_id,next_id,pListHead,temp,where); 5767 } 5768 5769 /// Input_Edge: 5770 void CustomStripifier::Input_Edge(int face_id, int *index, 5771 int size, int in_edge1, 5772 int in_edge2, ListHead *pListHead, 5773 int where) 5774 { 5775 /* The polygon had an input edge, specified by input1 and input2 */ 5776 5777 int output1,next_bucket; 5778 int vertex4, vertex5,dummy=60; 5779 5780 output1 = Get_Output_Edge(face_id,size,index,in_edge1,in_edge2); 5781 vertex5 = AdjacentEx(in_edge2,in_edge1,index,size); 5782 vertex4 = AdjacentEx(in_edge1,in_edge2,index,size); 5783 5784 if (vertex4 == output1) 5785 { 5786 Output_TriEx(in_edge2,in_edge1,output1,NULL,-1,where); 5787 /* Now delete the adjacencies by one for all the faces 5788 that are adjacent to the triangle that we just outputted. 5789 */ 5790 Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, 5791 &dummy,&dummy,&dummy); 5792 Delete_AdjEx(in_edge2,output1,&dummy,&dummy, 5793 face_id,&dummy,&dummy,&dummy); 5794 /* Put the new face in the proper bucket of adjacencies */ 5795 next_bucket=Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE); 5796 next_bucket=Change_FaceEx(face_id,in_edge2,output1,pListHead,FALSE); 5797 5798 /* Create a new edgelist without the triangle that 5799 was just outputted. 5800 */ 5801 Delete_From_ListEx(in_edge2,index,size); 5802 5803 } 5804 else if (vertex5 == output1) 5805 { 5806 Output_TriEx(in_edge1,in_edge2,vertex5,NULL,-1,where); 5807 /* Now delete the adjacencies by one for all the faces 5808 that are adjacent to the triangle that we just outputted. 5809 */ 5810 Delete_AdjEx(in_edge1,in_edge2,&dummy,&dummy,face_id, 5811 &dummy,&dummy,&dummy); 5812 Delete_AdjEx(in_edge1,vertex5,&dummy,&dummy, 5813 face_id,&dummy,&dummy,&dummy); 5814 /* Put the new face in the proper bucket of adjacencies */ 5815 next_bucket=Change_FaceEx(face_id,in_edge1,in_edge2,pListHead,FALSE); 5816 next_bucket=Change_FaceEx(face_id,in_edge1,vertex5,pListHead,FALSE); 5817 5818 /* Create a new edgelist without the triangle that 5819 was just outputted. 5820 */ 5821 Delete_From_ListEx(in_edge1,index,size); 5822 } 5823 5824 /* Update the face data structure, by deleting the old 5825 face and putting in the polygon minus the triangle 5826 as the new face, here we will be decrementing the size 5827 by one. 5828 */ 5829 New_Size_Face(face_id); 5830 return; 5831 } 5832 5833 /// Inside_Polygon: 5834 void CustomStripifier::Inside_Polygon(int size,int *index, 5835 int face_id,ListHead *pListHead, int where) 5836 { 5837 /* We know that we have a polygon that is greater than 4 sides, and 5838 that it is better for us to go inside the polygon for the next 5839 one, since inside will have less adjacencies than going outside. 5840 So, we are not doing partial for a part of the polygon. 5841 */ 5842 int id1,id2,id3; 5843 int new1,new2; 5844 5845 Last_Edge(&id1,&id2,&id3,0); 5846 5847 /* See if the input edge existed in the polygon, that will help us */ 5848 if (Exist(face_id,id2,id3)) 5849 Input_Edge(face_id,index,size,id2,id3,pListHead,where); 5850 else 5851 { 5852 /* Make one of the input edges 5853 We will choose it by trying to get an edge that has something 5854 in common with the last triangle, or by getting the edge that 5855 is adjacent to the least number of thigs, with preference given 5856 to the first option 5857 */ 5858 5859 Get_Input_Edge(index,id1,id2,id3,&new1,&new2,size,face_id); 5860 Input_Edge(face_id,index,size,new1,new2,pListHead,where); 5861 } 5862 } 5863 5864 /// Finished: 5865 int CustomStripifier::Finished(int *swap, FILE *output, int startnewstrip) 5866 { 5867 /* We have finished all the triangles, now is time to output to 5868 the data file. In the strips data structure, every three ids 5869 is a triangle. Now we see whether we can swap, or make a new strip 5870 or continue the strip, and output the data accordingly to the 5871 data file. 5872 */ 5873 int num,x,vertex1,vertex2; 5874 ListHead *pListHead; 5875 int id[2],other1,other2,index = 0,a,b,c; 5876 P_STRIPS temp1,temp2,temp3,temp4,temp5,temp6; 5877 BOOL cptexture; 5878 *swap =0; 5879 5880 cptexture = text; 5881 pListHead = strips[0]; 5882 if (pListHead == NULL) 5883 return 0; 5884 5885 num = NumOnList(pListHead); 5886 //printf ("There are %d triangles in the extend\n",num/3); 5887 5888 // Go through the list triangle by triangle 5889 temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 0); 5890 temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 1); 5891 temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 2); 5892 5893 // Next triangle for lookahead 5894 temp4 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 3); 5895 5896 // There is only one polygon in the strip 5897 if (temp4 == NULL) 5898 { 5899 // Data might be mixed and we do not have textures for some of the vertices 5900 if ((text) && (vt[temp3->face_id] == 0)) 5901 cptexture = FALSE; 5902 if ((norm) && (!cptexture)) { 5903 if (startnewstrip && orient) // If we want to keep orientation 5904 preserve_strip_orientation_with_normal(output, temp3->face_id+1,vn[temp3->face_id]+1, 5905 temp2->face_id+1,vn[temp2->face_id]+1, temp1->face_id+1,vn[temp1->face_id]+1); 5906 5907 fprintf(output," %d//%d %d//%d %d//%d", temp3->face_id+1,vn[temp3->face_id]+1, 5908 temp2->face_id+1,vn[temp2->face_id]+1, temp1->face_id+1,vn[temp1->face_id]+1); 5909 } 5910 else if ((cptexture) && (!norm)) { 5911 if (startnewstrip && orient) /* If we want to keep orientation */ 5912 preserve_strip_orientation_with_texture(output, temp3->face_id+1,vt[temp3->face_id]+1, 5913 temp2->face_id+1,vt[temp2->face_id]+1, temp1->face_id+1,vt[temp1->face_id]+1); 5914 5915 fprintf(output," %d/%d %d/%d %d/%d", temp3->face_id+1,vt[temp3->face_id]+1, 5916 temp2->face_id+1,vt[temp2->face_id]+1, temp1->face_id+1,vt[temp1->face_id]+1); 5917 } 5918 else if ((cptexture)&& (norm)) { 5919 if (startnewstrip && orient) /* If we want to keep orientation */ 5920 preserve_strip_orientation_with_texture_and_normal(output, temp3->face_id+1,vt[temp3->face_id]+1,vn[temp3->face_id]+1, 5921 temp2->face_id+1,vt[temp2->face_id]+1,vn[temp2->face_id]+1, temp1->face_id+1,vt[temp1->face_id]+1,vn[temp1->face_id]+1); 5922 5923 fprintf(output," %d/%d/%d %d/%d/%d %d/%d/%d", temp3->face_id+1,vt[temp3->face_id]+1,vn[temp3->face_id]+1, 5924 temp2->face_id+1,vt[temp2->face_id]+1,vn[temp2->face_id]+1, temp1->face_id+1,vt[temp1->face_id]+1,vn[temp1->face_id]+1); 5925 } 5926 else 5927 { 5928 if (startnewstrip && orient) /* If we want to keep orientation */ 5929 preserve_strip_orientation(output, temp3->face_id+1,temp2->face_id+1,temp1->face_id+1); 5930 5931 fprintf(output," %d %d %d", temp3->face_id+1,temp2->face_id+1,temp1->face_id+1); 5932 mi_vector[num_tiras].push_back(temp3->face_id); 5933 mi_vector[num_tiras].push_back(temp2->face_id); 5934 mi_vector[num_tiras].push_back(temp1->face_id); 5935 } 5936 Free_Strips(); 5937 5938 return 1; 5939 } 5940 5941 // We have a real strip 5942 temp5 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 4); 5943 temp6 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 5); 5944 5945 if ((temp1 == NULL) || (temp2 == NULL) || (temp3 == NULL) || (temp5 == NULL) || (temp6 == NULL)) 5946 { 5947 printf("There is an error in the output of the triangles\n"); 5948 exit(0); 5949 } 5950 5951 // Find the vertex in the first triangle that is not in the second 5952 vertex1 = Different(temp1->face_id,temp2->face_id,temp3->face_id, temp4->face_id,temp5->face_id,temp6->face_id, &other1,&other2); 5953 // Find the vertex in the second triangle that is not in the first 5954 vertex2 = Different(temp4->face_id,temp5->face_id,temp6->face_id, temp1->face_id,temp2->face_id,temp3->face_id, &other1,&other2); 5955 5956 // Lookahead for the correct order of the 2nd and 3rd vertex of the first triangle 5957 temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 6); 5958 temp2 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 7); 5959 temp3 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, 8); 5960 5961 if (temp1 != NULL) 5962 other1 = Different(temp3->face_id,temp4->face_id,temp5->face_id, temp1->face_id,temp2->face_id,temp3->face_id,&other1,&a); 5963 5964 id[index] = vertex1; index = !index; 5965 id[index] = other1; index = !index; 5966 id[index] = other2; index = !index; 5967 5968 a = temp4->face_id; 5969 b = temp5->face_id; 5970 c = temp6->face_id; 5971 5972 /* 5973 // If we need to rearrange the first sequence because otherwise there would have been a swap. 5974 if ((temp3 != NULL) && (text) && ( vt[temp3->face_id]==0)) 5975 cptexture = FALSE; 5976 if ((norm) && (!cptexture)) { 5977 if (orient && startnewstrip) // If we want to keep orientation 5978 preserve_strip_orientation_with_normal(output, vertex1+1,vn[vertex1]+1, other1+1,vn[other1]+1, other2+1,vn[other2]+1); 5979 5980 fprintf(output," %d//%d %d//%d %d//%d", vertex1+1,vn[vertex1]+1, other1+1,vn[other1]+1, other2+1,vn[other2]+1); 5981 } 5982 else if ((cptexture) && (!norm)) { 5983 if (orient && startnewstrip) // If we want to keep orientation 5984 preserve_strip_orientation_with_texture(output, vertex1+1,vt[vertex1]+1, other1+1,vt[other1]+1, other2+1,vt[other2]+1); 5985 5986 fprintf(output," %d/%d %d/%d %d/%d", vertex1+1,vt[vertex1]+1, other1+1,vt[other1]+1, other2+1,vt[other2]+1); 5987 } 5988 else if ((cptexture) && (norm)) { 5989 if (orient && startnewstrip) // If we want to keep orientation 5990 preserve_strip_orientation_with_texture_and_normal(output, vertex1+1,vt[vertex1]+1,vn[vertex1]+1, 5991 other1+1,vt[other1]+1,vn[other1]+1, other2+1,vt[other2]+1,vn[other2]+1); 5992 5993 fprintf(output," %d/%d/%d %d/%d/%d %d/%d/%d", vertex1+1,vt[vertex1]+1,vn[vertex1]+1, 5994 other1+1,vt[other1]+1,vn[other1]+1, other2+1,vt[other2]+1,vn[other2]+1); 5995 } 5996 else 5997 { 5998 */ 5999 if (orient && startnewstrip) // If we want to keep orientation 6000 preserve_strip_orientation(output,vertex1+1,other1+1,other2+1); 6001 6002 fprintf(output," %d %d %d",vertex1+1,other1+1,other2+1); 6003 mi_vector[num_tiras].push_back(vertex1); 6004 mi_vector[num_tiras].push_back(other1); 6005 mi_vector[num_tiras].push_back(other2); 6006 6007 /* 6008 } 6009 */ 6010 for (x = 6; x < num ; x = x+3) 6011 { 6012 // Get the next triangle 6013 temp1 = ( P_STRIPS ) PeekList( pListHead, LISTHEAD, x); 6014 temp2 = ( P_STRIPS ) GetNextNode(temp1); 6015 temp3 = ( P_STRIPS ) GetNextNode(temp2); 6016 6017 // Error checking 6018 if (!(member(id[0],a,b,c)) || !(member(id[1],a,b,c)) || !(member(vertex2,a,b,c))) 6019 { 6020 // If we used partial we might have a break in the middle of a strip 6021 fprintf(output,"\nt"); 6022 startnewstrip = 1; 6023 mi_vector_tipo nada; 6024 mi_vector.push_back(nada); 6025 num_tiras++; 6026 // Find the vertex in the first triangle that is not in the second 6027 vertex1 = Different(a,b,c,temp1->face_id,temp2->face_id,temp3->face_id,&other1,&other2); 6028 // Find the vertex in the second triangle that is not in the first 6029 vertex2 = Different(temp1->face_id,temp2->face_id,temp3->face_id, a,b,c,&other1,&other2); 6030 6031 id[index] = vertex1; index = !index; 6032 id[index] = other1; index = !index; 6033 id[index] = other2; index = !index; 6034 } 6035 6036 if ((temp1 == NULL ) || (temp2 == NULL) || (temp3 == NULL)) 6037 { 6038 printf("There is an error in the triangle list \n"); 6039 exit(0); 6040 } 6041 6042 if ((id[0] == id[1]) || (id[0] == vertex2)) 6043 continue; 6044 6045 if ((member(id[index],temp1->face_id,temp2->face_id,temp3->face_id))) 6046 { 6047 if ((text) && ( vt[id[index]]==0)) 6048 cptexture = FALSE; 6049 if ((!norm) && (!cptexture)) 6050 { 6051 fprintf(output," %d",id[index]+1); 6052 mi_vector[num_tiras].push_back(id[index]); 6053 } 6054 else if ((norm) && (!cptexture)) 6055 fprintf(output," %d//%d",id[index]+1,vn[id[index]]+1); 6056 else if ((!norm) && (cptexture)) 6057 fprintf(output," %d/%d",id[index]+1,vt[id[index]]+1); 6058 else 6059 fprintf(output," %d/%d/%d", id[index]+1,vt[id[index]]+1,vn[id[index]]+1); 6060 6061 index = !index; 6062 *swap = *swap + 1; 6063 } 6064 6065 if ((text) && ( vt[vertex2]==0)) 6066 cptexture = FALSE; 6067 if ((!norm) && (!cptexture)) 6068 { 6069 fprintf(output,"\nq %d",vertex2+1); 6070 mi_vector[num_tiras].push_back(vertex2); 6071 } 6072 else if ((norm) && (!cptexture)) 6073 fprintf(output,"\nq %d//%d",vertex2+1,vn[vertex2]+1); 6074 else if ((!norm) && (cptexture)) 6075 fprintf(output,"\nq %d/%d",vertex2+1,vt[vertex2]+1); 6076 else 6077 fprintf(output,"\nq %d/%d/%d",vertex2+1,vt[vertex2]+1,vn[vertex2]+1); 6078 6079 id[index] = vertex2; index = !index; 6080 6081 // Get the next vertex not in common 6082 vertex2 = Different(temp1->face_id,temp2->face_id,temp3->face_id, a,b,c,&other1,&other2); 6083 a = temp1->face_id; 6084 b = temp2->face_id; 6085 c = temp3->face_id; 6086 } 6087 // Do the last vertex 6088 if ((text) && (vt[vertex2]==0)) 6089 { 6090 if (cptexture) 6091 fprintf(output,"\nq"); 6092 cptexture = FALSE; 6093 } 6094 6095 if ((!norm) && (!cptexture)) 6096 { 6097 fprintf(output," %d",vertex2+1); 6098 mi_vector[num_tiras].push_back(vertex2); 6099 } 6100 else if ((norm) && (!cptexture)) 6101 fprintf(output," %d//%d",vertex2+1,vn[vertex2]+1); 6102 else if ((!norm) && (cptexture)) 6103 fprintf(output," %d/%d",vertex2+1,vt[vertex2]+1); 6104 else 6105 fprintf(output," %d/%d/%d",vertex2+1,vt[vertex2]+1,vn[vertex2]+1); 6106 6107 Free_Strips(); 6108 return (num/3); 6109 } 6110 6111 /// Output_Tri: 6112 void CustomStripifier::Output_Tri(int id1, int id2, int id3,BOOL end) 6113 { 6114 /* We will save everything into a list, rather than output at once, 6115 as was done in the old routine. This way for future modifications 6116 we can change the strips later on if we want to. 6117 */ 6118 6119 int temp1,temp2,temp3; 6120 6121 /* Make sure we do not have an error */ 6122 /* There are degeneracies in some of the files */ 6123 if ( (id1 == id2) || (id1 == id3) || (id2 == id3)) 6124 { 6125 printf("Degenerate triangle %d %d %d\n",id1,id2,id3); 6126 exit(0); 6127 } 6128 else 6129 { 6130 Last_Edge(&temp1,&temp2,&temp3,0); 6131 Add_Id_Strips(id1,end); 6132 Add_Id_Strips(id2,end); 6133 Add_Id_Strips(id3,end); 6134 Last_Edge(&id1,&id2,&id3,1); 6135 } 6136 } 6137 6138 /// Polygon_Output: 6139 int CustomStripifier::Polygon_Output( P_ADJACENCIES temp, int face_id, 6140 int bucket, ListHead *pListHead, 6141 BOOL first, int *swaps, 6142 FILE *bands, int color1, 6143 int color2, int color3, 6144 BOOL global, BOOL end) 6145 { 6146 ListHead *pListFace; 6147 PF_FACES face; 6148 int next_face_id,next_bucket,e1,e2,e3,other1,other2,other3; 6149 P_ADJACENCIES lpListInfo; 6150 int ties=0; 6151 6152 /* We have a polygon to output, the id is face id, and the number 6153 of adjacent polygons to it is bucket. This routine extends the patches from 6154 either end to make longer triangle strips. 6155 */ 6156 6157 6158 /* Now get the edge */ 6159 Last_Edge(&e1,&e2,&e3,0); 6160 6161 /* Get the polygon with id face_id */ 6162 pListFace = PolFaces[face_id]; 6163 face = (PF_FACES) PeekList(pListFace,LISTHEAD,0); 6164 6165 /* We can't go any more */ 6166 if ((face->nPolSize == 1) || ((face->nPolSize == 4) && (global))) 6167 /* if global, then we are still doing patches */ 6168 { 6169 /* Remove it from the list so we do not have to waste 6170 time visiting it in the future, or winding up in an infinite loop 6171 if it is the first on that we are looking at for a possible strip 6172 */ 6173 if (face->nPolSize == 1) { 6174 if (face_array[temp->face_id].head == pListHead) 6175 face_array[temp->face_id].pfNode = NULL; 6176 RemoveList(pListHead,(PLISTINFO) temp); 6177 } 6178 if (first) 6179 return 0; 6180 else 6181 return (Finished(swaps,bands,0)); 6182 } 6183 6184 if (face->nPolSize == 3) 6185 { 6186 /* It is already a triangle */ 6187 if (bucket == 0) 6188 { 6189 /* It is not adjacent to anything so we do not have to 6190 worry about the order of the sides or updating adjacencies 6191 */ 6192 6193 next_face_id = Different(*(face->pPolygon),*(face->pPolygon+1), 6194 *(face->pPolygon+2), 6195 e1,e2,e3,&other1,&other2); 6196 face->nPolSize = 1; 6197 6198 /* If this is the first triangle in the strip */ 6199 if ((e2 == 0) && (e3 ==0)) 6200 { 6201 e2 = other1; 6202 e3 = other2; 6203 } 6204 6205 Output_Tri(e2,e3,next_face_id,end); 6206 if (face_array[temp->face_id].head == pListHead) 6207 face_array[temp->face_id].pfNode = NULL; 6208 RemoveList(pListHead,(PLISTINFO) temp); 6209 return (Finished(swaps,bands,0)); 6210 } 6211 6212 6213 /* It is a triangle with adjacencies. This means that we 6214 have to: 6215 1. Update the adjacencies in the list, because we are 6216 using this polygon and it will be deleted. 6217 2. Get the next polygon. 6218 */ 6219 else 6220 { 6221 /* Return the face_id of the next polygon we will be using, 6222 while updating the adjacency list by decrementing the 6223 adjacencies of everything adjacent to the current triangle. 6224 */ 6225 6226 next_face_id = Update_Adjacencies(face_id, &next_bucket, &e1,&e2,&ties); 6227 /* Maybe we deleted something in a patch and could not 6228 find an adj polygon */ 6229 if (next_face_id == -1) 6230 { 6231 Output_Tri(*(face->pPolygon),*(face->pPolygon+1), 6232 *(face->pPolygon+2),end); 6233 face->nPolSize = 1; 6234 if (face_array[temp->face_id].head == pListHead) 6235 face_array[temp->face_id].pfNode = NULL; 6236 RemoveList(pListHead,(PLISTINFO) temp); 6237 return (Finished(swaps,bands,0)); 6238 } 6239 6240 6241 /* Find the other vertex to transmit in the triangle */ 6242 e3 = Return_Other(face->pPolygon,e1,e2); 6243 Last_Edge(&other1,&other2,&other3,0); 6244 6245 if ((other2 != 0) && (other3 != 0)) 6246 { 6247 /* See which vertex in the output edge is not in the input edge */ 6248 if ((e1 != other2) && (e1 != other3)) 6249 e3 = e1; 6250 else if ((e2 != other2) && (e2 != other3)) 6251 e3 = e2; 6252 else 6253 { 6254 printf("There is an error in the tri with adj\n"); 6255 exit(0); 6256 } 6257 6258 /* See which vertex of the input edge is not in the output edge */ 6259 if ((other2 != e1) && (other2 != e2)) 6260 { 6261 other1 = other2; 6262 other2 = other3; 6263 } 6264 else if ((other3 != e1) && (other3 != e2)) 6265 other1 = other3; 6266 else 6267 { 6268 printf("There is an error in getting the tri with adj\n"); 6269 exit(0); 6270 } 6271 6272 } 6273 else 6274 { 6275 /* We are the first triangle in the strip and the starting edge 6276 has not been set yet 6277 */ 6278 /* Maybe we deleted something in a patch and could not 6279 find an adj polygon */ 6280 if (next_face_id == -1) 6281 { 6282 Output_Tri(*(face->pPolygon),*(face->pPolygon+1), 6283 *(face->pPolygon+2),end); 6284 face->nPolSize = 1; 6285 face_array[temp->face_id].pfNode = NULL; 6286 RemoveList(pListHead,(PLISTINFO) temp); 6287 return (Finished(swaps,bands,0)); 6288 } 6289 6290 other1 = e3; 6291 e3 = e2; 6292 other2 = e1; 6293 } 6294 6295 /* At this point the adjacencies have been updated and we 6296 have the next polygon id 6297 */ 6298 6299 Output_Tri(other1,other2,e3,end); 6300 face->nPolSize = 1; 6301 if (face_array[temp->face_id].head == pListHead) 6302 face_array[temp->face_id].pfNode = NULL; 6303 RemoveList(pListHead,(PLISTINFO) temp); 6304 6305 /* Maybe we deleted something in a patch and could not 6306 find an adj polygon */ 6307 if (next_face_id == -1) 6308 return (Finished(swaps,bands,0)); 6309 6310 if (Done(next_face_id,&next_bucket) == NULL) 6311 { 6312 printf("We deleted the next face 4%d\n",next_face_id); 6313 exit(0); 6314 } 6315 6316 pListHead = array[next_bucket]; 6317 lpListInfo = face_array[next_face_id].pfNode; 6318 if (lpListInfo == NULL) 6319 { 6320 printf("There is an error finding the next polygon3 %d\n", 6321 next_face_id); 6322 exit(0); 6323 } 6324 return (Polygon_Output(lpListInfo,next_face_id,next_bucket, 6325 pListHead, FALSE, swaps,bands, 6326 color1,color2,color3,global,end)); 6327 6328 } 6329 } 6330 6331 else 6332 { 6333 /* It is not a triangle, we have to triangulate it . 6334 Since it is not adjacent to anything we can triangulate it 6335 blindly 6336 */ 6337 if (bucket == 0) 6338 { 6339 /* It is the first polygon in the strip, therefore there is no 6340 input edge to start with. 6341 */ 6342 if ((e2 == 0) && (e3 ==0)) 6343 Blind_Triangulate(face->nPolSize,face->pPolygon,TRUE,1); 6344 6345 else 6346 Blind_Triangulate(face->nPolSize,face->pPolygon,FALSE,1); 6347 6348 if (face_array[temp->face_id].head == pListHead) 6349 face_array[temp->face_id].pfNode = NULL; 6350 RemoveList(pListHead,(PLISTINFO) temp); 6351 6352 /* We will be at the beginning of the next strip. */ 6353 face->nPolSize = 1; 6354 return (Finished(swaps,bands,0)); 6355 } 6356 6357 6358 else 6359 { 6360 6361 6362 /* WHOLE triangulation */ 6363 /* It is not a triangle and has adjacencies. 6364 This means that we have to: 6365 1. Triangulate this polygon, not blindly because 6366 we have an edge that we want to come out on, that 6367 is the edge that is adjacent to a polygon with the 6368 least number of adjacencies. Also we must come in 6369 on the last seen edge. 6370 2. Update the adjacencies in the list, because we are 6371 using this polygon . 6372 3. Get the next polygon. 6373 */ 6374 /* Return the face_id of the next polygon we will be using, 6375 while updating the adjacency list by decrementing the 6376 adjacencies of everything adjacent to the current polygon. 6377 */ 6378 6379 next_face_id = Update_Adjacencies(face_id, &next_bucket, &e1,&e2,&ties); 6380 6381 /* Maybe we deleted something in a patch and could not 6382 find an adj polygon */ 6383 if (next_face_id == -1) 6384 { 6385 6386 /* If we are at the first polygon in the strip and 6387 there is no input 6388 edge, then begin is TRUE 6389 */ 6390 if ((e2 == 0) && (e3 == 0)) 6391 Blind_Triangulate(face->nPolSize,face->pPolygon,TRUE,1); 6392 6393 else 6394 Blind_Triangulate(face->nPolSize,face->pPolygon,FALSE,1); 6395 6396 if (face_array[temp->face_id].head == pListHead) 6397 face_array[temp->face_id].pfNode = NULL; 6398 RemoveList(pListHead,(PLISTINFO) temp); 6399 6400 /* We will be at the beginning of the next strip. */ 6401 face->nPolSize = 1; 6402 return (Finished(swaps,bands,0)); 6403 } 6404 6405 if (Done(next_face_id,&next_bucket) == NULL) 6406 { 6407 printf("We deleted the next face 6 %d %d\n",next_face_id,face_id); 6408 exit(0); 6409 } 6410 6411 Non_Blind_Triangulate(face->nPolSize,face->pPolygon, 6412 bands,next_face_id,face_id,1, 6413 color1,color2,color3); 6414 6415 if (face_array[temp->face_id].head == pListHead) 6416 face_array[temp->face_id].pfNode = NULL; 6417 RemoveList(pListHead,(PLISTINFO) temp); 6418 face->nPolSize = 1; 6419 pListHead = array[next_bucket]; 6420 lpListInfo = face_array[next_face_id].pfNode; 6421 6422 if (lpListInfo == NULL) 6423 { 6424 printf("There is an error finding the next polygon2 %d %d\n", 6425 next_face_id,next_bucket); 6426 exit(0); 6427 } 6428 return (Polygon_Output(lpListInfo,next_face_id,next_bucket, 6429 pListHead, FALSE, swaps,bands, 6430 color1,color2,color3,global,end)); 6431 } 6432 6433 } 6434 } 6435 6436 /// Extend_Face: 6437 int CustomStripifier::Extend_Face(int face_id, 6438 int e1, 6439 int e2, 6440 int *swaps, 6441 FILE *bands, 6442 int color1, 6443 int color2, 6444 int color3, 6445 int *vert_norm, 6446 int normals, 6447 int *vert_texture, 6448 int texture) 6449 { 6450 int dummy = 0; 6451 int next_bucket; 6452 P_ADJACENCIES lpListInfo; 6453 ListHead *pListHead; 6454 6455 /* Try to extend backwards off of the local strip that we just found */ 6456 6457 vn = vert_norm; 6458 vt = vert_texture; 6459 norm = normals; 6460 text = texture; 6461 6462 *swaps = 0; 6463 /* Find the face that is adjacent to the edge and is not the 6464 current face. 6465 */ 6466 face_id = Find_Face(face_id, e1, e2,&next_bucket); 6467 if (face_id == -1) 6468 return 0; 6469 6470 pListHead = array[next_bucket]; 6471 lpListInfo = face_array[face_id].pfNode; 6472 6473 if (lpListInfo == NULL) 6474 { 6475 printf("There is an error finding the next polygon3 %d\n",face_id); 6476 exit(0); 6477 } 6478 Last_Edge(&dummy,&e1,&e2,1); 6479 6480 /* Find a strip extending from the patch and return the cost */ 6481 return (Polygon_Output(lpListInfo,face_id,next_bucket,pListHead,TRUE,swaps, 6482 bands,color1,color2,color3,TRUE,TRUE)); 6483 } 6484 6485 /// ParseAndFreeList: 6486 void CustomStripifier::ParseAndFreeList( ListHead *pListHead ) 6487 { 6488 PLISTINFO value; 6489 register int c; 6490 register int num; 6491 6492 /* Freeing a linked list */ 6493 num = NumOnList(pListHead); 6494 6495 for (c = 0; c< num; c++) 6496 { 6497 value = RemHead(pListHead); 6498 } 6499 } 6500 6501 /// Free_Strips: 6502 void CustomStripifier::Free_Strips() 6503 { 6504 /* Free strips data structure */ 6505 if (strips[0] == NULL) 6506 return; 6507 else 6508 ParseAndFreeList(strips[0]); 6509 } 6510 6511 /// FreeFaceTable: 6512 void CustomStripifier::FreeFaceTable(int nSize) 6513 { 6514 register int nIndex; 6515 6516 for ( nIndex=0; nIndex < nSize; nIndex++ ) 6517 { 6518 if ( PolFaces[nIndex] != NULL ) 6519 ParseAndFreeList( PolFaces[nIndex] ); 6520 } 6521 free( PolFaces ); 6522 } 6523 6524 /// FreeEdgeTable: 6525 void CustomStripifier::FreeEdgeTable(int nSize) 6526 { 6527 register int nIndex; 6528 6529 for ( nIndex=0; nIndex < nSize; nIndex++ ) 6530 { 6531 if ( PolEdges[nIndex] != NULL ) 6532 ParseAndFreeList( PolEdges[nIndex] ); 6533 } 6534 free( PolEdges ); 6535 } 6536 6537 /// End_Face_Struct: 6538 void CustomStripifier::End_Face_Struct(int numfaces) 6539 { 6540 FreeFaceTable(numfaces); 6541 } 6542 6543 /// End_Edge_Struct: 6544 void CustomStripifier::End_Edge_Struct(int numverts) 6545 { 6546 FreeEdgeTable(numverts); 6547 } 6548 6549 /// Calculate_Walks: 6550 int CustomStripifier::Calculate_Walks(int lastvert,int y, PF_FACES temp2) 6551 { 6552 /* Find the length of the walk */ 6553 6554 int previous_edge1, previous_edge2; 6555 register int nextvert,numverts,counter,walk=0; 6556 BOOL flag; 6557 F_EDGES *node; 6558 ListHead *pListHead; 6559 static int seen = 0; 6560 6561 /* Find the edge that we are currently on */ 6562 if (y != 3) 6563 { 6564 previous_edge1 = *(temp2->pPolygon +y); 6565 previous_edge2 = *(temp2->pPolygon + y + 1); 6566 } 6567 else 6568 { 6569 previous_edge1 = *(temp2->pPolygon +y); 6570 previous_edge2 = *(temp2->pPolygon); 6571 } 6572 6573 temp2->seen = seen; 6574 counter = y; 6575 6576 /*Find the adjacent face to this edge */ 6577 node = *(temp2->VertandId+y); 6578 if (node->edge[2] != lastvert) 6579 nextvert = node->edge[2]; 6580 else 6581 nextvert = node->edge[1]; 6582 6583 /* Keep walking in this direction until we cannot do so */ 6584 while ((nextvert != lastvert) && (nextvert != -1)) 6585 { 6586 walk++; 6587 pListHead = PolFaces[nextvert]; 6588 temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); 6589 numverts = temp2->nPolSize; 6590 if ((numverts != 4) || (temp2->seen == seen)) 6591 { 6592 walk--; 6593 nextvert = -1; 6594 } 6595 else 6596 { 6597 temp2->seen = seen; 6598 /* Find edge that is not adjacent to the previous one */ 6599 counter = 0; 6600 flag = TRUE; 6601 while ((counter < 3) && (flag)) 6602 { 6603 if ( ((*(temp2->pPolygon+counter) == previous_edge1) || 6604 (*(temp2->pPolygon+counter+1) == previous_edge2)) || 6605 ((*(temp2->pPolygon+counter) == previous_edge2) || 6606 (*(temp2->pPolygon+counter+1) == previous_edge1)) ) 6607 counter++; 6608 else 6609 flag = FALSE; 6610 } 6611 /* Get the IDs of the next edge */ 6612 if (counter < 3) 6613 { 6614 previous_edge1 = *(temp2->pPolygon + counter); 6615 previous_edge2 = *(temp2->pPolygon + counter + 1); 6616 } 6617 else 6618 { 6619 previous_edge1 = *(temp2->pPolygon + counter); 6620 previous_edge2 = *(temp2->pPolygon); 6621 } 6622 6623 node = *(temp2->VertandId + counter); 6624 if (node->edge[1] == nextvert) 6625 nextvert = node->edge[2]; 6626 else 6627 nextvert = node->edge[1]; 6628 } 6629 } 6630 seen++; 6631 return walk; 6632 } 6633 6634 /// Check_Right: 6635 BOOL CustomStripifier::Check_Right( int last_seen,PF_FACES temp2, 6636 int y,int face_id) 6637 { 6638 /* Check when we last saw the face to the right of the current 6639 one. We want to have seen it just before we started this strip 6640 */ 6641 6642 F_EDGES *node; 6643 ListHead *pListHead; 6644 register int nextvert,oldy; 6645 PF_FACES t; 6646 6647 oldy = y; 6648 if (y != 3) 6649 y = y+1; 6650 else 6651 y = 0; 6652 node = *(temp2->VertandId + y); 6653 if (face_id == node->edge[1]) 6654 nextvert = node->edge[2]; 6655 else 6656 nextvert = node->edge[1]; 6657 6658 if (nextvert == -1) 6659 return FALSE; 6660 6661 pListHead = PolFaces[nextvert]; 6662 t = (PF_FACES) PeekList(pListHead,LISTHEAD,0); 6663 if (t->seen != (last_seen - 1)) 6664 { 6665 /* maybe because of the numbering, we are not 6666 on the right orientation, so we have to check the 6667 opposite one to be sure 6668 */ 6669 if (oldy != 0) 6670 y = oldy-1; 6671 else 6672 y = 3; 6673 node = *(temp2->VertandId + y); 6674 if (face_id == node->edge[1]) 6675 nextvert = node->edge[2]; 6676 else 6677 nextvert = node->edge[1]; 6678 if (nextvert == -1) 6679 return FALSE; 6680 pListHead = PolFaces[nextvert]; 6681 t = (PF_FACES) PeekList(pListHead,LISTHEAD,0); 6682 if (t->seen != (last_seen - 1)) 6683 return FALSE; 6684 } 6685 return TRUE; 6686 } 6687 6688 /// Update_and_Test: 6689 int CustomStripifier::Update_and_Test(PF_FACES temp2,int y, 6690 BOOL first,int distance, 6691 int lastvert, int val) 6692 { 6693 6694 static int last_seen = 17; 6695 int previous_edge1, previous_edge2; 6696 register int original_distance,nextvert,numverts,counter; 6697 BOOL flag; 6698 F_EDGES *node; 6699 ListHead *pListHead; 6700 6701 original_distance = distance; 6702 /* Find the edge that we are currently on */ 6703 if (y != 3) 6704 { 6705 previous_edge1 = *(temp2->pPolygon +y); 6706 previous_edge2 = *(temp2->pPolygon + y + 1); 6707 } 6708 else 6709 { 6710 previous_edge1 = *(temp2->pPolygon +y); 6711 previous_edge2 = *(temp2->pPolygon); 6712 } 6713 6714 temp2->seen = val; 6715 temp2->seen2 = val; 6716 6717 node = *(temp2->VertandId+y); 6718 if (lastvert != node->edge[2]) 6719 nextvert = node->edge[2]; 6720 else 6721 nextvert = node->edge[1]; 6722 6723 /* Keep walking in this direction until we cannot do so or 6724 we go to distance */ 6725 while ((distance > 0) && (nextvert != lastvert) && (nextvert != -1)) 6726 { 6727 distance--; 6728 6729 pListHead = PolFaces[nextvert]; 6730 temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); 6731 temp2->seen = val; 6732 6733 if (temp2->seen2 == val) 6734 { 6735 last_seen++; 6736 return (original_distance - distance); 6737 } 6738 6739 temp2->seen2 = val; 6740 6741 numverts = temp2->nPolSize; 6742 6743 if (numverts != 4) 6744 nextvert = -1; 6745 6746 else if ((!first) && (!(Check_Right(last_seen,temp2,y,nextvert)))) 6747 { 6748 last_seen++; 6749 return (original_distance - distance); 6750 } 6751 else 6752 { 6753 /* Find edge that is not adjacent to the previous one */ 6754 counter = 0; 6755 flag = TRUE; 6756 while ((counter < 3) && (flag)) 6757 { 6758 if ( ((*(temp2->pPolygon+counter) == previous_edge1) || 6759 (*(temp2->pPolygon+counter+1) == previous_edge2)) || 6760 ((*(temp2->pPolygon+counter) == previous_edge2) || 6761 (*(temp2->pPolygon+counter+1) == previous_edge1)) ) 6762 counter++; 6763 else 6764 flag = FALSE; 6765 } 6766 /* Get the IDs of the next edge */ 6767 if (counter < 3) 6768 { 6769 previous_edge1 = *(temp2->pPolygon + counter); 6770 previous_edge2 = *(temp2->pPolygon + counter + 1); 6771 } 6772 else 6773 { 6774 previous_edge1 = *(temp2->pPolygon + counter); 6775 previous_edge2 = *(temp2->pPolygon); 6776 } 6777 if ( ((*(temp2->walked+counter) == -1) && 6778 (*(temp2->walked+counter+2) == -1))) 6779 { 6780 printf("There is an error in the walks!\n"); 6781 printf("1Code %d %d \n",*(temp2->walked+counter), 6782 *(temp2->walked+counter+2)); 6783 exit(0); 6784 } 6785 else 6786 { 6787 if ((*(temp2->walked+counter) == -1) && 6788 (*(temp2->walked+counter-2) == -1)) 6789 { 6790 printf("There is an error in the walks!\n"); 6791 printf("2Code %d %d \n",*(temp2->walked+counter), 6792 *(temp2->walked+counter-2)); 6793 exit(0); 6794 } 6795 } 6796 node = *(temp2->VertandId + counter); 6797 y = counter; 6798 if (node->edge[1] == nextvert) 6799 nextvert = node->edge[2]; 6800 else 6801 nextvert = node->edge[1]; 6802 } 6803 } 6804 6805 last_seen++; 6806 6807 if (distance != 0) 6808 { 6809 if (((nextvert == -1) || (nextvert == lastvert)) && (distance != 1)) 6810 return (original_distance - distance); 6811 } 6812 return original_distance; 6813 } 6814 6815 /// Test_Adj: 6816 int CustomStripifier::Test_Adj(PF_FACES temp2,int x,int north,int distance,int lastvert, int value) 6817 { 6818 /* if first time, then just update the last seen field */ 6819 if (x==1) 6820 return(Update_and_Test(temp2,north,TRUE,distance,lastvert,value)); 6821 /* else we have to check if we are adjacent to the last strip */ 6822 else 6823 return(Update_and_Test(temp2,north,FALSE,distance,lastvert,value)); 6824 } 6825 6826 /// Find_Max: 6827 int CustomStripifier::Find_Max( PF_FACES temp2, int lastvert, 6828 int north, int left, 6829 int *lastminup, int *lastminleft) 6830 { 6831 int temp,walk,counter,minup,x,band_value; 6832 int previous_edge1, previous_edge2; 6833 F_EDGES *node; 6834 ListHead *pListHead; 6835 BOOL flag; 6836 static int last_seen = 0; 6837 register int smallest_so_far,nextvert,max=-1; 6838 6839 *lastminup = MAX_BAND; 6840 *lastminleft = 1; 6841 6842 if (left == 3) 6843 { 6844 previous_edge1 = *(temp2->pPolygon + left); 6845 previous_edge2 = *(temp2->pPolygon); 6846 } 6847 6848 else 6849 { 6850 previous_edge1 = *(temp2->pPolygon + left + 1); 6851 previous_edge2 = *(temp2->pPolygon + left); 6852 } 6853 6854 temp2->seen = last_seen; 6855 walk = *(temp2->walked + left); 6856 6857 for (x=1;x<=(walk+1); x++) 6858 { 6859 /* test to see if we have a true band 6860 that is, are they adjacent to each other 6861 */ 6862 6863 minup = *(temp2->walked + north) + 1; 6864 6865 /* if we are at the very first face, then we do not 6866 have to check the adjacent faces going up 6867 and our north distance is the distance of this face's 6868 north direction. 6869 */ 6870 if (x == 1) 6871 { 6872 *lastminup = minup; 6873 minup = Test_Adj(temp2,x,north,*lastminup,lastvert,last_seen); 6874 *lastminup = minup; 6875 smallest_so_far = minup; 6876 } 6877 6878 6879 /* find the largest band that we can have */ 6880 if (minup < (*lastminup)) 6881 { 6882 /* see if we really can go up all the way 6883 temp should by less than our equal to minup 6884 if it is less, then one of the faces was not 6885 adjacent to those next to it and the band height 6886 will be smaller 6887 */ 6888 temp = Test_Adj(temp2,x,north,minup,lastvert,last_seen); 6889 if (temp > minup) 6890 { 6891 printf("There is an error in the test adj\n"); 6892 exit(0); 6893 } 6894 minup = temp; 6895 band_value = x * minup; 6896 if (minup < smallest_so_far) 6897 { 6898 if (band_value > max) 6899 { 6900 smallest_so_far = minup; 6901 *lastminup = minup; 6902 *lastminleft = x; 6903 max = band_value; 6904 } 6905 else 6906 smallest_so_far = minup; 6907 } 6908 else 6909 { 6910 band_value = x * smallest_so_far; 6911 if (band_value > max) 6912 { 6913 *lastminup = smallest_so_far; 6914 *lastminleft = x; 6915 max = band_value; 6916 } 6917 } 6918 } 6919 else 6920 { 6921 if (x != 1) 6922 { 6923 temp = Test_Adj(temp2,x,north,smallest_so_far,lastvert,last_seen); 6924 if (temp > smallest_so_far) 6925 { 6926 printf("There is an error in the test adj\n"); 6927 exit(0); 6928 } 6929 smallest_so_far = temp; 6930 } 6931 band_value = x * smallest_so_far; 6932 if (band_value > max) 6933 { 6934 *lastminup = smallest_so_far; 6935 *lastminleft = x; 6936 max = band_value; 6937 } 6938 } 6939 if ( x != (walk + 1)) 6940 { 6941 node = *(temp2->VertandId+left); 6942 if (lastvert == node->edge[1]) 6943 nextvert = node->edge[2]; 6944 else 6945 nextvert = node->edge[1]; 6946 6947 lastvert = nextvert; 6948 6949 if (nextvert == -1) 6950 return max; 6951 6952 pListHead = PolFaces[nextvert]; 6953 temp2 = (PF_FACES) PeekList(pListHead, LISTHEAD, 0); 6954 6955 /* if we have visited this face before, then there is an error */ 6956 if (((*(temp2->walked) == -1) && (*(temp2->walked+1) == -1) && 6957 (*(temp2->walked+2) == -1) && (*(temp2->walked+3) == -1)) 6958 || (temp2->nPolSize !=4) || (temp2->seen == last_seen)) 6959 { 6960 6961 if (lastvert == node->edge[1]) 6962 nextvert = node->edge[2]; 6963 else 6964 nextvert = node->edge[1]; 6965 if (nextvert == -1) 6966 return max; 6967 lastvert = nextvert; 6968 /* Last attempt to get the face ... */ 6969 pListHead = PolFaces[nextvert]; 6970 temp2 = (PF_FACES) PeekList(pListHead, LISTHEAD, 0); 6971 if (((*(temp2->walked) == -1) && (*(temp2->walked+1) == -1) && 6972 (*(temp2->walked+2) == -1) && (*(temp2->walked+3) == -1)) 6973 || (temp2->nPolSize !=4) || (temp2->seen == last_seen)) 6974 return max; /* The polygon was not saved with the edge, not 6975 enough room. We will get the walk when we come 6976 to that polygon later. 6977 */ 6978 } 6979 else 6980 { 6981 counter = 0; 6982 flag = TRUE; 6983 temp2->seen = last_seen; 6984 6985 while ((counter < 3) && (flag)) 6986 { 6987 6988 if ( ((*(temp2->pPolygon+counter) == previous_edge1) || 6989 (*(temp2->pPolygon+counter+1) == previous_edge2)) || 6990 ((*(temp2->pPolygon+counter) == previous_edge2) || 6991 (*(temp2->pPolygon+counter+1) == previous_edge1)) ) 6992 counter++; 6993 else 6994 flag = FALSE; 6995 } 6996 } 6997 6998 /* Get the IDs of the next edge */ 6999 left = counter; 7000 north = left+1; 7001 if (left ==3) 7002 north = 0; 7003 if (counter < 3) 7004 { 7005 previous_edge1 = *(temp2->pPolygon + counter + 1); 7006 previous_edge2 = *(temp2->pPolygon + counter); 7007 } 7008 else 7009 { 7010 previous_edge1 = *(temp2->pPolygon + counter); 7011 previous_edge2 = *(temp2->pPolygon); 7012 } 7013 7014 } 7015 7016 } 7017 last_seen++; 7018 return max; 7019 } 7020 7021 /// Mark_Face: 7022 void CustomStripifier::Mark_Face( PF_FACES temp2, int color1, 7023 int color2, int color3, 7024 FILE *output_file, BOOL end, 7025 int *edge1, int *edge2, 7026 int *face_id, int norms, 7027 int texture) 7028 { 7029 static int last_quad[4]; 7030 register int x,y,z=0; 7031 int saved[2]; 7032 static int output1, output2,last_id; 7033 BOOL cptexture; 7034 7035 /* Are we done with the patch? If so return the last edge that 7036 we will come out on, and that will be the edge that we will 7037 start to extend upon. 7038 */ 7039 7040 cptexture = texture; 7041 if (end) 7042 { 7043 *edge1 = output1; 7044 *edge2 = output2; 7045 *face_id = last_id; 7046 return; 7047 } 7048 7049 last_id = *face_id; 7050 *(temp2->walked) = -1; 7051 *(temp2->walked+1) = -1; 7052 *(temp2->walked+2) = -1; 7053 *(temp2->walked+3) = -1; 7054 added_quad++; 7055 temp2->nPolSize = 1; 7056 7057 if (patch == 0) 7058 { 7059 /* At the first quad in the strip -- save it */ 7060 last_quad[0] = *(temp2->pPolygon); 7061 last_quad[1] = *(temp2->pPolygon+1); 7062 last_quad[2] = *(temp2->pPolygon+2); 7063 last_quad[3] = *(temp2->pPolygon+3); 7064 patch++; 7065 } 7066 else 7067 { 7068 /* Now we have a triangle to output, find the edge in common */ 7069 for (x=0; x < 4 ;x++) 7070 { 7071 for (y=0; y< 4; y++) 7072 { 7073 if (last_quad[x] == *(temp2->pPolygon+y)) 7074 { 7075 saved[z++] = last_quad[x]; 7076 if (z > 2) 7077 { 7078 /* This means that there was a non convex or 7079 an overlapping polygon 7080 */ 7081 z--; 7082 break; 7083 } 7084 } 7085 } 7086 } 7087 7088 if (z != 2) 7089 { 7090 printf("Z is not 2 %d \n",patch); 7091 printf("4 %d %d %d %d %d %d %d\n",*(temp2->pPolygon), 7092 *(temp2->pPolygon+1),*(temp2->pPolygon+2),*(temp2->pPolygon+3), 7093 color1,color2,color3); 7094 printf("%d %d %d %d\n",last_quad[0],last_quad[1], 7095 last_quad[2],last_quad[3]); 7096 exit(1); 7097 } 7098 7099 if (patch == 1) 7100 { 7101 /* First one to output, there was no output edge */ 7102 patch++; 7103 x = Adjacent(saved[0],saved[1],last_quad,4); 7104 y = Adjacent(saved[1],saved[0],last_quad,4); 7105 7106 /* Data might be mixed and we do not have textures 7107 for some of the vertices 7108 */ 7109 if ((texture) && 7110 (((vt[x]) == 0) || 7111 ((vt[y])==0) || 7112 ((vt[saved[1]])==0))) 7113 cptexture = FALSE; 7114 7115 if ((!norms) && (!cptexture)) 7116 { 7117 fprintf(output_file,"\nt"); 7118 if (orient) /* If we want to preserve normal orientation */ 7119 preserve_strip_orientation(output_file,x+1,y+1,saved[1]+1); 7120 7121 fprintf(output_file," %d %d %d",x+1,y+1,saved[1]+1); 7122 fprintf(output_file," %d",saved[0]+1); 7123 } 7124 else if ((norms) && (!cptexture)) 7125 { 7126 fprintf(output_file,"\nt"); 7127 if (orient) /* If we want to preserve normal orientation */ 7128 preserve_strip_orientation_with_normal(output_file, 7129 x+1,vn[x] +1, 7130 y+1,vn[y] +1, 7131 saved[1]+1,vn[saved[1]]+1); 7132 7133 fprintf(output_file," %d//%d %d//%d %d//%d", 7134 x+1,vn[x] +1, 7135 y+1,vn[y] +1, 7136 saved[1]+1,vn[saved[1]]+1); 7137 fprintf(output_file," %d//%d",saved[0]+1,vn[saved[0]]+1); 7138 } 7139 else if ((cptexture) && (!norms)) 7140 { 7141 fprintf(output_file,"\nt"); 7142 if (orient) /* If we want to preserve normal orientation */ 7143 preserve_strip_orientation_with_texture(output_file, 7144 x+1,vt[x] +1, 7145 y+1,vt[y] +1, 7146 saved[1]+1,vt[saved[1]]+1); 7147 7148 fprintf(output_file," %d/%d %d/%d %d/%d", 7149 x+1,vt[x] +1, 7150 y+1,vt[y] +1, 7151 saved[1]+1,vt[saved[1]]+1); 7152 7153 fprintf(output_file," %d//%d",saved[0]+1,vt[saved[0]]+1); 7154 } 7155 else 7156 { 7157 fprintf(output_file,"\nt"); 7158 if (orient) /* If we want to preserve normal orientation */ 7159 preserve_strip_orientation_with_texture_and_normal(output_file, 7160 x+1,vt[x]+1,vn[x] +1, 7161 y+1,vt[y]+1,vn[y] +1, 7162 saved[1]+1,vt[saved[1]]+1,vn[saved[1]]+1); 7163 7164 fprintf(output_file," %d/%d/%d %d/%d/%d %d/%d/%d", 7165 x+1,vt[x]+1,vn[x] +1, 7166 y+1,vt[y]+1,vn[y] +1, 7167 saved[1]+1,vt[saved[1]]+1,vn[saved[1]]+1); 7168 7169 fprintf(output_file," %d/%d/%d", 7170 saved[0]+1,vt[saved[0]]+1,vn[saved[0]]+1); 7171 } 7172 7173 x = Adjacent(saved[0],saved[1],temp2->pPolygon,4); 7174 y = Adjacent(saved[1],saved[0],temp2->pPolygon,4); 7175 7176 /* Data might be mixed and we do not have textures 7177 for some of the vertices 7178 */ 7179 if ((texture) && ( (vt[x] == 0) || (vt[y]==0))) 7180 { 7181 if (cptexture) 7182 fprintf(output_file,"\nq"); 7183 cptexture = FALSE; 7184 } 7185 if ((!norms) && (!cptexture)) 7186 { 7187 fprintf(output_file," %d",x+1); 7188 fprintf(output_file," %d",y+1); 7189 } 7190 else if ((norms) && (!cptexture)) 7191 { 7192 fprintf(output_file," %d//%d",x+1,vn[x]+1); 7193 fprintf(output_file," %d//%d",y+1,vn[y]+1); 7194 } 7195 else if ((cptexture) && (!norms)) 7196 { 7197 fprintf(output_file," %d/%d",x+1,vt[x]+1); 7198 fprintf(output_file," %d/%d",y+1,vt[y]+1); 7199 } 7200 else 7201 { 7202 fprintf(output_file," %d/%d/%d",x+1,vt[x]+1,vn[x]+1); 7203 fprintf(output_file," %d/%d/%d",y+1,vt[y]+1,vn[y]+1); 7204 } 7205 7206 output1 = x; 7207 output2 = y; 7208 } 7209 7210 else 7211 { 7212 x = Adjacent(output2,output1,temp2->pPolygon,4); 7213 y = Adjacent(output1,output2,temp2->pPolygon,4); 7214 /* Data might be mixed and we do not have textures 7215 for some of the vertices */ 7216 if ((texture) && ( ((vt[x]) == 0) || ((vt[y])==0) )) 7217 texture = FALSE; 7218 7219 if ((!norms) && (!texture)) 7220 { 7221 fprintf(output_file,"\nq %d",x+1); 7222 fprintf(output_file," %d",y+1); 7223 } 7224 else if ((norms) && (!texture)) 7225 { 7226 fprintf(output_file,"\nq %d//%d",x+1,vn[x]+1); 7227 fprintf(output_file," %d//%d" ,y+1,vn[y]+1); 7228 } 7229 else if ((texture) && (!norms)) 7230 { 7231 fprintf(output_file,"\nq %d/%d",x+1,vt[x]+1); 7232 fprintf(output_file," %d/%d",y+1,vt[y]+1); 7233 } 7234 else 7235 { 7236 fprintf(output_file,"\nq %d/%d/%d",x+1,vt[x]+1,vn[x]+1); 7237 fprintf(output_file," %d/%d/%d",y+1,vt[y]+1,vn[y]+1); 7238 } 7239 7240 output1 = x; 7241 output2 = y; 7242 } 7243 7244 last_quad[0] = *(temp2->pPolygon); 7245 last_quad[1] = *(temp2->pPolygon+1); 7246 last_quad[2] = *(temp2->pPolygon+2); 7247 last_quad[3] = *(temp2->pPolygon+3); 7248 } 7249 } 7250 7251 /// Assign_Walk: 7252 void CustomStripifier::Assign_Walk( int lastvert, PF_FACES temp2, 7253 int front_walk, int y, 7254 int back_walk) 7255 { 7256 /* Go back and do the walk again, but this time save the lengths inside 7257 the data structure. 7258 y was the starting edge number for the front_walk length 7259 back_walk is the length of the walk along the opposite edge 7260 */ 7261 int previous_edge1, previous_edge2; 7262 register int walk = 0,nextvert,numverts,counter; 7263 BOOL flag; 7264 F_EDGES *node; 7265 ListHead *pListHead; 7266 static int seen = 0; 7267 static BOOL first = TRUE; 7268 BOOL wrap = FALSE, set = FALSE; 7269 7270 7271 /* In the "Fast_Reset" resetting will be true */ 7272 if ((resetting) && (first)) 7273 { 7274 seen = 0; 7275 first = FALSE; 7276 } 7277 7278 seen++; 7279 7280 /* Had a band who could be a cycle */ 7281 if (front_walk == back_walk) 7282 wrap = TRUE; 7283 7284 /* Find the edge that we are currently on */ 7285 if (y != 3) 7286 { 7287 previous_edge1 = *(temp2->pPolygon +y); 7288 previous_edge2 = *(temp2->pPolygon + y + 1); 7289 } 7290 else 7291 { 7292 previous_edge1 = *(temp2->pPolygon +y); 7293 previous_edge2 = *(temp2->pPolygon); 7294 } 7295 7296 /* Assign the lengths */ 7297 if (y < 2) 7298 { 7299 *(temp2->walked+y) = front_walk--; 7300 *(temp2->walked+y+2) = back_walk++; 7301 } 7302 else 7303 { 7304 *(temp2->walked+y) = front_walk--; 7305 *(temp2->walked+y-2) = back_walk++; 7306 } 7307 7308 /*Find the adjacent face to this edge */ 7309 node = *(temp2->VertandId+y); 7310 7311 if (node->edge[2] != lastvert) 7312 nextvert = node->edge[2]; 7313 else 7314 nextvert = node->edge[1]; 7315 7316 temp2->seen3 = seen; 7317 7318 /* Keep walking in this direction until we cannot do so */ 7319 while ((nextvert != lastvert) && (nextvert != -1) && (front_walk >= 0)) 7320 { 7321 walk++; 7322 pListHead = PolFaces[nextvert]; 7323 7324 temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); 7325 numverts = temp2->nPolSize; 7326 if ((numverts != 4)) 7327 { 7328 nextvert = -1; 7329 /* Don't include this face in the walk */ 7330 walk--; 7331 } 7332 else 7333 { 7334 /* Find edge that is not adjacent to the previous one */ 7335 counter = 0; 7336 flag = TRUE; 7337 while ((counter < 3) && (flag)) 7338 { 7339 if ( ((*(temp2->pPolygon+counter) == previous_edge1) || 7340 (*(temp2->pPolygon+counter+1) == previous_edge2)) || 7341 ((*(temp2->pPolygon+counter) == previous_edge2) || 7342 (*(temp2->pPolygon+counter+1) == previous_edge1)) ) 7343 counter++; 7344 else 7345 flag = FALSE; 7346 } 7347 /* Get the IDs of the next edge */ 7348 if (counter < 3) 7349 { 7350 previous_edge1 = *(temp2->pPolygon + counter); 7351 previous_edge2 = *(temp2->pPolygon + counter + 1); 7352 } 7353 else 7354 { 7355 previous_edge1 = *(temp2->pPolygon + counter); 7356 previous_edge2 = *(temp2->pPolygon); 7357 } 7358 7359 7360 /* Put in the walk lengths */ 7361 if (counter < 2) 7362 { 7363 if (((*(temp2->walked + counter) >= 0) 7364 || (*(temp2->walked +counter + 2) >= 0))) 7365 { 7366 if ((resetting == FALSE) && ((temp2->seen3) != (seen-1))) 7367 { 7368 /* If there are more than 2 polygons adjacent 7369 to an edge then we can be trying to assign more than 7370 once. We will save the smaller one 7371 */ 7372 temp2->seen3 = seen; 7373 if ( (*(temp2->walked+counter) <= front_walk) && 7374 (*(temp2->walked+counter+2) <= back_walk) ) 7375 return; 7376 if (*(temp2->walked+counter) > front_walk) 7377 *(temp2->walked+counter) = front_walk--; 7378 else 7379 front_walk--; 7380 if (*(temp2->walked+counter+2) > back_walk) 7381 *(temp2->walked+counter+2) = back_walk++; 7382 else 7383 back_walk++; 7384 } 7385 else if (resetting == FALSE) 7386 { 7387 /* if there was a cycle then all lengths are the same */ 7388 walk--; 7389 back_walk--; 7390 front_walk++; 7391 temp2->seen3 = seen; 7392 *(temp2->walked+counter) = front_walk--; 7393 *(temp2->walked+counter+2) = back_walk++; 7394 } 7395 else if (((temp2->seen3 == (seen-1)) 7396 && (wrap) && (walk == 1)) || (set)) 7397 { 7398 /* if there was a cycle then all lengths are the same */ 7399 set = TRUE; 7400 walk--; 7401 back_walk--; 7402 front_walk++; 7403 temp2->seen3 = seen; 7404 *(temp2->walked+counter) = front_walk--; 7405 *(temp2->walked+counter+2) = back_walk++; 7406 } 7407 else 7408 { 7409 temp2->seen3 = seen; 7410 *(temp2->walked+counter) = front_walk--; 7411 *(temp2->walked+counter+2) = back_walk++; 7412 } 7413 } /* if was > 0 */ 7414 else 7415 { 7416 temp2->seen3 = seen; 7417 *(temp2->walked+counter) = front_walk--; 7418 *(temp2->walked+counter+2) = back_walk++; 7419 } 7420 } 7421 7422 else 7423 { 7424 if (((*(temp2->walked + counter) >= 0 ) 7425 || (*(temp2->walked +counter - 2) >= 0)) ) 7426 { 7427 if ((temp2->seen3 != (seen-1)) && (resetting == FALSE)) 7428 { 7429 /* If there are more than 2 polygons adjacent 7430 to an edge then we can be trying to assign more than 7431 once. We will save the smaller one 7432 */ 7433 temp2->seen3 = seen; 7434 if ( (*(temp2->walked+counter) <= front_walk) && 7435 (*(temp2->walked+counter-2) <= back_walk) ) 7436 return; 7437 if (*(temp2->walked+counter) > front_walk) 7438 *(temp2->walked+counter) = front_walk--; 7439 else 7440 front_walk--; 7441 if (*(temp2->walked+counter-2) > back_walk) 7442 *(temp2->walked+counter-2) = back_walk++; 7443 else 7444 back_walk++; 7445 } 7446 else if (resetting == FALSE) 7447 { 7448 walk--; 7449 back_walk--; 7450 front_walk++; 7451 temp2->seen3 = seen; 7452 *(temp2->walked+counter) = front_walk--; 7453 *(temp2->walked+counter-2) = back_walk++; 7454 } 7455 else if (((temp2->seen3 == (seen-1)) && (walk == 1) && (wrap)) 7456 || (set)) 7457 { 7458 /* if there was a cycle then all lengths are the same */ 7459 set = TRUE; 7460 walk--; 7461 back_walk--; 7462 front_walk++; 7463 temp2->seen3 = seen; 7464 *(temp2->walked+counter) = front_walk--; 7465 *(temp2->walked+counter-2) = back_walk++; 7466 } 7467 else 7468 { 7469 temp2->seen3 = seen; 7470 *(temp2->walked+counter) = front_walk--; 7471 *(temp2->walked+counter-2) = back_walk++; 7472 } 7473 } 7474 else 7475 { 7476 temp2->seen3 = seen; 7477 *(temp2->walked+counter) = front_walk--; 7478 *(temp2->walked+counter-2) = back_walk++; 7479 } 7480 7481 } 7482 if (nextvert != -1) 7483 { 7484 node = *(temp2->VertandId + counter); 7485 if (node->edge[1] == nextvert) 7486 nextvert = node->edge[2]; 7487 else 7488 nextvert = node->edge[1]; 7489 } 7490 7491 } 7492 } 7493 if ((EVEN(seen)) ) 7494 seen+=2; 7495 } 7496 7497 /// Fast_Reset: 7498 void CustomStripifier::Fast_Reset(int x) 7499 { 7500 register int y,numverts; 7501 register int front_walk, back_walk; 7502 ListHead *pListHead; 7503 PF_FACES temp = NULL; 7504 7505 pListHead = PolFaces[x]; 7506 temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0); 7507 numverts = temp->nPolSize; 7508 7509 front_walk = 0; 7510 back_walk = 0; 7511 resetting = TRUE; 7512 7513 /* we are doing this only for quads */ 7514 if (numverts == 4) 7515 { 7516 /* for each face not seen yet, do North and South together 7517 and East and West together 7518 */ 7519 for (y=0;y<2;y++) 7520 { 7521 /* Check if the opposite sides were seen already */ 7522 /* Find walk for the first edge */ 7523 front_walk = Calculate_Walks(x,y,temp); 7524 /* Find walk in the opposite direction */ 7525 back_walk = Calculate_Walks(x,y+2,temp); 7526 /* Now put into the data structure the numbers that 7527 we have found 7528 */ 7529 Assign_Walk(x,temp,front_walk,y,back_walk); 7530 Assign_Walk(x,temp,back_walk,y+2,front_walk); 7531 } 7532 } 7533 resetting = FALSE; 7534 } 7535 7536 /// Reset_Max: 7537 void CustomStripifier::Reset_Max( PF_FACES temp2,int face_id, 7538 int north,int last_north, 7539 int orientation,int last_left, 7540 FILE *output_file,int color1, 7541 int color2,int color3, 7542 BOOL start) 7543 { 7544 int previous_edge1,previous_edge2; 7545 F_EDGES *node; 7546 ListHead *pListHead; 7547 int f,t,nextvert,counter; 7548 BOOL flag; 7549 7550 7551 /* Reset walks on faces, since we just found a patch */ 7552 if (orientation !=3) 7553 { 7554 previous_edge1 = *(temp2->pPolygon + orientation+1); 7555 previous_edge2 = *(temp2->pPolygon + orientation ); 7556 } 7557 else 7558 { 7559 previous_edge1 = *(temp2->pPolygon + orientation ); 7560 previous_edge2 = *(temp2->pPolygon); 7561 } 7562 7563 /* only if we are going left, otherwise there will be -1 there */ 7564 /*Find the adjacent face to this edge */ 7565 7566 for (t = 0; t <=3 ; t++) 7567 { 7568 node = *(temp2->VertandId+t); 7569 7570 if (face_id == node->edge[1]) 7571 f = node->edge[2]; 7572 else 7573 f = node->edge[1]; 7574 7575 if (f != -1) 7576 Fast_Reset(f); 7577 } 7578 7579 node = *(temp2->VertandId+orientation); 7580 if (face_id == node->edge[1]) 7581 nextvert = node->edge[2]; 7582 else 7583 nextvert = node->edge[1]; 7584 7585 while ((last_left--) > 1) 7586 { 7587 7588 if (start) 7589 Reset_Max(temp2,face_id,orientation,last_left,north,last_north, 7590 output_file,color1,color2,color3,FALSE); 7591 7592 face_id = nextvert; 7593 pListHead = PolFaces[nextvert]; 7594 temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); 7595 if ((temp2->nPolSize != 4) && (temp2->nPolSize != 1)) 7596 { 7597 /* There is more than 2 polygons on the edge, and we could have 7598 gotten the wrong one 7599 */ 7600 if (nextvert != node->edge[1]) 7601 nextvert = node->edge[1]; 7602 else 7603 nextvert = node->edge[2]; 7604 pListHead = PolFaces[nextvert]; 7605 temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); 7606 node = *(temp2->VertandId+orientation); 7607 } 7608 7609 7610 if (!start) 7611 { 7612 for (t = 0; t <=3 ; t++) 7613 { 7614 node = *(temp2->VertandId+t); 7615 7616 if (face_id == node->edge[1]) 7617 f = node->edge[2]; 7618 else 7619 f = node->edge[1]; 7620 7621 if (f != -1) 7622 Fast_Reset(f); 7623 } 7624 } 7625 7626 7627 counter = 0; 7628 flag = TRUE; 7629 while ((counter < 3) && (flag)) 7630 { 7631 if ( ((*(temp2->pPolygon+counter) == previous_edge1) || 7632 (*(temp2->pPolygon+counter+1) == previous_edge2)) || 7633 ((*(temp2->pPolygon+counter) == previous_edge2) || 7634 (*(temp2->pPolygon+counter+1) == previous_edge1)) ) 7635 counter++; 7636 else 7637 flag = FALSE; 7638 } 7639 7640 /* Get the IDs of the next edge */ 7641 if (counter < 3) 7642 { 7643 previous_edge1 = *(temp2->pPolygon + counter+1); 7644 previous_edge2 = *(temp2->pPolygon + counter); 7645 } 7646 else 7647 { 7648 previous_edge1 = *(temp2->pPolygon + counter); 7649 previous_edge2 = *(temp2->pPolygon); 7650 } 7651 orientation = counter; 7652 7653 node = *(temp2->VertandId + counter); 7654 if (node->edge[1] == nextvert) 7655 nextvert = node->edge[2]; 7656 else 7657 nextvert = node->edge[1]; 7658 7659 if (!reversed) 7660 { 7661 if (counter != 3) 7662 north = counter +1; 7663 else 7664 north = 0; 7665 } 7666 else 7667 { 7668 if (counter != 0) 7669 north = counter -1; 7670 else 7671 north = 3; 7672 7673 } 7674 } 7675 if (start) 7676 Reset_Max(temp2,face_id,orientation,last_left,north,last_north,output_file, 7677 color1,color2,color3,FALSE); 7678 else if (nextvert != -1) 7679 Fast_Reset(nextvert); 7680 7681 } 7682 7683 /// Peel_Max 7684 int CustomStripifier::Peel_Max( PF_FACES temp2,int face_id, 7685 int north,int last_north, 7686 int orientation,int last_left, 7687 FILE *output_file,int color1, 7688 int color2,int color3, 7689 BOOL start, int *swaps_added, 7690 int norms, int texture) 7691 { 7692 int end1,end2,last_id,s=0,walk = 0; 7693 int previous_edge1,previous_edge2; 7694 int static last_seen = 1000; 7695 F_EDGES *node; 7696 ListHead *pListHead; 7697 int nextvert,numverts,counter,dummy,tris=0; 7698 BOOL flag; 7699 7700 /* Peel the patch from the model. 7701 We will try and extend off the end of each strip in the patch. We will return 7702 the number of triangles completed by this extension only, and the number of 7703 swaps in the extension only. 7704 */ 7705 patch = 0; 7706 7707 if (orientation !=3) 7708 { 7709 previous_edge1 = *(temp2->pPolygon + orientation+1); 7710 previous_edge2 = *(temp2->pPolygon + orientation ); 7711 } 7712 else 7713 { 7714 previous_edge1 = *(temp2->pPolygon + orientation ); 7715 previous_edge2 = *(temp2->pPolygon); 7716 } 7717 7718 7719 walk = *(temp2->walked + orientation); 7720 7721 /* only if we are going left, otherwise there will be -1 there */ 7722 if ((start) && ((walk+1) < last_left)) 7723 { 7724 printf("There is an error in the left %d %d\n",walk,last_left); 7725 exit(0); 7726 } 7727 7728 /* Find the adjacent face to this edge */ 7729 node = *(temp2->VertandId+orientation); 7730 if (face_id == node->edge[1]) 7731 nextvert = node->edge[2]; 7732 else 7733 nextvert = node->edge[1]; 7734 temp2->seen = last_seen; 7735 7736 7737 while ((last_left--) > 1) 7738 { 7739 if (start) 7740 tris += Peel_Max(temp2,face_id,orientation,last_left,north,last_north, 7741 output_file,color1,color2,color3,FALSE,swaps_added, 7742 norms,texture); 7743 else 7744 Mark_Face(temp2,color1,color2,color3,output_file,FALSE, 7745 &dummy,&dummy,&face_id,norms,texture); 7746 7747 7748 pListHead = PolFaces[nextvert]; 7749 temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); 7750 numverts = temp2->nPolSize; 7751 7752 if ((numverts != 4) || (temp2->seen == last_seen) 7753 || (nextvert == -1)) 7754 { 7755 7756 /* There is more than 2 polygons on the edge, and we could have 7757 gotten the wrong one 7758 */ 7759 if (nextvert != node->edge[1]) 7760 nextvert = node->edge[1]; 7761 else 7762 nextvert = node->edge[2]; 7763 pListHead = PolFaces[nextvert]; 7764 temp2 = (PF_FACES) PeekList(pListHead,LISTHEAD,0); 7765 numverts = temp2->nPolSize; 7766 if ((numverts != 4) || (temp2->seen == last_seen) ) 7767 { 7768 printf("Peel 2 %d\n",numverts); 7769 exit(1); 7770 } 7771 } 7772 7773 face_id = nextvert; 7774 temp2->seen = last_seen; 7775 7776 counter = 0; 7777 flag = TRUE; 7778 while ((counter < 3) && (flag)) 7779 { 7780 if ( ((*(temp2->pPolygon+counter) == previous_edge1) || 7781 (*(temp2->pPolygon+counter+1) == previous_edge2)) || 7782 ((*(temp2->pPolygon+counter) == previous_edge2) || 7783 (*(temp2->pPolygon+counter+1) == previous_edge1)) ) 7784 counter++; 7785 else 7786 flag = FALSE; 7787 } 7788 /* Get the IDs of the next edge */ 7789 if (counter < 3) 7790 { 7791 previous_edge1 = *(temp2->pPolygon + counter+1); 7792 previous_edge2 = *(temp2->pPolygon + counter); 7793 } 7794 else 7795 { 7796 previous_edge1 = *(temp2->pPolygon + counter); 7797 previous_edge2 = *(temp2->pPolygon); 7798 } 7799 orientation = counter; 7800 7801 node = *(temp2->VertandId + counter); 7802 if (node->edge[1] == nextvert) 7803 nextvert = node->edge[2]; 7804 else 7805 nextvert = node->edge[1]; 7806 7807 if (!reversed) 7808 { 7809 if (counter != 3) 7810 north = counter +1; 7811 else 7812 north = 0; 7813 } 7814 else 7815 { 7816 if (counter != 0) 7817 north = counter -1; 7818 else 7819 north = 3; 7820 } 7821 } 7822 7823 if (start) 7824 tris += Peel_Max(temp2,face_id,orientation,last_left,north,last_north, 7825 output_file,color1,color2,color3,FALSE,swaps_added, 7826 norms,texture); 7827 else 7828 Mark_Face(temp2,color1,color2,color3,output_file,FALSE, 7829 &dummy,&dummy,&face_id,norms,texture);/* do the last face */ 7830 7831 last_seen++; 7832 7833 /* Get the edge that we came out on the last strip of the patch */ 7834 Mark_Face(NULL,0,0,0,output_file,TRUE,&end1,&end2,&last_id,norms,texture); 7835 tris += Extend_Face(last_id,end1,end2,&s,output_file,color1,color2,color3, 7836 vn,norms,vt,texture); 7837 *swaps_added = *swaps_added + s; 7838 return tris; 7839 } 7840 7841 /// Find_Bands: 7842 void CustomStripifier::Find_Bands(int numfaces, FILE *output_file, 7843 int *swaps, int *bands, 7844 int *cost, int *tri, 7845 int norms, int *vert_norms, 7846 int texture, int *vert_texture) 7847 { 7848 7849 register int x,y,max1,max2,numverts,face_id,flag,maximum = 25; 7850 ListHead *pListHead; 7851 PF_FACES temp = NULL; 7852 int color1 = 0, color2 = 100, color3 = 255; 7853 int smaller; 7854 int north_length1,last_north,left_length1,last_left,north_length2,left_length2; 7855 int total_tri = 0, total_swaps = 0,last_id; 7856 int end1, end2,s=0; 7857 register int cutoff = 20; 7858 7859 /* Code that will find the patches. "Cutoff" will be 7860 the cutoff of the area of the patches that we will be allowing. After 7861 we reach this cutoff length, then we will run the local algorithm on the 7862 remaining faces. 7863 */ 7864 7865 /* For each faces that is left find the largest possible band that we can 7866 have with the remaining faces. Note that we will only be finding patches 7867 consisting of quads. 7868 */ 7869 7870 vn = vert_norms; 7871 vt = vert_texture; 7872 y=1; 7873 *bands = 0; 7874 7875 while ((maximum >= cutoff)) 7876 { 7877 y++; 7878 maximum = -1; 7879 for (x=0; x<numfaces; x++) 7880 { 7881 7882 /* Used to produce the triangle strips */ 7883 7884 /* for each face, get the face */ 7885 pListHead = PolFaces[x]; 7886 temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0); 7887 numverts = temp->nPolSize; 7888 7889 /* we are doing this only for quads */ 7890 if (numverts == 4) 7891 { 7892 /* We want a face that is has not been used yet, 7893 since we know that that face must be part of 7894 a band. Then we will find the largest band that 7895 the face may be contained in 7896 */ 7897 7898 /* Doing the north and the left */ 7899 if ((*(temp->walked) != -1) && (*(temp->walked+3) != -1)) 7900 max1 = Find_Max(temp,x,0,3,&north_length1,&left_length1); 7901 if ((*(temp->walked+1) != -1) && (*(temp->walked+2) != -1)) 7902 max2 = Find_Max(temp,x,2,1,&north_length2,&left_length2); 7903 if ((max1 != (north_length1 * left_length1)) || 7904 (max2 != (north_length2 * left_length2))) 7905 { 7906 printf("Max1 %d, %d %d Max2 %d, %d %d\n", 7907 max1,north_length1,left_length1,max2, 7908 north_length2,left_length2); 7909 exit(0); 7910 } 7911 7912 7913 if ((max1 > max2) && (max1 > maximum)) 7914 { 7915 maximum = max1; 7916 face_id = x; 7917 flag = 1; 7918 last_north = north_length1; 7919 last_left = left_length1; 7920 /* so we know we saved max1 */ 7921 } 7922 else if ((max2 > maximum) ) 7923 { 7924 maximum = max2; 7925 face_id = x; 7926 flag = 2; 7927 last_north = north_length2; 7928 last_left = left_length2; 7929 /* so we know we saved max2 */ 7930 } 7931 } 7932 } 7933 if ((maximum < cutoff) && (*bands == 0)) 7934 return; 7935 pListHead = PolFaces[face_id]; 7936 temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0); 7937 /* There are no patches that we found in this pass */ 7938 if (maximum == -1) 7939 break; 7940 /*printf("The maximum is face %d area %d: lengths %d %d\n",face_id,maximum,last_north,last_left);*/ 7941 7942 if (last_north > last_left) 7943 { 7944 smaller = last_left; 7945 } 7946 else 7947 { 7948 smaller = last_north; 7949 } 7950 7951 7952 if (flag == 1) 7953 { 7954 if (last_north > last_left) /* go north sequentially */ 7955 { 7956 total_tri += Peel_Max(temp,face_id,0,last_north,3,last_left, 7957 output_file,color1,color2,color3,TRUE, 7958 &s,norms,texture); 7959 Reset_Max(temp,face_id,0,last_north,3,last_left, 7960 output_file,color1,color2,color3,TRUE); 7961 total_swaps += s; 7962 } 7963 else 7964 { 7965 reversed = TRUE; 7966 total_tri += Peel_Max(temp,face_id,3,last_left,0,last_north, 7967 output_file,color1,color2,color3,TRUE, 7968 &s,norms,texture); 7969 Reset_Max(temp,face_id,3,last_left,0,last_north,output_file, 7970 color1,color2,color3,TRUE); 7971 reversed = FALSE; 7972 total_swaps += s; 7973 } 7974 7975 7976 /* Get the edge that we came out on the last strip of the patch */ 7977 Mark_Face(NULL,0,0,0,NULL,TRUE,&end1,&end2,&last_id,norms,texture); 7978 total_tri += Extend_Face(last_id,end1,end2,&s,output_file, 7979 color1,color2,color3,vn,norms,vt,texture); 7980 total_swaps += s; 7981 7982 } 7983 else 7984 { 7985 if (last_north > last_left) 7986 { 7987 total_tri += Peel_Max(temp,face_id,2,last_north,1,last_left, 7988 output_file,color1,color2,color3,TRUE, 7989 &s,norms,texture); 7990 Reset_Max(temp,face_id,2,last_north,1,last_left,output_file, 7991 color1,color2,color3,TRUE); 7992 total_swaps += s; 7993 } 7994 else 7995 { 7996 reversed = TRUE; 7997 total_tri += Peel_Max(temp,face_id,1,last_left,2,last_north, 7998 output_file,color1,color2,color3,TRUE, 7999 &s,norms,texture); 8000 Reset_Max(temp,face_id,1,last_left,2,last_north,output_file, 8001 color1,color2,color3,TRUE); 8002 reversed = FALSE; 8003 total_swaps += s; 8004 } 8005 8006 /* Get the edge that we came out on on the patch */ 8007 Mark_Face(NULL,0,0,0,NULL,TRUE,&end1,&end2,&last_id,norms,texture); 8008 total_tri += Extend_Face(last_id,end1,end2,&s,output_file, 8009 color1,color2,color3,vn,norms,vt,texture); 8010 total_swaps += s; 8011 } 8012 8013 /* Now compute the cost of transmitting this band, is equal to 8014 going across the larger portion sequentially, 8015 and swapping 3 times per other dimension 8016 */ 8017 8018 total_tri += (maximum * 2); 8019 *bands = *bands + smaller; 8020 8021 } 8022 8023 /*printf("We transmitted %d triangles,using %d swaps and %d strips\n",total_tri, 8024 total_swaps, *bands); 8025 printf("COST %d\n",total_tri + total_swaps + *bands + *bands);*/ 8026 *cost = total_tri + total_swaps + *bands + *bands; 8027 *tri = total_tri; 8028 added_quad = added_quad * 4; 8029 *swaps = total_swaps; 8030 } 8031 8032 /// Save_Rest: 8033 void CustomStripifier::Save_Rest(int *numfaces) 8034 { 8035 /* Put the polygons that are left into a data structure so that we can run the 8036 stripping code on it. 8037 */ 8038 register int x,y=0,numverts; 8039 ListHead *pListHead; 8040 PF_FACES temp=NULL; 8041 8042 for (x=0; x<*numfaces; x++) 8043 { 8044 /* for each face, get the face */ 8045 pListHead = PolFaces[x]; 8046 temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0); 8047 numverts = temp->nPolSize; 8048 /* If we did not do the face before add it to data structure with new 8049 face id number 8050 */ 8051 if (numverts != 1) 8052 { 8053 CopyFace(temp->pPolygon,numverts,y+1,temp->pNorms); 8054 y++; 8055 } 8056 /* Used it, so remove it */ 8057 else 8058 RemoveList(pListHead,(PLISTINFO) temp); 8059 8060 } 8061 *numfaces = y; 8062 } 8063 8064 /// Save_Walks: 8065 void CustomStripifier::Save_Walks(int numfaces) 8066 { 8067 int x,y,numverts; 8068 int front_walk, back_walk; 8069 ListHead *pListHead; 8070 PF_FACES temp = NULL; 8071 8072 for (x=0; x<numfaces; x++) 8073 { 8074 /* for each face, get the face */ 8075 pListHead = PolFaces[x]; 8076 temp = (PF_FACES) PeekList(pListHead,LISTHEAD,0); 8077 numverts = temp->nPolSize; 8078 front_walk = 0; 8079 back_walk = 0; 8080 8081 /* we are finding patches only for quads */ 8082 if (numverts == 4) 8083 { 8084 /* for each face not seen yet, do North and South together 8085 and East and West together 8086 */ 8087 for (y=0;y<2;y++) 8088 { 8089 /* Check if the opposite sides were seen already from another 8090 starting face, if they were then there is no need to do 8091 the walk again 8092 */ 8093 8094 if ( ((*(temp->walked+y) == -1) && 8095 (*(temp->walked+y+2) == -1) )) 8096 { 8097 /* Find walk for the first edge */ 8098 front_walk = Calculate_Walks(x,y,temp); 8099 /* Find walk in the opposite direction */ 8100 back_walk = Calculate_Walks(x,y+2,temp); 8101 /* Now put into the data structure the numbers that 8102 we have found 8103 */ 8104 Assign_Walk(x,temp,front_walk,y,back_walk); 8105 Assign_Walk(x,temp,back_walk,y+2,front_walk); 8106 } 8107 } 8108 } 8109 } 8110 } 8111 8112 /// OpenOutputFile: 8113 FILE * CustomStripifier::OpenOutputFile(char *fname) 8114 { 8115 FILE *bands; 8116 int flength = 0; 8117 char *newfname; 8118 8119 // get the length of the fname. 8120 flength = strlen(fname); 8121 8122 // make a new string in memory one larger than fname. 8123 newfname = (char *) malloc(sizeof(char) * (flength+2)); 8124 8125 // Copy the fname to the newfname. 8126 strcpy(newfname,fname); 8127 8128 // Add an 'f' to the end of it. 8129 newfname[flength] = 'f'; 8130 newfname[flength+1] = '\0'; 8131 8132 printf(" Output file : %s\n",newfname); 8133 8134 // File that will contain the triangle strip data 8135 bands = fopen(newfname,"w"); 8136 fprintf(bands,"#%s: a triangle strip representation created by STRIPE.\n#This is a .objf file\n#by Francine Evans\n",fname); 8137 8138 return bands; 8139 } 8140 8141 /// AllocateStruct: Reserves memory for structures. 8142 void CustomStripifier::AllocateStruct(int num_faces, 8143 int num_vert, 8144 int num_nvert, 8145 int num_texture) 8146 { 8147 /* Allocate structures for the information */ 8148 Start_Face_Struct(num_faces); 8149 Start_Vertex_Struct(num_vert); 8150 8151 vertices = (struct vert_struct *) 8152 malloc (sizeof (struct vert_struct) * num_vert); 8153 8154 if (num_nvert > 0) 8155 { 8156 nvertices = (struct vert_struct *) 8157 malloc (sizeof (struct vert_struct) * num_nvert); 8158 8159 vert_norms = (int *) 8160 malloc (sizeof (int) * num_vert); 8161 8162 /* Initialize entries to zero, in case there are 2 hits 8163 to the same vertex we will know it - used for determining 8164 the normal difference 8165 */ 8166 init_vert_norms(num_vert); 8167 } 8168 else 8169 nvertices = NULL; 8170 8171 if (num_texture > 0) 8172 { 8173 vert_texture = (int *) malloc (sizeof(int) * num_vert); 8174 8175 init_vert_texture(num_vert); 8176 } 8177 8178 /* Set up the temporary 'p' pointers */ 8179 pvertices = vertices; 8180 pnvertices = nvertices; 8181 8182 } 8183 8184 /// miReadFile: Loads the object in memory. 8185 void CustomStripifier::miReadFile(char *fname, char *file_open, FILE *bands, Geometry::SubMesh *geoSubMesh) 8186 { 8187 BOOL texture; 8188 BOOL normal; 8189 BOOL normal_and_texture; 8190 char *all; 8191 char *ptr; 8192 char *ptr2; 8193 char aux[255]; 8194 FILE *file; 8195 float center[3]; 8196 int num2; 8197 int face_id = 0; 8198 int aux1; 8199 int aux2; 8200 int aux3; 8201 int swaps; 8202 int strips; 8203 int triangles; 8204 int vert_count; 8205 int loop; 8206 int num_vert=0; 8207 int vertex; 8208 int vertex2; 8209 int temp[MAX1]; 8210 int i = 0; 8211 int num_buffers = 0; 8212 Geometry::VertexBuffer *geoVertexBuffer = geoSubMesh->mVertexBuffer; 8213 8214 /** 8215 * Faces 8216 */ 8217 for(int j = 0; j < geoSubMesh->mIndexCount; j = j + 3) 8218 { 8219 8220 // loop on the number of vertices in this line of face data. 8221 vert_count = 0; 8222 8223 // 3 vertices of a triangle. 8224 for(int k = 0;k < 3;k++) 8225 { 8226 // no nvertices. 8227 vertex = geoSubMesh->mIndex[j+k]; 8228 temp[vert_count] = vertex; 8229 8230 vert_count++; 8231 8232 add_vert_id(vertex,vert_count); 8233 } 8234 8235 // Increment the number of faces. 8236 face_id++; 8237 8238 // Add a new face to the list. 8239 AddNewFace(ids,vert_count,face_id,norms); 8240 8241 } 8242 8243 // Done reading in all the information into data structures. 8244 num_faces = face_id; 8245 8246 printf(" Done.\n\n"); 8247 8248 free(vertices); 8249 free(nvertices); 8250 8251 } 8252 8253 /// stripify: Make triangle strips for a given mesh. 8254 int CustomStripifier::stripify (char *fname, 8255 Geometry::Mesh *geoMesh) 8256 { 8257 BOOL quads = FALSE; 8258 BOOL oddStrip; 8259 FILE *bands; 8260 char *file_open; 8261 float norm_difference; 8262 int i; 8263 int j; 8264 int swaps; 8265 int strips; 8266 int triangles; 8267 int f; 8268 int t; 8269 int tr; 8270 int g; 8271 int num_buffers = 0; 8272 int cost = 0; 8273 int num_vert = 0; 8274 int num_faces = 0; 8275 int num_nvert = 0; 8276 int num_texture = 0; 8277 int num_tris = 0; 8278 int totalIndices; 8279 int totalStripIndices; 8280 unsigned int lui_Index; 8281 Geometry::SubMesh* geoSubMesh; 8282 mi_vector_tipo v_indices; 8283 8284 /* Scan the file once to find out the number of vertices, 8285 vertice normals, and faces so we can set up some memory structures.*/ 8286 f = ASCII; 8287 file_open = "w+"; 8288 tr = 1; 8289 t = 3; 8290 orient = 1; 8291 8292 // Proces OK. 8293 mError = 0; 8294 8295 8296 // 2006-02-14 8297 // Progress bar. 8298 float percent; 8299 percent = 100.0 / (geoMesh->mSubMeshCount * 10.0); 8300 //-------------------------- 8301 8302 // For all submeshes. 8303 for(int k = 0; k < geoMesh->mSubMeshCount; k++) 8304 { 8305 // Leaves submesh doesn't stripify. 8306 if (mSubMeshLeaves != k) 8307 { 8308 v_indices.clear(); 8309 mi_vector.clear(); 8310 mi_vector.push_back(v_indices); 8311 num_tiras = 0; 8312 8313 // Actual submesh. 8314 geoSubMesh = &geoMesh->mSubMesh[k]; 8315 8316 // Mesh type. 8317 geoSubMesh->mType = GEO_TRIANGLE_STRIPS; 8318 8319 num_vert = geoSubMesh->mVertexBuffer->mVertexCount; 8320 num_faces = geoSubMesh->mIndexCount / 3; 8321 num_tris = num_faces; 8322 8323 // Debug. 8324 //vt = new int[num_vert]; 8325 //vn = new int[num_vert]; 8326 text = 0; 8327 norm = 0; 8328 8329 // 2006-02-14. 8330 // Updtate progress bar. 8331 if (mUPB) 8332 { 8333 mUPB(percent); 8334 } 8335 //----------------------- 8336 8337 // Open the output file. 8338 bands = OpenOutputFile(fname); 8339 8340 // 2006-02-14. 8341 // Updtate progress bar. 8342 if (mUPB) 8343 { 8344 mUPB(percent); 8345 } 8346 //----------------------- 8347 8348 // Reserve memory for the mesh structure. 8349 AllocateStruct(num_faces,num_vert,num_nvert,num_texture); 8350 8351 // 2006-02-14. 8352 // Updtate progress bar. 8353 if (mUPB) 8354 { 8355 mUPB(percent); 8356 } 8357 //----------------------- 8358 8359 // Load the object into memory. 8360 miReadFile(fname,file_open,bands,geoSubMesh); 8361 8362 // 2006-02-14. 8363 // Updtate progress bar. 8364 if (mUPB) 8365 { 8366 mUPB(percent); 8367 } 8368 //----------------------- 8369 8370 Start_Edge_Struct(num_vert); 8371 Find_Adjacencies(num_faces); 8372 8373 // 2006-02-14. 8374 // Updtate progress bar. 8375 if (mUPB) 8376 { 8377 mUPB(percent); 8378 } 8379 //----------------------- 8380 8381 // If the mesh is not manifold. 8382 if (mError) 8383 { 8384 return 0; 8385 } 8386 8387 // Initialize it. 8388 face_array = NULL; 8389 Init_Table_SGI(num_faces); 8390 8391 // 2006-02-14. 8392 // Updtate progress bar. 8393 if (mUPB) 8394 { 8395 mUPB(percent); 8396 } 8397 //----------------------- 8398 8399 // Build it. 8400 Build_SGI_Table(num_faces); 8401 InitStripTable(); 8402 8403 // 2006-02-14. 8404 // Updtate progress bar. 8405 if (mUPB) 8406 { 8407 mUPB(percent); 8408 } 8409 //----------------------- 8410 8411 SGI_Strip(num_faces,bands,t,tr); 8412 8413 // 2006-02-14. 8414 // Updtate progress bar. 8415 if (mUPB) 8416 { 8417 mUPB(percent); 8418 } 8419 //----------------------- 8420 8421 // Get the total cost. 8422 Output_TriEx(-1,-2,-3,NULL,-20,cost); 8423 8424 End_Face_Struct(num_faces); 8425 End_Edge_Struct(num_vert); 8426 fclose(bands); 8427 8428 // 2006-02-14. 8429 // Updtate progress bar. 8430 if (mUPB) 8431 { 8432 mUPB(percent); 8433 } 8434 //----------------------- 8435 8436 num_vert = num_tiras; 8437 8438 totalStripIndices = 0; 8439 8440 8441 // Asigna el numero de tiras. 8442 geoSubMesh->mStripCount = num_tiras; 8443 8444 // Reserva memoria para el array de punteros al inicio 8445 // de las tiras. 8446 //for(i = 0; i < geoSubMesh->mStripCount; i++) 8447 //{ 8448 geoSubMesh->mStrip = (Index**) malloc( sizeof(Index*) 8449 * 8450 geoSubMesh->mStripCount); 8451 //} 8452 8453 // 2006-02-28. 8454 // La primera sera diferente. 8455 v_indices = mi_vector[1]; 8456 8457 // Number of vertices of a strip odd or even. 8458 if(v_indices.size() % 2) 8459 { 8460 oddStrip = TRUE; 8461 } 8462 else 8463 { 8464 oddStrip = FALSE; 8465 } 8466 8467 // Obtiene el total de indices de la primera strip. 8468 geoSubMesh->mIndexCount = v_indices.size(); 8469 8470 // Calculate the Index Count. 8471 for (i = 2; i <= num_tiras; i++) 8472 { 8473 v_indices = mi_vector[i]; 8474 geoSubMesh->mIndexCount += v_indices.size() + 2; 8475 8476 // Insert a new vertex if the strip es odd. 8477 if(oddStrip) 8478 { 8479 geoSubMesh->mIndexCount++; 8480 } 8481 8482 // Number of vertices of a strip odd or even. 8483 if(v_indices.size() % 2) 8484 { 8485 oddStrip = TRUE; 8486 } 8487 else 8488 { 8489 oddStrip = FALSE; 8490 } 8491 } 8492 8493 // Delete the actual indices. 8494 delete[] geoSubMesh->mIndex; 8495 geoSubMesh->mIndex = new Index[geoSubMesh->mIndexCount]; 8496 //-------------------------------------------- 8497 8498 // La primera sera diferente. 8499 v_indices = mi_vector[1]; 8500 8501 // Obtiene el total de indices de la primera strip. 8502 //geoSubMesh->mIndexCount = v_indices.size(); 8503 8504 8505 8506 // Copia la primera tira en el array de indices. 8507 for(j = 0;j < v_indices.size();j++) 8508 { 8509 geoSubMesh->mIndex[totalStripIndices++] = v_indices[j]; 8510 } 8511 8512 // Asigna el inicio de la primera tira de triangulos. 8513 geoSubMesh->mStrip[0] = &geoSubMesh->mIndex[0]; 8514 8515 // 2006-02-14. 8516 // Updtate progress bar. 8517 if (mUPB) 8518 { 8519 mUPB(percent); 8520 } 8521 //----------------------- 8522 8523 8524 // Number of vertices of a strip odd or even. 8525 if(v_indices.size() % 2) 8526 { 8527 oddStrip = TRUE; 8528 } 8529 else 8530 { 8531 oddStrip = FALSE; 8532 } 8533 8534 // Para todas las tiras menos la primera. 8535 for(i = 2;i <= num_tiras;i++) 8536 { 8537 /* copia en el inicio de la tira el final de la anterior. 8538 triangulos degenerados. */ 8539 geoSubMesh->mIndex[totalStripIndices++] = geoSubMesh-> 8540 mIndex[totalStripIndices-1]; 8541 8542 v_indices = mi_vector[i]; 8543 8544 //geoSubMesh->mIndexCount = geoSubMesh->mIndexCount + v_indices.size() + 2; 8545 8546 /* copia el inicio de la tira 2 veces. 8547 triangulos degenerados. 8548 */ 8549 geoSubMesh->mIndex[totalStripIndices++] = v_indices[0]; 8550 8551 // Asigna el inicio de la tira de triangulos. 8552 geoSubMesh->mStrip[i-1] = &geoSubMesh->mIndex[totalStripIndices - 1]; 8553 8554 // Triangulo Degenerado. 8555 geoSubMesh->mIndex[totalStripIndices++] = v_indices[0]; 8556 8557 // Insert a new vertex if the strip es odd. 8558 if(oddStrip) 8559 { 8560 // geoSubMesh->mIndexCount++; 8561 geoSubMesh->mIndex[totalStripIndices++] = v_indices[0]; 8562 } 8563 8564 // Number of vertices of a strip odd or even. 8565 if(v_indices.size() % 2) 8566 { 8567 oddStrip = TRUE; 8568 } 8569 else 8570 { 8571 oddStrip = FALSE; 8572 } 8573 8574 // Copia la tira en curso en el array de indices. 8575 for(j=1;j<v_indices.size();j++) 8576 { 8577 geoSubMesh->mIndex[totalStripIndices++] = v_indices[j]; 8578 } 8579 } 8580 } 8581 }// End For. SubMeshes. 8582 8583 // 2006-02-14. 8584 // Updtate progress bar. 8585 if (mUPB) 8586 { 8587 mUPB(100.0); 8588 } 8589 //----------------------- 8590 8591 return 1; 8592 } 18 8593 19 8594 //----------------------------------------------------------------------------- … … 32 8607 { 33 8608 } 34 35 8609 CustomStripifier::CustomStripifier( const Geometry::Mesh *geoMesh) 36 8610 { 37 mGeoMesh = new Mesh(); 38 *mGeoMesh = *geoMesh; 8611 MeshGlobal = new Geometry::Mesh(); 8612 *MeshGlobal = *geoMesh; 8613 8614 // Initialize the leaves submesh index. 8615 mSubMeshLeaves = -1; 39 8616 40 8617 // Sets the actual progress bar function. 41 8618 mUPB = NULL; 42 43 // Initialize the leaves submesh index.44 mSubMeshLeaves = -1;45 }46 47 // Set the progress bar function.48 void CustomStripifier::SetProgressFunc(TIPOFUNC upb)49 {50 // Sets the actual progress bar function.51 mUPB = upb;52 8619 } 53 8620 … … 56 8623 //----------------------------------------------------------------------------- 57 8624 CustomStripifier::~CustomStripifier() 58 { 59 delete mGeoMesh;8625 { 8626 delete MeshGlobal; 60 8627 } 61 8628 … … 68 8635 //----------------------------------------------------------------------------- 69 8636 70 /// Stripify .8637 /// Stripify: 71 8638 int CustomStripifier::Stripify() 72 8639 { 73 size_t index_count; 74 size_t strip_count; 75 size_t strip_index_count; 76 SubMesh *geosubmesh; 77 primitive_vector PrimitivesVector; 78 indices Indices; 79 float increment; 80 float update; 81 82 // For each submesh. 83 for (int submesh = 0; submesh < mGeoMesh->mSubMeshCount; submesh++) 84 { 85 // Gets the submesh. 86 geosubmesh = &mGeoMesh->mSubMesh[submesh]; 87 88 // Free index vector. 89 Indices.clear(); 90 91 // Progress bar increment. 92 increment = 20 / mGeoMesh->mSubMeshCount; 93 increment = increment / geosubmesh->mIndexCount; 94 update = 0.0; 95 96 // For each index. 97 for (int index = 0; index < geosubmesh->mIndexCount; index++) 98 { 99 // Update progress bar. 100 if (mUPB) 101 { 102 update = update + increment; 103 104 if (update > 0.9) 105 { 106 mUPB(1.0); 107 108 update = 0; 109 } 110 } 111 112 // Add an index. 113 Indices.push_back(geosubmesh->mIndex[index]); 114 } 115 116 // we want to time the tri_stripper object destruction as well. 117 tri_stripper TriStripper(Indices); 118 119 // Sets the progress bar function for stripper algorithm. 120 TriStripper.SetProgressFunc(mUPB,60/mGeoMesh->mSubMeshCount); 121 122 TriStripper.SetMinStripSize(2); 123 TriStripper.SetCacheSize(32); 124 //TriStripper.SetBackwardSearch(false); 125 126 TriStripper.Strip(&PrimitivesVector); 127 128 // Free submesh indices. 129 delete [] geosubmesh->mIndex; 130 131 // Initialize index count. 132 geosubmesh->mIndexCount = 0; 133 134 // Initialize strip count. 135 strip_count = 0; 136 137 // For each strip or triangle list. 138 for (size_t strip = 0; strip < PrimitivesVector.size(); ++strip) 139 { 140 if (PrimitivesVector[strip].Type == TRIANGLE_STRIP) 141 { 142 strip_count++; 143 144 // Gets the index count. 145 strip_index_count = PrimitivesVector[strip].Indices.size(); 146 147 // Adds indices of the current strip to total index count. 148 geosubmesh->mIndexCount += strip_index_count; 149 } 150 else 151 { 152 strip_count += PrimitivesVector[strip].Indices.size() / 3; 153 154 geosubmesh->mIndexCount += PrimitivesVector[strip].Indices.size(); 155 } 156 157 } 158 159 // Reserve memory for strips list. 160 geosubmesh->mStrip = new Index*[strip_count]; 161 geosubmesh->mStripCount = strip_count; 162 163 // Reserve memory for indices. 164 geosubmesh->mIndex = new Index[geosubmesh->mIndexCount]; 165 166 // Initialize index count. 167 index_count = 0; 168 169 // For each strip. 170 for (size_t strip = 0; strip < PrimitivesVector.size(); strip++) 171 { 172 if (PrimitivesVector[strip].Type == TRIANGLE_STRIP) 173 { 174 // Asigns the beginning of the strip. 175 geosubmesh->mStrip[strip] = &geosubmesh->mIndex[index_count]; 176 177 // Gets the index count of the current strip. 178 strip_index_count = PrimitivesVector[strip].Indices.size(); 179 180 181 // Fill up the index array. 182 for ( size_t index = 0; 183 index < PrimitivesVector[strip].Indices.size(); 184 index++) 185 { 186 geosubmesh->mIndex[index + index_count] = PrimitivesVector[strip].Indices[index]; 187 } 188 189 // Adds the current strip size to index count. 190 index_count += PrimitivesVector[strip].Indices.size(); 191 } 192 else 193 { 194 // For each index. 195 for ( size_t itri = 0; 196 itri < PrimitivesVector[strip].Indices.size() / 3; 197 itri ++) 198 { 199 // Asigns the beginning of the strip. 200 geosubmesh->mStrip[strip + itri] = &geosubmesh->mIndex[index_count]; 201 202 // Triangle indeces. 203 geosubmesh->mIndex[index_count++] = PrimitivesVector[strip].Indices[itri*3+0]; 204 geosubmesh->mIndex[index_count++] = PrimitivesVector[strip].Indices[itri*3+1]; 205 geosubmesh->mIndex[index_count++] = PrimitivesVector[strip].Indices[itri*3+2]; 206 207 } 208 } 209 } 210 211 // Sets the actual submesh type to triangle strips. 212 geosubmesh->mType = GEO_TRIANGLE_STRIPS; 213 } 214 215 // Update progress bar function. 216 if (mUPB) 217 { 218 mUPB(100); 219 } 220 221 // All wright. 222 return 1; 8640 // Init variables. 8641 resetting = FALSE; 8642 added_quad = 0; 8643 reversed = FALSE; 8644 patch = 0; 8645 out1 = -1; 8646 out2 = -1; 8647 out1Ex = -1; 8648 out2Ex = -1; 8649 last = 0; 8650 8651 // Make Triangle Strips. 8652 return stripify("out.obj",MeshGlobal); 223 8653 } 224 8654 … … 228 8658 Mesh *mesh_stripified; 229 8659 230 mesh_stripified = new Mesh();231 *mesh_stripified = *mGeoMesh;8660 mesh_stripified = new Mesh(); 8661 *mesh_stripified = *MeshGlobal; 232 8662 233 8663 return mesh_stripified; 8664 } 8665 8666 // Set the progress bar function. 8667 void CustomStripifier::SetProgressFunc(TIPOFUNC upb) 8668 { 8669 // Sets the actual progress bar function. 8670 mUPB = upb; 234 8671 } 235 8672 -
GTP/trunk/Lib/Geom/shared/GTGeometry/src/GeoSerializer.cpp
r774 r980 2 2 3 3 4 namespace Geometry {5 6 4 namespace Geometry 5 { 6 //--------------------------------------------------------------------- 7 7 Serializer::Serializer(String name, Mode mode) 8 8 : mMode(mode) 9 {10 char *char_mode = 0;11 switch (mMode)12 {13 case READ :14 char_mode = "rb";15 break;16 case APPEND:17 char_mode = "a+b";18 break;19 case WRITE:20 char_mode = "wb";21 break;22 }23 24 mFile = fopen(name.c_str(),char_mode);25 mSize = 0;26 assert(mFile);27 }28 29 30 31 9 { 10 char *char_mode = 0; 11 switch (mMode) 12 { 13 case READ : 14 char_mode = "rb"; 15 break; 16 case APPEND: 17 char_mode = "a+b"; 18 break; 19 case WRITE: 20 char_mode = "wb"; 21 break; 22 } 23 24 mFile = fopen(name.c_str(),char_mode); 25 mSize = 0; 26 assert(mFile); 27 } 28 29 //--------------------------------------------------------------------- 30 Serializer::~Serializer() 31 { 32 32 fflush(mFile); 33 33 fclose(mFile); 34 35 36 37 38 39 # if GEO_ENDIAN == GEO_ENDIAN_BIG 40 41 42 43 44 45 46 34 } 35 36 //--------------------------------------------------------------------- 37 void Serializer::WriteArray(const float* const pFloat, size_t count) 38 { 39 # if GEO_ENDIAN == GEO_ENDIAN_BIG 40 float *float_to_write = (float *)malloc(sizeof(float) * count); 41 memcpy(float_to_write, pFloat, sizeof(float) * count); 42 43 flipToLittleEndian(float_to_write, sizeof(float), count); 44 writeData(float_to_write, sizeof(float), count); 45 46 free(float_to_write); 47 47 # else 48 49 # endif 50 51 52 53 54 55 # if GEO_ENDIAN == GEO_ENDIAN_BIG 56 57 58 59 60 61 62 48 WriteData(pFloat, sizeof(float), count); 49 # endif 50 } 51 52 //--------------------------------------------------------------------- 53 void Serializer::WriteArray(const uint16* const pShort, size_t count = 1) 54 { 55 # if GEO_ENDIAN == GEO_ENDIAN_BIG 56 unsigned short *short_to_write = (unsigned short *)malloc(sizeof(unsigned short) * count); 57 memcpy(short_to_write, pShort, sizeof(unsigned short) * count); 58 59 flipToLittleEndian(short_to_write, sizeof(unsigned short), count); 60 WriteData(short_to_write, sizeof(unsigned short), count); 61 62 free(short_to_write); 63 63 # else 64 WriteData(pShort, sizeof(unsigned short), count); 65 # endif 66 } 67 //--------------------------------------------------------------------- 68 void Serializer::WriteArray(const uint32* const pInt, size_t count = 1) 69 { 70 # if GEO_ENDIAN == GEO_ENDIAN_BIG 71 unsigned int *int_to_write = (unsigned int *)malloc(sizeof(unsigned int) * count); 72 memcpy(int_to_write, pInt, sizeof(unsigned int) * count); 73 74 FlipToLittleEndian(int_to_write, sizeof(unsigned int), count); 75 WriteData(int_to_write, sizeof(unsigned int), count); 76 77 free(int_to_write); 64 WriteData(pShort, sizeof(unsigned short), count); 65 # endif 66 } 67 68 //--------------------------------------------------------------------- 69 void Serializer::WriteArray(const uint32* const pInt, size_t count = 1) 70 { 71 # if GEO_ENDIAN == GEO_ENDIAN_BIG 72 unsigned int *int_to_write = (unsigned int *)malloc(sizeof(unsigned int) * count); 73 memcpy(int_to_write, pInt, sizeof(unsigned int) * count); 74 75 FlipToLittleEndian(int_to_write, sizeof(unsigned int), count); 76 WriteData(int_to_write, sizeof(unsigned int), count); 77 78 free(int_to_write); 78 79 # else 79 80 # endif 81 82 83 84 80 WriteData(pInt, sizeof(unsigned int), count); 81 # endif 82 } 83 84 //--------------------------------------------------------------------- 85 void Serializer::WriteArray(const bool* const pBool, size_t count = 1) 85 86 { 86 87 //TODO: Apple has problems 87 WriteData(pBool, sizeof(bool), count); 88 } 88 WriteData(pBool, sizeof(bool), count); 89 } 90 89 91 //--------------------------------------------------------------------- 90 92 void Serializer::WriteArray(const Vector3* const pDest, size_t count) 91 92 93 { 94 for(size_t i = 0; i < count; ++i) 93 95 { 94 96 WriteArray(pDest[i].val,3); 95 97 } 96 } 98 } 99 97 100 //--------------------------------------------------------------------- 98 101 void Serializer::WriteArray(const Vector2* const pDest, size_t count) 99 100 102 { 103 for(size_t i = 0; i < count; ++i) 101 104 { 102 105 WriteArray(pDest[i].val,2); 103 106 } 104 105 106 107 108 107 } 108 109 //--------------------------------------------------------------------- 110 void Serializer::WriteData(const void* const buf, size_t size, size_t count) 111 { 109 112 size_t wcount = fwrite((void* const)buf, size, count, mFile); 110 113 assert(wcount == count); 111 114 mSize += size*count; 112 115 } 113 116 114 117 //--------------------------------------------------------------------- … … 138 141 void Serializer::WriteData(const String &string) 139 142 { 140 141 142 143 144 145 mSize += string.length() + 1;143 fputs(string.c_str(), mFile); 144 145 // Write terminating newline char 146 //fputc('\n', mFile); 147 148 mSize += string.length(); 146 149 } 147 150 // fin GPR 148 151 149 150 //--------------------------------------------------------------------- 151 void Serializer::ReadArray(bool *pDest, size_t count) 152 { 152 void Serializer::WriteData(const char *string) 153 { 154 fputs(string, mFile); 155 156 // Write terminating newline char 157 //fputc('\n', mFile); 158 159 mSize += strlen(string) /*+ 1*/; 160 } 161 162 //--------------------------------------------------------------------- 163 void Serializer::ReadArray(bool *pDest, size_t count) 164 { 153 165 //TODO:: Apple has problmes with bools 154 ReadData(pDest,sizeof(bool), count); 155 } 156 157 //--------------------------------------------------------------------- 158 void Serializer::ReadArray(float *pDest, size_t count) 159 { 160 ReadData(pDest, sizeof(float), count); 161 FlipFromLittleEndian(pDest, sizeof(float), count); 162 } 163 //--------------------------------------------------------------------- 164 void Serializer::ReadArray(unsigned short *pDest, size_t count) 165 { 166 ReadData(pDest, sizeof(unsigned short), count); 167 FlipFromLittleEndian(pDest, sizeof(unsigned short), count); 168 } 169 //--------------------------------------------------------------------- 170 void Serializer::ReadArray(unsigned int *pDest, size_t count) 171 { 172 ReadData(pDest, sizeof(unsigned int), count); 173 FlipFromLittleEndian(pDest, sizeof(unsigned int), count); 174 } 175 //--------------------------------------------------------------------- 176 void Serializer::ReadArray(Vector3 *pDest, size_t count) 177 { 178 for(size_t i = 0; i < count; ++i) 166 ReadData(pDest,sizeof(bool), count); 167 } 168 169 //--------------------------------------------------------------------- 170 void Serializer::ReadArray(float *pDest, size_t count) 171 { 172 ReadData(pDest, sizeof(float), count); 173 FlipFromLittleEndian(pDest, sizeof(float), count); 174 } 175 176 //--------------------------------------------------------------------- 177 void Serializer::ReadArray(unsigned short *pDest, size_t count) 178 { 179 ReadData(pDest, sizeof(unsigned short), count); 180 FlipFromLittleEndian(pDest, sizeof(unsigned short), count); 181 } 182 183 //--------------------------------------------------------------------- 184 void Serializer::ReadArray(unsigned int *pDest, size_t count) 185 { 186 ReadData(pDest, sizeof(unsigned int), count); 187 FlipFromLittleEndian(pDest, sizeof(unsigned int), count); 188 } 189 190 //--------------------------------------------------------------------- 191 void Serializer::ReadArray(Vector3 *pDest, size_t count) 192 { 193 for(size_t i = 0; i < count; ++i) 179 194 { 180 195 ReadArray(pDest[i].val,3); 181 196 } 182 } 197 } 198 183 199 //--------------------------------------------------------------------- 184 200 void Serializer::ReadArray(Vector2 *pDest, size_t count) 185 186 201 { 202 for(size_t i = 0; i < count; ++i) 187 203 { 188 204 ReadArray(pDest[i].val,2); 189 205 } 190 } 191 192 193 //--------------------------------------------------------------------- 194 195 196 void Serializer::FlipToLittleEndian(void *pData, size_t size, size_t count) 197 { 198 # if GEO_ENDIAN == GEO_ENDIAN_BIG 199 FlipEndian(pData, size, count); 200 # endif 201 } 202 203 void Serializer::FlipFromLittleEndian(void *pData, size_t size, size_t count) 204 { 205 # if GEO_ENDIAN == GEO_ENDIAN_BIG 206 FlipEndian(pData, size, count); 207 # endif 208 } 209 210 void Serializer::FlipEndian(void *pData, size_t size, size_t count) 211 { 212 for(unsigned int index = 0; index < count; index++) 213 { 214 FlipEndian((void *)((char*)pData + (index * size)), size); 215 } 216 } 217 218 void Serializer::FlipEndian(void *pData, size_t size) 219 { 220 char swapByte; 221 for(unsigned int byteIndex = 0; byteIndex < size/2; byteIndex++) 222 { 223 swapByte = *((char *)pData + byteIndex); 224 *((char *)pData + byteIndex) = *((char *)pData + size - byteIndex - 1); 225 *((char *)pData + size - byteIndex - 1) = swapByte; 226 } 227 } 228 206 } 207 208 //--------------------------------------------------------------------- 209 void Serializer::FlipToLittleEndian(void *pData, size_t size, size_t count) 210 { 211 # if GEO_ENDIAN == GEO_ENDIAN_BIG 212 FlipEndian(pData, size, count); 213 # endif 214 } 215 216 void Serializer::FlipFromLittleEndian(void *pData, size_t size, size_t count) 217 { 218 # if GEO_ENDIAN == GEO_ENDIAN_BIG 219 FlipEndian(pData, size, count); 220 # endif 221 } 222 223 void Serializer::FlipEndian(void *pData, size_t size, size_t count) 224 { 225 for(unsigned int index = 0; index < count; index++) 226 { 227 FlipEndian((void *)((char*)pData + (index * size)), size); 228 } 229 } 230 231 void Serializer::FlipEndian(void *pData, size_t size) 232 { 233 char swapByte; 234 for(unsigned int byteIndex = 0; byteIndex < size/2; byteIndex++) 235 { 236 swapByte = *((char *)pData + byteIndex); 237 *((char *)pData + byteIndex) = *((char *)pData + size - byteIndex - 1); 238 *((char *)pData + size - byteIndex - 1) = swapByte; 239 } 240 } 241 229 242 } 230 243 -
GTP/trunk/Lib/Geom/shared/GTGeometry/src/GeoSubMesh.cpp
r826 r980 6 6 mIndex(0), mVertexBuffer(0), mIndexCount(0),mSharedVertexBuffer(false), mStrip(0), mStripCount(0), mType(GEO_TRIANGLE_LIST) 7 7 { 8 strcpy(mMaterialName,""); 8 9 } 9 10 -
GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/SimplificationMethod.h
r774 r980 12 12 { 13 13 private: 14 Geometry::Mesh *mGeoMesh; 14 15 void compute_pair_info(qslim::pair_info*); 15 16 qslim::Model M0; … … 56 57 SimplificationMethod(const Geometry::Mesh *m); 57 58 void geomesh2simplifModel(void); 58 Geometry::MeshSimplificationSequence *Decimate(float lod, Geometry::Mesh **mesh,int simpliftype,Geometry::TIPOFUNC upb=0);59 Geometry::MeshSimplificationSequence *Decimate(float lod, int simpliftype,Geometry::TIPOFUNC upb=0); 59 60 void setMeshLeaves(int meshLeaves); 60 61 62 // Gets mesh simplified. 63 Geometry::Mesh * GetMesh(); 64 61 65 ///Destructor 62 66 ~SimplificationMethod();
Note: See TracChangeset
for help on using the changeset viewer.