Fixed: Windows target Subsystem was fixed for demos in CMake to match changes in...
[ode.git] / OPCODE / OPC_Model.cpp
blob418dd7e96663b7151fd4e2b57ba4d46979f029d1
1 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 /*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10 /**
11 * Contains code for OPCODE models.
12 * \file OPC_Model.cpp
13 * \author Pierre Terdiman
14 * \date March, 20, 2001
16 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
18 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19 /**
20 * The main collision wrapper, for all trees. Supported trees are:
21 * - Normal trees (2*N-1 nodes, full size)
22 * - No-leaf trees (N-1 nodes, full size)
23 * - Quantized trees (2*N-1 nodes, half size)
24 * - Quantized no-leaf trees (N-1 nodes, half size)
26 * Usage:
28 * 1) Create a static mesh interface using callbacks or pointers. (see OPC_MeshInterface.cpp).
29 * Keep it around in your app, since a pointer to this interface is saved internally and
30 * used until you release the collision structures.
32 * 2) Build a Model using a creation structure:
34 * \code
35 * Model Sample;
37 * OPCODECREATE OPCC;
38 * OPCC.IMesh = ...;
39 * OPCC.Rules = ...;
40 * OPCC.NoLeaf = ...;
41 * OPCC.Quantized = ...;
42 * OPCC.KeepOriginal = ...;
43 * bool Status = Sample.Build(OPCC);
44 * \endcode
46 * 3) Create a tree collider and set it up:
48 * \code
49 * AABBTreeCollider TC;
50 * TC.SetFirstContact(...);
51 * TC.SetFullBoxBoxTest(...);
52 * TC.SetFullPrimBoxTest(...);
53 * TC.SetTemporalCoherence(...);
54 * \endcode
56 * 4) Perform a collision query
58 * \code
59 * // Setup cache
60 * static BVTCache ColCache;
61 * ColCache.Model0 = &Model0;
62 * ColCache.Model1 = &Model1;
64 * // Collision query
65 * bool IsOk = TC.Collide(ColCache, World0, World1);
67 * // Get collision status => if true, objects overlap
68 * BOOL Status = TC.GetContactStatus();
70 * // Number of colliding pairs and list of pairs
71 * udword NbPairs = TC.GetNbPairs();
72 * const Pair* p = TC.GetPairs()
73 * \endcode
75 * 5) Stats
77 * \code
78 * Model0.GetUsedBytes() = number of bytes used for this collision tree
79 * TC.GetNbBVBVTests() = number of BV-BV overlap tests performed during last query
80 * TC.GetNbPrimPrimTests() = number of Triangle-Triangle overlap tests performed during last query
81 * TC.GetNbBVPrimTests() = number of Triangle-BV overlap tests performed during last query
82 * \endcode
84 * \class Model
85 * \author Pierre Terdiman
86 * \version 1.3
87 * \date March, 20, 2001
89 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
91 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
92 // Precompiled Header
93 #include "Stdafx.h"
95 using namespace Opcode;
97 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
98 /**
99 * Constructor.
101 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
102 Model::Model()
104 #ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE !
105 mHull = null;
106 #endif // __MESHMERIZER_H__
109 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
111 * Destructor.
113 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
114 Model::~Model()
116 Release();
119 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
121 * Releases the model.
123 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
124 void Model::Release()
126 ReleaseBase();
127 #ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE !
128 DELETESINGLE(mHull);
129 #endif // __MESHMERIZER_H__
132 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
134 * Builds a collision model.
135 * \param create [in] model creation structure
136 * \return true if success
138 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
139 bool Model::Build(const OPCODECREATE& create)
141 // 1) Checkings
142 if(!create.mIMesh || !create.mIMesh->IsValid()) return false;
144 // For this model, we only support complete trees
145 if(create.mSettings.mLimit!=1) return SetIceError("OPCODE WARNING: supports complete trees only! Use mLimit = 1.\n", null);
147 // Look for degenerate faces.
148 //udword NbDegenerate = create.mIMesh->CheckTopology();
149 //if(NbDegenerate) Log("OPCODE WARNING: found %d degenerate faces in model! Collision might report wrong results!\n", NbDegenerate);
150 // We continue nonetheless....
152 Release(); // Make sure previous tree has been discarded [Opcode 1.3, thanks Adam]
154 // 1-1) Setup mesh interface automatically [Opcode 1.3]
155 SetMeshInterface(create.mIMesh);
157 // Special case for 1-triangle meshes [Opcode 1.3]
158 udword NbTris = create.mIMesh->GetNbTriangles();
159 if(NbTris==1)
161 // We don't need to actually create a tree here, since we'll only have a single triangle to deal with anyway.
162 // It's a waste to use a "model" for this but at least it will work.
163 mModelCode |= OPC_SINGLE_NODE;
164 return true;
167 // 2) Build a generic AABB Tree.
168 mSource = new AABBTree;
169 CHECKALLOC(mSource);
171 // 2-1) Setup a builder. Our primitives here are triangles from input mesh,
172 // so we use an AABBTreeOfTrianglesBuilder.....
174 AABBTreeOfTrianglesBuilder TB;
175 TB.mIMesh = create.mIMesh;
176 TB.mSettings = create.mSettings;
177 TB.mNbPrimitives = NbTris;
178 if(!mSource->Build(&TB)) return false;
181 // 3) Create an optimized tree according to user-settings
182 if(!CreateTree(create.mNoLeaf, create.mQuantized)) return false;
184 // 3-2) Create optimized tree
185 if(!mTree->Build(mSource)) return false;
187 // 3-3) Delete generic tree if needed
188 if(!create.mKeepOriginal) DELETESINGLE(mSource);
190 #ifdef __MESHMERIZER_H__
191 // 4) Convex hull
192 if(create.mCollisionHull)
194 // Create hull
195 mHull = new CollisionHull;
196 CHECKALLOC(mHull);
198 CONVEXHULLCREATE CHC;
199 // ### doesn't work with strides
200 CHC.NbVerts = create.mIMesh->GetNbVertices();
201 CHC.Vertices = create.mIMesh->GetVerts();
202 CHC.UnifyNormals = true;
203 CHC.ReduceVertices = true;
204 CHC.WordFaces = false;
205 mHull->Compute(CHC);
207 #endif // __MESHMERIZER_H__
209 return true;
212 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
214 * Gets the number of bytes used by the tree.
215 * \return amount of bytes used
217 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
218 udword Model::GetUsedBytes() const
220 if(!mTree) return 0;
221 return mTree->GetUsedBytes();