Imported Upstream version 2.81
[platform/upstream/libbullet.git] / Extras / CDTestFramework / Opcode / OPC_Model.cpp
1 /*
2  *      OPCODE - Optimized Collision Detection
3  * http://www.codercorner.com/Opcode.htm
4  * 
5  * Copyright (c) 2001-2008 Pierre Terdiman,  pierre@codercorner.com
6
7 This software is provided 'as-is', without any express or implied warranty.
8 In no event will the authors be held liable for any damages arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose, 
10 including commercial applications, and to alter it and redistribute it freely, 
11 subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
14 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
15 3. This notice may not be removed or altered from any source distribution.
16 */
17
18 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19 /**
20  *      Contains code for OPCODE models.
21  *      \file           OPC_Model.cpp
22  *      \author         Pierre Terdiman
23  *      \date           March, 20, 2001
24  */
25 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
26
27 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
28 /**
29  *      The main collision wrapper, for all trees. Supported trees are:
30  *      - Normal trees (2*N-1 nodes, full size)
31  *      - No-leaf trees (N-1 nodes, full size)
32  *      - Quantized trees (2*N-1 nodes, half size)
33  *      - Quantized no-leaf trees (N-1 nodes, half size)
34  *
35  *      Usage:
36  *
37  *      1) Create a static mesh interface using callbacks or pointers. (see OPC_MeshInterface.cpp).
38  *      Keep it around in your app, since a pointer to this interface is saved internally and
39  *      used until you release the collision structures.
40  *
41  *      2) Build a Model using a creation structure:
42  *
43  *      \code
44  *              Model Sample;
45  *
46  *              OPCODECREATE OPCC;
47  *              OPCC.IMesh                      = ...;
48  *              OPCC.Rules                      = ...;
49  *              OPCC.NoLeaf                     = ...;
50  *              OPCC.Quantized          = ...;
51  *              OPCC.KeepOriginal       = ...;
52  *              bool Status = Sample.Build(OPCC);
53  *      \endcode
54  *
55  *      3) Create a tree collider and set it up:
56  *
57  *      \code
58  *              AABBTreeCollider TC;
59  *              TC.SetFirstContact(...);
60  *              TC.SetFullBoxBoxTest(...);
61  *              TC.SetFullPrimBoxTest(...);
62  *              TC.SetTemporalCoherence(...);
63  *      \endcode
64  *
65  *      4) Perform a collision query
66  *
67  *      \code
68  *              // Setup cache
69  *              static BVTCache ColCache;
70  *              ColCache.Model0 = &Model0;
71  *              ColCache.Model1 = &Model1;
72  *
73  *              // Collision query
74  *              bool IsOk = TC.Collide(ColCache, World0, World1);
75  *
76  *              // Get collision status => if true, objects overlap
77  *              BOOL Status = TC.GetContactStatus();
78  *
79  *              // Number of colliding pairs and list of pairs
80  *              udword NbPairs = TC.GetNbPairs();
81  *              const Pair* p = TC.GetPairs()
82  *      \endcode
83  *
84  *      5) Stats
85  *
86  *      \code
87  *              Model0.GetUsedBytes()   = number of bytes used for this collision tree
88  *              TC.GetNbBVBVTests()             = number of BV-BV overlap tests performed during last query
89  *              TC.GetNbPrimPrimTests() = number of Triangle-Triangle overlap tests performed during last query
90  *              TC.GetNbBVPrimTests()   = number of Triangle-BV overlap tests performed during last query
91  *      \endcode
92  *
93  *      \class          Model
94  *      \author         Pierre Terdiman
95  *      \version        1.3
96  *      \date           March, 20, 2001
97 */
98 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
99
100 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
101 // Precompiled Header
102 #include "Stdafx.h"
103
104 using namespace Opcode;
105
106 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
107 /**
108  *      Constructor.
109  */
110 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
111 Model::Model()
112 {
113 #ifdef __MESHMERIZER_H__        // Collision hulls only supported within ICE !
114         mHull   = null;
115 #endif // __MESHMERIZER_H__
116 }
117
118 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
119 /**
120  *      Destructor.
121  */
122 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
123 Model::~Model()
124 {
125         Release();
126 }
127
128 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
129 /**
130  *      Releases the model.
131  */
132 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
133 void Model::Release()
134 {
135         ReleaseBase();
136 #ifdef __MESHMERIZER_H__        // Collision hulls only supported within ICE !
137         DELETESINGLE(mHull);
138 #endif // __MESHMERIZER_H__
139 }
140
141 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
142 /**
143  *      Builds a collision model.
144  *      \param          create          [in] model creation structure
145  *      \return         true if success
146  */
147 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
148 bool Model::Build(const OPCODECREATE& create)
149 {
150         // 1) Checkings
151         if(!create.mIMesh || !create.mIMesh->IsValid()) return false;
152
153         // For this model, we only support complete trees
154         if(create.mSettings.mLimit!=1)  return SetIceError("OPCODE WARNING: supports complete trees only! Use mLimit = 1.\n", null);
155
156         // Look for degenerate faces.
157         udword NbDegenerate = create.mIMesh->CheckTopology();
158         if(NbDegenerate)        Log("OPCODE WARNING: found %d degenerate faces in model! Collision might report wrong results!\n", NbDegenerate);
159         // We continue nonetheless.... 
160
161         Release();      // Make sure previous tree has been discarded [Opcode 1.3, thanks Adam]
162
163         // 1-1) Setup mesh interface automatically [Opcode 1.3]
164         SetMeshInterface(create.mIMesh);
165
166         // Special case for 1-triangle meshes [Opcode 1.3]
167         udword NbTris = create.mIMesh->GetNbTriangles();
168         if(NbTris==1)
169         {
170                 // We don't need to actually create a tree here, since we'll only have a single triangle to deal with anyway.
171                 // It's a waste to use a "model" for this but at least it will work.
172                 mModelCode |= OPC_SINGLE_NODE;
173                 return true;
174         }
175
176         // 2) Build a generic AABB Tree.
177         mSource = new AABBTree;
178         CHECKALLOC(mSource);
179
180         // 2-1) Setup a builder. Our primitives here are triangles from input mesh,
181         // so we use an AABBTreeOfTrianglesBuilder.....
182         {
183                 AABBTreeOfTrianglesBuilder TB;
184                 TB.mIMesh                       = create.mIMesh;
185                 TB.mSettings            = create.mSettings;
186                 TB.mNbPrimitives        = NbTris;
187                 if(!mSource->Build(&TB))        return false;
188         }
189
190         // 3) Create an optimized tree according to user-settings
191         if(!CreateTree(create.mNoLeaf, create.mQuantized))      return false;
192
193         // 3-2) Create optimized tree
194         if(!mTree->Build(mSource))      return false;
195
196         // 3-3) Delete generic tree if needed
197         if(!create.mKeepOriginal)       DELETESINGLE(mSource);
198
199 #ifdef __MESHMERIZER_H__
200         // 4) Convex hull
201         if(create.mCollisionHull)
202         {
203                 // Create hull
204                 mHull = new CollisionHull;
205                 CHECKALLOC(mHull);
206
207                 CONVEXHULLCREATE CHC;
208                 // ### doesn't work with strides
209                 CHC.NbVerts                     = create.mIMesh->GetNbVertices();
210                 CHC.Vertices            = create.mIMesh->GetVerts();
211                 CHC.UnifyNormals        = true;
212                 CHC.ReduceVertices      = true;
213                 CHC.WordFaces           = false;
214                 mHull->Compute(CHC);
215         }
216 #endif // __MESHMERIZER_H__
217
218         return true;
219 }
220
221 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
222 /**
223  *      Gets the number of bytes used by the tree.
224  *      \return         amount of bytes used
225  */
226 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
227 udword Model::GetUsedBytes() const
228 {
229         if(!mTree)      return 0;
230         return mTree->GetUsedBytes();
231 }