00001 00002 /* 00003 * OPCODE - Optimized Collision Detection 00004 * Copyright (C) 2001 Pierre Terdiman 00005 * Homepage: http://www.codercorner.com/Opcode.htm 00006 */ 00008 00010 00016 00017 00019 00089 00090 00092 // Precompiled Header 00093 #include "Stdafx.h" 00094 00095 using namespace Opcode; 00096 00098 00101 00102 Model::Model() 00103 { 00104 #ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! 00105 mHull = null; 00106 #endif // __MESHMERIZER_H__ 00107 } 00108 00110 00113 00114 Model::~Model() 00115 { 00116 Release(); 00117 } 00118 00120 00123 00124 void Model::Release() 00125 { 00126 ReleaseBase(); 00127 #ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! 00128 DELETESINGLE(mHull); 00129 #endif // __MESHMERIZER_H__ 00130 } 00131 00133 00138 00139 bool Model::Build(const OPCODECREATE& create) 00140 { 00141 // 1) Checkings 00142 if(!create.mIMesh || !create.mIMesh->IsValid()) return false; 00143 00144 // For this model, we only support complete trees 00145 if(create.mSettings.mLimit!=1) return SetIceError("OPCODE WARNING: supports complete trees only! Use mLimit = 1.\n", null); 00146 00147 // Look for degenerate faces. 00148 udword NbDegenerate = create.mIMesh->CheckTopology(); 00149 if(NbDegenerate) Log("OPCODE WARNING: found %d degenerate faces in model! Collision might report wrong results!\n", NbDegenerate); 00150 // We continue nonetheless.... 00151 00152 Release(); // Make sure previous tree has been discarded [Opcode 1.3, thanks Adam] 00153 00154 // 1-1) Setup mesh interface automatically [Opcode 1.3] 00155 SetMeshInterface(create.mIMesh); 00156 00157 // Special case for 1-triangle meshes [Opcode 1.3] 00158 udword NbTris = create.mIMesh->GetNbTriangles(); 00159 /* 00160 if(NbTris==1) 00161 { 00162 // We don't need to actually create a tree here, since we'll only have a single triangle to deal with anyway. 00163 // It's a waste to use a "model" for this but at least it will work. 00164 mModelCode |= OPC_SINGLE_NODE; 00165 return true; 00166 } 00167 */ 00168 // 2) Build a generic AABB Tree. 00169 mSource = new AABBTree; 00170 CHECKALLOC(mSource); 00171 00172 // 2-1) Setup a builder. Our primitives here are triangles from input mesh, 00173 // so we use an AABBTreeOfTrianglesBuilder..... 00174 { 00175 AABBTreeOfTrianglesBuilder TB; 00176 TB.mIMesh = create.mIMesh; 00177 TB.mSettings = create.mSettings; 00178 TB.mNbPrimitives = NbTris; 00179 if(!mSource->Build(&TB)) return false; 00180 } 00181 00182 // 3) Create an optimized tree according to user-settings 00183 if(!CreateTree(create.mNoLeaf, create.mQuantized)) return false; 00184 00185 // 3-2) Create optimized tree 00186 if(!mTree->Build(mSource)) return false; 00187 00188 // 3-3) Delete generic tree if needed 00189 if(!create.mKeepOriginal) DELETESINGLE(mSource); 00190 00191 #ifdef __MESHMERIZER_H__ 00192 // 4) Convex hull 00193 if(create.mCollisionHull) 00194 { 00195 // Create hull 00196 mHull = new CollisionHull; 00197 CHECKALLOC(mHull); 00198 00199 CONVEXHULLCREATE CHC; 00200 // ### doesn't work with strides 00201 CHC.NbVerts = create.mIMesh->GetNbVertices(); 00202 CHC.Vertices = create.mIMesh->GetVerts(); 00203 CHC.UnifyNormals = true; 00204 CHC.ReduceVertices = true; 00205 CHC.WordFaces = false; 00206 mHull->Compute(CHC); 00207 } 00208 #endif // __MESHMERIZER_H__ 00209 00210 return true; 00211 } 00212 00214 00218 00219 udword Model::GetUsedBytes() const 00220 { 00221 if(!mTree) return 0; 00222 return mTree->GetUsedBytes(); 00223 }