aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ode-0.9/OPCODE
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceAABB.cpp405
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceAABB.h505
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceAxes.h54
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceBoundingSphere.h142
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceContainer.cpp345
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceContainer.h212
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceFPU.h337
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceHPoint.cpp70
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceHPoint.h160
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceIndexedTriangle.cpp548
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceIndexedTriangle.h72
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceLSS.h75
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceMatrix3x3.cpp48
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceMatrix3x3.h496
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceMatrix4x4.cpp135
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceMatrix4x4.h455
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceMemoryMacros.h109
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceOBB.cpp323
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceOBB.h177
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IcePairs.h45
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IcePlane.cpp45
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IcePlane.h113
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IcePoint.cpp193
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IcePoint.h528
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IcePreprocessor.h132
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceRandom.cpp35
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceRandom.h42
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceRay.cpp84
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceRay.h98
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceRevisitedRadix.cpp520
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceRevisitedRadix.h65
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceSegment.cpp57
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceSegment.h55
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceTriList.h61
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceTriangle.cpp286
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceTriangle.h68
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceTypes.h171
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceUtils.cpp39
-rw-r--r--libraries/ode-0.9/OPCODE/Ice/IceUtils.h256
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_AABBCollider.cpp696
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_AABBCollider.h97
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_AABBTree.cpp573
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_AABBTree.h137
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_BaseModel.cpp138
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_BaseModel.h175
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_BoxBoxOverlap.h122
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_BoxPruning.cpp367
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_BoxPruning.h31
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_Collider.cpp54
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_Collider.h176
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_Common.cpp48
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_Common.h101
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_HybridModel.cpp466
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_HybridModel.h106
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_IceHook.h70
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_LSSAABBOverlap.h523
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_LSSCollider.cpp725
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_LSSCollider.h99
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_LSSTriOverlap.h679
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_MeshInterface.cpp303
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_MeshInterface.h199
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_Model.cpp222
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_Model.h65
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_OBBCollider.cpp767
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_OBBCollider.h142
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_OptimizedTree.cpp782
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_OptimizedTree.h206
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_Picking.cpp182
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_Picking.h45
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_PlanesAABBOverlap.h50
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_PlanesCollider.cpp653
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_PlanesCollider.h121
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_PlanesTriOverlap.h40
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_RayAABBOverlap.h63
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_RayCollider.cpp762
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_RayCollider.h225
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_RayTriOverlap.h89
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_Settings.h49
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_SphereAABBOverlap.h128
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_SphereCollider.cpp739
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_SphereCollider.h96
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_SphereTriOverlap.h187
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_SweepAndPrune.cpp664
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_SweepAndPrune.h86
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_TreeBuilders.cpp255
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_TreeBuilders.h173
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_TreeCollider.cpp943
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_TreeCollider.h246
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_TriBoxOverlap.h339
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_TriTriOverlap.h279
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_VolumeCollider.cpp103
-rw-r--r--libraries/ode-0.9/OPCODE/OPC_VolumeCollider.h138
-rw-r--r--libraries/ode-0.9/OPCODE/Opcode.cpp65
-rw-r--r--libraries/ode-0.9/OPCODE/Opcode.dsp470
-rw-r--r--libraries/ode-0.9/OPCODE/Opcode.dsw29
-rw-r--r--libraries/ode-0.9/OPCODE/Opcode.h113
-rw-r--r--libraries/ode-0.9/OPCODE/README-ODE.txt13
-rw-r--r--libraries/ode-0.9/OPCODE/ReadMe.txt171
-rw-r--r--libraries/ode-0.9/OPCODE/StdAfx.cpp10
-rw-r--r--libraries/ode-0.9/OPCODE/Stdafx.h24
-rw-r--r--libraries/ode-0.9/OPCODE/TemporalCoherence.txt32
101 files changed, 23212 insertions, 0 deletions
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceAABB.cpp b/libraries/ode-0.9/OPCODE/Ice/IceAABB.cpp
new file mode 100644
index 0000000..d62b0ed
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceAABB.cpp
@@ -0,0 +1,405 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains AABB-related code.
4 * \file IceAABB.cpp
5 * \author Pierre Terdiman
6 * \date January, 29, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11/**
12 * AABB class.
13 * \class AABB
14 * \author Pierre Terdiman
15 * \version 1.0
16 */
17///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
18
19///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
20// Precompiled Header
21#include "Stdafx.h"
22
23using namespace IceMaths;
24
25///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
26/**
27 * Computes the sum of two AABBs.
28 * \param aabb [in] the other AABB
29 * \return Self-Reference
30 */
31///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
32AABB& AABB::Add(const AABB& aabb)
33{
34 // Compute new min & max values
35 Point Min; GetMin(Min);
36 Point Tmp; aabb.GetMin(Tmp);
37 Min.Min(Tmp);
38
39 Point Max; GetMax(Max);
40 aabb.GetMax(Tmp);
41 Max.Max(Tmp);
42
43 // Update this
44 SetMinMax(Min, Max);
45 return *this;
46}
47
48///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
49/**
50 * Makes a cube from the AABB.
51 * \param cube [out] the cube AABB
52 * \return cube edge length
53 */
54///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
55float AABB::MakeCube(AABB& cube) const
56{
57 Point Ext; GetExtents(Ext);
58 float Max = Ext.Max();
59
60 Point Cnt; GetCenter(Cnt);
61 cube.SetCenterExtents(Cnt, Point(Max, Max, Max));
62 return Max;
63}
64
65///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
66/**
67 * Makes a sphere from the AABB.
68 * \param sphere [out] sphere containing the AABB
69 */
70///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
71void AABB::MakeSphere(Sphere& sphere) const
72{
73 GetExtents(sphere.mCenter);
74 sphere.mRadius = sphere.mCenter.Magnitude() * 1.00001f; // To make sure sphere::Contains(*this) succeeds
75 GetCenter(sphere.mCenter);
76}
77
78///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
79/**
80 * Checks a box is inside another box.
81 * \param box [in] the other AABB
82 * \return true if current box is inside input box
83 */
84///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
85bool AABB::IsInside(const AABB& box) const
86{
87 if(box.GetMin(0)>GetMin(0)) return false;
88 if(box.GetMin(1)>GetMin(1)) return false;
89 if(box.GetMin(2)>GetMin(2)) return false;
90 if(box.GetMax(0)<GetMax(0)) return false;
91 if(box.GetMax(1)<GetMax(1)) return false;
92 if(box.GetMax(2)<GetMax(2)) return false;
93 return true;
94}
95
96///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
97/**
98 * Computes the AABB planes.
99 * \param planes [out] 6 planes surrounding the box
100 * \return true if success
101 */
102///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
103bool AABB::ComputePlanes(Plane* planes) const
104{
105 // Checkings
106 if(!planes) return false;
107
108 Point Center, Extents;
109 GetCenter(Center);
110 GetExtents(Extents);
111
112 // Writes normals
113 planes[0].n = Point(1.0f, 0.0f, 0.0f);
114 planes[1].n = Point(-1.0f, 0.0f, 0.0f);
115 planes[2].n = Point(0.0f, 1.0f, 0.0f);
116 planes[3].n = Point(0.0f, -1.0f, 0.0f);
117 planes[4].n = Point(0.0f, 0.0f, 1.0f);
118 planes[5].n = Point(0.0f, 0.0f, -1.0f);
119
120 // Compute a point on each plane
121 Point p0 = Point(Center.x+Extents.x, Center.y, Center.z);
122 Point p1 = Point(Center.x-Extents.x, Center.y, Center.z);
123 Point p2 = Point(Center.x, Center.y+Extents.y, Center.z);
124 Point p3 = Point(Center.x, Center.y-Extents.y, Center.z);
125 Point p4 = Point(Center.x, Center.y, Center.z+Extents.z);
126 Point p5 = Point(Center.x, Center.y, Center.z-Extents.z);
127
128 // Compute d
129 planes[0].d = -(planes[0].n|p0);
130 planes[1].d = -(planes[1].n|p1);
131 planes[2].d = -(planes[2].n|p2);
132 planes[3].d = -(planes[3].n|p3);
133 planes[4].d = -(planes[4].n|p4);
134 planes[5].d = -(planes[5].n|p5);
135
136 return true;
137}
138
139///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
140/**
141 * Computes the aabb points.
142 * \param pts [out] 8 box points
143 * \return true if success
144 */
145///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
146bool AABB::ComputePoints(Point* pts) const
147{
148 // Checkings
149 if(!pts) return false;
150
151 // Get box corners
152 Point min; GetMin(min);
153 Point max; GetMax(max);
154
155 // 7+------+6 0 = ---
156 // /| /| 1 = +--
157 // / | / | 2 = ++-
158 // / 4+---/--+5 3 = -+-
159 // 3+------+2 / y z 4 = --+
160 // | / | / | / 5 = +-+
161 // |/ |/ |/ 6 = +++
162 // 0+------+1 *---x 7 = -++
163
164 // Generate 8 corners of the bbox
165 pts[0] = Point(min.x, min.y, min.z);
166 pts[1] = Point(max.x, min.y, min.z);
167 pts[2] = Point(max.x, max.y, min.z);
168 pts[3] = Point(min.x, max.y, min.z);
169 pts[4] = Point(min.x, min.y, max.z);
170 pts[5] = Point(max.x, min.y, max.z);
171 pts[6] = Point(max.x, max.y, max.z);
172 pts[7] = Point(min.x, max.y, max.z);
173
174 return true;
175}
176
177///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
178/**
179 * Gets vertex normals.
180 * \param pts [out] 8 box points
181 * \return true if success
182 */
183///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
184const Point* AABB::GetVertexNormals() const
185{
186 static float VertexNormals[] =
187 {
188 -INVSQRT3, -INVSQRT3, -INVSQRT3,
189 INVSQRT3, -INVSQRT3, -INVSQRT3,
190 INVSQRT3, INVSQRT3, -INVSQRT3,
191 -INVSQRT3, INVSQRT3, -INVSQRT3,
192 -INVSQRT3, -INVSQRT3, INVSQRT3,
193 INVSQRT3, -INVSQRT3, INVSQRT3,
194 INVSQRT3, INVSQRT3, INVSQRT3,
195 -INVSQRT3, INVSQRT3, INVSQRT3
196 };
197 return (const Point*)VertexNormals;
198}
199
200///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
201/**
202 * Returns edges.
203 * \return 24 indices (12 edges) indexing the list returned by ComputePoints()
204 */
205///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
206const udword* AABB::GetEdges() const
207{
208 static udword Indices[] = {
209 0, 1, 1, 2, 2, 3, 3, 0,
210 7, 6, 6, 5, 5, 4, 4, 7,
211 1, 5, 6, 2,
212 3, 7, 4, 0
213 };
214 return Indices;
215}
216
217///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
218/**
219 * Returns edge normals.
220 * \return edge normals in local space
221 */
222///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
223const Point* AABB::GetEdgeNormals() const
224{
225 static float EdgeNormals[] =
226 {
227 0, -INVSQRT2, -INVSQRT2, // 0-1
228 INVSQRT2, 0, -INVSQRT2, // 1-2
229 0, INVSQRT2, -INVSQRT2, // 2-3
230 -INVSQRT2, 0, -INVSQRT2, // 3-0
231
232 0, INVSQRT2, INVSQRT2, // 7-6
233 INVSQRT2, 0, INVSQRT2, // 6-5
234 0, -INVSQRT2, INVSQRT2, // 5-4
235 -INVSQRT2, 0, INVSQRT2, // 4-7
236
237 INVSQRT2, -INVSQRT2, 0, // 1-5
238 INVSQRT2, INVSQRT2, 0, // 6-2
239 -INVSQRT2, INVSQRT2, 0, // 3-7
240 -INVSQRT2, -INVSQRT2, 0 // 4-0
241 };
242 return (const Point*)EdgeNormals;
243}
244
245// ===========================================================================
246// (C) 1996-98 Vienna University of Technology
247// ===========================================================================
248// NAME: bboxarea
249// TYPE: c++ code
250// PROJECT: Bounding Box Area
251// CONTENT: Computes area of 2D projection of 3D oriented bounding box
252// VERSION: 1.0
253// ===========================================================================
254// AUTHORS: ds Dieter Schmalstieg
255// ep Erik Pojar
256// ===========================================================================
257// HISTORY:
258//
259// 19-sep-99 15:23:03 ds last modification
260// 01-dec-98 15:23:03 ep created
261// ===========================================================================
262
263//----------------------------------------------------------------------------
264// SAMPLE CODE STARTS HERE
265//----------------------------------------------------------------------------
266
267// NOTE: This sample program requires OPEN INVENTOR!
268
269//indexlist: this table stores the 64 possible cases of classification of
270//the eyepoint with respect to the 6 defining planes of the bbox (2^6=64)
271//only 26 (3^3-1, where 1 is "inside" cube) of these cases are valid.
272//the first 6 numbers in each row are the indices of the bbox vertices that
273//form the outline of which we want to compute the area (counterclockwise
274//ordering), the 7th entry means the number of vertices in the outline.
275//there are 6 cases with a single face and and a 4-vertex outline, and
276//20 cases with 2 or 3 faces and a 6-vertex outline. a value of 0 indicates
277//an invalid case.
278
279
280// Original list was made of 7 items, I added an 8th element:
281// - to padd on a cache line
282// - to repeat the first entry to avoid modulos
283//
284// I also replaced original ints with sbytes.
285
286static const sbyte gIndexList[64][8] =
287{
288 {-1,-1,-1,-1,-1,-1,-1, 0}, // 0 inside
289 { 0, 4, 7, 3, 0,-1,-1, 4}, // 1 left
290 { 1, 2, 6, 5, 1,-1,-1, 4}, // 2 right
291 {-1,-1,-1,-1,-1,-1,-1, 0}, // 3 -
292 { 0, 1, 5, 4, 0,-1,-1, 4}, // 4 bottom
293 { 0, 1, 5, 4, 7, 3, 0, 6}, // 5 bottom, left
294 { 0, 1, 2, 6, 5, 4, 0, 6}, // 6 bottom, right
295 {-1,-1,-1,-1,-1,-1,-1, 0}, // 7 -
296 { 2, 3, 7, 6, 2,-1,-1, 4}, // 8 top
297 { 0, 4, 7, 6, 2, 3, 0, 6}, // 9 top, left
298 { 1, 2, 3, 7, 6, 5, 1, 6}, //10 top, right
299 {-1,-1,-1,-1,-1,-1,-1, 0}, //11 -
300 {-1,-1,-1,-1,-1,-1,-1, 0}, //12 -
301 {-1,-1,-1,-1,-1,-1,-1, 0}, //13 -
302 {-1,-1,-1,-1,-1,-1,-1, 0}, //14 -
303 {-1,-1,-1,-1,-1,-1,-1, 0}, //15 -
304 { 0, 3, 2, 1, 0,-1,-1, 4}, //16 front
305 { 0, 4, 7, 3, 2, 1, 0, 6}, //17 front, left
306 { 0, 3, 2, 6, 5, 1, 0, 6}, //18 front, right
307 {-1,-1,-1,-1,-1,-1,-1, 0}, //19 -
308 { 0, 3, 2, 1, 5, 4, 0, 6}, //20 front, bottom
309 { 1, 5, 4, 7, 3, 2, 1, 6}, //21 front, bottom, left
310 { 0, 3, 2, 6, 5, 4, 0, 6}, //22 front, bottom, right
311 {-1,-1,-1,-1,-1,-1,-1, 0}, //23 -
312 { 0, 3, 7, 6, 2, 1, 0, 6}, //24 front, top
313 { 0, 4, 7, 6, 2, 1, 0, 6}, //25 front, top, left
314 { 0, 3, 7, 6, 5, 1, 0, 6}, //26 front, top, right
315 {-1,-1,-1,-1,-1,-1,-1, 0}, //27 -
316 {-1,-1,-1,-1,-1,-1,-1, 0}, //28 -
317 {-1,-1,-1,-1,-1,-1,-1, 0}, //29 -
318 {-1,-1,-1,-1,-1,-1,-1, 0}, //30 -
319 {-1,-1,-1,-1,-1,-1,-1, 0}, //31 -
320 { 4, 5, 6, 7, 4,-1,-1, 4}, //32 back
321 { 0, 4, 5, 6, 7, 3, 0, 6}, //33 back, left
322 { 1, 2, 6, 7, 4, 5, 1, 6}, //34 back, right
323 {-1,-1,-1,-1,-1,-1,-1, 0}, //35 -
324 { 0, 1, 5, 6, 7, 4, 0, 6}, //36 back, bottom
325 { 0, 1, 5, 6, 7, 3, 0, 6}, //37 back, bottom, left
326 { 0, 1, 2, 6, 7, 4, 0, 6}, //38 back, bottom, right
327 {-1,-1,-1,-1,-1,-1,-1, 0}, //39 -
328 { 2, 3, 7, 4, 5, 6, 2, 6}, //40 back, top
329 { 0, 4, 5, 6, 2, 3, 0, 6}, //41 back, top, left
330 { 1, 2, 3, 7, 4, 5, 1, 6}, //42 back, top, right
331 {-1,-1,-1,-1,-1,-1,-1, 0}, //43 invalid
332 {-1,-1,-1,-1,-1,-1,-1, 0}, //44 invalid
333 {-1,-1,-1,-1,-1,-1,-1, 0}, //45 invalid
334 {-1,-1,-1,-1,-1,-1,-1, 0}, //46 invalid
335 {-1,-1,-1,-1,-1,-1,-1, 0}, //47 invalid
336 {-1,-1,-1,-1,-1,-1,-1, 0}, //48 invalid
337 {-1,-1,-1,-1,-1,-1,-1, 0}, //49 invalid
338 {-1,-1,-1,-1,-1,-1,-1, 0}, //50 invalid
339 {-1,-1,-1,-1,-1,-1,-1, 0}, //51 invalid
340 {-1,-1,-1,-1,-1,-1,-1, 0}, //52 invalid
341 {-1,-1,-1,-1,-1,-1,-1, 0}, //53 invalid
342 {-1,-1,-1,-1,-1,-1,-1, 0}, //54 invalid
343 {-1,-1,-1,-1,-1,-1,-1, 0}, //55 invalid
344 {-1,-1,-1,-1,-1,-1,-1, 0}, //56 invalid
345 {-1,-1,-1,-1,-1,-1,-1, 0}, //57 invalid
346 {-1,-1,-1,-1,-1,-1,-1, 0}, //58 invalid
347 {-1,-1,-1,-1,-1,-1,-1, 0}, //59 invalid
348 {-1,-1,-1,-1,-1,-1,-1, 0}, //60 invalid
349 {-1,-1,-1,-1,-1,-1,-1, 0}, //61 invalid
350 {-1,-1,-1,-1,-1,-1,-1, 0}, //62 invalid
351 {-1,-1,-1,-1,-1,-1,-1, 0} //63 invalid
352};
353
354const sbyte* AABB::ComputeOutline(const Point& local_eye, sdword& num) const
355{
356 // Get box corners
357 Point min; GetMin(min);
358 Point max; GetMax(max);
359
360 // Compute 6-bit code to classify eye with respect to the 6 defining planes of the bbox
361 int pos = ((local_eye.x < min.x) ? 1 : 0) // 1 = left
362 + ((local_eye.x > max.x) ? 2 : 0) // 2 = right
363 + ((local_eye.y < min.y) ? 4 : 0) // 4 = bottom
364 + ((local_eye.y > max.y) ? 8 : 0) // 8 = top
365 + ((local_eye.z < min.z) ? 16 : 0) // 16 = front
366 + ((local_eye.z > max.z) ? 32 : 0); // 32 = back
367
368 // Look up number of vertices in outline
369 num = (sdword)gIndexList[pos][7];
370 // Zero indicates invalid case
371 if(!num) return null;
372
373 return &gIndexList[pos][0];
374}
375
376// calculateBoxArea: computes the screen-projected 2D area of an oriented 3D bounding box
377
378//const Point& eye, //eye point (in bbox object coordinates)
379//const AABB& box, //3d bbox
380//const Matrix4x4& mat, //free transformation for bbox
381//float width, float height, int& num)
382float AABB::ComputeBoxArea(const Point& eye, const Matrix4x4& mat, float width, float height, sdword& num) const
383{
384 const sbyte* Outline = ComputeOutline(eye, num);
385 if(!Outline) return -1.0f;
386
387 // Compute box vertices
388 Point vertexBox[8], dst[8];
389 ComputePoints(vertexBox);
390
391 // Transform all outline corners into 2D screen space
392 for(sdword i=0;i<num;i++)
393 {
394 HPoint Projected;
395 vertexBox[Outline[i]].ProjectToScreen(width, height, mat, Projected);
396 dst[i] = Projected;
397 }
398
399 float Sum = (dst[num-1][0] - dst[0][0]) * (dst[num-1][1] + dst[0][1]);
400
401 for(int i=0; i<num-1; i++)
402 Sum += (dst[i][0] - dst[i+1][0]) * (dst[i][1] + dst[i+1][1]);
403
404 return Sum * 0.5f; //return computed value corrected by 0.5
405}
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceAABB.h b/libraries/ode-0.9/OPCODE/Ice/IceAABB.h
new file mode 100644
index 0000000..f71d7e9
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceAABB.h
@@ -0,0 +1,505 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains AABB-related code. (axis-aligned bounding box)
4 * \file IceAABB.h
5 * \author Pierre Terdiman
6 * \date January, 13, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICEAABB_H__
13#define __ICEAABB_H__
14
15 // Forward declarations
16 class Sphere;
17
18//! Declarations of type-independent methods (most of them implemented in the .cpp)
19#define AABB_COMMON_METHODS \
20 AABB& Add(const AABB& aabb); \
21 float MakeCube(AABB& cube) const; \
22 void MakeSphere(Sphere& sphere) const; \
23 const sbyte* ComputeOutline(const Point& local_eye, sdword& num) const; \
24 float ComputeBoxArea(const Point& eye, const Matrix4x4& mat, float width, float height, sdword& num) const; \
25 bool IsInside(const AABB& box) const; \
26 bool ComputePlanes(Plane* planes) const; \
27 bool ComputePoints(Point* pts) const; \
28 const Point* GetVertexNormals() const; \
29 const udword* GetEdges() const; \
30 const Point* GetEdgeNormals() const; \
31 inline_ BOOL ContainsPoint(const Point& p) const \
32 { \
33 if(p.x > GetMax(0) || p.x < GetMin(0)) return FALSE; \
34 if(p.y > GetMax(1) || p.y < GetMin(1)) return FALSE; \
35 if(p.z > GetMax(2) || p.z < GetMin(2)) return FALSE; \
36 return TRUE; \
37 }
38
39 enum AABBType
40 {
41 AABB_RENDER = 0, //!< AABB used for rendering. Not visible == not rendered.
42 AABB_UPDATE = 1, //!< AABB used for dynamic updates. Not visible == not updated.
43
44 AABB_FORCE_DWORD = 0x7fffffff,
45 };
46
47#ifdef USE_MINMAX
48
49 struct ICEMATHS_API ShadowAABB
50 {
51 Point mMin;
52 Point mMax;
53 };
54
55 class ICEMATHS_API AABB
56 {
57 public:
58 //! Constructor
59 inline_ AABB() {}
60 //! Destructor
61 inline_ ~AABB() {}
62
63 //! Type-independent methods
64 AABB_COMMON_METHODS;
65
66 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
67 /**
68 * Setups an AABB from min & max vectors.
69 * \param min [in] the min point
70 * \param max [in] the max point
71 */
72 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
73 void SetMinMax(const Point& min, const Point& max) { mMin = min; mMax = max; }
74
75 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
76 /**
77 * Setups an AABB from center & extents vectors.
78 * \param c [in] the center point
79 * \param e [in] the extents vector
80 */
81 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
82 void SetCenterExtents(const Point& c, const Point& e) { mMin = c - e; mMax = c + e; }
83
84 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
85 /**
86 * Setups an empty AABB.
87 */
88 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
89 void SetEmpty() { Point p(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); mMin = -p; mMax = p;}
90
91 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
92 /**
93 * Setups a point AABB.
94 */
95 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
96 void SetPoint(const Point& pt) { mMin = mMax = pt; }
97
98 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
99 /**
100 * Gets the size of the AABB. The size is defined as the longest extent.
101 * \return the size of the AABB
102 */
103 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
104 float GetSize() const { Point e; GetExtents(e); return e.Max(); }
105
106 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
107 /**
108 * Extends the AABB.
109 * \param p [in] the next point
110 */
111 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
112 void Extend(const Point& p)
113 {
114 if(p.x > mMax.x) mMax.x = p.x;
115 if(p.x < mMin.x) mMin.x = p.x;
116
117 if(p.y > mMax.y) mMax.y = p.y;
118 if(p.y < mMin.y) mMin.y = p.y;
119
120 if(p.z > mMax.z) mMax.z = p.z;
121 if(p.z < mMin.z) mMin.z = p.z;
122 }
123 // Data access
124
125 //! Get min point of the box
126 inline_ void GetMin(Point& min) const { min = mMin; }
127 //! Get max point of the box
128 inline_ void GetMax(Point& max) const { max = mMax; }
129
130 //! Get component of the box's min point along a given axis
131 inline_ float GetMin(udword axis) const { return mMin[axis]; }
132 //! Get component of the box's max point along a given axis
133 inline_ float GetMax(udword axis) const { return mMax[axis]; }
134
135 //! Get box center
136 inline_ void GetCenter(Point& center) const { center = (mMax + mMin)*0.5f; }
137 //! Get box extents
138 inline_ void GetExtents(Point& extents) const { extents = (mMax - mMin)*0.5f; }
139
140 //! Get component of the box's center along a given axis
141 inline_ float GetCenter(udword axis) const { return (mMax[axis] + mMin[axis])*0.5f; }
142 //! Get component of the box's extents along a given axis
143 inline_ float GetExtents(udword axis) const { return (mMax[axis] - mMin[axis])*0.5f; }
144
145 //! Get box diagonal
146 inline_ void GetDiagonal(Point& diagonal) const { diagonal = mMax - mMin; }
147 inline_ float GetWidth() const { return mMax.x - mMin.x; }
148 inline_ float GetHeight() const { return mMax.y - mMin.y; }
149 inline_ float GetDepth() const { return mMax.z - mMin.z; }
150
151 //! Volume
152 inline_ float GetVolume() const { return GetWidth() * GetHeight() * GetDepth(); }
153
154 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
155 /**
156 * Computes the intersection between two AABBs.
157 * \param a [in] the other AABB
158 * \return true on intersection
159 */
160 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
161 inline_ BOOL Intersect(const AABB& a) const
162 {
163 if(mMax.x < a.mMin.x
164 || a.mMax.x < mMin.x
165 || mMax.y < a.mMin.y
166 || a.mMax.y < mMin.y
167 || mMax.z < a.mMin.z
168 || a.mMax.z < mMin.z) return FALSE;
169
170 return TRUE;
171 }
172
173 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
174 /**
175 * Computes the 1D-intersection between two AABBs, on a given axis.
176 * \param a [in] the other AABB
177 * \param axis [in] the axis (0, 1, 2)
178 * \return true on intersection
179 */
180 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
181 inline_ BOOL Intersect(const AABB& a, udword axis) const
182 {
183 if(mMax[axis] < a.mMin[axis] || a.mMax[axis] < mMin[axis]) return FALSE;
184 return TRUE;
185 }
186
187 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
188 /**
189 * Recomputes the AABB after an arbitrary transform by a 4x4 matrix.
190 * Original code by Charles Bloom on the GD-Algorithm list. (I slightly modified it)
191 * \param mtx [in] the transform matrix
192 * \param aabb [out] the transformed AABB [can be *this]
193 */
194 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
195 inline_ void Rotate(const Matrix4x4& mtx, AABB& aabb) const
196 {
197 // The three edges transformed: you can efficiently transform an X-only vector
198 // by just getting the "X" column of the matrix
199 Point vx,vy,vz;
200 mtx.GetRow(0, vx); vx *= (mMax.x - mMin.x);
201 mtx.GetRow(1, vy); vy *= (mMax.y - mMin.y);
202 mtx.GetRow(2, vz); vz *= (mMax.z - mMin.z);
203
204 // Transform the min point
205 aabb.mMin = aabb.mMax = mMin * mtx;
206
207 // Take the transformed min & axes and find new extents
208 // Using CPU code in the right place is faster...
209 if(IS_NEGATIVE_FLOAT(vx.x)) aabb.mMin.x += vx.x; else aabb.mMax.x += vx.x;
210 if(IS_NEGATIVE_FLOAT(vx.y)) aabb.mMin.y += vx.y; else aabb.mMax.y += vx.y;
211 if(IS_NEGATIVE_FLOAT(vx.z)) aabb.mMin.z += vx.z; else aabb.mMax.z += vx.z;
212 if(IS_NEGATIVE_FLOAT(vy.x)) aabb.mMin.x += vy.x; else aabb.mMax.x += vy.x;
213 if(IS_NEGATIVE_FLOAT(vy.y)) aabb.mMin.y += vy.y; else aabb.mMax.y += vy.y;
214 if(IS_NEGATIVE_FLOAT(vy.z)) aabb.mMin.z += vy.z; else aabb.mMax.z += vy.z;
215 if(IS_NEGATIVE_FLOAT(vz.x)) aabb.mMin.x += vz.x; else aabb.mMax.x += vz.x;
216 if(IS_NEGATIVE_FLOAT(vz.y)) aabb.mMin.y += vz.y; else aabb.mMax.y += vz.y;
217 if(IS_NEGATIVE_FLOAT(vz.z)) aabb.mMin.z += vz.z; else aabb.mMax.z += vz.z;
218 }
219
220 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
221 /**
222 * Checks the AABB is valid.
223 * \return true if the box is valid
224 */
225 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
226 inline_ BOOL IsValid() const
227 {
228 // Consistency condition for (Min, Max) boxes: min < max
229 if(mMin.x > mMax.x) return FALSE;
230 if(mMin.y > mMax.y) return FALSE;
231 if(mMin.z > mMax.z) return FALSE;
232 return TRUE;
233 }
234
235 //! Operator for AABB *= float. Scales the extents, keeps same center.
236 inline_ AABB& operator*=(float s)
237 {
238 Point Center; GetCenter(Center);
239 Point Extents; GetExtents(Extents);
240 SetCenterExtents(Center, Extents * s);
241 return *this;
242 }
243
244 //! Operator for AABB /= float. Scales the extents, keeps same center.
245 inline_ AABB& operator/=(float s)
246 {
247 Point Center; GetCenter(Center);
248 Point Extents; GetExtents(Extents);
249 SetCenterExtents(Center, Extents / s);
250 return *this;
251 }
252
253 //! Operator for AABB += Point. Translates the box.
254 inline_ AABB& operator+=(const Point& trans)
255 {
256 mMin+=trans;
257 mMax+=trans;
258 return *this;
259 }
260 private:
261 Point mMin; //!< Min point
262 Point mMax; //!< Max point
263 };
264
265#else
266
267 class ICEMATHS_API AABB
268 {
269 public:
270 //! Constructor
271 inline_ AABB() {}
272 //! Destructor
273 inline_ ~AABB() {}
274
275 //! Type-independent methods
276 AABB_COMMON_METHODS;
277
278 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
279 /**
280 * Setups an AABB from min & max vectors.
281 * \param min [in] the min point
282 * \param max [in] the max point
283 */
284 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
285 void SetMinMax(const Point& min, const Point& max) { mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f; }
286
287 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
288 /**
289 * Setups an AABB from center & extents vectors.
290 * \param c [in] the center point
291 * \param e [in] the extents vector
292 */
293 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
294 void SetCenterExtents(const Point& c, const Point& e) { mCenter = c; mExtents = e; }
295
296 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
297 /**
298 * Setups an empty AABB.
299 */
300 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
301 void SetEmpty() { mCenter.Zero(); mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);}
302
303 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
304 /**
305 * Setups a point AABB.
306 */
307 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
308 void SetPoint(const Point& pt) { mCenter = pt; mExtents.Zero(); }
309
310 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
311 /**
312 * Gets the size of the AABB. The size is defined as the longest extent.
313 * \return the size of the AABB
314 */
315 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
316 float GetSize() const { return mExtents.Max(); }
317
318 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
319 /**
320 * Extends the AABB.
321 * \param p [in] the next point
322 */
323 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
324 void Extend(const Point& p)
325 {
326 Point Max = mCenter + mExtents;
327 Point Min = mCenter - mExtents;
328
329 if(p.x > Max.x) Max.x = p.x;
330 if(p.x < Min.x) Min.x = p.x;
331
332 if(p.y > Max.y) Max.y = p.y;
333 if(p.y < Min.y) Min.y = p.y;
334
335 if(p.z > Max.z) Max.z = p.z;
336 if(p.z < Min.z) Min.z = p.z;
337
338 SetMinMax(Min, Max);
339 }
340 // Data access
341
342 //! Get min point of the box
343 inline_ void GetMin(Point& min) const { min = mCenter - mExtents; }
344 //! Get max point of the box
345 inline_ void GetMax(Point& max) const { max = mCenter + mExtents; }
346
347 //! Get component of the box's min point along a given axis
348 inline_ float GetMin(udword axis) const { return mCenter[axis] - mExtents[axis]; }
349 //! Get component of the box's max point along a given axis
350 inline_ float GetMax(udword axis) const { return mCenter[axis] + mExtents[axis]; }
351
352 //! Get box center
353 inline_ void GetCenter(Point& center) const { center = mCenter; }
354 //! Get box extents
355 inline_ void GetExtents(Point& extents) const { extents = mExtents; }
356
357 //! Get component of the box's center along a given axis
358 inline_ float GetCenter(udword axis) const { return mCenter[axis]; }
359 //! Get component of the box's extents along a given axis
360 inline_ float GetExtents(udword axis) const { return mExtents[axis]; }
361
362 //! Get box diagonal
363 inline_ void GetDiagonal(Point& diagonal) const { diagonal = mExtents * 2.0f; }
364 inline_ float GetWidth() const { return mExtents.x * 2.0f; }
365 inline_ float GetHeight() const { return mExtents.y * 2.0f; }
366 inline_ float GetDepth() const { return mExtents.z * 2.0f; }
367
368 //! Volume
369 inline_ float GetVolume() const { return mExtents.x * mExtents.y * mExtents.z * 8.0f; }
370
371 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
372 /**
373 * Computes the intersection between two AABBs.
374 * \param a [in] the other AABB
375 * \return true on intersection
376 */
377 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
378 inline_ BOOL Intersect(const AABB& a) const
379 {
380 float tx = mCenter.x - a.mCenter.x; float ex = a.mExtents.x + mExtents.x; if(AIR(tx) > IR(ex)) return FALSE;
381 float ty = mCenter.y - a.mCenter.y; float ey = a.mExtents.y + mExtents.y; if(AIR(ty) > IR(ey)) return FALSE;
382 float tz = mCenter.z - a.mCenter.z; float ez = a.mExtents.z + mExtents.z; if(AIR(tz) > IR(ez)) return FALSE;
383 return TRUE;
384 }
385
386 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
387 /**
388 * The standard intersection method from Gamasutra. Just here to check its speed against the one above.
389 * \param a [in] the other AABB
390 * \return true on intersection
391 */
392 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
393 inline_ bool GomezIntersect(const AABB& a)
394 {
395 Point T = mCenter - a.mCenter; // Vector from A to B
396 return ((fabsf(T.x) <= (a.mExtents.x + mExtents.x))
397 && (fabsf(T.y) <= (a.mExtents.y + mExtents.y))
398 && (fabsf(T.z) <= (a.mExtents.z + mExtents.z)));
399 }
400
401 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
402 /**
403 * Computes the 1D-intersection between two AABBs, on a given axis.
404 * \param a [in] the other AABB
405 * \param axis [in] the axis (0, 1, 2)
406 * \return true on intersection
407 */
408 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
409 inline_ BOOL Intersect(const AABB& a, udword axis) const
410 {
411 float t = mCenter[axis] - a.mCenter[axis];
412 float e = a.mExtents[axis] + mExtents[axis];
413 if(AIR(t) > IR(e)) return FALSE;
414 return TRUE;
415 }
416
417 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
418 /**
419 * Recomputes the AABB after an arbitrary transform by a 4x4 matrix.
420 * \param mtx [in] the transform matrix
421 * \param aabb [out] the transformed AABB [can be *this]
422 */
423 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
424 inline_ void Rotate(const Matrix4x4& mtx, AABB& aabb) const
425 {
426 // Compute new center
427 aabb.mCenter = mCenter * mtx;
428
429 // Compute new extents. FPU code & CPU code have been interleaved for improved performance.
430 Point Ex(mtx.m[0][0] * mExtents.x, mtx.m[0][1] * mExtents.x, mtx.m[0][2] * mExtents.x);
431 IR(Ex.x)&=0x7fffffff; IR(Ex.y)&=0x7fffffff; IR(Ex.z)&=0x7fffffff;
432
433 Point Ey(mtx.m[1][0] * mExtents.y, mtx.m[1][1] * mExtents.y, mtx.m[1][2] * mExtents.y);
434 IR(Ey.x)&=0x7fffffff; IR(Ey.y)&=0x7fffffff; IR(Ey.z)&=0x7fffffff;
435
436 Point Ez(mtx.m[2][0] * mExtents.z, mtx.m[2][1] * mExtents.z, mtx.m[2][2] * mExtents.z);
437 IR(Ez.x)&=0x7fffffff; IR(Ez.y)&=0x7fffffff; IR(Ez.z)&=0x7fffffff;
438
439 aabb.mExtents.x = Ex.x + Ey.x + Ez.x;
440 aabb.mExtents.y = Ex.y + Ey.y + Ez.y;
441 aabb.mExtents.z = Ex.z + Ey.z + Ez.z;
442 }
443
444 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
445 /**
446 * Checks the AABB is valid.
447 * \return true if the box is valid
448 */
449 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
450 inline_ BOOL IsValid() const
451 {
452 // Consistency condition for (Center, Extents) boxes: Extents >= 0
453 if(IS_NEGATIVE_FLOAT(mExtents.x)) return FALSE;
454 if(IS_NEGATIVE_FLOAT(mExtents.y)) return FALSE;
455 if(IS_NEGATIVE_FLOAT(mExtents.z)) return FALSE;
456 return TRUE;
457 }
458
459 //! Operator for AABB *= float. Scales the extents, keeps same center.
460 inline_ AABB& operator*=(float s) { mExtents*=s; return *this; }
461
462 //! Operator for AABB /= float. Scales the extents, keeps same center.
463 inline_ AABB& operator/=(float s) { mExtents/=s; return *this; }
464
465 //! Operator for AABB += Point. Translates the box.
466 inline_ AABB& operator+=(const Point& trans)
467 {
468 mCenter+=trans;
469 return *this;
470 }
471 private:
472 Point mCenter; //!< AABB Center
473 Point mExtents; //!< x, y and z extents
474 };
475
476#endif
477
478 inline_ void ComputeMinMax(const Point& p, Point& min, Point& max)
479 {
480 if(p.x > max.x) max.x = p.x;
481 if(p.x < min.x) min.x = p.x;
482
483 if(p.y > max.y) max.y = p.y;
484 if(p.y < min.y) min.y = p.y;
485
486 if(p.z > max.z) max.z = p.z;
487 if(p.z < min.z) min.z = p.z;
488 }
489
490 inline_ void ComputeAABB(AABB& aabb, const Point* list, udword nb_pts)
491 {
492 if(list)
493 {
494 Point Maxi(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);
495 Point Mini(MAX_FLOAT, MAX_FLOAT, MAX_FLOAT);
496 while(nb_pts--)
497 {
498// _prefetch(list+1); // off by one ?
499 ComputeMinMax(*list++, Mini, Maxi);
500 }
501 aabb.SetMinMax(Mini, Maxi);
502 }
503 }
504
505#endif // __ICEAABB_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceAxes.h b/libraries/ode-0.9/OPCODE/Ice/IceAxes.h
new file mode 100644
index 0000000..8af57e1
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceAxes.h
@@ -0,0 +1,54 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains axes definition.
4 * \file IceAxes.h
5 * \author Pierre Terdiman
6 * \date January, 29, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICEAXES_H__
13#define __ICEAXES_H__
14
15 enum PointComponent
16 {
17 X = 0,
18 Y = 1,
19 Z = 2,
20 W = 3,
21
22 FORCE_DWORD = 0x7fffffff
23 };
24
25 enum AxisOrder
26 {
27 AXES_XYZ = (X)|(Y<<2)|(Z<<4),
28 AXES_XZY = (X)|(Z<<2)|(Y<<4),
29 AXES_YXZ = (Y)|(X<<2)|(Z<<4),
30 AXES_YZX = (Y)|(Z<<2)|(X<<4),
31 AXES_ZXY = (Z)|(X<<2)|(Y<<4),
32 AXES_ZYX = (Z)|(Y<<2)|(X<<4),
33
34 AXES_FORCE_DWORD = 0x7fffffff
35 };
36
37 class ICEMATHS_API Axes
38 {
39 public:
40
41 inline_ Axes(AxisOrder order)
42 {
43 mAxis0 = (order ) & 3;
44 mAxis1 = (order>>2) & 3;
45 mAxis2 = (order>>4) & 3;
46 }
47 inline_ ~Axes() {}
48
49 udword mAxis0;
50 udword mAxis1;
51 udword mAxis2;
52 };
53
54#endif // __ICEAXES_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceBoundingSphere.h b/libraries/ode-0.9/OPCODE/Ice/IceBoundingSphere.h
new file mode 100644
index 0000000..945d38c
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceBoundingSphere.h
@@ -0,0 +1,142 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code to compute the minimal bounding sphere.
4 * \file IceBoundingSphere.h
5 * \author Pierre Terdiman
6 * \date January, 29, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICEBOUNDINGSPHERE_H__
13#define __ICEBOUNDINGSPHERE_H__
14
15 enum BSphereMethod
16 {
17 BS_NONE,
18 BS_GEMS,
19 BS_MINIBALL,
20
21 BS_FORCE_DWORD = 0x7fffffff
22 };
23
24 class ICEMATHS_API Sphere
25 {
26 public:
27 //! Constructor
28 inline_ Sphere() {}
29 //! Constructor
30 inline_ Sphere(const Point& center, float radius) : mCenter(center), mRadius(radius) {}
31 //! Constructor
32 Sphere(udword nb_verts, const Point* verts);
33 //! Copy constructor
34 inline_ Sphere(const Sphere& sphere) : mCenter(sphere.mCenter), mRadius(sphere.mRadius) {}
35 //! Destructor
36 inline_ ~Sphere() {}
37
38 BSphereMethod Compute(udword nb_verts, const Point* verts);
39 bool FastCompute(udword nb_verts, const Point* verts);
40
41 // Access methods
42 inline_ const Point& GetCenter() const { return mCenter; }
43 inline_ float GetRadius() const { return mRadius; }
44
45 inline_ const Point& Center() const { return mCenter; }
46 inline_ float Radius() const { return mRadius; }
47
48 inline_ Sphere& Set(const Point& center, float radius) { mCenter = center; mRadius = radius; return *this; }
49 inline_ Sphere& SetCenter(const Point& center) { mCenter = center; return *this; }
50 inline_ Sphere& SetRadius(float radius) { mRadius = radius; return *this; }
51
52 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
53 /**
54 * Tests if a point is contained within the sphere.
55 * \param p [in] the point to test
56 * \return true if inside the sphere
57 */
58 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
59 inline_ bool Contains(const Point& p) const
60 {
61 return mCenter.SquareDistance(p) <= mRadius*mRadius;
62 }
63
64 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
65 /**
66 * Tests if a sphere is contained within the sphere.
67 * \param sphere [in] the sphere to test
68 * \return true if inside the sphere
69 */
70 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
71 inline_ bool Contains(const Sphere& sphere) const
72 {
73 // If our radius is the smallest, we can't possibly contain the other sphere
74 if(mRadius < sphere.mRadius) return false;
75 // So r is always positive or null now
76 float r = mRadius - sphere.mRadius;
77 return mCenter.SquareDistance(sphere.mCenter) <= r*r;
78 }
79
80 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
81 /**
82 * Tests if a box is contained within the sphere.
83 * \param aabb [in] the box to test
84 * \return true if inside the sphere
85 */
86 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
87 inline_ BOOL Contains(const AABB& aabb) const
88 {
89 // I assume if all 8 box vertices are inside the sphere, so does the whole box.
90 // Sounds ok but maybe there's a better way?
91 float R2 = mRadius * mRadius;
92#ifdef USE_MIN_MAX
93 const Point& Max = ((ShadowAABB&)&aabb).mMax;
94 const Point& Min = ((ShadowAABB&)&aabb).mMin;
95#else
96 Point Max; aabb.GetMax(Max);
97 Point Min; aabb.GetMin(Min);
98#endif
99 Point p;
100 p.x=Max.x; p.y=Max.y; p.z=Max.z; if(mCenter.SquareDistance(p)>=R2) return FALSE;
101 p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE;
102 p.x=Max.x; p.y=Min.y; if(mCenter.SquareDistance(p)>=R2) return FALSE;
103 p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE;
104 p.x=Max.x; p.y=Max.y; p.z=Min.z; if(mCenter.SquareDistance(p)>=R2) return FALSE;
105 p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE;
106 p.x=Max.x; p.y=Min.y; if(mCenter.SquareDistance(p)>=R2) return FALSE;
107 p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE;
108
109 return TRUE;
110 }
111
112 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
113 /**
114 * Tests if the sphere intersects another sphere
115 * \param sphere [in] the other sphere
116 * \return true if spheres overlap
117 */
118 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
119 inline_ bool Intersect(const Sphere& sphere) const
120 {
121 float r = mRadius + sphere.mRadius;
122 return mCenter.SquareDistance(sphere.mCenter) <= r*r;
123 }
124
125 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
126 /**
127 * Checks the sphere is valid.
128 * \return true if the box is valid
129 */
130 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
131 inline_ BOOL IsValid() const
132 {
133 // Consistency condition for spheres: Radius >= 0.0f
134 if(mRadius < 0.0f) return FALSE;
135 return TRUE;
136 }
137 public:
138 Point mCenter; //!< Sphere center
139 float mRadius; //!< Sphere radius
140 };
141
142#endif // __ICEBOUNDINGSPHERE_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceContainer.cpp b/libraries/ode-0.9/OPCODE/Ice/IceContainer.cpp
new file mode 100644
index 0000000..8a4a570
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceContainer.cpp
@@ -0,0 +1,345 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains a simple container class.
4 * \file IceContainer.cpp
5 * \author Pierre Terdiman
6 * \date February, 5, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11/**
12 * Contains a list of 32-bits values.
13 * Use this class when you need to store an unknown number of values. The list is automatically
14 * resized and can contains 32-bits entities (dwords or floats)
15 *
16 * \class Container
17 * \author Pierre Terdiman
18 * \version 1.0
19 * \date 08.15.98
20*/
21///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
22
23///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
24// Precompiled Header
25#include "Stdafx.h"
26
27using namespace IceCore;
28
29// Static members
30#ifdef CONTAINER_STATS
31udword Container::mNbContainers = 0;
32udword Container::mUsedRam = 0;
33#endif
34
35///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
36/**
37 * Constructor. No entries allocated there.
38 */
39///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
40Container::Container() : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f)
41{
42#ifdef CONTAINER_STATS
43 mNbContainers++;
44 mUsedRam+=sizeof(Container);
45#endif
46}
47
48///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
49/**
50 * Constructor. Also allocates a given number of entries.
51 */
52///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
53Container::Container(udword size, float growth_factor) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(growth_factor)
54{
55#ifdef CONTAINER_STATS
56 mNbContainers++;
57 mUsedRam+=sizeof(Container);
58#endif
59 SetSize(size);
60}
61
62///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
63/**
64 * Copy constructor.
65 */
66///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
67Container::Container(const Container& object) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f)
68{
69#ifdef CONTAINER_STATS
70 mNbContainers++;
71 mUsedRam+=sizeof(Container);
72#endif
73 *this = object;
74}
75
76///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
77/**
78 * Destructor. Frees everything and leaves.
79 */
80///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
81Container::~Container()
82{
83 Empty();
84#ifdef CONTAINER_STATS
85 mNbContainers--;
86 mUsedRam-=GetUsedRam();
87#endif
88}
89
90///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
91/**
92 * Clears the container. All stored values are deleted, and it frees used ram.
93 * \see Reset()
94 * \return Self-Reference
95 */
96///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
97Container& Container::Empty()
98{
99#ifdef CONTAINER_STATS
100 mUsedRam-=mMaxNbEntries*sizeof(udword);
101#endif
102 DELETEARRAY(mEntries);
103 mCurNbEntries = mMaxNbEntries = 0;
104 return *this;
105}
106
107///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
108/**
109 * Resizes the container.
110 * \param needed [in] assume the container can be added at least "needed" values
111 * \return true if success.
112 */
113///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
114bool Container::Resize(udword needed)
115{
116#ifdef CONTAINER_STATS
117 // Subtract previous amount of bytes
118 mUsedRam-=mMaxNbEntries*sizeof(udword);
119#endif
120
121 // Get more entries
122 mMaxNbEntries = mMaxNbEntries ? udword(float(mMaxNbEntries)*mGrowthFactor) : 2; // Default nb Entries = 2
123 if(mMaxNbEntries<mCurNbEntries + needed) mMaxNbEntries = mCurNbEntries + needed;
124
125 // Get some bytes for new entries
126 udword* NewEntries = new udword[mMaxNbEntries];
127 CHECKALLOC(NewEntries);
128
129#ifdef CONTAINER_STATS
130 // Add current amount of bytes
131 mUsedRam+=mMaxNbEntries*sizeof(udword);
132#endif
133
134 // Copy old data if needed
135 if(mCurNbEntries) CopyMemory(NewEntries, mEntries, mCurNbEntries*sizeof(udword));
136
137 // Delete old data
138 DELETEARRAY(mEntries);
139
140 // Assign new pointer
141 mEntries = NewEntries;
142
143 return true;
144}
145
146///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
147/**
148 * Sets the initial size of the container. If it already contains something, it's discarded.
149 * \param nb [in] Number of entries
150 * \return true if success
151 */
152///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
153bool Container::SetSize(udword nb)
154{
155 // Make sure it's empty
156 Empty();
157
158 // Checkings
159 if(!nb) return false;
160
161 // Initialize for nb entries
162 mMaxNbEntries = nb;
163
164 // Get some bytes for new entries
165 mEntries = new udword[mMaxNbEntries];
166 CHECKALLOC(mEntries);
167
168#ifdef CONTAINER_STATS
169 // Add current amount of bytes
170 mUsedRam+=mMaxNbEntries*sizeof(udword);
171#endif
172 return true;
173}
174
175///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
176/**
177 * Refits the container and get rid of unused bytes.
178 * \return true if success
179 */
180///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
181bool Container::Refit()
182{
183#ifdef CONTAINER_STATS
184 // Subtract previous amount of bytes
185 mUsedRam-=mMaxNbEntries*sizeof(udword);
186#endif
187
188 // Get just enough entries
189 mMaxNbEntries = mCurNbEntries;
190 if(!mMaxNbEntries) return false;
191
192 // Get just enough bytes
193 udword* NewEntries = new udword[mMaxNbEntries];
194 CHECKALLOC(NewEntries);
195
196#ifdef CONTAINER_STATS
197 // Add current amount of bytes
198 mUsedRam+=mMaxNbEntries*sizeof(udword);
199#endif
200
201 // Copy old data
202 CopyMemory(NewEntries, mEntries, mCurNbEntries*sizeof(udword));
203
204 // Delete old data
205 DELETEARRAY(mEntries);
206
207 // Assign new pointer
208 mEntries = NewEntries;
209
210 return true;
211}
212
213///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
214/**
215 * Checks whether the container already contains a given value.
216 * \param entry [in] the value to look for in the container
217 * \param location [out] a possible pointer to store the entry location
218 * \see Add(udword entry)
219 * \see Add(float entry)
220 * \see Empty()
221 * \return true if the value has been found in the container, else false.
222 */
223///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
224bool Container::Contains(udword entry, udword* location) const
225{
226 // Look for the entry
227 for(udword i=0;i<mCurNbEntries;i++)
228 {
229 if(mEntries[i]==entry)
230 {
231 if(location) *location = i;
232 return true;
233 }
234 }
235 return false;
236}
237
238///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
239/**
240 * Deletes an entry. If the container contains such an entry, it's removed.
241 * \param entry [in] the value to delete.
242 * \return true if the value has been found in the container, else false.
243 * \warning This method is arbitrary slow (O(n)) and should be used carefully. Insertion order is not preserved.
244 */
245///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
246bool Container::Delete(udword entry)
247{
248 // Look for the entry
249 for(udword i=0;i<mCurNbEntries;i++)
250 {
251 if(mEntries[i]==entry)
252 {
253 // Entry has been found at index i. The strategy is to copy the last current entry at index i, and decrement the current number of entries.
254 DeleteIndex(i);
255 return true;
256 }
257 }
258 return false;
259}
260
261///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
262/**
263 * Deletes an entry, preserving the insertion order. If the container contains such an entry, it's removed.
264 * \param entry [in] the value to delete.
265 * \return true if the value has been found in the container, else false.
266 * \warning This method is arbitrary slow (O(n)) and should be used carefully.
267 */
268///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
269bool Container::DeleteKeepingOrder(udword entry)
270{
271 // Look for the entry
272 for(udword i=0;i<mCurNbEntries;i++)
273 {
274 if(mEntries[i]==entry)
275 {
276 // Entry has been found at index i.
277 // Shift entries to preserve order. You really should use a linked list instead.
278 mCurNbEntries--;
279 for(udword j=i;j<mCurNbEntries;j++)
280 {
281 mEntries[j] = mEntries[j+1];
282 }
283 return true;
284 }
285 }
286 return false;
287}
288
289///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
290/**
291 * Gets the next entry, starting from input one.
292 * \param entry [in/out] On input, the entry to look for. On output, the next entry
293 * \param find_mode [in] wrap/clamp
294 * \return Self-Reference
295 */
296///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
297Container& Container::FindNext(udword& entry, FindMode find_mode)
298{
299 udword Location;
300 if(Contains(entry, &Location))
301 {
302 Location++;
303 if(Location==mCurNbEntries) Location = find_mode==FIND_WRAP ? 0 : mCurNbEntries-1;
304 entry = mEntries[Location];
305 }
306 return *this;
307}
308
309///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
310/**
311 * Gets the previous entry, starting from input one.
312 * \param entry [in/out] On input, the entry to look for. On output, the previous entry
313 * \param find_mode [in] wrap/clamp
314 * \return Self-Reference
315 */
316///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
317Container& Container::FindPrev(udword& entry, FindMode find_mode)
318{
319 udword Location;
320 if(Contains(entry, &Location))
321 {
322 Location--;
323 if(Location==0xffffffff) Location = find_mode==FIND_WRAP ? mCurNbEntries-1 : 0;
324 entry = mEntries[Location];
325 }
326 return *this;
327}
328
329///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
330/**
331 * Gets the ram used by the container.
332 * \return the ram used in bytes.
333 */
334///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
335udword Container::GetUsedRam() const
336{
337 return sizeof(Container) + mMaxNbEntries * sizeof(udword);
338}
339
340/*void Container::operator=(const Container& object)
341{
342 SetSize(object.GetNbEntries());
343 CopyMemory(mEntries, object.GetEntries(), mMaxNbEntries*sizeof(udword));
344 mCurNbEntries = mMaxNbEntries;
345}*/
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceContainer.h b/libraries/ode-0.9/OPCODE/Ice/IceContainer.h
new file mode 100644
index 0000000..d726c2a
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceContainer.h
@@ -0,0 +1,212 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains a simple container class.
4 * \file IceContainer.h
5 * \author Pierre Terdiman
6 * \date February, 5, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICECONTAINER_H__
13#define __ICECONTAINER_H__
14
15 #define CONTAINER_STATS
16
17 enum FindMode
18 {
19 FIND_CLAMP,
20 FIND_WRAP,
21
22 FIND_FORCE_DWORD = 0x7fffffff
23 };
24
25 class ICECORE_API Container
26 {
27 public:
28 // Constructor / Destructor
29 Container();
30 Container(const Container& object);
31 Container(udword size, float growth_factor);
32 ~Container();
33 // Management
34 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
35 /**
36 * A O(1) method to add a value in the container. The container is automatically resized if needed.
37 * The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation
38 * costs a lot more than the call overhead...
39 *
40 * \param entry [in] a udword to store in the container
41 * \see Add(float entry)
42 * \see Empty()
43 * \see Contains(udword entry)
44 * \return Self-Reference
45 */
46 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
47 inline_ Container& Add(udword entry)
48 {
49 // Resize if needed
50 if(mCurNbEntries==mMaxNbEntries) Resize();
51
52 // Add new entry
53 mEntries[mCurNbEntries++] = entry;
54 return *this;
55 }
56
57 inline_ Container& Add(const udword* entries, udword nb)
58 {
59 // Resize if needed
60 if(mCurNbEntries+nb>mMaxNbEntries) Resize(nb);
61
62 // Add new entry
63 CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(udword));
64 mCurNbEntries+=nb;
65 return *this;
66 }
67
68 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
69 /**
70 * A O(1) method to add a value in the container. The container is automatically resized if needed.
71 * The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation
72 * costs a lot more than the call overhead...
73 *
74 * \param entry [in] a float to store in the container
75 * \see Add(udword entry)
76 * \see Empty()
77 * \see Contains(udword entry)
78 * \return Self-Reference
79 */
80 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
81 inline_ Container& Add(float entry)
82 {
83 // Resize if needed
84 if(mCurNbEntries==mMaxNbEntries) Resize();
85
86 // Add new entry
87 mEntries[mCurNbEntries++] = IR(entry);
88 return *this;
89 }
90
91 inline_ Container& Add(const float* entries, udword nb)
92 {
93 // Resize if needed
94 if(mCurNbEntries+nb>mMaxNbEntries) Resize(nb);
95
96 // Add new entry
97 CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(float));
98 mCurNbEntries+=nb;
99 return *this;
100 }
101
102 //! Add unique [slow]
103 inline_ Container& AddUnique(udword entry)
104 {
105 if(!Contains(entry)) Add(entry);
106 return *this;
107 }
108
109 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
110 /**
111 * Clears the container. All stored values are deleted, and it frees used ram.
112 * \see Reset()
113 * \return Self-Reference
114 */
115 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
116 Container& Empty();
117
118 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
119 /**
120 * Resets the container. Stored values are discarded but the buffer is kept so that further calls don't need resizing again.
121 * That's a kind of temporal coherence.
122 * \see Empty()
123 */
124 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
125 inline_ void Reset()
126 {
127 // Avoid the write if possible
128 // ### CMOV
129 if(mCurNbEntries) mCurNbEntries = 0;
130 }
131
132 // HANDLE WITH CARE
133 inline_ void ForceSize(udword size)
134 {
135 mCurNbEntries = size;
136 }
137
138 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
139 /**
140 * Sets the initial size of the container. If it already contains something, it's discarded.
141 * \param nb [in] Number of entries
142 * \return true if success
143 */
144 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
145 bool SetSize(udword nb);
146
147 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
148 /**
149 * Refits the container and get rid of unused bytes.
150 * \return true if success
151 */
152 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
153 bool Refit();
154
155 // Checks whether the container already contains a given value.
156 bool Contains(udword entry, udword* location=null) const;
157 // Deletes an entry - doesn't preserve insertion order.
158 bool Delete(udword entry);
159 // Deletes an entry - does preserve insertion order.
160 bool DeleteKeepingOrder(udword entry);
161 //! Deletes the very last entry.
162 inline_ void DeleteLastEntry() { if(mCurNbEntries) mCurNbEntries--; }
163 //! Deletes the entry whose index is given
164 inline_ void DeleteIndex(udword index) { mEntries[index] = mEntries[--mCurNbEntries]; }
165
166 // Helpers
167 Container& FindNext(udword& entry, FindMode find_mode=FIND_CLAMP);
168 Container& FindPrev(udword& entry, FindMode find_mode=FIND_CLAMP);
169 // Data access.
170 inline_ udword GetNbEntries() const { return mCurNbEntries; } //!< Returns the current number of entries.
171 inline_ udword GetEntry(udword i) const { return mEntries[i]; } //!< Returns ith entry
172 inline_ udword* GetEntries() const { return mEntries; } //!< Returns the list of entries.
173
174 inline_ udword GetFirst() const { return mEntries[0]; }
175 inline_ udword GetLast() const { return mEntries[mCurNbEntries-1]; }
176
177 // Growth control
178 inline_ float GetGrowthFactor() const { return mGrowthFactor; } //!< Returns the growth factor
179 inline_ void SetGrowthFactor(float growth) { mGrowthFactor = growth; } //!< Sets the growth factor
180 inline_ bool IsFull() const { return mCurNbEntries==mMaxNbEntries; } //!< Checks the container is full
181 inline_ BOOL IsNotEmpty() const { return mCurNbEntries; } //!< Checks the container is empty
182
183 //! Read-access as an array
184 inline_ udword operator[](udword i) const { ASSERT(i>=0 && i<mCurNbEntries); return mEntries[i]; }
185 //! Write-access as an array
186 inline_ udword& operator[](udword i) { ASSERT(i>=0 && i<mCurNbEntries); return mEntries[i]; }
187
188 // Stats
189 udword GetUsedRam() const;
190
191 //! Operator for "Container A = Container B"
192 //void operator = (const Container& object);
193
194#ifdef CONTAINER_STATS
195 inline_ udword GetNbContainers() const { return mNbContainers; }
196 inline_ udword GetTotalBytes() const { return mUsedRam; }
197 private:
198
199 static udword mNbContainers; //!< Number of containers around
200 static udword mUsedRam; //!< Amount of bytes used by containers in the system
201#endif
202 private:
203 // Resizing
204 bool Resize(udword needed=1);
205 // Data
206 udword mMaxNbEntries; //!< Maximum possible number of entries
207 udword mCurNbEntries; //!< Current number of entries
208 udword* mEntries; //!< List of entries
209 float mGrowthFactor; //!< Resize: new number of entries = old number * mGrowthFactor
210 };
211
212#endif // __ICECONTAINER_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceFPU.h b/libraries/ode-0.9/OPCODE/Ice/IceFPU.h
new file mode 100644
index 0000000..0cae4cb
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceFPU.h
@@ -0,0 +1,337 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains FPU related code.
4 * \file IceFPU.h
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICEFPU_H__
13#define __ICEFPU_H__
14
15 #define SIGN_BITMASK 0x80000000
16
17 //! Integer representation of a floating-point value.
18 #define IR(x) ((udword&)(x))
19
20 //! Signed integer representation of a floating-point value.
21 #define SIR(x) ((sdword&)(x))
22
23 //! Absolute integer representation of a floating-point value
24 #define AIR(x) (IR(x)&0x7fffffff)
25
26 //! Floating-point representation of an integer value.
27 #define FR(x) ((float&)(x))
28
29 //! Integer-based comparison of a floating point value.
30 //! Don't use it blindly, it can be faster or slower than the FPU comparison, depends on the context.
31 #define IS_NEGATIVE_FLOAT(x) (IR(x)&0x80000000)
32
33 //! Fast fabs for floating-point values. It just clears the sign bit.
34 //! Don't use it blindy, it can be faster or slower than the FPU comparison, depends on the context.
35 inline_ float FastFabs(float x)
36 {
37 udword FloatBits = IR(x)&0x7fffffff;
38 return FR(FloatBits);
39 }
40
41 //! Fast square root for floating-point values.
42 inline_ float FastSqrt(float square)
43 {
44#ifdef _MSC_VER
45 float retval;
46
47 __asm {
48 mov eax, square
49 sub eax, 0x3F800000
50 sar eax, 1
51 add eax, 0x3F800000
52 mov [retval], eax
53 }
54 return retval;
55#else
56 return sqrt(square);
57#endif
58 }
59
60 //! Saturates positive to zero.
61 inline_ float fsat(float f)
62 {
63 udword y = (udword&)f & ~((sdword&)f >>31);
64 return (float&)y;
65 }
66
67 //! Computes 1.0f / sqrtf(x).
68 inline_ float frsqrt(float f)
69 {
70 float x = f * 0.5f;
71 udword y = 0x5f3759df - ((udword&)f >> 1);
72 // Iteration...
73 (float&)y = (float&)y * ( 1.5f - ( x * (float&)y * (float&)y ) );
74 // Result
75 return (float&)y;
76 }
77
78 //! Computes 1.0f / sqrtf(x). Comes from NVIDIA.
79 inline_ float InvSqrt(const float& x)
80 {
81 udword tmp = (udword(IEEE_1_0 << 1) + IEEE_1_0 - *(udword*)&x) >> 1;
82 float y = *(float*)&tmp;
83 return y * (1.47f - 0.47f * x * y * y);
84 }
85
86 //! Computes 1.0f / sqrtf(x). Comes from Quake3. Looks like the first one I had above.
87 //! See http://www.magic-software.com/3DGEDInvSqrt.html
88 inline_ float RSqrt(float number)
89 {
90 long i;
91 float x2, y;
92 const float threehalfs = 1.5f;
93
94 x2 = number * 0.5f;
95 y = number;
96 i = * (long *) &y;
97 i = 0x5f3759df - (i >> 1);
98 y = * (float *) &i;
99 y = y * (threehalfs - (x2 * y * y));
100
101 return y;
102 }
103
104 //! TO BE DOCUMENTED
105 inline_ float fsqrt(float f)
106 {
107 udword y = ( ( (sdword&)f - 0x3f800000 ) >> 1 ) + 0x3f800000;
108 // Iteration...?
109 // (float&)y = (3.0f - ((float&)y * (float&)y) / f) * (float&)y * 0.5f;
110 // Result
111 return (float&)y;
112 }
113
114 //! Returns the float ranged espilon value.
115 inline_ float fepsilon(float f)
116 {
117 udword b = (udword&)f & 0xff800000;
118 udword a = b | 0x00000001;
119 (float&)a -= (float&)b;
120 // Result
121 return (float&)a;
122 }
123
124 //! Is the float valid ?
125 inline_ bool IsNAN(float value) { return (IR(value)&0x7f800000) == 0x7f800000; }
126 inline_ bool IsIndeterminate(float value) { return IR(value) == 0xffc00000; }
127 inline_ bool IsPlusInf(float value) { return IR(value) == 0x7f800000; }
128 inline_ bool IsMinusInf(float value) { return IR(value) == 0xff800000; }
129
130 inline_ bool IsValidFloat(float value)
131 {
132 if(IsNAN(value)) return false;
133 if(IsIndeterminate(value)) return false;
134 if(IsPlusInf(value)) return false;
135 if(IsMinusInf(value)) return false;
136 return true;
137 }
138
139 #define CHECK_VALID_FLOAT(x) ASSERT(IsValidFloat(x));
140
141/*
142 //! FPU precision setting function.
143 inline_ void SetFPU()
144 {
145 // This function evaluates whether the floating-point
146 // control word is set to single precision/round to nearest/
147 // exceptions disabled. If these conditions don't hold, the
148 // function changes the control word to set them and returns
149 // TRUE, putting the old control word value in the passback
150 // location pointed to by pwOldCW.
151 {
152 uword wTemp, wSave;
153
154 __asm fstcw wSave
155 if (wSave & 0x300 || // Not single mode
156 0x3f != (wSave & 0x3f) || // Exceptions enabled
157 wSave & 0xC00) // Not round to nearest mode
158 {
159 __asm
160 {
161 mov ax, wSave
162 and ax, not 300h ;; single mode
163 or ax, 3fh ;; disable all exceptions
164 and ax, not 0xC00 ;; round to nearest mode
165 mov wTemp, ax
166 fldcw wTemp
167 }
168 }
169 }
170 }
171*/
172 //! This function computes the slowest possible floating-point value (you can also directly use FLT_EPSILON)
173 inline_ float ComputeFloatEpsilon()
174 {
175 float f = 1.0f;
176 ((udword&)f)^=1;
177 return f - 1.0f; // You can check it's the same as FLT_EPSILON
178 }
179
180 inline_ bool IsFloatZero(float x, float epsilon=1e-6f)
181 {
182 return x*x < epsilon;
183 }
184
185 #define FCOMI_ST0 _asm _emit 0xdb _asm _emit 0xf0
186 #define FCOMIP_ST0 _asm _emit 0xdf _asm _emit 0xf0
187 #define FCMOVB_ST0 _asm _emit 0xda _asm _emit 0xc0
188 #define FCMOVNB_ST0 _asm _emit 0xdb _asm _emit 0xc0
189
190 #define FCOMI_ST1 _asm _emit 0xdb _asm _emit 0xf1
191 #define FCOMIP_ST1 _asm _emit 0xdf _asm _emit 0xf1
192 #define FCMOVB_ST1 _asm _emit 0xda _asm _emit 0xc1
193 #define FCMOVNB_ST1 _asm _emit 0xdb _asm _emit 0xc1
194
195 #define FCOMI_ST2 _asm _emit 0xdb _asm _emit 0xf2
196 #define FCOMIP_ST2 _asm _emit 0xdf _asm _emit 0xf2
197 #define FCMOVB_ST2 _asm _emit 0xda _asm _emit 0xc2
198 #define FCMOVNB_ST2 _asm _emit 0xdb _asm _emit 0xc2
199
200 #define FCOMI_ST3 _asm _emit 0xdb _asm _emit 0xf3
201 #define FCOMIP_ST3 _asm _emit 0xdf _asm _emit 0xf3
202 #define FCMOVB_ST3 _asm _emit 0xda _asm _emit 0xc3
203 #define FCMOVNB_ST3 _asm _emit 0xdb _asm _emit 0xc3
204
205 #define FCOMI_ST4 _asm _emit 0xdb _asm _emit 0xf4
206 #define FCOMIP_ST4 _asm _emit 0xdf _asm _emit 0xf4
207 #define FCMOVB_ST4 _asm _emit 0xda _asm _emit 0xc4
208 #define FCMOVNB_ST4 _asm _emit 0xdb _asm _emit 0xc4
209
210 #define FCOMI_ST5 _asm _emit 0xdb _asm _emit 0xf5
211 #define FCOMIP_ST5 _asm _emit 0xdf _asm _emit 0xf5
212 #define FCMOVB_ST5 _asm _emit 0xda _asm _emit 0xc5
213 #define FCMOVNB_ST5 _asm _emit 0xdb _asm _emit 0xc5
214
215 #define FCOMI_ST6 _asm _emit 0xdb _asm _emit 0xf6
216 #define FCOMIP_ST6 _asm _emit 0xdf _asm _emit 0xf6
217 #define FCMOVB_ST6 _asm _emit 0xda _asm _emit 0xc6
218 #define FCMOVNB_ST6 _asm _emit 0xdb _asm _emit 0xc6
219
220 #define FCOMI_ST7 _asm _emit 0xdb _asm _emit 0xf7
221 #define FCOMIP_ST7 _asm _emit 0xdf _asm _emit 0xf7
222 #define FCMOVB_ST7 _asm _emit 0xda _asm _emit 0xc7
223 #define FCMOVNB_ST7 _asm _emit 0xdb _asm _emit 0xc7
224
225 //! A global function to find MAX(a,b) using FCOMI/FCMOV
226 inline_ float FCMax2(float a, float b)
227 {
228#ifdef _MSC_VER
229 float Res;
230 _asm fld [a]
231 _asm fld [b]
232 FCOMI_ST1
233 FCMOVB_ST1
234 _asm fstp [Res]
235 _asm fcomp
236 return Res;
237#else
238 return (a > b) ? a : b;
239#endif
240 }
241
242 //! A global function to find MIN(a,b) using FCOMI/FCMOV
243 inline_ float FCMin2(float a, float b)
244 {
245#ifdef _MSC_VER
246 float Res;
247 _asm fld [a]
248 _asm fld [b]
249 FCOMI_ST1
250 FCMOVNB_ST1
251 _asm fstp [Res]
252 _asm fcomp
253 return Res;
254#else
255 return (a < b) ? a : b;
256#endif
257 }
258
259 //! A global function to find MAX(a,b,c) using FCOMI/FCMOV
260 inline_ float FCMax3(float a, float b, float c)
261 {
262#ifdef _MSC_VER
263 float Res;
264 _asm fld [a]
265 _asm fld [b]
266 _asm fld [c]
267 FCOMI_ST1
268 FCMOVB_ST1
269 FCOMI_ST2
270 FCMOVB_ST2
271 _asm fstp [Res]
272 _asm fcompp
273 return Res;
274#else
275 return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
276#endif
277 }
278
279 //! A global function to find MIN(a,b,c) using FCOMI/FCMOV
280 inline_ float FCMin3(float a, float b, float c)
281 {
282#ifdef _MSC_VER
283 float Res;
284 _asm fld [a]
285 _asm fld [b]
286 _asm fld [c]
287 FCOMI_ST1
288 FCMOVNB_ST1
289 FCOMI_ST2
290 FCMOVNB_ST2
291 _asm fstp [Res]
292 _asm fcompp
293 return Res;
294#else
295 return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
296#endif
297 }
298
299 inline_ int ConvertToSortable(float f)
300 {
301 int& Fi = (int&)f;
302 int Fmask = (Fi>>31);
303 Fi ^= Fmask;
304 Fmask &= ~(1<<31);
305 Fi -= Fmask;
306 return Fi;
307 }
308
309 enum FPUMode
310 {
311 FPU_FLOOR = 0,
312 FPU_CEIL = 1,
313 FPU_BEST = 2,
314
315 FPU_FORCE_DWORD = 0x7fffffff
316 };
317
318 FUNCTION ICECORE_API FPUMode GetFPUMode();
319 FUNCTION ICECORE_API void SaveFPU();
320 FUNCTION ICECORE_API void RestoreFPU();
321 FUNCTION ICECORE_API void SetFPUFloorMode();
322 FUNCTION ICECORE_API void SetFPUCeilMode();
323 FUNCTION ICECORE_API void SetFPUBestMode();
324
325 FUNCTION ICECORE_API void SetFPUPrecision24();
326 FUNCTION ICECORE_API void SetFPUPrecision53();
327 FUNCTION ICECORE_API void SetFPUPrecision64();
328 FUNCTION ICECORE_API void SetFPURoundingChop();
329 FUNCTION ICECORE_API void SetFPURoundingUp();
330 FUNCTION ICECORE_API void SetFPURoundingDown();
331 FUNCTION ICECORE_API void SetFPURoundingNear();
332
333 FUNCTION ICECORE_API int intChop(const float& f);
334 FUNCTION ICECORE_API int intFloor(const float& f);
335 FUNCTION ICECORE_API int intCeil(const float& f);
336
337#endif // __ICEFPU_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceHPoint.cpp b/libraries/ode-0.9/OPCODE/Ice/IceHPoint.cpp
new file mode 100644
index 0000000..f806a0c
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceHPoint.cpp
@@ -0,0 +1,70 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code for homogeneous points.
4 * \file IceHPoint.cpp
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11/**
12 * Homogeneous point.
13 *
14 * Use it:
15 * - for clipping in homogeneous space (standard way)
16 * - to differentiate between points (w=1) and vectors (w=0).
17 * - in some cases you can also use it instead of Point for padding reasons.
18 *
19 * \class HPoint
20 * \author Pierre Terdiman
21 * \version 1.0
22 * \warning No cross-product in 4D.
23 * \warning HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4
24 */
25///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
26
27///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
28// Precompiled Header
29#include "Stdafx.h"
30
31using namespace IceMaths;
32
33///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
34// Point Mul = HPoint * Matrix3x3;
35///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
36Point HPoint::operator*(const Matrix3x3& mat) const
37{
38 return Point(
39 x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0],
40 x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1],
41 x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] );
42}
43
44///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
45// HPoint Mul = HPoint * Matrix4x4;
46///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
47HPoint HPoint::operator*(const Matrix4x4& mat) const
48{
49 return HPoint(
50 x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0],
51 x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1],
52 x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2],
53 x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3]);
54}
55
56///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
57// HPoint *= Matrix4x4
58///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
59HPoint& HPoint::operator*=(const Matrix4x4& mat)
60{
61 float xp = x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0];
62 float yp = x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1];
63 float zp = x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2];
64 float wp = x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3];
65
66 x = xp; y = yp; z = zp; w = wp;
67
68 return *this;
69}
70
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceHPoint.h b/libraries/ode-0.9/OPCODE/Ice/IceHPoint.h
new file mode 100644
index 0000000..a3770cd
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceHPoint.h
@@ -0,0 +1,160 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code for homogeneous points.
4 * \file IceHPoint.h
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICEHPOINT_H__
13#define __ICEHPOINT_H__
14
15 class ICEMATHS_API HPoint : public Point
16 {
17 public:
18
19 //! Empty constructor
20 inline_ HPoint() {}
21 //! Constructor from floats
22 inline_ HPoint(float xx, float yy, float zz, float ww=0.0f) : Point(xx, yy, zz), w(ww) {}
23 //! Constructor from array
24 inline_ HPoint(const float f[4]) : Point(f), w(f[3]) {}
25 //! Constructor from a Point
26 inline_ HPoint(const Point& p, float ww=0.0f) : Point(p), w(ww) {}
27 //! Destructor
28 inline_ ~HPoint() {}
29
30 //! Clear the point
31 inline_ HPoint& Zero() { x = y = z = w = 0.0f; return *this; }
32
33 //! Assignment from values
34 inline_ HPoint& Set(float xx, float yy, float zz, float ww ) { x = xx; y = yy; z = zz; w = ww; return *this; }
35 //! Assignment from array
36 inline_ HPoint& Set(const float f[4]) { x = f[X]; y = f[Y]; z = f[Z]; w = f[W]; return *this; }
37 //! Assignment from another h-point
38 inline_ HPoint& Set(const HPoint& src) { x = src.x; y = src.y; z = src.z; w = src.w; return *this; }
39
40 //! Add a vector
41 inline_ HPoint& Add(float xx, float yy, float zz, float ww ) { x += xx; y += yy; z += zz; w += ww; return *this; }
42 //! Add a vector
43 inline_ HPoint& Add(const float f[4]) { x += f[X]; y += f[Y]; z += f[Z]; w += f[W]; return *this; }
44
45 //! Subtract a vector
46 inline_ HPoint& Sub(float xx, float yy, float zz, float ww ) { x -= xx; y -= yy; z -= zz; w -= ww; return *this; }
47 //! Subtract a vector
48 inline_ HPoint& Sub(const float f[4]) { x -= f[X]; y -= f[Y]; z -= f[Z]; w -= f[W]; return *this; }
49
50 //! Multiplies by a scalar
51 inline_ HPoint& Mul(float s) { x *= s; y *= s; z *= s; w *= s; return *this; }
52
53 //! Returns MIN(x, y, z, w);
54 float Min() const { return MIN(x, MIN(y, MIN(z, w))); }
55 //! Returns MAX(x, y, z, w);
56 float Max() const { return MAX(x, MAX(y, MAX(z, w))); }
57 //! Sets each element to be componentwise minimum
58 HPoint& Min(const HPoint& p) { x = MIN(x, p.x); y = MIN(y, p.y); z = MIN(z, p.z); w = MIN(w, p.w); return *this; }
59 //! Sets each element to be componentwise maximum
60 HPoint& Max(const HPoint& p) { x = MAX(x, p.x); y = MAX(y, p.y); z = MAX(z, p.z); w = MAX(w, p.w); return *this; }
61
62 //! Computes square magnitude
63 inline_ float SquareMagnitude() const { return x*x + y*y + z*z + w*w; }
64 //! Computes magnitude
65 inline_ float Magnitude() const { return sqrtf(x*x + y*y + z*z + w*w); }
66
67 //! Normalize the vector
68 inline_ HPoint& Normalize()
69 {
70 float M = Magnitude();
71 if(M)
72 {
73 M = 1.0f / M;
74 x *= M;
75 y *= M;
76 z *= M;
77 w *= M;
78 }
79 return *this;
80 }
81
82 // Arithmetic operators
83 //! Operator for HPoint Negate = - HPoint;
84 inline_ HPoint operator-() const { return HPoint(-x, -y, -z, -w); }
85
86 //! Operator for HPoint Plus = HPoint + HPoint;
87 inline_ HPoint operator+(const HPoint& p) const { return HPoint(x + p.x, y + p.y, z + p.z, w + p.w); }
88 //! Operator for HPoint Minus = HPoint - HPoint;
89 inline_ HPoint operator-(const HPoint& p) const { return HPoint(x - p.x, y - p.y, z - p.z, w - p.w); }
90
91 //! Operator for HPoint Mul = HPoint * HPoint;
92 inline_ HPoint operator*(const HPoint& p) const { return HPoint(x * p.x, y * p.y, z * p.z, w * p.w); }
93 //! Operator for HPoint Scale = HPoint * float;
94 inline_ HPoint operator*(float s) const { return HPoint(x * s, y * s, z * s, w * s); }
95 //! Operator for HPoint Scale = float * HPoint;
96 inline_ friend HPoint operator*(float s, const HPoint& p) { return HPoint(s * p.x, s * p.y, s * p.z, s * p.w); }
97
98 //! Operator for HPoint Div = HPoint / HPoint;
99 inline_ HPoint operator/(const HPoint& p) const { return HPoint(x / p.x, y / p.y, z / p.z, w / p.w); }
100 //! Operator for HPoint Scale = HPoint / float;
101 inline_ HPoint operator/(float s) const { s = 1.0f / s; return HPoint(x * s, y * s, z * s, w * s); }
102 //! Operator for HPoint Scale = float / HPoint;
103 inline_ friend HPoint operator/(float s, const HPoint& p) { return HPoint(s / p.x, s / p.y, s / p.z, s / p.w); }
104
105 //! Operator for float DotProd = HPoint | HPoint;
106 inline_ float operator|(const HPoint& p) const { return x*p.x + y*p.y + z*p.z + w*p.w; }
107 // No cross-product in 4D
108
109 //! Operator for HPoint += HPoint;
110 inline_ HPoint& operator+=(const HPoint& p) { x += p.x; y += p.y; z += p.z; w += p.w; return *this; }
111 //! Operator for HPoint += float;
112 inline_ HPoint& operator+=(float s) { x += s; y += s; z += s; w += s; return *this; }
113
114 //! Operator for HPoint -= HPoint;
115 inline_ HPoint& operator-=(const HPoint& p) { x -= p.x; y -= p.y; z -= p.z; w -= p.w; return *this; }
116 //! Operator for HPoint -= float;
117 inline_ HPoint& operator-=(float s) { x -= s; y -= s; z -= s; w -= s; return *this; }
118
119 //! Operator for HPoint *= HPoint;
120 inline_ HPoint& operator*=(const HPoint& p) { x *= p.x; y *= p.y; z *= p.z; w *= p.w; return *this; }
121 //! Operator for HPoint *= float;
122 inline_ HPoint& operator*=(float s) { x*=s; y*=s; z*=s; w*=s; return *this; }
123
124 //! Operator for HPoint /= HPoint;
125 inline_ HPoint& operator/=(const HPoint& p) { x /= p.x; y /= p.y; z /= p.z; w /= p.w; return *this; }
126 //! Operator for HPoint /= float;
127 inline_ HPoint& operator/=(float s) { s = 1.0f / s; x*=s; y*=s; z*=s; w*=s; return *this; }
128
129 // Arithmetic operators
130
131 //! Operator for Point Mul = HPoint * Matrix3x3;
132 Point operator*(const Matrix3x3& mat) const;
133 //! Operator for HPoint Mul = HPoint * Matrix4x4;
134 HPoint operator*(const Matrix4x4& mat) const;
135
136 // HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4
137 //! Operator for HPoint *= Matrix4x4
138 HPoint& operator*=(const Matrix4x4& mat);
139
140 // Logical operators
141
142 //! Operator for "if(HPoint==HPoint)"
143 inline_ bool operator==(const HPoint& p) const { return ( (x==p.x)&&(y==p.y)&&(z==p.z)&&(w==p.w)); }
144 //! Operator for "if(HPoint!=HPoint)"
145 inline_ bool operator!=(const HPoint& p) const { return ( (x!=p.x)||(y!=p.y)||(z!=p.z)||(w!=p.w)); }
146
147 // Cast operators
148
149 //! Cast a HPoint to a Point. w is discarded.
150#ifdef _MSC_VER
151 inline_ operator Point() const { return Point(x, y, z); }
152 // gcc complains that conversion to a base class will never use a type conversion operator
153#endif
154
155 public:
156 float w;
157 };
158
159#endif // __ICEHPOINT_H__
160
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceIndexedTriangle.cpp b/libraries/ode-0.9/OPCODE/Ice/IceIndexedTriangle.cpp
new file mode 100644
index 0000000..db279c4
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceIndexedTriangle.cpp
@@ -0,0 +1,548 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains a handy indexed triangle class.
4 * \file IceIndexedTriangle.cpp
5 * \author Pierre Terdiman
6 * \date January, 17, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Precompiled Header
12#include "Stdafx.h"
13
14using namespace IceMaths;
15
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17/**
18 * Contains an indexed triangle class.
19 *
20 * \class Triangle
21 * \author Pierre Terdiman
22 * \version 1.0
23 * \date 08.15.98
24*/
25///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
26
27///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
28/**
29 * Flips the winding order.
30 */
31///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
32void IndexedTriangle::Flip()
33{
34 Swap(mVRef[1], mVRef[2]);
35}
36
37///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
38/**
39 * Computes the triangle area.
40 * \param verts [in] the list of indexed vertices
41 * \return the area
42 */
43///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
44float IndexedTriangle::Area(const Point* verts) const
45{
46 if(!verts) return 0.0f;
47 const Point& p0 = verts[0];
48 const Point& p1 = verts[1];
49 const Point& p2 = verts[2];
50 return ((p0-p1)^(p0-p2)).Magnitude() * 0.5f;
51}
52
53///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
54/**
55 * Computes the triangle perimeter.
56 * \param verts [in] the list of indexed vertices
57 * \return the perimeter
58 */
59///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
60float IndexedTriangle::Perimeter(const Point* verts) const
61{
62 if(!verts) return 0.0f;
63 const Point& p0 = verts[0];
64 const Point& p1 = verts[1];
65 const Point& p2 = verts[2];
66 return p0.Distance(p1)
67 + p0.Distance(p2)
68 + p1.Distance(p2);
69}
70
71///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
72/**
73 * Computes the triangle compacity.
74 * \param verts [in] the list of indexed vertices
75 * \return the compacity
76 */
77///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
78float IndexedTriangle::Compacity(const Point* verts) const
79{
80 if(!verts) return 0.0f;
81 float P = Perimeter(verts);
82 if(P==0.0f) return 0.0f;
83 return (4.0f*PI*Area(verts)/(P*P));
84}
85
86///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
87/**
88 * Computes the triangle normal.
89 * \param verts [in] the list of indexed vertices
90 * \param normal [out] the computed normal
91 */
92///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
93void IndexedTriangle::Normal(const Point* verts, Point& normal) const
94{
95 if(!verts) return;
96
97 const Point& p0 = verts[mVRef[0]];
98 const Point& p1 = verts[mVRef[1]];
99 const Point& p2 = verts[mVRef[2]];
100 normal = ((p2-p1)^(p0-p1)).Normalize();
101}
102
103///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
104/**
105 * Computes the triangle denormalized normal.
106 * \param verts [in] the list of indexed vertices
107 * \param normal [out] the computed normal
108 */
109///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
110void IndexedTriangle::DenormalizedNormal(const Point* verts, Point& normal) const
111{
112 if(!verts) return;
113
114 const Point& p0 = verts[mVRef[0]];
115 const Point& p1 = verts[mVRef[1]];
116 const Point& p2 = verts[mVRef[2]];
117 normal = ((p2-p1)^(p0-p1));
118}
119
120///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
121/**
122 * Computes the triangle center.
123 * \param verts [in] the list of indexed vertices
124 * \param center [out] the computed center
125 */
126///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
127void IndexedTriangle::Center(const Point* verts, Point& center) const
128{
129 if(!verts) return;
130
131 const Point& p0 = verts[mVRef[0]];
132 const Point& p1 = verts[mVRef[1]];
133 const Point& p2 = verts[mVRef[2]];
134 center = (p0+p1+p2)*INV3;
135}
136
137///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
138/**
139 * Computes the centered normal
140 * \param verts [in] the list of indexed vertices
141 * \param normal [out] the computed centered normal
142 */
143///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
144void IndexedTriangle::CenteredNormal(const Point* verts, Point& normal) const
145{
146 if(!verts) return;
147
148 const Point& p0 = verts[mVRef[0]];
149 const Point& p1 = verts[mVRef[1]];
150 const Point& p2 = verts[mVRef[2]];
151 Point Center = (p0+p1+p2)*INV3;
152 normal = Center + ((p2-p1)^(p0-p1)).Normalize();
153}
154
155///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
156/**
157 * Computes a random point within the triangle.
158 * \param verts [in] the list of indexed vertices
159 * \param normal [out] the computed centered normal
160 */
161///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
162void IndexedTriangle::RandomPoint(const Point* verts, Point& random) const
163{
164 if(!verts) return;
165
166 // Random barycentric coords
167 float Alpha = UnitRandomFloat();
168 float Beta = UnitRandomFloat();
169 float Gamma = UnitRandomFloat();
170 float OneOverTotal = 1.0f / (Alpha + Beta + Gamma);
171 Alpha *= OneOverTotal;
172 Beta *= OneOverTotal;
173 Gamma *= OneOverTotal;
174
175 const Point& p0 = verts[mVRef[0]];
176 const Point& p1 = verts[mVRef[1]];
177 const Point& p2 = verts[mVRef[2]];
178 random = Alpha*p0 + Beta*p1 + Gamma*p2;
179}
180
181///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
182/**
183 * Computes backface culling.
184 * \param verts [in] the list of indexed vertices
185 * \param source [in] source point (in local space) from which culling must be computed
186 * \return true if the triangle is visible from the source point
187 */
188///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
189bool IndexedTriangle::IsVisible(const Point* verts, const Point& source) const
190{
191 // Checkings
192 if(!verts) return false;
193
194 const Point& p0 = verts[mVRef[0]];
195 const Point& p1 = verts[mVRef[1]];
196 const Point& p2 = verts[mVRef[2]];
197
198 // Compute denormalized normal
199 Point Normal = (p2 - p1)^(p0 - p1);
200
201 // Backface culling
202 return (Normal | source) >= 0.0f;
203
204// Same as:
205// Plane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]);
206// return PL.Distance(source) > PL.d;
207}
208
209///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
210/**
211 * Computes backface culling.
212 * \param verts [in] the list of indexed vertices
213 * \param source [in] source point (in local space) from which culling must be computed
214 * \return true if the triangle is visible from the source point
215 */
216///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
217bool IndexedTriangle::BackfaceCulling(const Point* verts, const Point& source) const
218{
219 // Checkings
220 if(!verts) return false;
221
222 const Point& p0 = verts[mVRef[0]];
223 const Point& p1 = verts[mVRef[1]];
224 const Point& p2 = verts[mVRef[2]];
225
226 // Compute base
227// Point Base = (p0 + p1 + p2)*INV3;
228
229 // Compute denormalized normal
230 Point Normal = (p2 - p1)^(p0 - p1);
231
232 // Backface culling
233// return (Normal | (source - Base)) >= 0.0f;
234 return (Normal | (source - p0)) >= 0.0f;
235
236// Same as: (but a bit faster)
237// Plane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]);
238// return PL.Distance(source)>0.0f;
239}
240
241///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
242/**
243 * Computes the occlusion potential of the triangle.
244 * \param verts [in] the list of indexed vertices
245 * \param source [in] source point (in local space) from which occlusion potential must be computed
246 * \return the occlusion potential
247 */
248///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
249float IndexedTriangle::ComputeOcclusionPotential(const Point* verts, const Point& view) const
250{
251 if(!verts) return 0.0f;
252 // Occlusion potential: -(A * (N|V) / d^2)
253 // A = polygon area
254 // N = polygon normal
255 // V = view vector
256 // d = distance viewpoint-center of polygon
257
258 float A = Area(verts);
259 Point N; Normal(verts, N);
260 Point C; Center(verts, C);
261 float d = view.Distance(C);
262 return -(A*(N|view))/(d*d);
263}
264
265///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
266/**
267 * Replaces a vertex reference with another one.
268 * \param oldref [in] the vertex reference to replace
269 * \param newref [in] the new vertex reference
270 * \return true if success, else false if the input vertex reference doesn't belong to the triangle
271 */
272///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
273bool IndexedTriangle::ReplaceVertex(udword oldref, udword newref)
274{
275 if(mVRef[0]==oldref) { mVRef[0] = newref; return true; }
276 else if(mVRef[1]==oldref) { mVRef[1] = newref; return true; }
277 else if(mVRef[2]==oldref) { mVRef[2] = newref; return true; }
278 return false;
279}
280
281///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
282/**
283 * Checks whether the triangle is degenerate or not. A degenerate triangle has two common vertex references. This is a zero-area triangle.
284 * \return true if the triangle is degenerate
285 */
286///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
287bool IndexedTriangle::IsDegenerate() const
288{
289 if(mVRef[0]==mVRef[1]) return true;
290 if(mVRef[1]==mVRef[2]) return true;
291 if(mVRef[2]==mVRef[0]) return true;
292 return false;
293}
294
295///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
296/**
297 * Checks whether the input vertex reference belongs to the triangle or not.
298 * \param ref [in] the vertex reference to look for
299 * \return true if the triangle contains the vertex reference
300 */
301///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
302bool IndexedTriangle::HasVertex(udword ref) const
303{
304 if(mVRef[0]==ref) return true;
305 if(mVRef[1]==ref) return true;
306 if(mVRef[2]==ref) return true;
307 return false;
308}
309
310///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
311/**
312 * Checks whether the input vertex reference belongs to the triangle or not.
313 * \param ref [in] the vertex reference to look for
314 * \param index [out] the corresponding index in the triangle
315 * \return true if the triangle contains the vertex reference
316 */
317///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
318bool IndexedTriangle::HasVertex(udword ref, udword* index) const
319{
320 if(mVRef[0]==ref) { *index = 0; return true; }
321 if(mVRef[1]==ref) { *index = 1; return true; }
322 if(mVRef[2]==ref) { *index = 2; return true; }
323 return false;
324}
325
326///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
327/**
328 * Finds an edge in a tri, given two vertex references.
329 * \param vref0 [in] the edge's first vertex reference
330 * \param vref1 [in] the edge's second vertex reference
331 * \return the edge number between 0 and 2, or 0xff if input refs are wrong.
332 */
333///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
334ubyte IndexedTriangle::FindEdge(udword vref0, udword vref1) const
335{
336 if(mVRef[0]==vref0 && mVRef[1]==vref1) return 0;
337 else if(mVRef[0]==vref1 && mVRef[1]==vref0) return 0;
338 else if(mVRef[0]==vref0 && mVRef[2]==vref1) return 1;
339 else if(mVRef[0]==vref1 && mVRef[2]==vref0) return 1;
340 else if(mVRef[1]==vref0 && mVRef[2]==vref1) return 2;
341 else if(mVRef[1]==vref1 && mVRef[2]==vref0) return 2;
342 return 0xff;
343}
344
345///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
346/**
347 * Gets the last reference given the first two.
348 * \param vref0 [in] the first vertex reference
349 * \param vref1 [in] the second vertex reference
350 * \return the last reference, or INVALID_ID if input refs are wrong.
351 */
352///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
353udword IndexedTriangle::OppositeVertex(udword vref0, udword vref1) const
354{
355 if(mVRef[0]==vref0 && mVRef[1]==vref1) return mVRef[2];
356 else if(mVRef[0]==vref1 && mVRef[1]==vref0) return mVRef[2];
357 else if(mVRef[0]==vref0 && mVRef[2]==vref1) return mVRef[1];
358 else if(mVRef[0]==vref1 && mVRef[2]==vref0) return mVRef[1];
359 else if(mVRef[1]==vref0 && mVRef[2]==vref1) return mVRef[0];
360 else if(mVRef[1]==vref1 && mVRef[2]==vref0) return mVRef[0];
361 return INVALID_ID;
362}
363
364///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
365/**
366 * Gets the three sorted vertex references according to an edge number.
367 * edgenb = 0 => edge 0-1, returns references 0, 1, 2
368 * edgenb = 1 => edge 0-2, returns references 0, 2, 1
369 * edgenb = 2 => edge 1-2, returns references 1, 2, 0
370 *
371 * \param edgenb [in] the edge number, 0, 1 or 2
372 * \param vref0 [out] the returned first vertex reference
373 * \param vref1 [out] the returned second vertex reference
374 * \param vref2 [out] the returned third vertex reference
375 */
376///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
377void IndexedTriangle::GetVRefs(ubyte edgenb, udword& vref0, udword& vref1, udword& vref2) const
378{
379 if(edgenb==0)
380 {
381 vref0 = mVRef[0];
382 vref1 = mVRef[1];
383 vref2 = mVRef[2];
384 }
385 else if(edgenb==1)
386 {
387 vref0 = mVRef[0];
388 vref1 = mVRef[2];
389 vref2 = mVRef[1];
390 }
391 else if(edgenb==2)
392 {
393 vref0 = mVRef[1];
394 vref1 = mVRef[2];
395 vref2 = mVRef[0];
396 }
397}
398
399///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
400/**
401 * Computes the triangle's smallest edge length.
402 * \param verts [in] the list of indexed vertices
403 * \return the smallest edge length
404 */
405///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
406float IndexedTriangle::MinEdgeLength(const Point* verts) const
407{
408 if(!verts) return 0.0f;
409
410 float Min = MAX_FLOAT;
411 float Length01 = verts[0].Distance(verts[1]);
412 float Length02 = verts[0].Distance(verts[2]);
413 float Length12 = verts[1].Distance(verts[2]);
414 if(Length01 < Min) Min = Length01;
415 if(Length02 < Min) Min = Length02;
416 if(Length12 < Min) Min = Length12;
417 return Min;
418}
419
420///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
421/**
422 * Computes the triangle's largest edge length.
423 * \param verts [in] the list of indexed vertices
424 * \return the largest edge length
425 */
426///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
427float IndexedTriangle::MaxEdgeLength(const Point* verts) const
428{
429 if(!verts) return 0.0f;
430
431 float Max = MIN_FLOAT;
432 float Length01 = verts[0].Distance(verts[1]);
433 float Length02 = verts[0].Distance(verts[2]);
434 float Length12 = verts[1].Distance(verts[2]);
435 if(Length01 > Max) Max = Length01;
436 if(Length02 > Max) Max = Length02;
437 if(Length12 > Max) Max = Length12;
438 return Max;
439}
440
441///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
442/**
443 * Computes a point on the triangle according to the stabbing information.
444 * \param verts [in] the list of indexed vertices
445 * \param u,v [in] point's barycentric coordinates
446 * \param pt [out] point on triangle
447 * \param nearvtx [out] index of nearest vertex
448 */
449///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
450void IndexedTriangle::ComputePoint(const Point* verts, float u, float v, Point& pt, udword* nearvtx) const
451{
452 // Checkings
453 if(!verts) return;
454
455 // Get face in local or global space
456 const Point& p0 = verts[mVRef[0]];
457 const Point& p1 = verts[mVRef[1]];
458 const Point& p2 = verts[mVRef[2]];
459
460 // Compute point coordinates
461 pt = (1.0f - u - v)*p0 + u*p1 + v*p2;
462
463 // Compute nearest vertex if needed
464 if(nearvtx)
465 {
466 // Compute distance vector
467 Point d(p0.SquareDistance(pt), // Distance^2 from vertex 0 to point on the face
468 p1.SquareDistance(pt), // Distance^2 from vertex 1 to point on the face
469 p2.SquareDistance(pt)); // Distance^2 from vertex 2 to point on the face
470
471 // Get smallest distance
472 *nearvtx = mVRef[d.SmallestAxis()];
473 }
474}
475
476 //**************************************
477 // Angle between two vectors (in radians)
478 // we use this formula
479 // uv = |u||v| cos(u,v)
480 // u ^ v = w
481 // |w| = |u||v| |sin(u,v)|
482 //**************************************
483 float Angle(const Point& u, const Point& v)
484 {
485 float NormU = u.Magnitude(); // |u|
486 float NormV = v.Magnitude(); // |v|
487 float Product = NormU*NormV; // |u||v|
488 if(Product==0.0f) return 0.0f;
489 float OneOverProduct = 1.0f / Product;
490
491 // Cosinus
492 float Cosinus = (u|v) * OneOverProduct;
493
494 // Sinus
495 Point w = u^v;
496 float NormW = w.Magnitude();
497
498 float AbsSinus = NormW * OneOverProduct;
499
500 // Remove degeneracy
501 if(AbsSinus > 1.0f) AbsSinus = 1.0f;
502 if(AbsSinus < -1.0f) AbsSinus = -1.0f;
503
504 if(Cosinus>=0.0f) return asinf(AbsSinus);
505 else return (PI-asinf(AbsSinus));
506 }
507
508///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
509/**
510 * Computes the angle between two triangles.
511 * \param tri [in] the other triangle
512 * \param verts [in] the list of indexed vertices
513 * \return the angle in radians
514 */
515///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
516float IndexedTriangle::Angle(const IndexedTriangle& tri, const Point* verts) const
517{
518 // Checkings
519 if(!verts) return 0.0f;
520
521 // Compute face normals
522 Point n0, n1;
523 Normal(verts, n0);
524 tri.Normal(verts, n1);
525
526 // Compute angle
527 float dp = n0|n1;
528 if(dp>1.0f) return 0.0f;
529 if(dp<-1.0f) return PI;
530 return acosf(dp);
531
532// return ::Angle(n0,n1);
533}
534
535///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
536/**
537 * Checks a triangle is the same as another one.
538 * \param tri [in] the other triangle
539 * \return true if same triangle
540 */
541///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
542bool IndexedTriangle::Equal(const IndexedTriangle& tri) const
543{
544 // Test all vertex references
545 return (HasVertex(tri.mVRef[0]) &&
546 HasVertex(tri.mVRef[1]) &&
547 HasVertex(tri.mVRef[2]));
548}
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceIndexedTriangle.h b/libraries/ode-0.9/OPCODE/Ice/IceIndexedTriangle.h
new file mode 100644
index 0000000..b34c485
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceIndexedTriangle.h
@@ -0,0 +1,72 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains a handy indexed triangle class.
4 * \file IceIndexedTriangle.h
5 * \author Pierre Terdiman
6 * \date January, 17, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICEINDEXEDTRIANGLE_H__
13#define __ICEINDEXEDTRIANGLE_H__
14
15 // Forward declarations
16#ifdef _MSC_VER
17 enum CubeIndex;
18#else
19 typedef int CubeIndex;
20#endif
21
22 // An indexed triangle class.
23 class ICEMATHS_API IndexedTriangle
24 {
25 public:
26 //! Constructor
27 inline_ IndexedTriangle() {}
28 //! Constructor
29 inline_ IndexedTriangle(udword r0, udword r1, udword r2) { mVRef[0]=r0; mVRef[1]=r1; mVRef[2]=r2; }
30 //! Copy constructor
31 inline_ IndexedTriangle(const IndexedTriangle& triangle)
32 {
33 mVRef[0] = triangle.mVRef[0];
34 mVRef[1] = triangle.mVRef[1];
35 mVRef[2] = triangle.mVRef[2];
36 }
37 //! Destructor
38 inline_ ~IndexedTriangle() {}
39 //! Vertex-references
40 udword mVRef[3];
41
42 // Methods
43 void Flip();
44 float Area(const Point* verts) const;
45 float Perimeter(const Point* verts) const;
46 float Compacity(const Point* verts) const;
47 void Normal(const Point* verts, Point& normal) const;
48 void DenormalizedNormal(const Point* verts, Point& normal) const;
49 void Center(const Point* verts, Point& center) const;
50 void CenteredNormal(const Point* verts, Point& normal) const;
51 void RandomPoint(const Point* verts, Point& random) const;
52 bool IsVisible(const Point* verts, const Point& source) const;
53 bool BackfaceCulling(const Point* verts, const Point& source) const;
54 float ComputeOcclusionPotential(const Point* verts, const Point& view) const;
55 bool ReplaceVertex(udword oldref, udword newref);
56 bool IsDegenerate() const;
57 bool HasVertex(udword ref) const;
58 bool HasVertex(udword ref, udword* index) const;
59 ubyte FindEdge(udword vref0, udword vref1) const;
60 udword OppositeVertex(udword vref0, udword vref1) const;
61 inline_ udword OppositeVertex(ubyte edgenb) const { return mVRef[2-edgenb]; }
62 void GetVRefs(ubyte edgenb, udword& vref0, udword& vref1, udword& vref2) const;
63 float MinEdgeLength(const Point* verts) const;
64 float MaxEdgeLength(const Point* verts) const;
65 void ComputePoint(const Point* verts, float u, float v, Point& pt, udword* nearvtx=null) const;
66 float Angle(const IndexedTriangle& tri, const Point* verts) const;
67 inline_ Plane PlaneEquation(const Point* verts) const { return Plane(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); }
68 bool Equal(const IndexedTriangle& tri) const;
69 CubeIndex ComputeCubeIndex(const Point* verts) const;
70 };
71
72#endif // __ICEINDEXEDTRIANGLE_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceLSS.h b/libraries/ode-0.9/OPCODE/Ice/IceLSS.h
new file mode 100644
index 0000000..bd260c1
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceLSS.h
@@ -0,0 +1,75 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code for line-swept spheres.
4 * \file IceLSS.h
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICELSS_H__
13#define __ICELSS_H__
14
15 class ICEMATHS_API LSS : public Segment
16 {
17 public:
18 //! Constructor
19 inline_ LSS() {}
20 //! Constructor
21 inline_ LSS(const Segment& seg, float radius) : Segment(seg), mRadius(radius) {}
22 //! Destructor
23 inline_ ~LSS() {}
24
25 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
26 /**
27 * Computes an OBB surrounding the LSS.
28 * \param box [out] the OBB
29 */
30 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
31 void ComputeOBB(OBB& box);
32
33 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
34 /**
35 * Tests if a point is contained within the LSS.
36 * \param pt [in] the point to test
37 * \return true if inside the LSS
38 * \warning point and LSS must be in same space
39 */
40 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
41 inline_ bool Contains(const Point& pt) const { return SquareDistance(pt) <= mRadius*mRadius; }
42
43 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
44 /**
45 * Tests if a sphere is contained within the LSS.
46 * \param sphere [in] the sphere to test
47 * \return true if inside the LSS
48 * \warning sphere and LSS must be in same space
49 */
50 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
51 inline_ bool Contains(const Sphere& sphere)
52 {
53 float d = mRadius - sphere.mRadius;
54 if(d>=0.0f) return SquareDistance(sphere.mCenter) <= d*d;
55 else return false;
56 }
57
58 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
59 /**
60 * Tests if an LSS is contained within the LSS.
61 * \param lss [in] the LSS to test
62 * \return true if inside the LSS
63 * \warning both LSS must be in same space
64 */
65 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
66 inline_ bool Contains(const LSS& lss)
67 {
68 // We check the LSS contains the two spheres at the start and end of the sweep
69 return Contains(Sphere(lss.mP0, lss.mRadius)) && Contains(Sphere(lss.mP0, lss.mRadius));
70 }
71
72 float mRadius; //!< Sphere radius
73 };
74
75#endif // __ICELSS_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceMatrix3x3.cpp b/libraries/ode-0.9/OPCODE/Ice/IceMatrix3x3.cpp
new file mode 100644
index 0000000..af56d3e
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceMatrix3x3.cpp
@@ -0,0 +1,48 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code for 3x3 matrices.
4 * \file IceMatrix3x3.cpp
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11/**
12 * 3x3 matrix.
13 * DirectX-compliant, ie row-column order, ie m[Row][Col].
14 * Same as:
15 * m11 m12 m13 first row.
16 * m21 m22 m23 second row.
17 * m31 m32 m33 third row.
18 * Stored in memory as m11 m12 m13 m21...
19 *
20 * Multiplication rules:
21 *
22 * [x'y'z'] = [xyz][M]
23 *
24 * x' = x*m11 + y*m21 + z*m31
25 * y' = x*m12 + y*m22 + z*m32
26 * z' = x*m13 + y*m23 + z*m33
27 *
28 * \class Matrix3x3
29 * \author Pierre Terdiman
30 * \version 1.0
31 */
32///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
33
34///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
35// Precompiled Header
36#include "Stdafx.h"
37
38using namespace IceMaths;
39
40// Cast operator
41Matrix3x3::operator Matrix4x4() const
42{
43 return Matrix4x4(
44 m[0][0], m[0][1], m[0][2], 0.0f,
45 m[1][0], m[1][1], m[1][2], 0.0f,
46 m[2][0], m[2][1], m[2][2], 0.0f,
47 0.0f, 0.0f, 0.0f, 1.0f);
48}
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceMatrix3x3.h b/libraries/ode-0.9/OPCODE/Ice/IceMatrix3x3.h
new file mode 100644
index 0000000..a30680d
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceMatrix3x3.h
@@ -0,0 +1,496 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code for 3x3 matrices.
4 * \file IceMatrix3x3.h
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICEMATRIX3X3_H__
13#define __ICEMATRIX3X3_H__
14
15 // Forward declarations
16 class Quat;
17
18 #define MATRIX3X3_EPSILON (1.0e-7f)
19
20 class ICEMATHS_API Matrix3x3
21 {
22 public:
23 //! Empty constructor
24 inline_ Matrix3x3() {}
25 //! Constructor from 9 values
26 inline_ Matrix3x3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22)
27 {
28 m[0][0] = m00; m[0][1] = m01; m[0][2] = m02;
29 m[1][0] = m10; m[1][1] = m11; m[1][2] = m12;
30 m[2][0] = m20; m[2][1] = m21; m[2][2] = m22;
31 }
32 //! Copy constructor
33 inline_ Matrix3x3(const Matrix3x3& mat) { CopyMemory(m, &mat.m, 9*sizeof(float)); }
34 //! Destructor
35 inline_ ~Matrix3x3() {}
36
37 //! Assign values
38 inline_ void Set(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22)
39 {
40 m[0][0] = m00; m[0][1] = m01; m[0][2] = m02;
41 m[1][0] = m10; m[1][1] = m11; m[1][2] = m12;
42 m[2][0] = m20; m[2][1] = m21; m[2][2] = m22;
43 }
44
45 //! Sets the scale from a Point. The point is put on the diagonal.
46 inline_ void SetScale(const Point& p) { m[0][0] = p.x; m[1][1] = p.y; m[2][2] = p.z; }
47
48 //! Sets the scale from floats. Values are put on the diagonal.
49 inline_ void SetScale(float sx, float sy, float sz) { m[0][0] = sx; m[1][1] = sy; m[2][2] = sz; }
50
51 //! Scales from a Point. Each row is multiplied by a component.
52 inline_ void Scale(const Point& p)
53 {
54 m[0][0] *= p.x; m[0][1] *= p.x; m[0][2] *= p.x;
55 m[1][0] *= p.y; m[1][1] *= p.y; m[1][2] *= p.y;
56 m[2][0] *= p.z; m[2][1] *= p.z; m[2][2] *= p.z;
57 }
58
59 //! Scales from floats. Each row is multiplied by a value.
60 inline_ void Scale(float sx, float sy, float sz)
61 {
62 m[0][0] *= sx; m[0][1] *= sx; m[0][2] *= sx;
63 m[1][0] *= sy; m[1][1] *= sy; m[1][2] *= sy;
64 m[2][0] *= sz; m[2][1] *= sz; m[2][2] *= sz;
65 }
66
67 //! Copy from a Matrix3x3
68 inline_ void Copy(const Matrix3x3& source) { CopyMemory(m, source.m, 9*sizeof(float)); }
69
70 // Row-column access
71 //! Returns a row.
72 inline_ void GetRow(const udword r, Point& p) const { p.x = m[r][0]; p.y = m[r][1]; p.z = m[r][2]; }
73 //! Returns a row.
74 inline_ const Point& GetRow(const udword r) const { return *(const Point*)&m[r][0]; }
75 //! Returns a row.
76 inline_ Point& GetRow(const udword r) { return *(Point*)&m[r][0]; }
77 //! Sets a row.
78 inline_ void SetRow(const udword r, const Point& p) { m[r][0] = p.x; m[r][1] = p.y; m[r][2] = p.z; }
79 //! Returns a column.
80 inline_ void GetCol(const udword c, Point& p) const { p.x = m[0][c]; p.y = m[1][c]; p.z = m[2][c]; }
81 //! Sets a column.
82 inline_ void SetCol(const udword c, const Point& p) { m[0][c] = p.x; m[1][c] = p.y; m[2][c] = p.z; }
83
84 //! Computes the trace. The trace is the sum of the 3 diagonal components.
85 inline_ float Trace() const { return m[0][0] + m[1][1] + m[2][2]; }
86 //! Clears the matrix.
87 inline_ void Zero() { ZeroMemory(&m, sizeof(m)); }
88 //! Sets the identity matrix.
89 inline_ void Identity() { Zero(); m[0][0] = m[1][1] = m[2][2] = 1.0f; }
90 //! Checks for identity
91 inline_ bool IsIdentity() const
92 {
93 if(IR(m[0][0])!=IEEE_1_0) return false;
94 if(IR(m[0][1])!=0) return false;
95 if(IR(m[0][2])!=0) return false;
96
97 if(IR(m[1][0])!=0) return false;
98 if(IR(m[1][1])!=IEEE_1_0) return false;
99 if(IR(m[1][2])!=0) return false;
100
101 if(IR(m[2][0])!=0) return false;
102 if(IR(m[2][1])!=0) return false;
103 if(IR(m[2][2])!=IEEE_1_0) return false;
104
105 return true;
106 }
107
108 //! Checks matrix validity
109 inline_ BOOL IsValid() const
110 {
111 for(udword j=0;j<3;j++)
112 {
113 for(udword i=0;i<3;i++)
114 {
115 if(!IsValidFloat(m[j][i])) return FALSE;
116 }
117 }
118 return TRUE;
119 }
120
121 //! Makes a skew-symmetric matrix (a.k.a. Star(*) Matrix)
122 //! [ 0.0 -a.z a.y ]
123 //! [ a.z 0.0 -a.x ]
124 //! [ -a.y a.x 0.0 ]
125 //! This is also called a "cross matrix" since for any vectors A and B,
126 //! A^B = Skew(A) * B = - B * Skew(A);
127 inline_ void SkewSymmetric(const Point& a)
128 {
129 m[0][0] = 0.0f;
130 m[0][1] = -a.z;
131 m[0][2] = a.y;
132
133 m[1][0] = a.z;
134 m[1][1] = 0.0f;
135 m[1][2] = -a.x;
136
137 m[2][0] = -a.y;
138 m[2][1] = a.x;
139 m[2][2] = 0.0f;
140 }
141
142 //! Negates the matrix
143 inline_ void Neg()
144 {
145 m[0][0] = -m[0][0]; m[0][1] = -m[0][1]; m[0][2] = -m[0][2];
146 m[1][0] = -m[1][0]; m[1][1] = -m[1][1]; m[1][2] = -m[1][2];
147 m[2][0] = -m[2][0]; m[2][1] = -m[2][1]; m[2][2] = -m[2][2];
148 }
149
150 //! Neg from another matrix
151 inline_ void Neg(const Matrix3x3& mat)
152 {
153 m[0][0] = -mat.m[0][0]; m[0][1] = -mat.m[0][1]; m[0][2] = -mat.m[0][2];
154 m[1][0] = -mat.m[1][0]; m[1][1] = -mat.m[1][1]; m[1][2] = -mat.m[1][2];
155 m[2][0] = -mat.m[2][0]; m[2][1] = -mat.m[2][1]; m[2][2] = -mat.m[2][2];
156 }
157
158 //! Add another matrix
159 inline_ void Add(const Matrix3x3& mat)
160 {
161 m[0][0] += mat.m[0][0]; m[0][1] += mat.m[0][1]; m[0][2] += mat.m[0][2];
162 m[1][0] += mat.m[1][0]; m[1][1] += mat.m[1][1]; m[1][2] += mat.m[1][2];
163 m[2][0] += mat.m[2][0]; m[2][1] += mat.m[2][1]; m[2][2] += mat.m[2][2];
164 }
165
166 //! Sub another matrix
167 inline_ void Sub(const Matrix3x3& mat)
168 {
169 m[0][0] -= mat.m[0][0]; m[0][1] -= mat.m[0][1]; m[0][2] -= mat.m[0][2];
170 m[1][0] -= mat.m[1][0]; m[1][1] -= mat.m[1][1]; m[1][2] -= mat.m[1][2];
171 m[2][0] -= mat.m[2][0]; m[2][1] -= mat.m[2][1]; m[2][2] -= mat.m[2][2];
172 }
173 //! Mac
174 inline_ void Mac(const Matrix3x3& a, const Matrix3x3& b, float s)
175 {
176 m[0][0] = a.m[0][0] + b.m[0][0] * s;
177 m[0][1] = a.m[0][1] + b.m[0][1] * s;
178 m[0][2] = a.m[0][2] + b.m[0][2] * s;
179
180 m[1][0] = a.m[1][0] + b.m[1][0] * s;
181 m[1][1] = a.m[1][1] + b.m[1][1] * s;
182 m[1][2] = a.m[1][2] + b.m[1][2] * s;
183
184 m[2][0] = a.m[2][0] + b.m[2][0] * s;
185 m[2][1] = a.m[2][1] + b.m[2][1] * s;
186 m[2][2] = a.m[2][2] + b.m[2][2] * s;
187 }
188 //! Mac
189 inline_ void Mac(const Matrix3x3& a, float s)
190 {
191 m[0][0] += a.m[0][0] * s; m[0][1] += a.m[0][1] * s; m[0][2] += a.m[0][2] * s;
192 m[1][0] += a.m[1][0] * s; m[1][1] += a.m[1][1] * s; m[1][2] += a.m[1][2] * s;
193 m[2][0] += a.m[2][0] * s; m[2][1] += a.m[2][1] * s; m[2][2] += a.m[2][2] * s;
194 }
195
196 //! this = A * s
197 inline_ void Mult(const Matrix3x3& a, float s)
198 {
199 m[0][0] = a.m[0][0] * s; m[0][1] = a.m[0][1] * s; m[0][2] = a.m[0][2] * s;
200 m[1][0] = a.m[1][0] * s; m[1][1] = a.m[1][1] * s; m[1][2] = a.m[1][2] * s;
201 m[2][0] = a.m[2][0] * s; m[2][1] = a.m[2][1] * s; m[2][2] = a.m[2][2] * s;
202 }
203
204 inline_ void Add(const Matrix3x3& a, const Matrix3x3& b)
205 {
206 m[0][0] = a.m[0][0] + b.m[0][0]; m[0][1] = a.m[0][1] + b.m[0][1]; m[0][2] = a.m[0][2] + b.m[0][2];
207 m[1][0] = a.m[1][0] + b.m[1][0]; m[1][1] = a.m[1][1] + b.m[1][1]; m[1][2] = a.m[1][2] + b.m[1][2];
208 m[2][0] = a.m[2][0] + b.m[2][0]; m[2][1] = a.m[2][1] + b.m[2][1]; m[2][2] = a.m[2][2] + b.m[2][2];
209 }
210
211 inline_ void Sub(const Matrix3x3& a, const Matrix3x3& b)
212 {
213 m[0][0] = a.m[0][0] - b.m[0][0]; m[0][1] = a.m[0][1] - b.m[0][1]; m[0][2] = a.m[0][2] - b.m[0][2];
214 m[1][0] = a.m[1][0] - b.m[1][0]; m[1][1] = a.m[1][1] - b.m[1][1]; m[1][2] = a.m[1][2] - b.m[1][2];
215 m[2][0] = a.m[2][0] - b.m[2][0]; m[2][1] = a.m[2][1] - b.m[2][1]; m[2][2] = a.m[2][2] - b.m[2][2];
216 }
217
218 //! this = a * b
219 inline_ void Mult(const Matrix3x3& a, const Matrix3x3& b)
220 {
221 m[0][0] = a.m[0][0] * b.m[0][0] + a.m[0][1] * b.m[1][0] + a.m[0][2] * b.m[2][0];
222 m[0][1] = a.m[0][0] * b.m[0][1] + a.m[0][1] * b.m[1][1] + a.m[0][2] * b.m[2][1];
223 m[0][2] = a.m[0][0] * b.m[0][2] + a.m[0][1] * b.m[1][2] + a.m[0][2] * b.m[2][2];
224 m[1][0] = a.m[1][0] * b.m[0][0] + a.m[1][1] * b.m[1][0] + a.m[1][2] * b.m[2][0];
225 m[1][1] = a.m[1][0] * b.m[0][1] + a.m[1][1] * b.m[1][1] + a.m[1][2] * b.m[2][1];
226 m[1][2] = a.m[1][0] * b.m[0][2] + a.m[1][1] * b.m[1][2] + a.m[1][2] * b.m[2][2];
227 m[2][0] = a.m[2][0] * b.m[0][0] + a.m[2][1] * b.m[1][0] + a.m[2][2] * b.m[2][0];
228 m[2][1] = a.m[2][0] * b.m[0][1] + a.m[2][1] * b.m[1][1] + a.m[2][2] * b.m[2][1];
229 m[2][2] = a.m[2][0] * b.m[0][2] + a.m[2][1] * b.m[1][2] + a.m[2][2] * b.m[2][2];
230 }
231
232 //! this = transpose(a) * b
233 inline_ void MultAtB(const Matrix3x3& a, const Matrix3x3& b)
234 {
235 m[0][0] = a.m[0][0] * b.m[0][0] + a.m[1][0] * b.m[1][0] + a.m[2][0] * b.m[2][0];
236 m[0][1] = a.m[0][0] * b.m[0][1] + a.m[1][0] * b.m[1][1] + a.m[2][0] * b.m[2][1];
237 m[0][2] = a.m[0][0] * b.m[0][2] + a.m[1][0] * b.m[1][2] + a.m[2][0] * b.m[2][2];
238 m[1][0] = a.m[0][1] * b.m[0][0] + a.m[1][1] * b.m[1][0] + a.m[2][1] * b.m[2][0];
239 m[1][1] = a.m[0][1] * b.m[0][1] + a.m[1][1] * b.m[1][1] + a.m[2][1] * b.m[2][1];
240 m[1][2] = a.m[0][1] * b.m[0][2] + a.m[1][1] * b.m[1][2] + a.m[2][1] * b.m[2][2];
241 m[2][0] = a.m[0][2] * b.m[0][0] + a.m[1][2] * b.m[1][0] + a.m[2][2] * b.m[2][0];
242 m[2][1] = a.m[0][2] * b.m[0][1] + a.m[1][2] * b.m[1][1] + a.m[2][2] * b.m[2][1];
243 m[2][2] = a.m[0][2] * b.m[0][2] + a.m[1][2] * b.m[1][2] + a.m[2][2] * b.m[2][2];
244 }
245
246 //! this = a * transpose(b)
247 inline_ void MultABt(const Matrix3x3& a, const Matrix3x3& b)
248 {
249 m[0][0] = a.m[0][0] * b.m[0][0] + a.m[0][1] * b.m[0][1] + a.m[0][2] * b.m[0][2];
250 m[0][1] = a.m[0][0] * b.m[1][0] + a.m[0][1] * b.m[1][1] + a.m[0][2] * b.m[1][2];
251 m[0][2] = a.m[0][0] * b.m[2][0] + a.m[0][1] * b.m[2][1] + a.m[0][2] * b.m[2][2];
252 m[1][0] = a.m[1][0] * b.m[0][0] + a.m[1][1] * b.m[0][1] + a.m[1][2] * b.m[0][2];
253 m[1][1] = a.m[1][0] * b.m[1][0] + a.m[1][1] * b.m[1][1] + a.m[1][2] * b.m[1][2];
254 m[1][2] = a.m[1][0] * b.m[2][0] + a.m[1][1] * b.m[2][1] + a.m[1][2] * b.m[2][2];
255 m[2][0] = a.m[2][0] * b.m[0][0] + a.m[2][1] * b.m[0][1] + a.m[2][2] * b.m[0][2];
256 m[2][1] = a.m[2][0] * b.m[1][0] + a.m[2][1] * b.m[1][1] + a.m[2][2] * b.m[1][2];
257 m[2][2] = a.m[2][0] * b.m[2][0] + a.m[2][1] * b.m[2][1] + a.m[2][2] * b.m[2][2];
258 }
259
260 //! Makes a rotation matrix mapping vector "from" to vector "to".
261 Matrix3x3& FromTo(const Point& from, const Point& to);
262
263 //! Set a rotation matrix around the X axis.
264 //! 1 0 0
265 //! RX = 0 cx sx
266 //! 0 -sx cx
267 void RotX(float angle);
268 //! Set a rotation matrix around the Y axis.
269 //! cy 0 -sy
270 //! RY = 0 1 0
271 //! sy 0 cy
272 void RotY(float angle);
273 //! Set a rotation matrix around the Z axis.
274 //! cz sz 0
275 //! RZ = -sz cz 0
276 //! 0 0 1
277 void RotZ(float angle);
278 //! cy sx.sy -sy.cx
279 //! RY.RX 0 cx sx
280 //! sy -sx.cy cx.cy
281 void RotYX(float y, float x);
282
283 //! Make a rotation matrix about an arbitrary axis
284 Matrix3x3& Rot(float angle, const Point& axis);
285
286 //! Transpose the matrix.
287 void Transpose()
288 {
289 IR(m[1][0]) ^= IR(m[0][1]); IR(m[0][1]) ^= IR(m[1][0]); IR(m[1][0]) ^= IR(m[0][1]);
290 IR(m[2][0]) ^= IR(m[0][2]); IR(m[0][2]) ^= IR(m[2][0]); IR(m[2][0]) ^= IR(m[0][2]);
291 IR(m[2][1]) ^= IR(m[1][2]); IR(m[1][2]) ^= IR(m[2][1]); IR(m[2][1]) ^= IR(m[1][2]);
292 }
293
294 //! this = Transpose(a)
295 void Transpose(const Matrix3x3& a)
296 {
297 m[0][0] = a.m[0][0]; m[0][1] = a.m[1][0]; m[0][2] = a.m[2][0];
298 m[1][0] = a.m[0][1]; m[1][1] = a.m[1][1]; m[1][2] = a.m[2][1];
299 m[2][0] = a.m[0][2]; m[2][1] = a.m[1][2]; m[2][2] = a.m[2][2];
300 }
301
302 //! Compute the determinant of the matrix. We use the rule of Sarrus.
303 float Determinant() const
304 {
305 return (m[0][0]*m[1][1]*m[2][2] + m[0][1]*m[1][2]*m[2][0] + m[0][2]*m[1][0]*m[2][1])
306 - (m[2][0]*m[1][1]*m[0][2] + m[2][1]*m[1][2]*m[0][0] + m[2][2]*m[1][0]*m[0][1]);
307 }
308/*
309 //! Compute a cofactor. Used for matrix inversion.
310 float CoFactor(ubyte row, ubyte column) const
311 {
312 static sdword gIndex[3+2] = { 0, 1, 2, 0, 1 };
313 return (m[gIndex[row+1]][gIndex[column+1]]*m[gIndex[row+2]][gIndex[column+2]] - m[gIndex[row+2]][gIndex[column+1]]*m[gIndex[row+1]][gIndex[column+2]]);
314 }
315*/
316 //! Invert the matrix. Determinant must be different from zero, else matrix can't be inverted.
317 Matrix3x3& Invert()
318 {
319 float Det = Determinant(); // Must be !=0
320 float OneOverDet = 1.0f / Det;
321
322 Matrix3x3 Temp;
323 Temp.m[0][0] = +(m[1][1] * m[2][2] - m[2][1] * m[1][2]) * OneOverDet;
324 Temp.m[1][0] = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]) * OneOverDet;
325 Temp.m[2][0] = +(m[1][0] * m[2][1] - m[2][0] * m[1][1]) * OneOverDet;
326 Temp.m[0][1] = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]) * OneOverDet;
327 Temp.m[1][1] = +(m[0][0] * m[2][2] - m[2][0] * m[0][2]) * OneOverDet;
328 Temp.m[2][1] = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]) * OneOverDet;
329 Temp.m[0][2] = +(m[0][1] * m[1][2] - m[1][1] * m[0][2]) * OneOverDet;
330 Temp.m[1][2] = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]) * OneOverDet;
331 Temp.m[2][2] = +(m[0][0] * m[1][1] - m[1][0] * m[0][1]) * OneOverDet;
332
333 *this = Temp;
334
335 return *this;
336 }
337
338 Matrix3x3& Normalize();
339
340 //! this = exp(a)
341 Matrix3x3& Exp(const Matrix3x3& a);
342
343void FromQuat(const Quat &q);
344void FromQuatL2(const Quat &q, float l2);
345
346 // Arithmetic operators
347 //! Operator for Matrix3x3 Plus = Matrix3x3 + Matrix3x3;
348 inline_ Matrix3x3 operator+(const Matrix3x3& mat) const
349 {
350 return Matrix3x3(
351 m[0][0] + mat.m[0][0], m[0][1] + mat.m[0][1], m[0][2] + mat.m[0][2],
352 m[1][0] + mat.m[1][0], m[1][1] + mat.m[1][1], m[1][2] + mat.m[1][2],
353 m[2][0] + mat.m[2][0], m[2][1] + mat.m[2][1], m[2][2] + mat.m[2][2]);
354 }
355
356 //! Operator for Matrix3x3 Minus = Matrix3x3 - Matrix3x3;
357 inline_ Matrix3x3 operator-(const Matrix3x3& mat) const
358 {
359 return Matrix3x3(
360 m[0][0] - mat.m[0][0], m[0][1] - mat.m[0][1], m[0][2] - mat.m[0][2],
361 m[1][0] - mat.m[1][0], m[1][1] - mat.m[1][1], m[1][2] - mat.m[1][2],
362 m[2][0] - mat.m[2][0], m[2][1] - mat.m[2][1], m[2][2] - mat.m[2][2]);
363 }
364
365 //! Operator for Matrix3x3 Mul = Matrix3x3 * Matrix3x3;
366 inline_ Matrix3x3 operator*(const Matrix3x3& mat) const
367 {
368 return Matrix3x3(
369 m[0][0]*mat.m[0][0] + m[0][1]*mat.m[1][0] + m[0][2]*mat.m[2][0],
370 m[0][0]*mat.m[0][1] + m[0][1]*mat.m[1][1] + m[0][2]*mat.m[2][1],
371 m[0][0]*mat.m[0][2] + m[0][1]*mat.m[1][2] + m[0][2]*mat.m[2][2],
372
373 m[1][0]*mat.m[0][0] + m[1][1]*mat.m[1][0] + m[1][2]*mat.m[2][0],
374 m[1][0]*mat.m[0][1] + m[1][1]*mat.m[1][1] + m[1][2]*mat.m[2][1],
375 m[1][0]*mat.m[0][2] + m[1][1]*mat.m[1][2] + m[1][2]*mat.m[2][2],
376
377 m[2][0]*mat.m[0][0] + m[2][1]*mat.m[1][0] + m[2][2]*mat.m[2][0],
378 m[2][0]*mat.m[0][1] + m[2][1]*mat.m[1][1] + m[2][2]*mat.m[2][1],
379 m[2][0]*mat.m[0][2] + m[2][1]*mat.m[1][2] + m[2][2]*mat.m[2][2]);
380 }
381
382 //! Operator for Point Mul = Matrix3x3 * Point;
383 inline_ Point operator*(const Point& v) const { return Point(GetRow(0)|v, GetRow(1)|v, GetRow(2)|v); }
384
385 //! Operator for Matrix3x3 Mul = Matrix3x3 * float;
386 inline_ Matrix3x3 operator*(float s) const
387 {
388 return Matrix3x3(
389 m[0][0]*s, m[0][1]*s, m[0][2]*s,
390 m[1][0]*s, m[1][1]*s, m[1][2]*s,
391 m[2][0]*s, m[2][1]*s, m[2][2]*s);
392 }
393
394 //! Operator for Matrix3x3 Mul = float * Matrix3x3;
395 inline_ friend Matrix3x3 operator*(float s, const Matrix3x3& mat)
396 {
397 return Matrix3x3(
398 s*mat.m[0][0], s*mat.m[0][1], s*mat.m[0][2],
399 s*mat.m[1][0], s*mat.m[1][1], s*mat.m[1][2],
400 s*mat.m[2][0], s*mat.m[2][1], s*mat.m[2][2]);
401 }
402
403 //! Operator for Matrix3x3 Div = Matrix3x3 / float;
404 inline_ Matrix3x3 operator/(float s) const
405 {
406 if (s) s = 1.0f / s;
407 return Matrix3x3(
408 m[0][0]*s, m[0][1]*s, m[0][2]*s,
409 m[1][0]*s, m[1][1]*s, m[1][2]*s,
410 m[2][0]*s, m[2][1]*s, m[2][2]*s);
411 }
412
413 //! Operator for Matrix3x3 Div = float / Matrix3x3;
414 inline_ friend Matrix3x3 operator/(float s, const Matrix3x3& mat)
415 {
416 return Matrix3x3(
417 s/mat.m[0][0], s/mat.m[0][1], s/mat.m[0][2],
418 s/mat.m[1][0], s/mat.m[1][1], s/mat.m[1][2],
419 s/mat.m[2][0], s/mat.m[2][1], s/mat.m[2][2]);
420 }
421
422 //! Operator for Matrix3x3 += Matrix3x3
423 inline_ Matrix3x3& operator+=(const Matrix3x3& mat)
424 {
425 m[0][0] += mat.m[0][0]; m[0][1] += mat.m[0][1]; m[0][2] += mat.m[0][2];
426 m[1][0] += mat.m[1][0]; m[1][1] += mat.m[1][1]; m[1][2] += mat.m[1][2];
427 m[2][0] += mat.m[2][0]; m[2][1] += mat.m[2][1]; m[2][2] += mat.m[2][2];
428 return *this;
429 }
430
431 //! Operator for Matrix3x3 -= Matrix3x3
432 inline_ Matrix3x3& operator-=(const Matrix3x3& mat)
433 {
434 m[0][0] -= mat.m[0][0]; m[0][1] -= mat.m[0][1]; m[0][2] -= mat.m[0][2];
435 m[1][0] -= mat.m[1][0]; m[1][1] -= mat.m[1][1]; m[1][2] -= mat.m[1][2];
436 m[2][0] -= mat.m[2][0]; m[2][1] -= mat.m[2][1]; m[2][2] -= mat.m[2][2];
437 return *this;
438 }
439
440 //! Operator for Matrix3x3 *= Matrix3x3
441 inline_ Matrix3x3& operator*=(const Matrix3x3& mat)
442 {
443 Point TempRow;
444
445 GetRow(0, TempRow);
446 m[0][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0];
447 m[0][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1];
448 m[0][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2];
449
450 GetRow(1, TempRow);
451 m[1][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0];
452 m[1][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1];
453 m[1][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2];
454
455 GetRow(2, TempRow);
456 m[2][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0];
457 m[2][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1];
458 m[2][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2];
459 return *this;
460 }
461
462 //! Operator for Matrix3x3 *= float
463 inline_ Matrix3x3& operator*=(float s)
464 {
465 m[0][0] *= s; m[0][1] *= s; m[0][2] *= s;
466 m[1][0] *= s; m[1][1] *= s; m[1][2] *= s;
467 m[2][0] *= s; m[2][1] *= s; m[2][2] *= s;
468 return *this;
469 }
470
471 //! Operator for Matrix3x3 /= float
472 inline_ Matrix3x3& operator/=(float s)
473 {
474 if (s) s = 1.0f / s;
475 m[0][0] *= s; m[0][1] *= s; m[0][2] *= s;
476 m[1][0] *= s; m[1][1] *= s; m[1][2] *= s;
477 m[2][0] *= s; m[2][1] *= s; m[2][2] *= s;
478 return *this;
479 }
480
481 // Cast operators
482 //! Cast a Matrix3x3 to a Matrix4x4.
483 operator Matrix4x4() const;
484 //! Cast a Matrix3x3 to a Quat.
485 operator Quat() const;
486
487 inline_ const Point& operator[](int row) const { return *(const Point*)&m[row][0]; }
488 inline_ Point& operator[](int row) { return *(Point*)&m[row][0]; }
489
490 public:
491
492 float m[3][3];
493 };
494
495#endif // __ICEMATRIX3X3_H__
496
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceMatrix4x4.cpp b/libraries/ode-0.9/OPCODE/Ice/IceMatrix4x4.cpp
new file mode 100644
index 0000000..0b258f0
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceMatrix4x4.cpp
@@ -0,0 +1,135 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code for 4x4 matrices.
4 * \file IceMatrix4x4.cpp
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11/**
12 * 4x4 matrix.
13 * DirectX-compliant, ie row-column order, ie m[Row][Col].
14 * Same as:
15 * m11 m12 m13 m14 first row.
16 * m21 m22 m23 m24 second row.
17 * m31 m32 m33 m34 third row.
18 * m41 m42 m43 m44 fourth row.
19 * Translation is (m41, m42, m43), (m14, m24, m34, m44) = (0, 0, 0, 1).
20 * Stored in memory as m11 m12 m13 m14 m21...
21 *
22 * Multiplication rules:
23 *
24 * [x'y'z'1] = [xyz1][M]
25 *
26 * x' = x*m11 + y*m21 + z*m31 + m41
27 * y' = x*m12 + y*m22 + z*m32 + m42
28 * z' = x*m13 + y*m23 + z*m33 + m43
29 * 1' = 0 + 0 + 0 + m44
30 *
31 * \class Matrix4x4
32 * \author Pierre Terdiman
33 * \version 1.0
34 */
35///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
36
37///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
38// Precompiled Header
39#include "Stdafx.h"
40
41using namespace IceMaths;
42
43///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
44/**
45 * Inverts a PR matrix. (which only contains a rotation and a translation)
46 * This is faster and less subject to FPU errors than the generic inversion code.
47 *
48 * \relates Matrix4x4
49 * \fn InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src)
50 * \param dest [out] destination matrix
51 * \param src [in] source matrix
52 */
53///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
54ICEMATHS_API void IceMaths::InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src)
55{
56 dest.m[0][0] = src.m[0][0];
57 dest.m[1][0] = src.m[0][1];
58 dest.m[2][0] = src.m[0][2];
59 dest.m[3][0] = -(src.m[3][0]*src.m[0][0] + src.m[3][1]*src.m[0][1] + src.m[3][2]*src.m[0][2]);
60
61 dest.m[0][1] = src.m[1][0];
62 dest.m[1][1] = src.m[1][1];
63 dest.m[2][1] = src.m[1][2];
64 dest.m[3][1] = -(src.m[3][0]*src.m[1][0] + src.m[3][1]*src.m[1][1] + src.m[3][2]*src.m[1][2]);
65
66 dest.m[0][2] = src.m[2][0];
67 dest.m[1][2] = src.m[2][1];
68 dest.m[2][2] = src.m[2][2];
69 dest.m[3][2] = -(src.m[3][0]*src.m[2][0] + src.m[3][1]*src.m[2][1] + src.m[3][2]*src.m[2][2]);
70
71 dest.m[0][3] = 0.0f;
72 dest.m[1][3] = 0.0f;
73 dest.m[2][3] = 0.0f;
74 dest.m[3][3] = 1.0f;
75}
76
77///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
78// Compute the cofactor of the Matrix at a specified location
79///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
80float Matrix4x4::CoFactor(udword row, udword col) const
81{
82 return (( m[(row+1)&3][(col+1)&3]*m[(row+2)&3][(col+2)&3]*m[(row+3)&3][(col+3)&3] +
83 m[(row+1)&3][(col+2)&3]*m[(row+2)&3][(col+3)&3]*m[(row+3)&3][(col+1)&3] +
84 m[(row+1)&3][(col+3)&3]*m[(row+2)&3][(col+1)&3]*m[(row+3)&3][(col+2)&3])
85 - (m[(row+3)&3][(col+1)&3]*m[(row+2)&3][(col+2)&3]*m[(row+1)&3][(col+3)&3] +
86 m[(row+3)&3][(col+2)&3]*m[(row+2)&3][(col+3)&3]*m[(row+1)&3][(col+1)&3] +
87 m[(row+3)&3][(col+3)&3]*m[(row+2)&3][(col+1)&3]*m[(row+1)&3][(col+2)&3])) * ((row + col) & 1 ? -1.0f : +1.0f);
88}
89
90///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
91// Compute the determinant of the Matrix
92///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
93float Matrix4x4::Determinant() const
94{
95 return m[0][0] * CoFactor(0, 0) +
96 m[0][1] * CoFactor(0, 1) +
97 m[0][2] * CoFactor(0, 2) +
98 m[0][3] * CoFactor(0, 3);
99}
100
101///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
102// Compute the inverse of the matrix
103///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
104Matrix4x4& Matrix4x4::Invert()
105{
106 float Det = Determinant();
107 Matrix4x4 Temp;
108
109 if(fabsf(Det) < MATRIX4X4_EPSILON)
110 return *this; // The matrix is not invertible! Singular case!
111
112 float IDet = 1.0f / Det;
113
114 Temp.m[0][0] = CoFactor(0,0) * IDet;
115 Temp.m[1][0] = CoFactor(0,1) * IDet;
116 Temp.m[2][0] = CoFactor(0,2) * IDet;
117 Temp.m[3][0] = CoFactor(0,3) * IDet;
118 Temp.m[0][1] = CoFactor(1,0) * IDet;
119 Temp.m[1][1] = CoFactor(1,1) * IDet;
120 Temp.m[2][1] = CoFactor(1,2) * IDet;
121 Temp.m[3][1] = CoFactor(1,3) * IDet;
122 Temp.m[0][2] = CoFactor(2,0) * IDet;
123 Temp.m[1][2] = CoFactor(2,1) * IDet;
124 Temp.m[2][2] = CoFactor(2,2) * IDet;
125 Temp.m[3][2] = CoFactor(2,3) * IDet;
126 Temp.m[0][3] = CoFactor(3,0) * IDet;
127 Temp.m[1][3] = CoFactor(3,1) * IDet;
128 Temp.m[2][3] = CoFactor(3,2) * IDet;
129 Temp.m[3][3] = CoFactor(3,3) * IDet;
130
131 *this = Temp;
132
133 return *this;
134}
135
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceMatrix4x4.h b/libraries/ode-0.9/OPCODE/Ice/IceMatrix4x4.h
new file mode 100644
index 0000000..45919be
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceMatrix4x4.h
@@ -0,0 +1,455 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code for 4x4 matrices.
4 * \file IceMatrix4x4.h
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICEMATRIX4X4_H__
13#define __ICEMATRIX4X4_H__
14
15 // Forward declarations
16 class PRS;
17 class PR;
18
19 #define MATRIX4X4_EPSILON (1.0e-7f)
20
21 class ICEMATHS_API Matrix4x4
22 {
23// void LUBackwardSubstitution( sdword *indx, float* b );
24// void LUDecomposition( sdword* indx, float* d );
25
26 public:
27 //! Empty constructor.
28 inline_ Matrix4x4() {}
29 //! Constructor from 16 values
30 inline_ Matrix4x4( float m00, float m01, float m02, float m03,
31 float m10, float m11, float m12, float m13,
32 float m20, float m21, float m22, float m23,
33 float m30, float m31, float m32, float m33)
34 {
35 m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03;
36 m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13;
37 m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23;
38 m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33;
39 }
40 //! Copy constructor
41 inline_ Matrix4x4(const Matrix4x4& mat) { CopyMemory(m, &mat.m, 16*sizeof(float)); }
42 //! Destructor.
43 inline_ ~Matrix4x4() {}
44
45 //! Assign values (rotation only)
46 inline_ Matrix4x4& Set( float m00, float m01, float m02,
47 float m10, float m11, float m12,
48 float m20, float m21, float m22)
49 {
50 m[0][0] = m00; m[0][1] = m01; m[0][2] = m02;
51 m[1][0] = m10; m[1][1] = m11; m[1][2] = m12;
52 m[2][0] = m20; m[2][1] = m21; m[2][2] = m22;
53 return *this;
54 }
55 //! Assign values
56 inline_ Matrix4x4& Set( float m00, float m01, float m02, float m03,
57 float m10, float m11, float m12, float m13,
58 float m20, float m21, float m22, float m23,
59 float m30, float m31, float m32, float m33)
60 {
61 m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03;
62 m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13;
63 m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23;
64 m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33;
65 return *this;
66 }
67
68 //! Copy from a Matrix4x4
69 inline_ void Copy(const Matrix4x4& source) { CopyMemory(m, source.m, 16*sizeof(float)); }
70
71 // Row-column access
72 //! Returns a row.
73 inline_ void GetRow(const udword r, HPoint& p) const { p.x=m[r][0]; p.y=m[r][1]; p.z=m[r][2]; p.w=m[r][3]; }
74 //! Returns a row.
75 inline_ void GetRow(const udword r, Point& p) const { p.x=m[r][0]; p.y=m[r][1]; p.z=m[r][2]; }
76 //! Returns a row.
77 inline_ const HPoint& GetRow(const udword r) const { return *(const HPoint*)&m[r][0]; }
78 //! Returns a row.
79 inline_ HPoint& GetRow(const udword r) { return *(HPoint*)&m[r][0]; }
80 //! Sets a row.
81 inline_ void SetRow(const udword r, const HPoint& p) { m[r][0]=p.x; m[r][1]=p.y; m[r][2]=p.z; m[r][3]=p.w; }
82 //! Sets a row.
83 inline_ void SetRow(const udword r, const Point& p) { m[r][0]=p.x; m[r][1]=p.y; m[r][2]=p.z; m[r][3]= (r!=3) ? 0.0f : 1.0f; }
84 //! Returns a column.
85 inline_ void GetCol(const udword c, HPoint& p) const { p.x=m[0][c]; p.y=m[1][c]; p.z=m[2][c]; p.w=m[3][c]; }
86 //! Returns a column.
87 inline_ void GetCol(const udword c, Point& p) const { p.x=m[0][c]; p.y=m[1][c]; p.z=m[2][c]; }
88 //! Sets a column.
89 inline_ void SetCol(const udword c, const HPoint& p) { m[0][c]=p.x; m[1][c]=p.y; m[2][c]=p.z; m[3][c]=p.w; }
90 //! Sets a column.
91 inline_ void SetCol(const udword c, const Point& p) { m[0][c]=p.x; m[1][c]=p.y; m[2][c]=p.z; m[3][c]= (c!=3) ? 0.0f : 1.0f; }
92
93 // Translation
94 //! Returns the translation part of the matrix.
95 inline_ const HPoint& GetTrans() const { return GetRow(3); }
96 //! Gets the translation part of the matrix
97 inline_ void GetTrans(Point& p) const { p.x=m[3][0]; p.y=m[3][1]; p.z=m[3][2]; }
98 //! Sets the translation part of the matrix, from a Point.
99 inline_ void SetTrans(const Point& p) { m[3][0]=p.x; m[3][1]=p.y; m[3][2]=p.z; }
100 //! Sets the translation part of the matrix, from a HPoint.
101 inline_ void SetTrans(const HPoint& p) { m[3][0]=p.x; m[3][1]=p.y; m[3][2]=p.z; m[3][3]=p.w; }
102 //! Sets the translation part of the matrix, from floats.
103 inline_ void SetTrans(float tx, float ty, float tz) { m[3][0]=tx; m[3][1]=ty; m[3][2]=tz; }
104
105 // Scale
106 //! Sets the scale from a Point. The point is put on the diagonal.
107 inline_ void SetScale(const Point& p) { m[0][0]=p.x; m[1][1]=p.y; m[2][2]=p.z; }
108 //! Sets the scale from floats. Values are put on the diagonal.
109 inline_ void SetScale(float sx, float sy, float sz) { m[0][0]=sx; m[1][1]=sy; m[2][2]=sz; }
110 //! Scales from a Point. Each row is multiplied by a component.
111 void Scale(const Point& p)
112 {
113 m[0][0] *= p.x; m[1][0] *= p.y; m[2][0] *= p.z;
114 m[0][1] *= p.x; m[1][1] *= p.y; m[2][1] *= p.z;
115 m[0][2] *= p.x; m[1][2] *= p.y; m[2][2] *= p.z;
116 }
117 //! Scales from floats. Each row is multiplied by a value.
118 void Scale(float sx, float sy, float sz)
119 {
120 m[0][0] *= sx; m[1][0] *= sy; m[2][0] *= sz;
121 m[0][1] *= sx; m[1][1] *= sy; m[2][1] *= sz;
122 m[0][2] *= sx; m[1][2] *= sy; m[2][2] *= sz;
123 }
124/*
125 //! Returns a row.
126 inline_ HPoint GetRow(const udword row) const { return mRow[row]; }
127 //! Sets a row.
128 inline_ Matrix4x4& SetRow(const udword row, const HPoint& p) { mRow[row] = p; return *this; }
129 //! Sets a row.
130 Matrix4x4& SetRow(const udword row, const Point& p)
131 {
132 m[row][0] = p.x;
133 m[row][1] = p.y;
134 m[row][2] = p.z;
135 m[row][3] = (row != 3) ? 0.0f : 1.0f;
136 return *this;
137 }
138 //! Returns a column.
139 HPoint GetCol(const udword col) const
140 {
141 HPoint Res;
142 Res.x = m[0][col];
143 Res.y = m[1][col];
144 Res.z = m[2][col];
145 Res.w = m[3][col];
146 return Res;
147 }
148 //! Sets a column.
149 Matrix4x4& SetCol(const udword col, const HPoint& p)
150 {
151 m[0][col] = p.x;
152 m[1][col] = p.y;
153 m[2][col] = p.z;
154 m[3][col] = p.w;
155 return *this;
156 }
157 //! Sets a column.
158 Matrix4x4& SetCol(const udword col, const Point& p)
159 {
160 m[0][col] = p.x;
161 m[1][col] = p.y;
162 m[2][col] = p.z;
163 m[3][col] = (col != 3) ? 0.0f : 1.0f;
164 return *this;
165 }
166*/
167 //! Computes the trace. The trace is the sum of the 4 diagonal components.
168 inline_ float Trace() const { return m[0][0] + m[1][1] + m[2][2] + m[3][3]; }
169 //! Computes the trace of the upper 3x3 matrix.
170 inline_ float Trace3x3() const { return m[0][0] + m[1][1] + m[2][2]; }
171 //! Clears the matrix.
172 inline_ void Zero() { ZeroMemory(&m, sizeof(m)); }
173 //! Sets the identity matrix.
174 inline_ void Identity() { Zero(); m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; }
175 //! Checks for identity
176 inline_ bool IsIdentity() const
177 {
178 if(IR(m[0][0])!=IEEE_1_0) return false;
179 if(IR(m[0][1])!=0) return false;
180 if(IR(m[0][2])!=0) return false;
181 if(IR(m[0][3])!=0) return false;
182
183 if(IR(m[1][0])!=0) return false;
184 if(IR(m[1][1])!=IEEE_1_0) return false;
185 if(IR(m[1][2])!=0) return false;
186 if(IR(m[1][3])!=0) return false;
187
188 if(IR(m[2][0])!=0) return false;
189 if(IR(m[2][1])!=0) return false;
190 if(IR(m[2][2])!=IEEE_1_0) return false;
191 if(IR(m[2][3])!=0) return false;
192
193 if(IR(m[3][0])!=0) return false;
194 if(IR(m[3][1])!=0) return false;
195 if(IR(m[3][2])!=0) return false;
196 if(IR(m[3][3])!=IEEE_1_0) return false;
197 return true;
198 }
199
200 //! Checks matrix validity
201 inline_ BOOL IsValid() const
202 {
203 for(udword j=0;j<4;j++)
204 {
205 for(udword i=0;i<4;i++)
206 {
207 if(!IsValidFloat(m[j][i])) return FALSE;
208 }
209 }
210 return TRUE;
211 }
212
213 //! Sets a rotation matrix around the X axis.
214 void RotX(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[1][1] = m[2][2] = Cos; m[2][1] = -Sin; m[1][2] = Sin; }
215 //! Sets a rotation matrix around the Y axis.
216 void RotY(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[2][2] = Cos; m[2][0] = Sin; m[0][2] = -Sin; }
217 //! Sets a rotation matrix around the Z axis.
218 void RotZ(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[1][1] = Cos; m[1][0] = -Sin; m[0][1] = Sin; }
219
220 //! Makes a rotation matrix about an arbitrary axis
221 Matrix4x4& Rot(float angle, Point& p1, Point& p2);
222
223 //! Transposes the matrix.
224 void Transpose()
225 {
226 IR(m[1][0]) ^= IR(m[0][1]); IR(m[0][1]) ^= IR(m[1][0]); IR(m[1][0]) ^= IR(m[0][1]);
227 IR(m[2][0]) ^= IR(m[0][2]); IR(m[0][2]) ^= IR(m[2][0]); IR(m[2][0]) ^= IR(m[0][2]);
228 IR(m[3][0]) ^= IR(m[0][3]); IR(m[0][3]) ^= IR(m[3][0]); IR(m[3][0]) ^= IR(m[0][3]);
229 IR(m[1][2]) ^= IR(m[2][1]); IR(m[2][1]) ^= IR(m[1][2]); IR(m[1][2]) ^= IR(m[2][1]);
230 IR(m[1][3]) ^= IR(m[3][1]); IR(m[3][1]) ^= IR(m[1][3]); IR(m[1][3]) ^= IR(m[3][1]);
231 IR(m[2][3]) ^= IR(m[3][2]); IR(m[3][2]) ^= IR(m[2][3]); IR(m[2][3]) ^= IR(m[3][2]);
232 }
233
234 //! Computes a cofactor. Used for matrix inversion.
235 float CoFactor(udword row, udword col) const;
236 //! Computes the determinant of the matrix.
237 float Determinant() const;
238 //! Inverts the matrix. Determinant must be different from zero, else matrix can't be inverted.
239 Matrix4x4& Invert();
240// Matrix& ComputeAxisMatrix(Point& axis, float angle);
241
242 // Cast operators
243 //! Casts a Matrix4x4 to a Matrix3x3.
244 inline_ operator Matrix3x3() const
245 {
246 return Matrix3x3(
247 m[0][0], m[0][1], m[0][2],
248 m[1][0], m[1][1], m[1][2],
249 m[2][0], m[2][1], m[2][2]);
250 }
251 //! Casts a Matrix4x4 to a Quat.
252 operator Quat() const;
253 //! Casts a Matrix4x4 to a PR.
254 operator PR() const;
255
256 // Arithmetic operators
257 //! Operator for Matrix4x4 Plus = Matrix4x4 + Matrix4x4;
258 inline_ Matrix4x4 operator+(const Matrix4x4& mat) const
259 {
260 return Matrix4x4(
261 m[0][0]+mat.m[0][0], m[0][1]+mat.m[0][1], m[0][2]+mat.m[0][2], m[0][3]+mat.m[0][3],
262 m[1][0]+mat.m[1][0], m[1][1]+mat.m[1][1], m[1][2]+mat.m[1][2], m[1][3]+mat.m[1][3],
263 m[2][0]+mat.m[2][0], m[2][1]+mat.m[2][1], m[2][2]+mat.m[2][2], m[2][3]+mat.m[2][3],
264 m[3][0]+mat.m[3][0], m[3][1]+mat.m[3][1], m[3][2]+mat.m[3][2], m[3][3]+mat.m[3][3]);
265 }
266
267 //! Operator for Matrix4x4 Minus = Matrix4x4 - Matrix4x4;
268 inline_ Matrix4x4 operator-(const Matrix4x4& mat) const
269 {
270 return Matrix4x4(
271 m[0][0]-mat.m[0][0], m[0][1]-mat.m[0][1], m[0][2]-mat.m[0][2], m[0][3]-mat.m[0][3],
272 m[1][0]-mat.m[1][0], m[1][1]-mat.m[1][1], m[1][2]-mat.m[1][2], m[1][3]-mat.m[1][3],
273 m[2][0]-mat.m[2][0], m[2][1]-mat.m[2][1], m[2][2]-mat.m[2][2], m[2][3]-mat.m[2][3],
274 m[3][0]-mat.m[3][0], m[3][1]-mat.m[3][1], m[3][2]-mat.m[3][2], m[3][3]-mat.m[3][3]);
275 }
276
277 //! Operator for Matrix4x4 Mul = Matrix4x4 * Matrix4x4;
278 inline_ Matrix4x4 operator*(const Matrix4x4& mat) const
279 {
280 return Matrix4x4(
281 m[0][0]*mat.m[0][0] + m[0][1]*mat.m[1][0] + m[0][2]*mat.m[2][0] + m[0][3]*mat.m[3][0],
282 m[0][0]*mat.m[0][1] + m[0][1]*mat.m[1][1] + m[0][2]*mat.m[2][1] + m[0][3]*mat.m[3][1],
283 m[0][0]*mat.m[0][2] + m[0][1]*mat.m[1][2] + m[0][2]*mat.m[2][2] + m[0][3]*mat.m[3][2],
284 m[0][0]*mat.m[0][3] + m[0][1]*mat.m[1][3] + m[0][2]*mat.m[2][3] + m[0][3]*mat.m[3][3],
285
286 m[1][0]*mat.m[0][0] + m[1][1]*mat.m[1][0] + m[1][2]*mat.m[2][0] + m[1][3]*mat.m[3][0],
287 m[1][0]*mat.m[0][1] + m[1][1]*mat.m[1][1] + m[1][2]*mat.m[2][1] + m[1][3]*mat.m[3][1],
288 m[1][0]*mat.m[0][2] + m[1][1]*mat.m[1][2] + m[1][2]*mat.m[2][2] + m[1][3]*mat.m[3][2],
289 m[1][0]*mat.m[0][3] + m[1][1]*mat.m[1][3] + m[1][2]*mat.m[2][3] + m[1][3]*mat.m[3][3],
290
291 m[2][0]*mat.m[0][0] + m[2][1]*mat.m[1][0] + m[2][2]*mat.m[2][0] + m[2][3]*mat.m[3][0],
292 m[2][0]*mat.m[0][1] + m[2][1]*mat.m[1][1] + m[2][2]*mat.m[2][1] + m[2][3]*mat.m[3][1],
293 m[2][0]*mat.m[0][2] + m[2][1]*mat.m[1][2] + m[2][2]*mat.m[2][2] + m[2][3]*mat.m[3][2],
294 m[2][0]*mat.m[0][3] + m[2][1]*mat.m[1][3] + m[2][2]*mat.m[2][3] + m[2][3]*mat.m[3][3],
295
296 m[3][0]*mat.m[0][0] + m[3][1]*mat.m[1][0] + m[3][2]*mat.m[2][0] + m[3][3]*mat.m[3][0],
297 m[3][0]*mat.m[0][1] + m[3][1]*mat.m[1][1] + m[3][2]*mat.m[2][1] + m[3][3]*mat.m[3][1],
298 m[3][0]*mat.m[0][2] + m[3][1]*mat.m[1][2] + m[3][2]*mat.m[2][2] + m[3][3]*mat.m[3][2],
299 m[3][0]*mat.m[0][3] + m[3][1]*mat.m[1][3] + m[3][2]*mat.m[2][3] + m[3][3]*mat.m[3][3]);
300 }
301
302 //! Operator for HPoint Mul = Matrix4x4 * HPoint;
303 inline_ HPoint operator*(const HPoint& v) const { return HPoint(GetRow(0)|v, GetRow(1)|v, GetRow(2)|v, GetRow(3)|v); }
304
305 //! Operator for Point Mul = Matrix4x4 * Point;
306 inline_ Point operator*(const Point& v) const
307 {
308 return Point( m[0][0]*v.x + m[0][1]*v.y + m[0][2]*v.z + m[0][3],
309 m[1][0]*v.x + m[1][1]*v.y + m[1][2]*v.z + m[1][3],
310 m[2][0]*v.x + m[2][1]*v.y + m[2][2]*v.z + m[2][3] );
311 }
312
313 //! Operator for Matrix4x4 Scale = Matrix4x4 * float;
314 inline_ Matrix4x4 operator*(float s) const
315 {
316 return Matrix4x4(
317 m[0][0]*s, m[0][1]*s, m[0][2]*s, m[0][3]*s,
318 m[1][0]*s, m[1][1]*s, m[1][2]*s, m[1][3]*s,
319 m[2][0]*s, m[2][1]*s, m[2][2]*s, m[2][3]*s,
320 m[3][0]*s, m[3][1]*s, m[3][2]*s, m[3][3]*s);
321 }
322
323 //! Operator for Matrix4x4 Scale = float * Matrix4x4;
324 inline_ friend Matrix4x4 operator*(float s, const Matrix4x4& mat)
325 {
326 return Matrix4x4(
327 s*mat.m[0][0], s*mat.m[0][1], s*mat.m[0][2], s*mat.m[0][3],
328 s*mat.m[1][0], s*mat.m[1][1], s*mat.m[1][2], s*mat.m[1][3],
329 s*mat.m[2][0], s*mat.m[2][1], s*mat.m[2][2], s*mat.m[2][3],
330 s*mat.m[3][0], s*mat.m[3][1], s*mat.m[3][2], s*mat.m[3][3]);
331 }
332
333 //! Operator for Matrix4x4 Div = Matrix4x4 / float;
334 inline_ Matrix4x4 operator/(float s) const
335 {
336 if(s) s = 1.0f / s;
337
338 return Matrix4x4(
339 m[0][0]*s, m[0][1]*s, m[0][2]*s, m[0][3]*s,
340 m[1][0]*s, m[1][1]*s, m[1][2]*s, m[1][3]*s,
341 m[2][0]*s, m[2][1]*s, m[2][2]*s, m[2][3]*s,
342 m[3][0]*s, m[3][1]*s, m[3][2]*s, m[3][3]*s);
343 }
344
345 //! Operator for Matrix4x4 Div = float / Matrix4x4;
346 inline_ friend Matrix4x4 operator/(float s, const Matrix4x4& mat)
347 {
348 return Matrix4x4(
349 s/mat.m[0][0], s/mat.m[0][1], s/mat.m[0][2], s/mat.m[0][3],
350 s/mat.m[1][0], s/mat.m[1][1], s/mat.m[1][2], s/mat.m[1][3],
351 s/mat.m[2][0], s/mat.m[2][1], s/mat.m[2][2], s/mat.m[2][3],
352 s/mat.m[3][0], s/mat.m[3][1], s/mat.m[3][2], s/mat.m[3][3]);
353 }
354
355 //! Operator for Matrix4x4 += Matrix4x4;
356 inline_ Matrix4x4& operator+=(const Matrix4x4& mat)
357 {
358 m[0][0]+=mat.m[0][0]; m[0][1]+=mat.m[0][1]; m[0][2]+=mat.m[0][2]; m[0][3]+=mat.m[0][3];
359 m[1][0]+=mat.m[1][0]; m[1][1]+=mat.m[1][1]; m[1][2]+=mat.m[1][2]; m[1][3]+=mat.m[1][3];
360 m[2][0]+=mat.m[2][0]; m[2][1]+=mat.m[2][1]; m[2][2]+=mat.m[2][2]; m[2][3]+=mat.m[2][3];
361 m[3][0]+=mat.m[3][0]; m[3][1]+=mat.m[3][1]; m[3][2]+=mat.m[3][2]; m[3][3]+=mat.m[3][3];
362 return *this;
363 }
364
365 //! Operator for Matrix4x4 -= Matrix4x4;
366 inline_ Matrix4x4& operator-=(const Matrix4x4& mat)
367 {
368 m[0][0]-=mat.m[0][0]; m[0][1]-=mat.m[0][1]; m[0][2]-=mat.m[0][2]; m[0][3]-=mat.m[0][3];
369 m[1][0]-=mat.m[1][0]; m[1][1]-=mat.m[1][1]; m[1][2]-=mat.m[1][2]; m[1][3]-=mat.m[1][3];
370 m[2][0]-=mat.m[2][0]; m[2][1]-=mat.m[2][1]; m[2][2]-=mat.m[2][2]; m[2][3]-=mat.m[2][3];
371 m[3][0]-=mat.m[3][0]; m[3][1]-=mat.m[3][1]; m[3][2]-=mat.m[3][2]; m[3][3]-=mat.m[3][3];
372 return *this;
373 }
374
375 //! Operator for Matrix4x4 *= Matrix4x4;
376 Matrix4x4& operator*=(const Matrix4x4& mat)
377 {
378 HPoint TempRow;
379
380 GetRow(0, TempRow);
381 m[0][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
382 m[0][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
383 m[0][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
384 m[0][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
385
386 GetRow(1, TempRow);
387 m[1][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
388 m[1][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
389 m[1][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
390 m[1][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
391
392 GetRow(2, TempRow);
393 m[2][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
394 m[2][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
395 m[2][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
396 m[2][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
397
398 GetRow(3, TempRow);
399 m[3][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
400 m[3][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
401 m[3][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
402 m[3][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
403
404 return *this;
405 }
406
407 //! Operator for Matrix4x4 *= float;
408 inline_ Matrix4x4& operator*=(float s)
409 {
410 m[0][0]*=s; m[0][1]*=s; m[0][2]*=s; m[0][3]*=s;
411 m[1][0]*=s; m[1][1]*=s; m[1][2]*=s; m[1][3]*=s;
412 m[2][0]*=s; m[2][1]*=s; m[2][2]*=s; m[2][3]*=s;
413 m[3][0]*=s; m[3][1]*=s; m[3][2]*=s; m[3][3]*=s;
414 return *this;
415 }
416
417 //! Operator for Matrix4x4 /= float;
418 inline_ Matrix4x4& operator/=(float s)
419 {
420 if(s) s = 1.0f / s;
421 m[0][0]*=s; m[0][1]*=s; m[0][2]*=s; m[0][3]*=s;
422 m[1][0]*=s; m[1][1]*=s; m[1][2]*=s; m[1][3]*=s;
423 m[2][0]*=s; m[2][1]*=s; m[2][2]*=s; m[2][3]*=s;
424 m[3][0]*=s; m[3][1]*=s; m[3][2]*=s; m[3][3]*=s;
425 return *this;
426 }
427
428 inline_ const HPoint& operator[](int row) const { return *(const HPoint*)&m[row][0]; }
429 inline_ HPoint& operator[](int row) { return *(HPoint*)&m[row][0]; }
430
431 public:
432
433 float m[4][4];
434 };
435
436 //! Quickly rotates & translates a vector, using the 4x3 part of a 4x4 matrix
437 inline_ void TransformPoint4x3(Point& dest, const Point& source, const Matrix4x4& rot)
438 {
439 dest.x = rot.m[3][0] + source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0];
440 dest.y = rot.m[3][1] + source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1];
441 dest.z = rot.m[3][2] + source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2];
442 }
443
444 //! Quickly rotates a vector, using the 3x3 part of a 4x4 matrix
445 inline_ void TransformPoint3x3(Point& dest, const Point& source, const Matrix4x4& rot)
446 {
447 dest.x = source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0];
448 dest.y = source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1];
449 dest.z = source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2];
450 }
451
452 ICEMATHS_API void InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src);
453
454#endif // __ICEMATRIX4X4_H__
455
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceMemoryMacros.h b/libraries/ode-0.9/OPCODE/Ice/IceMemoryMacros.h
new file mode 100644
index 0000000..6386333
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceMemoryMacros.h
@@ -0,0 +1,109 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains all memory macros.
4 * \file IceMemoryMacros.h
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICEMEMORYMACROS_H__
13#define __ICEMEMORYMACROS_H__
14
15#undef ZeroMemory
16#undef CopyMemory
17#undef MoveMemory
18#undef FillMemory
19
20 //! Clears a buffer.
21 //! \param addr [in] buffer address
22 //! \param size [in] buffer length
23 //! \see FillMemory
24 //! \see StoreDwords
25 //! \see CopyMemory
26 //! \see MoveMemory
27 inline_ void ZeroMemory(void* addr, udword size) { memset(addr, 0, size); }
28
29 //! Fills a buffer with a given byte.
30 //! \param addr [in] buffer address
31 //! \param size [in] buffer length
32 //! \param val [in] the byte value
33 //! \see StoreDwords
34 //! \see ZeroMemory
35 //! \see CopyMemory
36 //! \see MoveMemory
37 inline_ void FillMemory(void* dest, udword size, ubyte val) { memset(dest, val, size); }
38
39 //! Fills a buffer with a given dword.
40 //! \param addr [in] buffer address
41 //! \param nb [in] number of dwords to write
42 //! \param value [in] the dword value
43 //! \see FillMemory
44 //! \see ZeroMemory
45 //! \see CopyMemory
46 //! \see MoveMemory
47 //! \warning writes nb*4 bytes !
48 inline_ void StoreDwords(udword* dest, udword nb, udword value)
49 {
50 // The asm code below **SHOULD** be equivalent to one of those C versions
51 // or the other if your compiled is good: (checked on VC++ 6.0)
52 //
53 // 1) while(nb--) *dest++ = value;
54 //
55 // 2) for(udword i=0;i<nb;i++) dest[i] = value;
56 //
57#ifdef _MSC_VER
58 _asm push eax
59 _asm push ecx
60 _asm push edi
61 _asm mov edi, dest
62 _asm mov ecx, nb
63 _asm mov eax, value
64 _asm rep stosd
65 _asm pop edi
66 _asm pop ecx
67 _asm pop eax
68#else
69 while(nb--) *dest++ = value;
70#endif
71 }
72
73 //! Copies a buffer.
74 //! \param addr [in] destination buffer address
75 //! \param addr [in] source buffer address
76 //! \param size [in] buffer length
77 //! \see ZeroMemory
78 //! \see FillMemory
79 //! \see StoreDwords
80 //! \see MoveMemory
81 inline_ void CopyMemory(void* dest, const void* src, udword size) { memcpy(dest, src, size); }
82
83 //! Moves a buffer.
84 //! \param addr [in] destination buffer address
85 //! \param addr [in] source buffer address
86 //! \param size [in] buffer length
87 //! \see ZeroMemory
88 //! \see FillMemory
89 //! \see StoreDwords
90 //! \see CopyMemory
91 inline_ void MoveMemory(void* dest, const void* src, udword size) { memmove(dest, src, size); }
92
93 #define SIZEOFOBJECT sizeof(*this) //!< Gives the size of current object. Avoid some mistakes (e.g. "sizeof(this)").
94 //#define CLEAROBJECT { memset(this, 0, SIZEOFOBJECT); } //!< Clears current object. Laziness is my business. HANDLE WITH CARE.
95 #define DELETESINGLE(x) if (x) { delete x; x = null; } //!< Deletes an instance of a class.
96 #define DELETEARRAY(x) if (x) { delete []x; x = null; } //!< Deletes an array.
97 #define SAFE_RELEASE(x) if (x) { (x)->Release(); (x) = null; } //!< Safe D3D-style release
98 #define SAFE_DESTRUCT(x) if (x) { (x)->SelfDestruct(); (x) = null; } //!< Safe ICE-style release
99
100#ifdef __ICEERROR_H__
101 #define CHECKALLOC(x) if(!x) return SetIceError("Out of memory.", EC_OUT_OF_MEMORY); //!< Standard alloc checking. HANDLE WITH CARE.
102#else
103 #define CHECKALLOC(x) if(!x) return false;
104#endif
105
106 //! Standard allocation cycle
107 #define SAFE_ALLOC(ptr, type, count) DELETEARRAY(ptr); ptr = new type[count]; CHECKALLOC(ptr);
108
109#endif // __ICEMEMORYMACROS_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceOBB.cpp b/libraries/ode-0.9/OPCODE/Ice/IceOBB.cpp
new file mode 100644
index 0000000..0b1b6f7
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceOBB.cpp
@@ -0,0 +1,323 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains OBB-related code.
4 * \file IceOBB.cpp
5 * \author Pierre Terdiman
6 * \date January, 29, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11/**
12 * An Oriented Bounding Box (OBB).
13 * \class OBB
14 * \author Pierre Terdiman
15 * \version 1.0
16 */
17///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
18
19///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
20// Precompiled Header
21#include "Stdafx.h"
22
23using namespace IceMaths;
24
25///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
26/**
27 * Tests if a point is contained within the OBB.
28 * \param p [in] the world point to test
29 * \return true if inside the OBB
30 */
31///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
32bool OBB::ContainsPoint(const Point& p) const
33{
34 // Point in OBB test using lazy evaluation and early exits
35
36 // Translate to box space
37 Point RelPoint = p - mCenter;
38
39 // Point * mRot maps from box space to world space
40 // mRot * Point maps from world space to box space (what we need here)
41
42 float f = mRot.m[0][0] * RelPoint.x + mRot.m[0][1] * RelPoint.y + mRot.m[0][2] * RelPoint.z;
43 if(f >= mExtents.x || f <= -mExtents.x) return false;
44
45 f = mRot.m[1][0] * RelPoint.x + mRot.m[1][1] * RelPoint.y + mRot.m[1][2] * RelPoint.z;
46 if(f >= mExtents.y || f <= -mExtents.y) return false;
47
48 f = mRot.m[2][0] * RelPoint.x + mRot.m[2][1] * RelPoint.y + mRot.m[2][2] * RelPoint.z;
49 if(f >= mExtents.z || f <= -mExtents.z) return false;
50 return true;
51}
52
53///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
54/**
55 * Builds an OBB from an AABB and a world transform.
56 * \param aabb [in] the aabb
57 * \param mat [in] the world transform
58 */
59///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
60void OBB::Create(const AABB& aabb, const Matrix4x4& mat)
61{
62 // Note: must be coherent with Rotate()
63
64 aabb.GetCenter(mCenter);
65 aabb.GetExtents(mExtents);
66 // Here we have the same as OBB::Rotate(mat) where the obb is (mCenter, mExtents, Identity).
67
68 // So following what's done in Rotate:
69 // - x-form the center
70 mCenter *= mat;
71 // - combine rotation with identity, i.e. just use given matrix
72 mRot = mat;
73}
74
75///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
76/**
77 * Computes the obb planes.
78 * \param planes [out] 6 box planes
79 * \return true if success
80 */
81///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
82bool OBB::ComputePlanes(Plane* planes) const
83{
84 // Checkings
85 if(!planes) return false;
86
87 Point Axis0 = mRot[0];
88 Point Axis1 = mRot[1];
89 Point Axis2 = mRot[2];
90
91 // Writes normals
92 planes[0].n = Axis0;
93 planes[1].n = -Axis0;
94 planes[2].n = Axis1;
95 planes[3].n = -Axis1;
96 planes[4].n = Axis2;
97 planes[5].n = -Axis2;
98
99 // Compute a point on each plane
100 Point p0 = mCenter + Axis0 * mExtents.x;
101 Point p1 = mCenter - Axis0 * mExtents.x;
102 Point p2 = mCenter + Axis1 * mExtents.y;
103 Point p3 = mCenter - Axis1 * mExtents.y;
104 Point p4 = mCenter + Axis2 * mExtents.z;
105 Point p5 = mCenter - Axis2 * mExtents.z;
106
107 // Compute d
108 planes[0].d = -(planes[0].n|p0);
109 planes[1].d = -(planes[1].n|p1);
110 planes[2].d = -(planes[2].n|p2);
111 planes[3].d = -(planes[3].n|p3);
112 planes[4].d = -(planes[4].n|p4);
113 planes[5].d = -(planes[5].n|p5);
114
115 return true;
116}
117
118///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
119/**
120 * Computes the obb points.
121 * \param pts [out] 8 box points
122 * \return true if success
123 */
124///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
125bool OBB::ComputePoints(Point* pts) const
126{
127 // Checkings
128 if(!pts) return false;
129
130 Point Axis0 = mRot[0];
131 Point Axis1 = mRot[1];
132 Point Axis2 = mRot[2];
133
134 Axis0 *= mExtents.x;
135 Axis1 *= mExtents.y;
136 Axis2 *= mExtents.z;
137
138 // 7+------+6 0 = ---
139 // /| /| 1 = +--
140 // / | / | 2 = ++-
141 // / 4+---/--+5 3 = -+-
142 // 3+------+2 / y z 4 = --+
143 // | / | / | / 5 = +-+
144 // |/ |/ |/ 6 = +++
145 // 0+------+1 *---x 7 = -++
146
147 pts[0] = mCenter - Axis0 - Axis1 - Axis2;
148 pts[1] = mCenter + Axis0 - Axis1 - Axis2;
149 pts[2] = mCenter + Axis0 + Axis1 - Axis2;
150 pts[3] = mCenter - Axis0 + Axis1 - Axis2;
151 pts[4] = mCenter - Axis0 - Axis1 + Axis2;
152 pts[5] = mCenter + Axis0 - Axis1 + Axis2;
153 pts[6] = mCenter + Axis0 + Axis1 + Axis2;
154 pts[7] = mCenter - Axis0 + Axis1 + Axis2;
155
156 return true;
157}
158
159///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
160/**
161 * Computes vertex normals.
162 * \param pts [out] 8 box points
163 * \return true if success
164 */
165///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
166bool OBB::ComputeVertexNormals(Point* pts) const
167{
168 static float VertexNormals[] =
169 {
170 -INVSQRT3, -INVSQRT3, -INVSQRT3,
171 INVSQRT3, -INVSQRT3, -INVSQRT3,
172 INVSQRT3, INVSQRT3, -INVSQRT3,
173 -INVSQRT3, INVSQRT3, -INVSQRT3,
174 -INVSQRT3, -INVSQRT3, INVSQRT3,
175 INVSQRT3, -INVSQRT3, INVSQRT3,
176 INVSQRT3, INVSQRT3, INVSQRT3,
177 -INVSQRT3, INVSQRT3, INVSQRT3
178 };
179
180 if(!pts) return false;
181
182 const Point* VN = (const Point*)VertexNormals;
183 for(udword i=0;i<8;i++)
184 {
185 pts[i] = VN[i] * mRot;
186 }
187
188 return true;
189}
190
191///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
192/**
193 * Returns edges.
194 * \return 24 indices (12 edges) indexing the list returned by ComputePoints()
195 */
196///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
197const udword* OBB::GetEdges() const
198{
199 static udword Indices[] = {
200 0, 1, 1, 2, 2, 3, 3, 0,
201 7, 6, 6, 5, 5, 4, 4, 7,
202 1, 5, 6, 2,
203 3, 7, 4, 0
204 };
205 return Indices;
206}
207
208///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
209/**
210 * Returns local edge normals.
211 * \return edge normals in local space
212 */
213///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
214const Point* OBB::GetLocalEdgeNormals() const
215{
216 static float EdgeNormals[] =
217 {
218 0, -INVSQRT2, -INVSQRT2, // 0-1
219 INVSQRT2, 0, -INVSQRT2, // 1-2
220 0, INVSQRT2, -INVSQRT2, // 2-3
221 -INVSQRT2, 0, -INVSQRT2, // 3-0
222
223 0, INVSQRT2, INVSQRT2, // 7-6
224 INVSQRT2, 0, INVSQRT2, // 6-5
225 0, -INVSQRT2, INVSQRT2, // 5-4
226 -INVSQRT2, 0, INVSQRT2, // 4-7
227
228 INVSQRT2, -INVSQRT2, 0, // 1-5
229 INVSQRT2, INVSQRT2, 0, // 6-2
230 -INVSQRT2, INVSQRT2, 0, // 3-7
231 -INVSQRT2, -INVSQRT2, 0 // 4-0
232 };
233 return (const Point*)EdgeNormals;
234}
235
236///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
237/**
238 * Returns world edge normal
239 * \param edge_index [in] 0 <= edge index < 12
240 * \param world_normal [out] edge normal in world space
241 */
242///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
243void OBB::ComputeWorldEdgeNormal(udword edge_index, Point& world_normal) const
244{
245 ASSERT(edge_index<12);
246 world_normal = GetLocalEdgeNormals()[edge_index] * mRot;
247}
248
249///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
250/**
251 * Computes an LSS surrounding the OBB.
252 * \param lss [out] the LSS
253 */
254///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
255void OBB::ComputeLSS(LSS& lss) const
256{
257 Point Axis0 = mRot[0];
258 Point Axis1 = mRot[1];
259 Point Axis2 = mRot[2];
260
261 switch(mExtents.LargestAxis())
262 {
263 case 0:
264 lss.mRadius = (mExtents.y + mExtents.z)*0.5f;
265 lss.mP0 = mCenter + Axis0 * (mExtents.x - lss.mRadius);
266 lss.mP1 = mCenter - Axis0 * (mExtents.x - lss.mRadius);
267 break;
268 case 1:
269 lss.mRadius = (mExtents.x + mExtents.z)*0.5f;
270 lss.mP0 = mCenter + Axis1 * (mExtents.y - lss.mRadius);
271 lss.mP1 = mCenter - Axis1 * (mExtents.y - lss.mRadius);
272 break;
273 case 2:
274 lss.mRadius = (mExtents.x + mExtents.y)*0.5f;
275 lss.mP0 = mCenter + Axis2 * (mExtents.z - lss.mRadius);
276 lss.mP1 = mCenter - Axis2 * (mExtents.z - lss.mRadius);
277 break;
278 }
279}
280
281///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
282/**
283 * Checks the OBB is inside another OBB.
284 * \param box [in] the other OBB
285 * \return TRUE if we're inside the other box
286 */
287///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
288BOOL OBB::IsInside(const OBB& box) const
289{
290 // Make a 4x4 from the box & inverse it
291 Matrix4x4 M0Inv;
292 {
293 Matrix4x4 M0 = box.mRot;
294 M0.SetTrans(box.mCenter);
295 InvertPRMatrix(M0Inv, M0);
296 }
297
298 // With our inversed 4x4, create box1 in space of box0
299 OBB _1in0;
300 Rotate(M0Inv, _1in0);
301
302 // This should cancel out box0's rotation, i.e. it's now an AABB.
303 // => Center(0,0,0), Rot(identity)
304
305 // The two boxes are in the same space so now we can compare them.
306
307 // Create the AABB of (box1 in space of box0)
308 const Matrix3x3& mtx = _1in0.mRot;
309
310 float f = fabsf(mtx.m[0][0] * mExtents.x) + fabsf(mtx.m[1][0] * mExtents.y) + fabsf(mtx.m[2][0] * mExtents.z) - box.mExtents.x;
311 if(f > _1in0.mCenter.x) return FALSE;
312 if(-f < _1in0.mCenter.x) return FALSE;
313
314 f = fabsf(mtx.m[0][1] * mExtents.x) + fabsf(mtx.m[1][1] * mExtents.y) + fabsf(mtx.m[2][1] * mExtents.z) - box.mExtents.y;
315 if(f > _1in0.mCenter.y) return FALSE;
316 if(-f < _1in0.mCenter.y) return FALSE;
317
318 f = fabsf(mtx.m[0][2] * mExtents.x) + fabsf(mtx.m[1][2] * mExtents.y) + fabsf(mtx.m[2][2] * mExtents.z) - box.mExtents.z;
319 if(f > _1in0.mCenter.z) return FALSE;
320 if(-f < _1in0.mCenter.z) return FALSE;
321
322 return TRUE;
323}
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceOBB.h b/libraries/ode-0.9/OPCODE/Ice/IceOBB.h
new file mode 100644
index 0000000..d6cf43e
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceOBB.h
@@ -0,0 +1,177 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains OBB-related code. (oriented bounding box)
4 * \file IceOBB.h
5 * \author Pierre Terdiman
6 * \date January, 13, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICEOBB_H__
13#define __ICEOBB_H__
14
15 // Forward declarations
16 class LSS;
17
18 class ICEMATHS_API OBB
19 {
20 public:
21 //! Constructor
22 inline_ OBB() {}
23 //! Constructor
24 inline_ OBB(const Point& center, const Point& extents, const Matrix3x3& rot) : mCenter(center), mExtents(extents), mRot(rot) {}
25 //! Destructor
26 inline_ ~OBB() {}
27
28 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
29 /**
30 * Setups an empty OBB.
31 */
32 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
33 void SetEmpty()
34 {
35 mCenter.Zero();
36 mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);
37 mRot.Identity();
38 }
39
40 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
41 /**
42 * Tests if a point is contained within the OBB.
43 * \param p [in] the world point to test
44 * \return true if inside the OBB
45 */
46 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
47 bool ContainsPoint(const Point& p) const;
48
49 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
50 /**
51 * Builds an OBB from an AABB and a world transform.
52 * \param aabb [in] the aabb
53 * \param mat [in] the world transform
54 */
55 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
56 void Create(const AABB& aabb, const Matrix4x4& mat);
57
58 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
59 /**
60 * Recomputes the OBB after an arbitrary transform by a 4x4 matrix.
61 * \param mtx [in] the transform matrix
62 * \param obb [out] the transformed OBB
63 */
64 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
65 inline_ void Rotate(const Matrix4x4& mtx, OBB& obb) const
66 {
67 // The extents remain constant
68 obb.mExtents = mExtents;
69 // The center gets x-formed
70 obb.mCenter = mCenter * mtx;
71 // Combine rotations
72 obb.mRot = mRot * Matrix3x3(mtx);
73 }
74
75 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
76 /**
77 * Checks the OBB is valid.
78 * \return true if the box is valid
79 */
80 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
81 inline_ BOOL IsValid() const
82 {
83 // Consistency condition for (Center, Extents) boxes: Extents >= 0.0f
84 if(mExtents.x < 0.0f) return FALSE;
85 if(mExtents.y < 0.0f) return FALSE;
86 if(mExtents.z < 0.0f) return FALSE;
87 return TRUE;
88 }
89
90 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
91 /**
92 * Computes the obb planes.
93 * \param planes [out] 6 box planes
94 * \return true if success
95 */
96 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
97 bool ComputePlanes(Plane* planes) const;
98
99 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
100 /**
101 * Computes the obb points.
102 * \param pts [out] 8 box points
103 * \return true if success
104 */
105 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
106 bool ComputePoints(Point* pts) const;
107
108 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
109 /**
110 * Computes vertex normals.
111 * \param pts [out] 8 box points
112 * \return true if success
113 */
114 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
115 bool ComputeVertexNormals(Point* pts) const;
116
117 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
118 /**
119 * Returns edges.
120 * \return 24 indices (12 edges) indexing the list returned by ComputePoints()
121 */
122 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
123 const udword* GetEdges() const;
124
125 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
126 /**
127 * Returns local edge normals.
128 * \return edge normals in local space
129 */
130 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
131 const Point* GetLocalEdgeNormals() const;
132
133 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
134 /**
135 * Returns world edge normal
136 * \param edge_index [in] 0 <= edge index < 12
137 * \param world_normal [out] edge normal in world space
138 */
139 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
140 void ComputeWorldEdgeNormal(udword edge_index, Point& world_normal) const;
141
142 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
143 /**
144 * Computes an LSS surrounding the OBB.
145 * \param lss [out] the LSS
146 */
147 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
148 void ComputeLSS(LSS& lss) const;
149
150 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
151 /**
152 * Checks the OBB is inside another OBB.
153 * \param box [in] the other OBB
154 * \return TRUE if we're inside the other box
155 */
156 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
157 BOOL IsInside(const OBB& box) const;
158
159 inline_ const Point& GetCenter() const { return mCenter; }
160 inline_ const Point& GetExtents() const { return mExtents; }
161 inline_ const Matrix3x3& GetRot() const { return mRot; }
162
163 inline_ void GetRotatedExtents(Matrix3x3& extents) const
164 {
165 extents = mRot;
166 extents.Scale(mExtents);
167 }
168
169 Point mCenter; //!< B for Box
170 Point mExtents; //!< B for Bounding
171 Matrix3x3 mRot; //!< O for Oriented
172
173 // Orientation is stored in row-major format,
174 // i.e. rows = eigen vectors of the covariance matrix
175 };
176
177#endif // __ICEOBB_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IcePairs.h b/libraries/ode-0.9/OPCODE/Ice/IcePairs.h
new file mode 100644
index 0000000..2c09b92
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IcePairs.h
@@ -0,0 +1,45 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains a simple pair class.
4 * \file IcePairs.h
5 * \author Pierre Terdiman
6 * \date January, 13, 2003
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICEPAIRS_H__
13#define __ICEPAIRS_H__
14
15 //! A generic couple structure
16 struct ICECORE_API Pair
17 {
18 inline_ Pair() {}
19 inline_ Pair(udword i0, udword i1) : id0(i0), id1(i1) {}
20
21 udword id0; //!< First index of the pair
22 udword id1; //!< Second index of the pair
23 };
24
25 class ICECORE_API Pairs : private Container
26 {
27 public:
28 // Constructor / Destructor
29 Pairs() {}
30 ~Pairs() {}
31
32 inline_ udword GetNbPairs() const { return GetNbEntries()>>1; }
33 inline_ const Pair* GetPairs() const { return (const Pair*)GetEntries(); }
34 inline_ const Pair* GetPair(udword i) const { return (const Pair*)&GetEntries()[i+i]; }
35
36 inline_ BOOL HasPairs() const { return IsNotEmpty(); }
37
38 inline_ void ResetPairs() { Reset(); }
39 inline_ void DeleteLastPair() { DeleteLastEntry(); DeleteLastEntry(); }
40
41 inline_ void AddPair(const Pair& p) { Add(p.id0).Add(p.id1); }
42 inline_ void AddPair(udword id0, udword id1) { Add(id0).Add(id1); }
43 };
44
45#endif // __ICEPAIRS_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IcePlane.cpp b/libraries/ode-0.9/OPCODE/Ice/IcePlane.cpp
new file mode 100644
index 0000000..394b31b
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IcePlane.cpp
@@ -0,0 +1,45 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code for planes.
4 * \file IcePlane.cpp
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11/**
12 * Plane class.
13 * \class Plane
14 * \author Pierre Terdiman
15 * \version 1.0
16 */
17///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
18
19///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
20// Precompiled Header
21#include "Stdafx.h"
22
23using namespace IceMaths;
24
25///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
26/**
27 * Computes the plane equation from 3 points.
28 * \param p0 [in] first point
29 * \param p1 [in] second point
30 * \param p2 [in] third point
31 * \return Self-reference
32 */
33///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
34Plane& Plane::Set(const Point& p0, const Point& p1, const Point& p2)
35{
36 Point Edge0 = p1 - p0;
37 Point Edge1 = p2 - p0;
38
39 n = Edge0 ^ Edge1;
40 n.Normalize();
41
42 d = -(p0 | n);
43
44 return *this;
45}
diff --git a/libraries/ode-0.9/OPCODE/Ice/IcePlane.h b/libraries/ode-0.9/OPCODE/Ice/IcePlane.h
new file mode 100644
index 0000000..4d47081
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IcePlane.h
@@ -0,0 +1,113 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code for planes.
4 * \file IcePlane.h
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICEPLANE_H__
13#define __ICEPLANE_H__
14
15 #define PLANE_EPSILON (1.0e-7f)
16
17 class ICEMATHS_API Plane
18 {
19 public:
20 //! Constructor
21 inline_ Plane() { }
22 //! Constructor from a normal and a distance
23 inline_ Plane(float nx, float ny, float nz, float d) { Set(nx, ny, nz, d); }
24 //! Constructor from a point on the plane and a normal
25 inline_ Plane(const Point& p, const Point& n) { Set(p, n); }
26 //! Constructor from three points
27 inline_ Plane(const Point& p0, const Point& p1, const Point& p2) { Set(p0, p1, p2); }
28 //! Constructor from a normal and a distance
29 inline_ Plane(const Point& _n, float _d) { n = _n; d = _d; }
30 //! Copy constructor
31 inline_ Plane(const Plane& plane) : n(plane.n), d(plane.d) { }
32 //! Destructor
33 inline_ ~Plane() { }
34
35 inline_ Plane& Zero() { n.Zero(); d = 0.0f; return *this; }
36 inline_ Plane& Set(float nx, float ny, float nz, float _d) { n.Set(nx, ny, nz); d = _d; return *this; }
37 inline_ Plane& Set(const Point& p, const Point& _n) { n = _n; d = - p | _n; return *this; }
38 Plane& Set(const Point& p0, const Point& p1, const Point& p2);
39
40 inline_ float Distance(const Point& p) const { return (p | n) + d; }
41 inline_ bool Belongs(const Point& p) const { return fabsf(Distance(p)) < PLANE_EPSILON; }
42
43 inline_ void Normalize()
44 {
45 float Denom = 1.0f / n.Magnitude();
46 n.x *= Denom;
47 n.y *= Denom;
48 n.z *= Denom;
49 d *= Denom;
50 }
51 public:
52 // Members
53 Point n; //!< The normal to the plane
54 float d; //!< The distance from the origin
55
56 // Cast operators
57 inline_ operator Point() const { return n; }
58 inline_ operator HPoint() const { return HPoint(n, d); }
59
60 // Arithmetic operators
61 inline_ Plane operator*(const Matrix4x4& m) const
62 {
63 // Old code from Irion. Kept for reference.
64 Plane Ret(*this);
65 return Ret *= m;
66 }
67
68 inline_ Plane& operator*=(const Matrix4x4& m)
69 {
70 // Old code from Irion. Kept for reference.
71 Point n2 = HPoint(n, 0.0f) * m;
72 d = -((Point) (HPoint( -d*n, 1.0f ) * m) | n2);
73 n = n2;
74 return *this;
75 }
76 };
77
78 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
79 /**
80 * Transforms a plane by a 4x4 matrix. Same as Plane * Matrix4x4 operator, but faster.
81 * \param transformed [out] transformed plane
82 * \param plane [in] source plane
83 * \param transform [in] transform matrix
84 * \warning the plane normal must be unit-length
85 */
86 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
87 inline_ void TransformPlane(Plane& transformed, const Plane& plane, const Matrix4x4& transform)
88 {
89 // Rotate the normal using the rotation part of the 4x4 matrix
90 transformed.n = plane.n * Matrix3x3(transform);
91
92 // Compute new d
93 transformed.d = plane.d - (Point(transform.GetTrans())|transformed.n);
94 }
95
96 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
97 /**
98 * Transforms a plane by a 4x4 matrix. Same as Plane * Matrix4x4 operator, but faster.
99 * \param plane [in/out] source plane (transformed on return)
100 * \param transform [in] transform matrix
101 * \warning the plane normal must be unit-length
102 */
103 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
104 inline_ void TransformPlane(Plane& plane, const Matrix4x4& transform)
105 {
106 // Rotate the normal using the rotation part of the 4x4 matrix
107 plane.n *= Matrix3x3(transform);
108
109 // Compute new d
110 plane.d -= Point(transform.GetTrans())|plane.n;
111 }
112
113#endif // __ICEPLANE_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IcePoint.cpp b/libraries/ode-0.9/OPCODE/Ice/IcePoint.cpp
new file mode 100644
index 0000000..e715055
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IcePoint.cpp
@@ -0,0 +1,193 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code for 3D vectors.
4 * \file IcePoint.cpp
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11/**
12 * 3D point.
13 *
14 * The name is "Point" instead of "Vector" since a vector is N-dimensional, whereas a point is an implicit "vector of dimension 3".
15 * So the choice was between "Point" and "Vector3", the first one looked better (IMHO).
16 *
17 * Some people, then, use a typedef to handle both points & vectors using the same class: typedef Point Vector3;
18 * This is bad since it opens the door to a lot of confusion while reading the code. I know it may sounds weird but check this out:
19 *
20 * \code
21 * Point P0,P1 = some 3D points;
22 * Point Delta = P1 - P0;
23 * \endcode
24 *
25 * This compiles fine, although you should have written:
26 *
27 * \code
28 * Point P0,P1 = some 3D points;
29 * Vector3 Delta = P1 - P0;
30 * \endcode
31 *
32 * Subtle things like this are not caught at compile-time, and when you find one in the code, you never know whether it's a mistake
33 * from the author or something you don't get.
34 *
35 * One way to handle it at compile-time would be to use different classes for Point & Vector3, only overloading operator "-" for vectors.
36 * But then, you get a lot of redundant code in thoses classes, and basically it's really a lot of useless work.
37 *
38 * Another way would be to use homogeneous points: w=1 for points, w=0 for vectors. That's why the HPoint class exists. Now, to store
39 * your model's vertices and in most cases, you really want to use Points to save ram.
40 *
41 * \class Point
42 * \author Pierre Terdiman
43 * \version 1.0
44 */
45///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
46
47///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
48// Precompiled Header
49#include "Stdafx.h"
50
51using namespace IceMaths;
52
53///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
54/**
55 * Creates a positive unit random vector.
56 * \return Self-reference
57 */
58///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
59Point& Point::PositiveUnitRandomVector()
60{
61 x = UnitRandomFloat();
62 y = UnitRandomFloat();
63 z = UnitRandomFloat();
64 Normalize();
65 return *this;
66}
67
68///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
69/**
70 * Creates a unit random vector.
71 * \return Self-reference
72 */
73///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
74Point& Point::UnitRandomVector()
75{
76 x = UnitRandomFloat() - 0.5f;
77 y = UnitRandomFloat() - 0.5f;
78 z = UnitRandomFloat() - 0.5f;
79 Normalize();
80 return *this;
81}
82
83// Cast operator
84// WARNING: not inlined
85Point::operator HPoint() const { return HPoint(x, y, z, 0.0f); }
86
87Point& Point::Refract(const Point& eye, const Point& n, float refractindex, Point& refracted)
88{
89 // Point EyePt = eye position
90 // Point p = current vertex
91 // Point n = vertex normal
92 // Point rv = refracted vector
93 // Eye vector - doesn't need to be normalized
94 Point Env;
95 Env.x = eye.x - x;
96 Env.y = eye.y - y;
97 Env.z = eye.z - z;
98
99 float NDotE = n|Env;
100 float NDotN = n|n;
101 NDotE /= refractindex;
102
103 // Refracted vector
104 refracted = n*NDotE - Env*NDotN;
105
106 return *this;
107}
108
109Point& Point::ProjectToPlane(const Plane& p)
110{
111 *this-= (p.d + (*this|p.n))*p.n;
112 return *this;
113}
114
115void Point::ProjectToScreen(float halfrenderwidth, float halfrenderheight, const Matrix4x4& mat, HPoint& projected) const
116{
117 projected = HPoint(x, y, z, 1.0f) * mat;
118 projected.w = 1.0f / projected.w;
119
120 projected.x*=projected.w;
121 projected.y*=projected.w;
122 projected.z*=projected.w;
123
124 projected.x *= halfrenderwidth; projected.x += halfrenderwidth;
125 projected.y *= -halfrenderheight; projected.y += halfrenderheight;
126}
127
128void Point::SetNotUsed()
129{
130 // We use a particular integer pattern : 0xffffffff everywhere. This is a NAN.
131 IR(x) = 0xffffffff;
132 IR(y) = 0xffffffff;
133 IR(z) = 0xffffffff;
134}
135
136BOOL Point::IsNotUsed() const
137{
138 if(IR(x)!=0xffffffff) return FALSE;
139 if(IR(y)!=0xffffffff) return FALSE;
140 if(IR(z)!=0xffffffff) return FALSE;
141 return TRUE;
142}
143
144Point& Point::Mult(const Matrix3x3& mat, const Point& a)
145{
146 x = a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2];
147 y = a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2];
148 z = a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2];
149 return *this;
150}
151
152Point& Point::Mult2(const Matrix3x3& mat1, const Point& a1, const Matrix3x3& mat2, const Point& a2)
153{
154 x = a1.x * mat1.m[0][0] + a1.y * mat1.m[0][1] + a1.z * mat1.m[0][2] + a2.x * mat2.m[0][0] + a2.y * mat2.m[0][1] + a2.z * mat2.m[0][2];
155 y = a1.x * mat1.m[1][0] + a1.y * mat1.m[1][1] + a1.z * mat1.m[1][2] + a2.x * mat2.m[1][0] + a2.y * mat2.m[1][1] + a2.z * mat2.m[1][2];
156 z = a1.x * mat1.m[2][0] + a1.y * mat1.m[2][1] + a1.z * mat1.m[2][2] + a2.x * mat2.m[2][0] + a2.y * mat2.m[2][1] + a2.z * mat2.m[2][2];
157 return *this;
158}
159
160Point& Point::Mac(const Matrix3x3& mat, const Point& a)
161{
162 x += a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2];
163 y += a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2];
164 z += a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2];
165 return *this;
166}
167
168Point& Point::TransMult(const Matrix3x3& mat, const Point& a)
169{
170 x = a.x * mat.m[0][0] + a.y * mat.m[1][0] + a.z * mat.m[2][0];
171 y = a.x * mat.m[0][1] + a.y * mat.m[1][1] + a.z * mat.m[2][1];
172 z = a.x * mat.m[0][2] + a.y * mat.m[1][2] + a.z * mat.m[2][2];
173 return *this;
174}
175
176Point& Point::Transform(const Point& r, const Matrix3x3& rotpos, const Point& linpos)
177{
178 x = r.x * rotpos.m[0][0] + r.y * rotpos.m[0][1] + r.z * rotpos.m[0][2] + linpos.x;
179 y = r.x * rotpos.m[1][0] + r.y * rotpos.m[1][1] + r.z * rotpos.m[1][2] + linpos.y;
180 z = r.x * rotpos.m[2][0] + r.y * rotpos.m[2][1] + r.z * rotpos.m[2][2] + linpos.z;
181 return *this;
182}
183
184Point& Point::InvTransform(const Point& r, const Matrix3x3& rotpos, const Point& linpos)
185{
186 float sx = r.x - linpos.x;
187 float sy = r.y - linpos.y;
188 float sz = r.z - linpos.z;
189 x = sx * rotpos.m[0][0] + sy * rotpos.m[1][0] + sz * rotpos.m[2][0];
190 y = sx * rotpos.m[0][1] + sy * rotpos.m[1][1] + sz * rotpos.m[2][1];
191 z = sx * rotpos.m[0][2] + sy * rotpos.m[1][2] + sz * rotpos.m[2][2];
192 return *this;
193}
diff --git a/libraries/ode-0.9/OPCODE/Ice/IcePoint.h b/libraries/ode-0.9/OPCODE/Ice/IcePoint.h
new file mode 100644
index 0000000..a97fbe6
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IcePoint.h
@@ -0,0 +1,528 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code for 3D vectors.
4 * \file IcePoint.h
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICEPOINT_H__
13#define __ICEPOINT_H__
14
15 // Forward declarations
16 class HPoint;
17 class Plane;
18 class Matrix3x3;
19 class Matrix4x4;
20
21 #define CROSS2D(a, b) (a.x*b.y - b.x*a.y)
22
23 const float EPSILON2 = 1.0e-20f;
24
25 class ICEMATHS_API Point
26 {
27 public:
28
29 //! Empty constructor
30 inline_ Point() {}
31 //! Constructor from a single float
32// inline_ Point(float val) : x(val), y(val), z(val) {}
33// Removed since it introduced the nasty "Point T = *Matrix4x4.GetTrans();" bug.......
34 //! Constructor from floats
35 inline_ Point(float xx, float yy, float zz) : x(xx), y(yy), z(zz) {}
36 //! Constructor from array
37 inline_ Point(const float f[3]) : x(f[X]), y(f[Y]), z(f[Z]) {}
38 //! Copy constructor
39 inline_ Point(const Point& p) : x(p.x), y(p.y), z(p.z) {}
40 //! Destructor
41 inline_ ~Point() {}
42
43 //! Clears the vector
44 inline_ Point& Zero() { x = y = z = 0.0f; return *this; }
45
46 //! + infinity
47 inline_ Point& SetPlusInfinity() { x = y = z = MAX_FLOAT; return *this; }
48 //! - infinity
49 inline_ Point& SetMinusInfinity() { x = y = z = MIN_FLOAT; return *this; }
50
51 //! Sets positive unit random vector
52 Point& PositiveUnitRandomVector();
53 //! Sets unit random vector
54 Point& UnitRandomVector();
55
56 //! Assignment from values
57 inline_ Point& Set(float xx, float yy, float zz) { x = xx; y = yy; z = zz; return *this; }
58 //! Assignment from array
59 inline_ Point& Set(const float f[3]) { x = f[X]; y = f[Y]; z = f[Z]; return *this; }
60 //! Assignment from another point
61 inline_ Point& Set(const Point& src) { x = src.x; y = src.y; z = src.z; return *this; }
62
63 //! Adds a vector
64 inline_ Point& Add(const Point& p) { x += p.x; y += p.y; z += p.z; return *this; }
65 //! Adds a vector
66 inline_ Point& Add(float xx, float yy, float zz) { x += xx; y += yy; z += zz; return *this; }
67 //! Adds a vector
68 inline_ Point& Add(const float f[3]) { x += f[X]; y += f[Y]; z += f[Z]; return *this; }
69 //! Adds vectors
70 inline_ Point& Add(const Point& p, const Point& q) { x = p.x+q.x; y = p.y+q.y; z = p.z+q.z; return *this; }
71
72 //! Subtracts a vector
73 inline_ Point& Sub(const Point& p) { x -= p.x; y -= p.y; z -= p.z; return *this; }
74 //! Subtracts a vector
75 inline_ Point& Sub(float xx, float yy, float zz) { x -= xx; y -= yy; z -= zz; return *this; }
76 //! Subtracts a vector
77 inline_ Point& Sub(const float f[3]) { x -= f[X]; y -= f[Y]; z -= f[Z]; return *this; }
78 //! Subtracts vectors
79 inline_ Point& Sub(const Point& p, const Point& q) { x = p.x-q.x; y = p.y-q.y; z = p.z-q.z; return *this; }
80
81 //! this = -this
82 inline_ Point& Neg() { x = -x; y = -y; z = -z; return *this; }
83 //! this = -a
84 inline_ Point& Neg(const Point& a) { x = -a.x; y = -a.y; z = -a.z; return *this; }
85
86 //! Multiplies by a scalar
87 inline_ Point& Mult(float s) { x *= s; y *= s; z *= s; return *this; }
88
89 //! this = a * scalar
90 inline_ Point& Mult(const Point& a, float scalar)
91 {
92 x = a.x * scalar;
93 y = a.y * scalar;
94 z = a.z * scalar;
95 return *this;
96 }
97
98 //! this = a + b * scalar
99 inline_ Point& Mac(const Point& a, const Point& b, float scalar)
100 {
101 x = a.x + b.x * scalar;
102 y = a.y + b.y * scalar;
103 z = a.z + b.z * scalar;
104 return *this;
105 }
106
107 //! this = this + a * scalar
108 inline_ Point& Mac(const Point& a, float scalar)
109 {
110 x += a.x * scalar;
111 y += a.y * scalar;
112 z += a.z * scalar;
113 return *this;
114 }
115
116 //! this = a - b * scalar
117 inline_ Point& Msc(const Point& a, const Point& b, float scalar)
118 {
119 x = a.x - b.x * scalar;
120 y = a.y - b.y * scalar;
121 z = a.z - b.z * scalar;
122 return *this;
123 }
124
125 //! this = this - a * scalar
126 inline_ Point& Msc(const Point& a, float scalar)
127 {
128 x -= a.x * scalar;
129 y -= a.y * scalar;
130 z -= a.z * scalar;
131 return *this;
132 }
133
134 //! this = a + b * scalarb + c * scalarc
135 inline_ Point& Mac2(const Point& a, const Point& b, float scalarb, const Point& c, float scalarc)
136 {
137 x = a.x + b.x * scalarb + c.x * scalarc;
138 y = a.y + b.y * scalarb + c.y * scalarc;
139 z = a.z + b.z * scalarb + c.z * scalarc;
140 return *this;
141 }
142
143 //! this = a - b * scalarb - c * scalarc
144 inline_ Point& Msc2(const Point& a, const Point& b, float scalarb, const Point& c, float scalarc)
145 {
146 x = a.x - b.x * scalarb - c.x * scalarc;
147 y = a.y - b.y * scalarb - c.y * scalarc;
148 z = a.z - b.z * scalarb - c.z * scalarc;
149 return *this;
150 }
151
152 //! this = mat * a
153 inline_ Point& Mult(const Matrix3x3& mat, const Point& a);
154
155 //! this = mat1 * a1 + mat2 * a2
156 inline_ Point& Mult2(const Matrix3x3& mat1, const Point& a1, const Matrix3x3& mat2, const Point& a2);
157
158 //! this = this + mat * a
159 inline_ Point& Mac(const Matrix3x3& mat, const Point& a);
160
161 //! this = transpose(mat) * a
162 inline_ Point& TransMult(const Matrix3x3& mat, const Point& a);
163
164 //! Linear interpolate between two vectors: this = a + t * (b - a)
165 inline_ Point& Lerp(const Point& a, const Point& b, float t)
166 {
167 x = a.x + t * (b.x - a.x);
168 y = a.y + t * (b.y - a.y);
169 z = a.z + t * (b.z - a.z);
170 return *this;
171 }
172
173 //! Hermite interpolate between p1 and p2. p0 and p3 are used for finding gradient at p1 and p2.
174 //! this = p0 * (2t^2 - t^3 - t)/2
175 //! + p1 * (3t^3 - 5t^2 + 2)/2
176 //! + p2 * (4t^2 - 3t^3 + t)/2
177 //! + p3 * (t^3 - t^2)/2
178 inline_ Point& Herp(const Point& p0, const Point& p1, const Point& p2, const Point& p3, float t)
179 {
180 float t2 = t * t;
181 float t3 = t2 * t;
182 float kp0 = (2.0f * t2 - t3 - t) * 0.5f;
183 float kp1 = (3.0f * t3 - 5.0f * t2 + 2.0f) * 0.5f;
184 float kp2 = (4.0f * t2 - 3.0f * t3 + t) * 0.5f;
185 float kp3 = (t3 - t2) * 0.5f;
186 x = p0.x * kp0 + p1.x * kp1 + p2.x * kp2 + p3.x * kp3;
187 y = p0.y * kp0 + p1.y * kp1 + p2.y * kp2 + p3.y * kp3;
188 z = p0.z * kp0 + p1.z * kp1 + p2.z * kp2 + p3.z * kp3;
189 return *this;
190 }
191
192 //! this = rotpos * r + linpos
193 inline_ Point& Transform(const Point& r, const Matrix3x3& rotpos, const Point& linpos);
194
195 //! this = trans(rotpos) * (r - linpos)
196 inline_ Point& InvTransform(const Point& r, const Matrix3x3& rotpos, const Point& linpos);
197
198 //! Returns MIN(x, y, z);
199 inline_ float Min() const { return MIN(x, MIN(y, z)); }
200 //! Returns MAX(x, y, z);
201 inline_ float Max() const { return MAX(x, MAX(y, z)); }
202 //! Sets each element to be componentwise minimum
203 inline_ Point& Min(const Point& p) { x = MIN(x, p.x); y = MIN(y, p.y); z = MIN(z, p.z); return *this; }
204 //! Sets each element to be componentwise maximum
205 inline_ Point& Max(const Point& p) { x = MAX(x, p.x); y = MAX(y, p.y); z = MAX(z, p.z); return *this; }
206
207 //! Clamps each element
208 inline_ Point& Clamp(float min, float max)
209 {
210 if(x<min) x=min; if(x>max) x=max;
211 if(y<min) y=min; if(y>max) y=max;
212 if(z<min) z=min; if(z>max) z=max;
213 return *this;
214 }
215
216 //! Computes square magnitude
217 inline_ float SquareMagnitude() const { return x*x + y*y + z*z; }
218 //! Computes magnitude
219 inline_ float Magnitude() const { return sqrtf(x*x + y*y + z*z); }
220 //! Computes volume
221 inline_ float Volume() const { return x * y * z; }
222
223 //! Checks the point is near zero
224 inline_ bool ApproxZero() const { return SquareMagnitude() < EPSILON2; }
225
226 //! Tests for exact zero vector
227 inline_ BOOL IsZero() const
228 {
229 if(IR(x) || IR(y) || IR(z)) return FALSE;
230 return TRUE;
231 }
232
233 //! Checks point validity
234 inline_ BOOL IsValid() const
235 {
236 if(!IsValidFloat(x)) return FALSE;
237 if(!IsValidFloat(y)) return FALSE;
238 if(!IsValidFloat(z)) return FALSE;
239 return TRUE;
240 }
241
242 //! Slighty moves the point
243 void Tweak(udword coord_mask, udword tweak_mask)
244 {
245 if(coord_mask&1) { udword Dummy = IR(x); Dummy^=tweak_mask; x = FR(Dummy); }
246 if(coord_mask&2) { udword Dummy = IR(y); Dummy^=tweak_mask; y = FR(Dummy); }
247 if(coord_mask&4) { udword Dummy = IR(z); Dummy^=tweak_mask; z = FR(Dummy); }
248 }
249
250 #define TWEAKMASK 0x3fffff
251 #define TWEAKNOTMASK ~TWEAKMASK
252 //! Slighty moves the point out
253 inline_ void TweakBigger()
254 {
255 udword Dummy = (IR(x)&TWEAKNOTMASK); if(!IS_NEGATIVE_FLOAT(x)) Dummy+=TWEAKMASK+1; x = FR(Dummy);
256 Dummy = (IR(y)&TWEAKNOTMASK); if(!IS_NEGATIVE_FLOAT(y)) Dummy+=TWEAKMASK+1; y = FR(Dummy);
257 Dummy = (IR(z)&TWEAKNOTMASK); if(!IS_NEGATIVE_FLOAT(z)) Dummy+=TWEAKMASK+1; z = FR(Dummy);
258 }
259
260 //! Slighty moves the point in
261 inline_ void TweakSmaller()
262 {
263 udword Dummy = (IR(x)&TWEAKNOTMASK); if(IS_NEGATIVE_FLOAT(x)) Dummy+=TWEAKMASK+1; x = FR(Dummy);
264 Dummy = (IR(y)&TWEAKNOTMASK); if(IS_NEGATIVE_FLOAT(y)) Dummy+=TWEAKMASK+1; y = FR(Dummy);
265 Dummy = (IR(z)&TWEAKNOTMASK); if(IS_NEGATIVE_FLOAT(z)) Dummy+=TWEAKMASK+1; z = FR(Dummy);
266 }
267
268 //! Normalizes the vector
269 inline_ Point& Normalize()
270 {
271 float M = x*x + y*y + z*z;
272 if(M)
273 {
274 M = 1.0f / sqrtf(M);
275 x *= M;
276 y *= M;
277 z *= M;
278 }
279 return *this;
280 }
281
282 //! Sets vector length
283 inline_ Point& SetLength(float length)
284 {
285 float NewLength = length / Magnitude();
286 x *= NewLength;
287 y *= NewLength;
288 z *= NewLength;
289 return *this;
290 }
291
292 //! Clamps vector length
293 inline_ Point& ClampLength(float limit_length)
294 {
295 if(limit_length>=0.0f) // Magnitude must be positive
296 {
297 float CurrentSquareLength = SquareMagnitude();
298
299 if(CurrentSquareLength > limit_length * limit_length)
300 {
301 float Coeff = limit_length / sqrtf(CurrentSquareLength);
302 x *= Coeff;
303 y *= Coeff;
304 z *= Coeff;
305 }
306 }
307 return *this;
308 }
309
310 //! Computes distance to another point
311 inline_ float Distance(const Point& b) const
312 {
313 return sqrtf((x - b.x)*(x - b.x) + (y - b.y)*(y - b.y) + (z - b.z)*(z - b.z));
314 }
315
316 //! Computes square distance to another point
317 inline_ float SquareDistance(const Point& b) const
318 {
319 return ((x - b.x)*(x - b.x) + (y - b.y)*(y - b.y) + (z - b.z)*(z - b.z));
320 }
321
322 //! Dot product dp = this|a
323 inline_ float Dot(const Point& p) const { return p.x * x + p.y * y + p.z * z; }
324
325 //! Cross product this = a x b
326 inline_ Point& Cross(const Point& a, const Point& b)
327 {
328 x = a.y * b.z - a.z * b.y;
329 y = a.z * b.x - a.x * b.z;
330 z = a.x * b.y - a.y * b.x;
331 return *this;
332 }
333
334 //! Vector code ( bitmask = sign(z) | sign(y) | sign(x) )
335 inline_ udword VectorCode() const
336 {
337 return (IR(x)>>31) | ((IR(y)&SIGN_BITMASK)>>30) | ((IR(z)&SIGN_BITMASK)>>29);
338 }
339
340 //! Returns largest axis
341 inline_ PointComponent LargestAxis() const
342 {
343 const float* Vals = &x;
344 PointComponent m = X;
345 if(Vals[Y] > Vals[m]) m = Y;
346 if(Vals[Z] > Vals[m]) m = Z;
347 return m;
348 }
349
350 //! Returns closest axis
351 inline_ PointComponent ClosestAxis() const
352 {
353 const float* Vals = &x;
354 PointComponent m = X;
355 if(AIR(Vals[Y]) > AIR(Vals[m])) m = Y;
356 if(AIR(Vals[Z]) > AIR(Vals[m])) m = Z;
357 return m;
358 }
359
360 //! Returns smallest axis
361 inline_ PointComponent SmallestAxis() const
362 {
363 const float* Vals = &x;
364 PointComponent m = X;
365 if(Vals[Y] < Vals[m]) m = Y;
366 if(Vals[Z] < Vals[m]) m = Z;
367 return m;
368 }
369
370 //! Refracts the point
371 Point& Refract(const Point& eye, const Point& n, float refractindex, Point& refracted);
372
373 //! Projects the point onto a plane
374 Point& ProjectToPlane(const Plane& p);
375
376 //! Projects the point onto the screen
377 void ProjectToScreen(float halfrenderwidth, float halfrenderheight, const Matrix4x4& mat, HPoint& projected) const;
378
379 //! Unfolds the point onto a plane according to edge(a,b)
380 Point& Unfold(Plane& p, Point& a, Point& b);
381
382 //! Hash function from Ville Miettinen
383 inline_ udword GetHashValue() const
384 {
385 const udword* h = (const udword*)(this);
386 udword f = (h[0]+h[1]*11-(h[2]*17)) & 0x7fffffff; // avoid problems with +-0
387 return (f>>22)^(f>>12)^(f);
388 }
389
390 //! Stuff magic values in the point, marking it as explicitely not used.
391 void SetNotUsed();
392 //! Checks the point is marked as not used
393 BOOL IsNotUsed() const;
394
395 // Arithmetic operators
396
397 //! Unary operator for Point Negate = - Point
398 inline_ Point operator-() const { return Point(-x, -y, -z); }
399
400 //! Operator for Point Plus = Point + Point.
401 inline_ Point operator+(const Point& p) const { return Point(x + p.x, y + p.y, z + p.z); }
402 //! Operator for Point Minus = Point - Point.
403 inline_ Point operator-(const Point& p) const { return Point(x - p.x, y - p.y, z - p.z); }
404
405 //! Operator for Point Mul = Point * Point.
406 inline_ Point operator*(const Point& p) const { return Point(x * p.x, y * p.y, z * p.z); }
407 //! Operator for Point Scale = Point * float.
408 inline_ Point operator*(float s) const { return Point(x * s, y * s, z * s ); }
409 //! Operator for Point Scale = float * Point.
410 inline_ friend Point operator*(float s, const Point& p) { return Point(s * p.x, s * p.y, s * p.z); }
411
412 //! Operator for Point Div = Point / Point.
413 inline_ Point operator/(const Point& p) const { return Point(x / p.x, y / p.y, z / p.z); }
414 //! Operator for Point Scale = Point / float.
415 inline_ Point operator/(float s) const { s = 1.0f / s; return Point(x * s, y * s, z * s); }
416 //! Operator for Point Scale = float / Point.
417 inline_ friend Point operator/(float s, const Point& p) { return Point(s / p.x, s / p.y, s / p.z); }
418
419 //! Operator for float DotProd = Point | Point.
420 inline_ float operator|(const Point& p) const { return x*p.x + y*p.y + z*p.z; }
421 //! Operator for Point VecProd = Point ^ Point.
422 inline_ Point operator^(const Point& p) const
423 {
424 return Point(
425 y * p.z - z * p.y,
426 z * p.x - x * p.z,
427 x * p.y - y * p.x );
428 }
429
430 //! Operator for Point += Point.
431 inline_ Point& operator+=(const Point& p) { x += p.x; y += p.y; z += p.z; return *this; }
432 //! Operator for Point += float.
433 inline_ Point& operator+=(float s) { x += s; y += s; z += s; return *this; }
434
435 //! Operator for Point -= Point.
436 inline_ Point& operator-=(const Point& p) { x -= p.x; y -= p.y; z -= p.z; return *this; }
437 //! Operator for Point -= float.
438 inline_ Point& operator-=(float s) { x -= s; y -= s; z -= s; return *this; }
439
440 //! Operator for Point *= Point.
441 inline_ Point& operator*=(const Point& p) { x *= p.x; y *= p.y; z *= p.z; return *this; }
442 //! Operator for Point *= float.
443 inline_ Point& operator*=(float s) { x *= s; y *= s; z *= s; return *this; }
444
445 //! Operator for Point /= Point.
446 inline_ Point& operator/=(const Point& p) { x /= p.x; y /= p.y; z /= p.z; return *this; }
447 //! Operator for Point /= float.
448 inline_ Point& operator/=(float s) { s = 1.0f/s; x *= s; y *= s; z *= s; return *this; }
449
450 // Logical operators
451
452 //! Operator for "if(Point==Point)"
453 inline_ bool operator==(const Point& p) const { return ( (IR(x)==IR(p.x))&&(IR(y)==IR(p.y))&&(IR(z)==IR(p.z))); }
454 //! Operator for "if(Point!=Point)"
455 inline_ bool operator!=(const Point& p) const { return ( (IR(x)!=IR(p.x))||(IR(y)!=IR(p.y))||(IR(z)!=IR(p.z))); }
456
457 // Arithmetic operators
458
459 //! Operator for Point Mul = Point * Matrix3x3.
460 inline_ Point operator*(const Matrix3x3& mat) const
461 {
462 class ShadowMatrix3x3{ public: float m[3][3]; }; // To allow inlining
463 const ShadowMatrix3x3* Mat = (const ShadowMatrix3x3*)&mat;
464
465 return Point(
466 x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0],
467 x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1],
468 x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] );
469 }
470
471 //! Operator for Point Mul = Point * Matrix4x4.
472 inline_ Point operator*(const Matrix4x4& mat) const
473 {
474 class ShadowMatrix4x4{ public: float m[4][4]; }; // To allow inlining
475 const ShadowMatrix4x4* Mat = (const ShadowMatrix4x4*)&mat;
476
477 return Point(
478 x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0] + Mat->m[3][0],
479 x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1] + Mat->m[3][1],
480 x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] + Mat->m[3][2]);
481 }
482
483 //! Operator for Point *= Matrix3x3.
484 inline_ Point& operator*=(const Matrix3x3& mat)
485 {
486 class ShadowMatrix3x3{ public: float m[3][3]; }; // To allow inlining
487 const ShadowMatrix3x3* Mat = (const ShadowMatrix3x3*)&mat;
488
489 float xp = x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0];
490 float yp = x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1];
491 float zp = x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2];
492
493 x = xp; y = yp; z = zp;
494
495 return *this;
496 }
497
498 //! Operator for Point *= Matrix4x4.
499 inline_ Point& operator*=(const Matrix4x4& mat)
500 {
501 class ShadowMatrix4x4{ public: float m[4][4]; }; // To allow inlining
502 const ShadowMatrix4x4* Mat = (const ShadowMatrix4x4*)&mat;
503
504 float xp = x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0] + Mat->m[3][0];
505 float yp = x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1] + Mat->m[3][1];
506 float zp = x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] + Mat->m[3][2];
507
508 x = xp; y = yp; z = zp;
509
510 return *this;
511 }
512
513 // Cast operators
514
515 //! Cast a Point to a HPoint. w is set to zero.
516 operator HPoint() const;
517
518 inline_ operator const float*() const { return &x; }
519 inline_ operator float*() { return &x; }
520
521 public:
522 float x, y, z;
523 };
524
525 FUNCTION ICEMATHS_API void Normalize1(Point& a);
526 FUNCTION ICEMATHS_API void Normalize2(Point& a);
527
528#endif //__ICEPOINT_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IcePreprocessor.h b/libraries/ode-0.9/OPCODE/Ice/IcePreprocessor.h
new file mode 100644
index 0000000..dbeca38
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IcePreprocessor.h
@@ -0,0 +1,132 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains preprocessor stuff. This should be the first included header.
4 * \file IcePreprocessor.h
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICEPREPROCESSOR_H__
13#define __ICEPREPROCESSOR_H__
14
15 // Check platform
16 #if defined( _WIN32 ) || defined( WIN32 )
17 // #pragma message("Compiling on Windows...")
18 #define PLATFORM_WINDOWS
19 #else
20 // don't issue pragmas on unknown platforms
21 // #pragma message("Compiling on unknown platform...")
22 #endif
23
24 // Check compiler
25 #if defined(_MSC_VER)
26 // #pragma message("Compiling with VC++...")
27 #define COMPILER_VISUAL_CPP
28 #else
29 // don't issue pragmas on unknown platforms
30 // #pragma message("Compiling with unknown compiler...")
31 #endif
32
33 // Check compiler options. If this file is included in user-apps, this
34 // shouldn't be needed, so that they can use what they like best.
35 #ifndef ICE_DONT_CHECK_COMPILER_OPTIONS
36 #ifdef COMPILER_VISUAL_CPP
37 #if defined(_CHAR_UNSIGNED)
38 #endif
39
40 #if defined(_CPPRTTI)
41 #error Please disable RTTI...
42 #endif
43
44 #if defined(_CPPUNWIND)
45 #error Please disable exceptions...
46 #endif
47
48 #if defined(_MT)
49 // Multithreading
50 #endif
51 #endif
52 #endif
53
54 // Check debug mode
55 #ifdef DEBUG // May be defined instead of _DEBUG. Let's fix it.
56 #ifndef _DEBUG
57 #define _DEBUG
58 #endif
59 #endif
60
61 #ifdef _DEBUG
62 // Here you may define items for debug builds
63 #endif
64
65 #ifndef THIS_FILE
66 #define THIS_FILE __FILE__
67 #endif
68
69 #ifndef ICE_NO_DLL
70 #ifdef ICECORE_EXPORTS
71 #define ICECORE_API __declspec(dllexport)
72 #else
73 #define ICECORE_API __declspec(dllimport)
74 #endif
75 #else
76 #define ICECORE_API
77 #endif
78
79 // Don't override new/delete
80// #define DEFAULT_NEWDELETE
81 #define DONT_TRACK_MEMORY_LEAKS
82
83 #define FUNCTION extern "C"
84
85 // Cosmetic stuff [mainly useful with multiple inheritance]
86 #define override(base_class) virtual
87
88 // Our own inline keyword, so that:
89 // - we can switch to __forceinline to check it's really better or not
90 // - we can remove __forceinline if the compiler doesn't support it
91// #define inline_ __forceinline
92// #define inline_ inline
93
94 // Contributed by Bruce Mitchener
95 #if defined(COMPILER_VISUAL_CPP)
96 #define inline_ __forceinline
97// #define inline_ inline
98 #elif defined(__GNUC__) && __GNUC__ < 3
99 #define inline_ inline
100 #elif defined(__GNUC__)
101 #define inline_ inline __attribute__ ((always_inline))
102 #else
103 #define inline_ inline
104 #endif
105
106 // Down the hatch
107#ifdef _MSC_VER
108 #pragma inline_depth( 255 )
109#endif
110
111 #ifdef COMPILER_VISUAL_CPP
112 #pragma intrinsic(memcmp)
113 #pragma intrinsic(memcpy)
114 #pragma intrinsic(memset)
115 #pragma intrinsic(strcat)
116 #pragma intrinsic(strcmp)
117 #pragma intrinsic(strcpy)
118 #pragma intrinsic(strlen)
119 #pragma intrinsic(abs)
120 #pragma intrinsic(labs)
121 #endif
122
123 // ANSI compliance
124 #ifdef _DEBUG
125 // Remove painful warning in debug
126 inline_ bool __False__(){ return false; }
127 #define for if(__False__()){} else for
128 #else
129 #define for if(0){} else for
130 #endif
131
132#endif // __ICEPREPROCESSOR_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceRandom.cpp b/libraries/ode-0.9/OPCODE/Ice/IceRandom.cpp
new file mode 100644
index 0000000..cc63a04
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceRandom.cpp
@@ -0,0 +1,35 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code for random generators.
4 * \file IceRandom.cpp
5 * \author Pierre Terdiman
6 * \date August, 9, 2001
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Precompiled Header
12#include "Stdafx.h"
13
14using namespace IceCore;
15
16void IceCore:: SRand(udword seed)
17{
18 srand(seed);
19}
20
21udword IceCore::Rand()
22{
23 return rand();
24}
25
26
27static BasicRandom gRandomGenerator(42);
28
29udword IceCore::GetRandomIndex(udword max_index)
30{
31 // We don't use rand() since it's limited to RAND_MAX
32 udword Index = gRandomGenerator.Randomize();
33 return Index % max_index;
34}
35
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceRandom.h b/libraries/ode-0.9/OPCODE/Ice/IceRandom.h
new file mode 100644
index 0000000..3170b33
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceRandom.h
@@ -0,0 +1,42 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code for random generators.
4 * \file IceRandom.h
5 * \author Pierre Terdiman
6 * \date August, 9, 2001
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICERANDOM_H__
13#define __ICERANDOM_H__
14
15 FUNCTION ICECORE_API void SRand(udword seed);
16 FUNCTION ICECORE_API udword Rand();
17
18 //! Returns a unit random floating-point value
19 inline_ float UnitRandomFloat() { return float(Rand()) * ONE_OVER_RAND_MAX; }
20
21 //! Returns a random index so that 0<= index < max_index
22 ICECORE_API udword GetRandomIndex(udword max_index);
23
24 class ICECORE_API BasicRandom
25 {
26 public:
27
28 //! Constructor
29 inline_ BasicRandom(udword seed=0) : mRnd(seed) {}
30 //! Destructor
31 inline_ ~BasicRandom() {}
32
33 inline_ void SetSeed(udword seed) { mRnd = seed; }
34 inline_ udword GetCurrentValue() const { return mRnd; }
35 inline_ udword Randomize() { mRnd = mRnd * 2147001325 + 715136305; return mRnd; }
36
37 private:
38 udword mRnd;
39 };
40
41#endif // __ICERANDOM_H__
42
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceRay.cpp b/libraries/ode-0.9/OPCODE/Ice/IceRay.cpp
new file mode 100644
index 0000000..6cf0330
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceRay.cpp
@@ -0,0 +1,84 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code for rays.
4 * \file IceRay.cpp
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11/**
12 * Ray class.
13 * A ray is a half-line P(t) = mOrig + mDir * t, with 0 <= t <= +infinity
14 * \class Ray
15 * \author Pierre Terdiman
16 * \version 1.0
17 */
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19
20/*
21 O = Origin = impact point
22 i = normalized vector along the x axis
23 j = normalized vector along the y axis = actually the normal vector in O
24 D = Direction vector, norm |D| = 1
25 N = Projection of D on y axis, norm |N| = normal reaction
26 T = Projection of D on x axis, norm |T| = tangential reaction
27 R = Reflexion vector
28
29 ^y
30 |
31 |
32 |
33 _ _ _| _ _ _
34 * * *|
35 \ | /
36 \ |N / |
37 R\ | /D
38 \ | / |
39 \ | /
40 _________\|/______*_______>x
41 O T
42
43 Let define theta = angle between D and N. Then cos(theta) = |N| / |D| = |N| since D is normalized.
44
45 j|D = |j|*|D|*cos(theta) => |N| = j|D
46
47 Then we simply have:
48
49 D = N + T
50
51 To compute tangential reaction :
52
53 T = D - N
54
55 To compute reflexion vector :
56
57 R = N - T = N - (D-N) = 2*N - D
58*/
59
60///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
61// Precompiled Header
62#include "Stdafx.h"
63
64using namespace IceMaths;
65
66float Ray::SquareDistance(const Point& point, float* t) const
67{
68 Point Diff = point - mOrig;
69 float fT = Diff | mDir;
70
71 if(fT<=0.0f)
72 {
73 fT = 0.0f;
74 }
75 else
76 {
77 fT /= mDir.SquareMagnitude();
78 Diff -= fT*mDir;
79 }
80
81 if(t) *t = fT;
82
83 return Diff.SquareMagnitude();
84}
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceRay.h b/libraries/ode-0.9/OPCODE/Ice/IceRay.h
new file mode 100644
index 0000000..0268287
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceRay.h
@@ -0,0 +1,98 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code for rays.
4 * \file IceRay.h
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICERAY_H__
13#define __ICERAY_H__
14
15 class ICEMATHS_API Ray
16 {
17 public:
18 //! Constructor
19 inline_ Ray() {}
20 //! Constructor
21 inline_ Ray(const Point& orig, const Point& dir) : mOrig(orig), mDir(dir) {}
22 //! Copy constructor
23 inline_ Ray(const Ray& ray) : mOrig(ray.mOrig), mDir(ray.mDir) {}
24 //! Destructor
25 inline_ ~Ray() {}
26
27 float SquareDistance(const Point& point, float* t=null) const;
28 inline_ float Distance(const Point& point, float* t=null) const { return sqrtf(SquareDistance(point, t)); }
29
30 Point mOrig; //!< Ray origin
31 Point mDir; //!< Normalized direction
32 };
33
34 inline_ void ComputeReflexionVector(Point& reflected, const Point& incoming_dir, const Point& outward_normal)
35 {
36 reflected = incoming_dir - outward_normal * 2.0f * (incoming_dir|outward_normal);
37 }
38
39 inline_ void ComputeReflexionVector(Point& reflected, const Point& source, const Point& impact, const Point& normal)
40 {
41 Point V = impact - source;
42 reflected = V - normal * 2.0f * (V|normal);
43 }
44
45 inline_ void DecomposeVector(Point& normal_compo, Point& tangent_compo, const Point& outward_dir, const Point& outward_normal)
46 {
47 normal_compo = outward_normal * (outward_dir|outward_normal);
48 tangent_compo = outward_dir - normal_compo;
49 }
50
51 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
52 /**
53 * Transforms a direction vector from world space to local space
54 * \param local_dir [out] direction vector in local space
55 * \param world_dir [in] direction vector in world space
56 * \param world [in] world transform
57 */
58 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
59 inline_ void ComputeLocalDirection(Point& local_dir, const Point& world_dir, const Matrix4x4& world)
60 {
61 // Get world direction back in local space
62// Matrix3x3 InvWorld = world;
63// local_dir = InvWorld * world_dir;
64 local_dir = Matrix3x3(world) * world_dir;
65 }
66
67 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
68 /**
69 * Transforms a position vector from world space to local space
70 * \param local_pt [out] position vector in local space
71 * \param world_pt [in] position vector in world space
72 * \param world [in] world transform
73 */
74 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
75 inline_ void ComputeLocalPoint(Point& local_pt, const Point& world_pt, const Matrix4x4& world)
76 {
77 // Get world vertex back in local space
78 Matrix4x4 InvWorld = world;
79 InvWorld.Invert();
80 local_pt = world_pt * InvWorld;
81 }
82
83 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
84 /**
85 * Transforms a ray from world space to local space
86 * \param local_ray [out] ray in local space
87 * \param world_ray [in] ray in world space
88 * \param world [in] world transform
89 */
90 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
91 inline_ void ComputeLocalRay(Ray& local_ray, const Ray& world_ray, const Matrix4x4& world)
92 {
93 // Get world ray back in local space
94 ComputeLocalDirection(local_ray.mDir, world_ray.mDir, world);
95 ComputeLocalPoint(local_ray.mOrig, world_ray.mOrig, world);
96 }
97
98#endif // __ICERAY_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceRevisitedRadix.cpp b/libraries/ode-0.9/OPCODE/Ice/IceRevisitedRadix.cpp
new file mode 100644
index 0000000..3e351da
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceRevisitedRadix.cpp
@@ -0,0 +1,520 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains source code from the article "Radix Sort Revisited".
4 * \file IceRevisitedRadix.cpp
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11/**
12 * Revisited Radix Sort.
13 * This is my new radix routine:
14 * - it uses indices and doesn't recopy the values anymore, hence wasting less ram
15 * - it creates all the histograms in one run instead of four
16 * - it sorts words faster than dwords and bytes faster than words
17 * - it correctly sorts negative floating-point values by patching the offsets
18 * - it automatically takes advantage of temporal coherence
19 * - multiple keys support is a side effect of temporal coherence
20 * - it may be worth recoding in asm... (mainly to use FCOMI, FCMOV, etc) [it's probably memory-bound anyway]
21 *
22 * History:
23 * - 08.15.98: very first version
24 * - 04.04.00: recoded for the radix article
25 * - 12.xx.00: code lifting
26 * - 09.18.01: faster CHECK_PASS_VALIDITY thanks to Mark D. Shattuck (who provided other tips, not included here)
27 * - 10.11.01: added local ram support
28 * - 01.20.02: bugfix! In very particular cases the last pass was skipped in the float code-path, leading to incorrect sorting......
29 * - 01.02.02: - "mIndices" renamed => "mRanks". That's a rank sorter after all.
30 * - ranks are not "reset" anymore, but implicit on first calls
31 * - 07.05.02: - offsets rewritten with one less indirection.
32 * - 11.03.02: - "bool" replaced with RadixHint enum
33 *
34 * \class RadixSort
35 * \author Pierre Terdiman
36 * \version 1.4
37 * \date August, 15, 1998
38 */
39///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
40
41/*
42To do:
43 - add an offset parameter between two input values (avoid some data recopy sometimes)
44 - unroll ? asm ?
45 - 11 bits trick & 3 passes as Michael did
46 - prefetch stuff the day I have a P3
47 - make a version with 16-bits indices ?
48*/
49
50///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
51// Precompiled Header
52#include "Stdafx.h"
53
54using namespace IceCore;
55
56#define INVALIDATE_RANKS mCurrentSize|=0x80000000
57#define VALIDATE_RANKS mCurrentSize&=0x7fffffff
58#define CURRENT_SIZE (mCurrentSize&0x7fffffff)
59#define INVALID_RANKS (mCurrentSize&0x80000000)
60
61#define CHECK_RESIZE(n) \
62 if(n!=mPreviousSize) \
63 { \
64 if(n>mCurrentSize) Resize(n); \
65 else ResetRanks(); \
66 mPreviousSize = n; \
67 }
68
69#define CREATE_HISTOGRAMS(type, buffer) \
70 /* Clear counters/histograms */ \
71 ZeroMemory(mHistogram, 256*4*sizeof(udword)); \
72 \
73 /* Prepare to count */ \
74 ubyte* p = (ubyte*)input; \
75 ubyte* pe = &p[nb*4]; \
76 udword* h0= &mHistogram[0]; /* Histogram for first pass (LSB) */ \
77 udword* h1= &mHistogram[256]; /* Histogram for second pass */ \
78 udword* h2= &mHistogram[512]; /* Histogram for third pass */ \
79 udword* h3= &mHistogram[768]; /* Histogram for last pass (MSB) */ \
80 \
81 bool AlreadySorted = true; /* Optimism... */ \
82 \
83 if(INVALID_RANKS) \
84 { \
85 /* Prepare for temporal coherence */ \
86 type* Running = (type*)buffer; \
87 type PrevVal = *Running; \
88 \
89 while(p!=pe) \
90 { \
91 /* Read input buffer in previous sorted order */ \
92 type Val = *Running++; \
93 /* Check whether already sorted or not */ \
94 if(Val<PrevVal) { AlreadySorted = false; break; } /* Early out */ \
95 /* Update for next iteration */ \
96 PrevVal = Val; \
97 \
98 /* Create histograms */ \
99 h0[*p++]++; h1[*p++]++; h2[*p++]++; h3[*p++]++; \
100 } \
101 \
102 /* If all input values are already sorted, we just have to return and leave the */ \
103 /* previous list unchanged. That way the routine may take advantage of temporal */ \
104 /* coherence, for example when used to sort transparent faces. */ \
105 if(AlreadySorted) \
106 { \
107 mNbHits++; \
108 for(udword i=0;i<nb;i++) mRanks[i] = i; \
109 return *this; \
110 } \
111 } \
112 else \
113 { \
114 /* Prepare for temporal coherence */ \
115 udword* Indices = mRanks; \
116 type PrevVal = (type)buffer[*Indices]; \
117 \
118 while(p!=pe) \
119 { \
120 /* Read input buffer in previous sorted order */ \
121 type Val = (type)buffer[*Indices++]; \
122 /* Check whether already sorted or not */ \
123 if(Val<PrevVal) { AlreadySorted = false; break; } /* Early out */ \
124 /* Update for next iteration */ \
125 PrevVal = Val; \
126 \
127 /* Create histograms */ \
128 h0[*p++]++; h1[*p++]++; h2[*p++]++; h3[*p++]++; \
129 } \
130 \
131 /* If all input values are already sorted, we just have to return and leave the */ \
132 /* previous list unchanged. That way the routine may take advantage of temporal */ \
133 /* coherence, for example when used to sort transparent faces. */ \
134 if(AlreadySorted) { mNbHits++; return *this; } \
135 } \
136 \
137 /* Else there has been an early out and we must finish computing the histograms */ \
138 while(p!=pe) \
139 { \
140 /* Create histograms without the previous overhead */ \
141 h0[*p++]++; h1[*p++]++; h2[*p++]++; h3[*p++]++; \
142 }
143
144#define CHECK_PASS_VALIDITY(pass) \
145 /* Shortcut to current counters */ \
146 udword* CurCount = &mHistogram[pass<<8]; \
147 \
148 /* Reset flag. The sorting pass is supposed to be performed. (default) */ \
149 bool PerformPass = true; \
150 \
151 /* Check pass validity */ \
152 \
153 /* If all values have the same byte, sorting is useless. */ \
154 /* It may happen when sorting bytes or words instead of dwords. */ \
155 /* This routine actually sorts words faster than dwords, and bytes */ \
156 /* faster than words. Standard running time (O(4*n))is reduced to O(2*n) */ \
157 /* for words and O(n) for bytes. Running time for floats depends on actual values... */ \
158 \
159 /* Get first byte */ \
160 ubyte UniqueVal = *(((ubyte*)input)+pass); \
161 \
162 /* Check that byte's counter */ \
163 if(CurCount[UniqueVal]==nb) PerformPass=false;
164
165///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
166/**
167 * Constructor.
168 */
169///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
170RadixSort::RadixSort() : mRanks(null), mRanks2(null), mCurrentSize(0), mTotalCalls(0), mNbHits(0)
171{
172#ifndef RADIX_LOCAL_RAM
173 // Allocate input-independent ram
174 mHistogram = new udword[256*4];
175 mOffset = new udword[256];
176#endif
177 // Initialize indices
178 INVALIDATE_RANKS;
179}
180
181///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
182/**
183 * Destructor.
184 */
185///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
186RadixSort::~RadixSort()
187{
188 // Release everything
189#ifndef RADIX_LOCAL_RAM
190 DELETEARRAY(mOffset);
191 DELETEARRAY(mHistogram);
192#endif
193 DELETEARRAY(mRanks2);
194 DELETEARRAY(mRanks);
195}
196
197///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
198/**
199 * Resizes the inner lists.
200 * \param nb [in] new size (number of dwords)
201 * \return true if success
202 */
203///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
204bool RadixSort::Resize(udword nb)
205{
206 // Free previously used ram
207 DELETEARRAY(mRanks2);
208 DELETEARRAY(mRanks);
209
210 // Get some fresh one
211 mRanks = new udword[nb]; CHECKALLOC(mRanks);
212 mRanks2 = new udword[nb]; CHECKALLOC(mRanks2);
213
214 return true;
215}
216
217inline_ void RadixSort::CheckResize(udword nb)
218{
219 udword CurSize = CURRENT_SIZE;
220 if(nb!=CurSize)
221 {
222 if(nb>CurSize) Resize(nb);
223 mCurrentSize = nb;
224 INVALIDATE_RANKS;
225 }
226}
227
228///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
229/**
230 * Main sort routine.
231 * This one is for integer values. After the call, mRanks contains a list of indices in sorted order, i.e. in the order you may process your data.
232 * \param input [in] a list of integer values to sort
233 * \param nb [in] number of values to sort, must be < 2^31
234 * \param hint [in] RADIX_SIGNED to handle negative values, RADIX_UNSIGNED if you know your input buffer only contains positive values
235 * \return Self-Reference
236 */
237///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
238RadixSort& RadixSort::Sort(const udword* input, udword nb, RadixHint hint)
239{
240 // Checkings
241 if(!input || !nb || nb&0x80000000) return *this;
242
243 // Stats
244 mTotalCalls++;
245
246 // Resize lists if needed
247 CheckResize(nb);
248
249#ifdef RADIX_LOCAL_RAM
250 // Allocate histograms & offsets on the stack
251 udword mHistogram[256*4];
252// udword mOffset[256];
253 udword* mLink[256];
254#endif
255
256 // Create histograms (counters). Counters for all passes are created in one run.
257 // Pros: read input buffer once instead of four times
258 // Cons: mHistogram is 4Kb instead of 1Kb
259 // We must take care of signed/unsigned values for temporal coherence.... I just
260 // have 2 code paths even if just a single opcode changes. Self-modifying code, someone?
261 if(hint==RADIX_UNSIGNED) { CREATE_HISTOGRAMS(udword, input); }
262 else { CREATE_HISTOGRAMS(sdword, input); }
263
264 // Compute #negative values involved if needed
265 udword NbNegativeValues = 0;
266 if(hint==RADIX_SIGNED)
267 {
268 // An efficient way to compute the number of negatives values we'll have to deal with is simply to sum the 128
269 // last values of the last histogram. Last histogram because that's the one for the Most Significant Byte,
270 // responsible for the sign. 128 last values because the 128 first ones are related to positive numbers.
271 udword* h3= &mHistogram[768];
272 for(udword i=128;i<256;i++) NbNegativeValues += h3[i]; // 768 for last histogram, 128 for negative part
273 }
274
275 // Radix sort, j is the pass number (0=LSB, 3=MSB)
276 for(udword j=0;j<4;j++)
277 {
278 CHECK_PASS_VALIDITY(j);
279
280 // Sometimes the fourth (negative) pass is skipped because all numbers are negative and the MSB is 0xFF (for example). This is
281 // not a problem, numbers are correctly sorted anyway.
282 if(PerformPass)
283 {
284 // Should we care about negative values?
285 if(j!=3 || hint==RADIX_UNSIGNED)
286 {
287 // Here we deal with positive values only
288
289 // Create offsets
290// mOffset[0] = 0;
291// for(udword i=1;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1];
292 mLink[0] = mRanks2;
293 for(udword i=1;i<256;i++) mLink[i] = mLink[i-1] + CurCount[i-1];
294 }
295 else
296 {
297 // This is a special case to correctly handle negative integers. They're sorted in the right order but at the wrong place.
298
299 // Create biased offsets, in order for negative numbers to be sorted as well
300// mOffset[0] = NbNegativeValues; // First positive number takes place after the negative ones
301 mLink[0] = &mRanks2[NbNegativeValues]; // First positive number takes place after the negative ones
302// for(udword i=1;i<128;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers
303 for(udword i=1;i<128;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers
304
305 // Fixing the wrong place for negative values
306// mOffset[128] = 0;
307 mLink[128] = mRanks2;
308// for(i=129;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1];
309 for(udword i=129;i<256;i++) mLink[i] = mLink[i-1] + CurCount[i-1];
310 }
311
312 // Perform Radix Sort
313 ubyte* InputBytes = (ubyte*)input;
314 InputBytes += j;
315 if(INVALID_RANKS)
316 {
317// for(udword i=0;i<nb;i++) mRanks2[mOffset[InputBytes[i<<2]]++] = i;
318 for(udword i=0;i<nb;i++) *mLink[InputBytes[i<<2]]++ = i;
319 VALIDATE_RANKS;
320 }
321 else
322 {
323 udword* Indices = mRanks;
324 udword* IndicesEnd = &mRanks[nb];
325 while(Indices!=IndicesEnd)
326 {
327 udword id = *Indices++;
328// mRanks2[mOffset[InputBytes[id<<2]]++] = id;
329 *mLink[InputBytes[id<<2]]++ = id;
330 }
331 }
332
333 // Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap.
334 udword* Tmp = mRanks; mRanks = mRanks2; mRanks2 = Tmp;
335 }
336 }
337 return *this;
338}
339
340///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
341/**
342 * Main sort routine.
343 * This one is for floating-point values. After the call, mRanks contains a list of indices in sorted order, i.e. in the order you may process your data.
344 * \param input [in] a list of floating-point values to sort
345 * \param nb [in] number of values to sort, must be < 2^31
346 * \return Self-Reference
347 * \warning only sorts IEEE floating-point values
348 */
349///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
350RadixSort& RadixSort::Sort(const float* input2, udword nb)
351{
352 // Checkings
353 if(!input2 || !nb || nb&0x80000000) return *this;
354
355 // Stats
356 mTotalCalls++;
357
358 udword* input = (udword*)input2;
359
360 // Resize lists if needed
361 CheckResize(nb);
362
363#ifdef RADIX_LOCAL_RAM
364 // Allocate histograms & offsets on the stack
365 udword mHistogram[256*4];
366// udword mOffset[256];
367 udword* mLink[256];
368#endif
369
370 // Create histograms (counters). Counters for all passes are created in one run.
371 // Pros: read input buffer once instead of four times
372 // Cons: mHistogram is 4Kb instead of 1Kb
373 // Floating-point values are always supposed to be signed values, so there's only one code path there.
374 // Please note the floating point comparison needed for temporal coherence! Although the resulting asm code
375 // is dreadful, this is surprisingly not such a performance hit - well, I suppose that's a big one on first
376 // generation Pentiums....We can't make comparison on integer representations because, as Chris said, it just
377 // wouldn't work with mixed positive/negative values....
378 { CREATE_HISTOGRAMS(float, input2); }
379
380 // Compute #negative values involved if needed
381 udword NbNegativeValues = 0;
382 // An efficient way to compute the number of negatives values we'll have to deal with is simply to sum the 128
383 // last values of the last histogram. Last histogram because that's the one for the Most Significant Byte,
384 // responsible for the sign. 128 last values because the 128 first ones are related to positive numbers.
385 udword* h3= &mHistogram[768];
386 for(udword i=128;i<256;i++) NbNegativeValues += h3[i]; // 768 for last histogram, 128 for negative part
387
388 // Radix sort, j is the pass number (0=LSB, 3=MSB)
389 for(udword j=0;j<4;j++)
390 {
391 // Should we care about negative values?
392 if(j!=3)
393 {
394 // Here we deal with positive values only
395 CHECK_PASS_VALIDITY(j);
396
397 if(PerformPass)
398 {
399 // Create offsets
400// mOffset[0] = 0;
401 mLink[0] = mRanks2;
402// for(udword i=1;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1];
403 for(udword i=1;i<256;i++) mLink[i] = mLink[i-1] + CurCount[i-1];
404
405 // Perform Radix Sort
406 ubyte* InputBytes = (ubyte*)input;
407 InputBytes += j;
408 if(INVALID_RANKS)
409 {
410// for(i=0;i<nb;i++) mRanks2[mOffset[InputBytes[i<<2]]++] = i;
411 for(udword i=0;i<nb;i++) *mLink[InputBytes[i<<2]]++ = i;
412 VALIDATE_RANKS;
413 }
414 else
415 {
416 udword* Indices = mRanks;
417 udword* IndicesEnd = &mRanks[nb];
418 while(Indices!=IndicesEnd)
419 {
420 udword id = *Indices++;
421// mRanks2[mOffset[InputBytes[id<<2]]++] = id;
422 *mLink[InputBytes[id<<2]]++ = id;
423 }
424 }
425
426 // Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap.
427 udword* Tmp = mRanks; mRanks = mRanks2; mRanks2 = Tmp;
428 }
429 }
430 else
431 {
432 // This is a special case to correctly handle negative values
433 CHECK_PASS_VALIDITY(j);
434
435 if(PerformPass)
436 {
437 // Create biased offsets, in order for negative numbers to be sorted as well
438// mOffset[0] = NbNegativeValues; // First positive number takes place after the negative ones
439 mLink[0] = &mRanks2[NbNegativeValues]; // First positive number takes place after the negative ones
440// for(udword i=1;i<128;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers
441 for(udword i=1;i<128;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers
442
443 // We must reverse the sorting order for negative numbers!
444// mOffset[255] = 0;
445 mLink[255] = mRanks2;
446// for(i=0;i<127;i++) mOffset[254-i] = mOffset[255-i] + CurCount[255-i]; // Fixing the wrong order for negative values
447 for(udword i=0;i<127;i++) mLink[254-i] = mLink[255-i] + CurCount[255-i]; // Fixing the wrong order for negative values
448// for(i=128;i<256;i++) mOffset[i] += CurCount[i]; // Fixing the wrong place for negative values
449 for(udword i=128;i<256;i++) mLink[i] += CurCount[i]; // Fixing the wrong place for negative values
450
451 // Perform Radix Sort
452 if(INVALID_RANKS)
453 {
454 for(udword i=0;i<nb;i++)
455 {
456 udword Radix = input[i]>>24; // Radix byte, same as above. AND is useless here (udword).
457 // ### cmp to be killed. Not good. Later.
458// if(Radix<128) mRanks2[mOffset[Radix]++] = i; // Number is positive, same as above
459// else mRanks2[--mOffset[Radix]] = i; // Number is negative, flip the sorting order
460 if(Radix<128) *mLink[Radix]++ = i; // Number is positive, same as above
461 else *(--mLink[Radix]) = i; // Number is negative, flip the sorting order
462 }
463 VALIDATE_RANKS;
464 }
465 else
466 {
467 for(udword i=0;i<nb;i++)
468 {
469 udword Radix = input[mRanks[i]]>>24; // Radix byte, same as above. AND is useless here (udword).
470 // ### cmp to be killed. Not good. Later.
471// if(Radix<128) mRanks2[mOffset[Radix]++] = mRanks[i]; // Number is positive, same as above
472// else mRanks2[--mOffset[Radix]] = mRanks[i]; // Number is negative, flip the sorting order
473 if(Radix<128) *mLink[Radix]++ = mRanks[i]; // Number is positive, same as above
474 else *(--mLink[Radix]) = mRanks[i]; // Number is negative, flip the sorting order
475 }
476 }
477 // Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap.
478 udword* Tmp = mRanks; mRanks = mRanks2; mRanks2 = Tmp;
479 }
480 else
481 {
482 // The pass is useless, yet we still have to reverse the order of current list if all values are negative.
483 if(UniqueVal>=128)
484 {
485 if(INVALID_RANKS)
486 {
487 // ###Possible?
488 for(udword i=0;i<nb;i++) mRanks2[i] = nb-i-1;
489 VALIDATE_RANKS;
490 }
491 else
492 {
493 for(udword i=0;i<nb;i++) mRanks2[i] = mRanks[nb-i-1];
494 }
495
496 // Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap.
497 udword* Tmp = mRanks; mRanks = mRanks2; mRanks2 = Tmp;
498 }
499 }
500 }
501 }
502 return *this;
503}
504
505///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
506/**
507 * Gets the ram used.
508 * \return memory used in bytes
509 */
510///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
511udword RadixSort::GetUsedRam() const
512{
513 udword UsedRam = sizeof(RadixSort);
514#ifndef RADIX_LOCAL_RAM
515 UsedRam += 256*4*sizeof(udword); // Histograms
516 UsedRam += 256*sizeof(udword); // Offsets
517#endif
518 UsedRam += 2*CURRENT_SIZE*sizeof(udword); // 2 lists of indices
519 return UsedRam;
520}
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceRevisitedRadix.h b/libraries/ode-0.9/OPCODE/Ice/IceRevisitedRadix.h
new file mode 100644
index 0000000..3bdfc22
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceRevisitedRadix.h
@@ -0,0 +1,65 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains source code from the article "Radix Sort Revisited".
4 * \file IceRevisitedRadix.h
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICERADIXSORT_H__
13#define __ICERADIXSORT_H__
14
15 //! Allocate histograms & offsets locally
16 #define RADIX_LOCAL_RAM
17
18 enum RadixHint
19 {
20 RADIX_SIGNED, //!< Input values are signed
21 RADIX_UNSIGNED, //!< Input values are unsigned
22
23 RADIX_FORCE_DWORD = 0x7fffffff
24 };
25
26 class ICECORE_API RadixSort
27 {
28 public:
29 // Constructor/Destructor
30 RadixSort();
31 ~RadixSort();
32 // Sorting methods
33 RadixSort& Sort(const udword* input, udword nb, RadixHint hint=RADIX_SIGNED);
34 RadixSort& Sort(const float* input, udword nb);
35
36 //! Access to results. mRanks is a list of indices in sorted order, i.e. in the order you may further process your data
37 inline_ const udword* GetRanks() const { return mRanks; }
38
39 //! mIndices2 gets trashed on calling the sort routine, but otherwise you can recycle it the way you want.
40 inline_ udword* GetRecyclable() const { return mRanks2; }
41
42 // Stats
43 udword GetUsedRam() const;
44 //! Returns the total number of calls to the radix sorter.
45 inline_ udword GetNbTotalCalls() const { return mTotalCalls; }
46 //! Returns the number of eraly exits due to temporal coherence.
47 inline_ udword GetNbHits() const { return mNbHits; }
48
49 private:
50#ifndef RADIX_LOCAL_RAM
51 udword* mHistogram; //!< Counters for each byte
52 udword* mOffset; //!< Offsets (nearly a cumulative distribution function)
53#endif
54 udword mCurrentSize; //!< Current size of the indices list
55 udword* mRanks; //!< Two lists, swapped each pass
56 udword* mRanks2;
57 // Stats
58 udword mTotalCalls; //!< Total number of calls to the sort routine
59 udword mNbHits; //!< Number of early exits due to coherence
60 // Internal methods
61 void CheckResize(udword nb);
62 bool Resize(udword nb);
63 };
64
65#endif // __ICERADIXSORT_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceSegment.cpp b/libraries/ode-0.9/OPCODE/Ice/IceSegment.cpp
new file mode 100644
index 0000000..cd9ceb7
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceSegment.cpp
@@ -0,0 +1,57 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code for segments.
4 * \file IceSegment.cpp
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11/**
12 * Segment class.
13 * A segment is defined by S(t) = mP0 * (1 - t) + mP1 * t, with 0 <= t <= 1
14 * Alternatively, a segment is S(t) = Origin + t * Direction for 0 <= t <= 1.
15 * Direction is not necessarily unit length. The end points are Origin = mP0 and Origin + Direction = mP1.
16 *
17 * \class Segment
18 * \author Pierre Terdiman
19 * \version 1.0
20 */
21///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
22
23///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
24// Precompiled Header
25#include "Stdafx.h"
26
27using namespace IceMaths;
28
29float Segment::SquareDistance(const Point& point, float* t) const
30{
31 Point Diff = point - mP0;
32 Point Dir = mP1 - mP0;
33 float fT = Diff | Dir;
34
35 if(fT<=0.0f)
36 {
37 fT = 0.0f;
38 }
39 else
40 {
41 float SqrLen= Dir.SquareMagnitude();
42 if(fT>=SqrLen)
43 {
44 fT = 1.0f;
45 Diff -= Dir;
46 }
47 else
48 {
49 fT /= SqrLen;
50 Diff -= fT*Dir;
51 }
52 }
53
54 if(t) *t = fT;
55
56 return Diff.SquareMagnitude();
57}
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceSegment.h b/libraries/ode-0.9/OPCODE/Ice/IceSegment.h
new file mode 100644
index 0000000..8d66322
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceSegment.h
@@ -0,0 +1,55 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code for segments.
4 * \file IceSegment.h
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICESEGMENT_H__
13#define __ICESEGMENT_H__
14
15 class ICEMATHS_API Segment
16 {
17 public:
18 //! Constructor
19 inline_ Segment() {}
20 //! Constructor
21 inline_ Segment(const Point& p0, const Point& p1) : mP0(p0), mP1(p1) {}
22 //! Copy constructor
23 inline_ Segment(const Segment& seg) : mP0(seg.mP0), mP1(seg.mP1) {}
24 //! Destructor
25 inline_ ~Segment() {}
26
27 inline_ const Point& GetOrigin() const { return mP0; }
28 inline_ Point ComputeDirection() const { return mP1 - mP0; }
29 inline_ void ComputeDirection(Point& dir) const { dir = mP1 - mP0; }
30 inline_ float ComputeLength() const { return mP1.Distance(mP0); }
31 inline_ float ComputeSquareLength() const { return mP1.SquareDistance(mP0); }
32
33 inline_ void SetOriginDirection(const Point& origin, const Point& direction)
34 {
35 mP0 = mP1 = origin;
36 mP1 += direction;
37 }
38
39 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
40 /**
41 * Computes a point on the segment
42 * \param pt [out] point on segment
43 * \param t [in] point's parameter [t=0 => pt = mP0, t=1 => pt = mP1]
44 */
45 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
46 inline_ void ComputePoint(Point& pt, float t) const { pt = mP0 + t * (mP1 - mP0); }
47
48 float SquareDistance(const Point& point, float* t=null) const;
49 inline_ float Distance(const Point& point, float* t=null) const { return sqrtf(SquareDistance(point, t)); }
50
51 Point mP0; //!< Start of segment
52 Point mP1; //!< End of segment
53 };
54
55#endif // __ICESEGMENT_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceTriList.h b/libraries/ode-0.9/OPCODE/Ice/IceTriList.h
new file mode 100644
index 0000000..b2b6ecf
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceTriList.h
@@ -0,0 +1,61 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains code for a triangle container.
4 * \file IceTrilist.h
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICETRILIST_H__
13#define __ICETRILIST_H__
14
15 class ICEMATHS_API TriList : public Container
16 {
17 public:
18 // Constructor / Destructor
19 TriList() {}
20 ~TriList() {}
21
22 inline_ udword GetNbTriangles() const { return GetNbEntries()/9; }
23 inline_ Triangle* GetTriangles() const { return (Triangle*)GetEntries(); }
24
25 void AddTri(const Triangle& tri)
26 {
27 Add(tri.mVerts[0].x).Add(tri.mVerts[0].y).Add(tri.mVerts[0].z);
28 Add(tri.mVerts[1].x).Add(tri.mVerts[1].y).Add(tri.mVerts[1].z);
29 Add(tri.mVerts[2].x).Add(tri.mVerts[2].y).Add(tri.mVerts[2].z);
30 }
31
32 void AddTri(const Point& p0, const Point& p1, const Point& p2)
33 {
34 Add(p0.x).Add(p0.y).Add(p0.z);
35 Add(p1.x).Add(p1.y).Add(p1.z);
36 Add(p2.x).Add(p2.y).Add(p2.z);
37 }
38 };
39
40 class ICEMATHS_API TriangleList : public Container
41 {
42 public:
43 // Constructor / Destructor
44 TriangleList() {}
45 ~TriangleList() {}
46
47 inline_ udword GetNbTriangles() const { return GetNbEntries()/3; }
48 inline_ IndexedTriangle* GetTriangles() const { return (IndexedTriangle*)GetEntries();}
49
50 void AddTriangle(const IndexedTriangle& tri)
51 {
52 Add(tri.mVRef[0]).Add(tri.mVRef[1]).Add(tri.mVRef[2]);
53 }
54
55 void AddTriangle(udword vref0, udword vref1, udword vref2)
56 {
57 Add(vref0).Add(vref1).Add(vref2);
58 }
59 };
60
61#endif //__ICETRILIST_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceTriangle.cpp b/libraries/ode-0.9/OPCODE/Ice/IceTriangle.cpp
new file mode 100644
index 0000000..4268ff4
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceTriangle.cpp
@@ -0,0 +1,286 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains a handy triangle class.
4 * \file IceTriangle.cpp
5 * \author Pierre Terdiman
6 * \date January, 17, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Precompiled Header
12#include "Stdafx.h"
13
14using namespace IceMaths;
15
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17/**
18 * Contains a triangle class.
19 *
20 * \class Tri
21 * \author Pierre Terdiman
22 * \version 1.0
23 * \date 08.15.98
24*/
25///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
26
27static sdword VPlaneSideEps(const Point& v, const Plane& plane, float epsilon)
28{
29 // Compute distance from current vertex to the plane
30 float Dist = plane.Distance(v);
31 // Compute side:
32 // 1 = the vertex is on the positive side of the plane
33 // -1 = the vertex is on the negative side of the plane
34 // 0 = the vertex is on the plane (within epsilon)
35 return Dist > epsilon ? 1 : Dist < -epsilon ? -1 : 0;
36}
37
38///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
39/**
40 * Flips the winding order.
41 */
42///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
43void Triangle::Flip()
44{
45 Point Tmp = mVerts[1];
46 mVerts[1] = mVerts[2];
47 mVerts[2] = Tmp;
48}
49
50///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
51/**
52 * Computes the triangle area.
53 * \return the area
54 */
55///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
56float Triangle::Area() const
57{
58 const Point& p0 = mVerts[0];
59 const Point& p1 = mVerts[1];
60 const Point& p2 = mVerts[2];
61 return ((p0 - p1)^(p0 - p2)).Magnitude() * 0.5f;
62}
63
64///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
65/**
66 * Computes the triangle perimeter.
67 * \return the perimeter
68 */
69///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
70float Triangle::Perimeter() const
71{
72 const Point& p0 = mVerts[0];
73 const Point& p1 = mVerts[1];
74 const Point& p2 = mVerts[2];
75 return p0.Distance(p1)
76 + p0.Distance(p2)
77 + p1.Distance(p2);
78}
79
80///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
81/**
82 * Computes the triangle compacity.
83 * \return the compacity
84 */
85///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
86float Triangle::Compacity() const
87{
88 float P = Perimeter();
89 if(P==0.0f) return 0.0f;
90 return (4.0f*PI*Area()/(P*P));
91}
92
93///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
94/**
95 * Computes the triangle normal.
96 * \param normal [out] the computed normal
97 */
98///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
99void Triangle::Normal(Point& normal) const
100{
101 const Point& p0 = mVerts[0];
102 const Point& p1 = mVerts[1];
103 const Point& p2 = mVerts[2];
104 normal = ((p0 - p1)^(p0 - p2)).Normalize();
105}
106
107///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
108/**
109 * Computes the triangle denormalized normal.
110 * \param normal [out] the computed normal
111 */
112///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
113void Triangle::DenormalizedNormal(Point& normal) const
114{
115 const Point& p0 = mVerts[0];
116 const Point& p1 = mVerts[1];
117 const Point& p2 = mVerts[2];
118 normal = ((p0 - p1)^(p0 - p2));
119}
120
121///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
122/**
123 * Computes the triangle center.
124 * \param center [out] the computed center
125 */
126///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
127void Triangle::Center(Point& center) const
128{
129 const Point& p0 = mVerts[0];
130 const Point& p1 = mVerts[1];
131 const Point& p2 = mVerts[2];
132 center = (p0 + p1 + p2)*INV3;
133}
134
135PartVal Triangle::TestAgainstPlane(const Plane& plane, float epsilon) const
136{
137 bool Pos = false, Neg = false;
138
139 // Loop through all vertices
140 for(udword i=0;i<3;i++)
141 {
142 // Compute side:
143 sdword Side = VPlaneSideEps(mVerts[i], plane, epsilon);
144
145 if (Side < 0) Neg = true;
146 else if (Side > 0) Pos = true;
147 }
148
149 if (!Pos && !Neg) return TRI_ON_PLANE;
150 else if (Pos && Neg) return TRI_INTERSECT;
151 else if (Pos && !Neg) return TRI_PLUS_SPACE;
152 else if (!Pos && Neg) return TRI_MINUS_SPACE;
153
154 // What?!
155 return TRI_FORCEDWORD;
156}
157
158///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
159/**
160 * Computes the triangle moment.
161 * \param m [out] the moment
162 */
163///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
164/*
165void Triangle::ComputeMoment(Moment& m)
166{
167 // Compute the area of the triangle
168 m.mArea = Area();
169
170 // Compute the centroid
171 Center(m.mCentroid);
172
173 // Second-order components. Handle zero-area faces.
174 Point& p = mVerts[0];
175 Point& q = mVerts[1];
176 Point& r = mVerts[2];
177 if(m.mArea==0.0f)
178 {
179 // This triangle has zero area. The second order components would be eliminated with the usual formula, so, for the
180 // sake of robustness we use an alternative form. These are the centroid and second-order components of the triangle's vertices.
181 m.mCovariance.m[0][0] = (p.x*p.x + q.x*q.x + r.x*r.x);
182 m.mCovariance.m[0][1] = (p.x*p.y + q.x*q.y + r.x*r.y);
183 m.mCovariance.m[0][2] = (p.x*p.z + q.x*q.z + r.x*r.z);
184 m.mCovariance.m[1][1] = (p.y*p.y + q.y*q.y + r.y*r.y);
185 m.mCovariance.m[1][2] = (p.y*p.z + q.y*q.z + r.y*r.z);
186 m.mCovariance.m[2][2] = (p.z*p.z + q.z*q.z + r.z*r.z);
187 m.mCovariance.m[2][1] = m.mCovariance.m[1][2];
188 m.mCovariance.m[1][0] = m.mCovariance.m[0][1];
189 m.mCovariance.m[2][0] = m.mCovariance.m[0][2];
190 }
191 else
192 {
193 const float OneOverTwelve = 1.0f / 12.0f;
194 m.mCovariance.m[0][0] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.x + p.x*p.x + q.x*q.x + r.x*r.x) * OneOverTwelve;
195 m.mCovariance.m[0][1] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.y + p.x*p.y + q.x*q.y + r.x*r.y) * OneOverTwelve;
196 m.mCovariance.m[1][1] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.y + p.y*p.y + q.y*q.y + r.y*r.y) * OneOverTwelve;
197 m.mCovariance.m[0][2] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.z + p.x*p.z + q.x*q.z + r.x*r.z) * OneOverTwelve;
198 m.mCovariance.m[1][2] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.z + p.y*p.z + q.y*q.z + r.y*r.z) * OneOverTwelve;
199 m.mCovariance.m[2][2] = m.mArea * (9.0f * m.mCentroid.z*m.mCentroid.z + p.z*p.z + q.z*q.z + r.z*r.z) * OneOverTwelve;
200 m.mCovariance.m[2][1] = m.mCovariance.m[1][2];
201 m.mCovariance.m[1][0] = m.mCovariance.m[0][1];
202 m.mCovariance.m[2][0] = m.mCovariance.m[0][2];
203 }
204}
205*/
206
207///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
208/**
209 * Computes the triangle's smallest edge length.
210 * \return the smallest edge length
211 */
212///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
213float Triangle::MinEdgeLength() const
214{
215 float Min = MAX_FLOAT;
216 float Length01 = mVerts[0].Distance(mVerts[1]);
217 float Length02 = mVerts[0].Distance(mVerts[2]);
218 float Length12 = mVerts[1].Distance(mVerts[2]);
219 if(Length01 < Min) Min = Length01;
220 if(Length02 < Min) Min = Length02;
221 if(Length12 < Min) Min = Length12;
222 return Min;
223}
224
225///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
226/**
227 * Computes the triangle's largest edge length.
228 * \return the largest edge length
229 */
230///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
231float Triangle::MaxEdgeLength() const
232{
233 float Max = MIN_FLOAT;
234 float Length01 = mVerts[0].Distance(mVerts[1]);
235 float Length02 = mVerts[0].Distance(mVerts[2]);
236 float Length12 = mVerts[1].Distance(mVerts[2]);
237 if(Length01 > Max) Max = Length01;
238 if(Length02 > Max) Max = Length02;
239 if(Length12 > Max) Max = Length12;
240 return Max;
241}
242
243///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
244/**
245 * Computes a point on the triangle according to the stabbing information.
246 * \param u,v [in] point's barycentric coordinates
247 * \param pt [out] point on triangle
248 * \param nearvtx [out] index of nearest vertex
249 */
250///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
251void Triangle::ComputePoint(float u, float v, Point& pt, udword* nearvtx) const
252{
253 // Compute point coordinates
254 pt = (1.0f - u - v)*mVerts[0] + u*mVerts[1] + v*mVerts[2];
255
256 // Compute nearest vertex if needed
257 if(nearvtx)
258 {
259 // Compute distance vector
260 Point d(mVerts[0].SquareDistance(pt), // Distance^2 from vertex 0 to point on the face
261 mVerts[1].SquareDistance(pt), // Distance^2 from vertex 1 to point on the face
262 mVerts[2].SquareDistance(pt)); // Distance^2 from vertex 2 to point on the face
263
264 // Get smallest distance
265 *nearvtx = d.SmallestAxis();
266 }
267}
268
269void Triangle::Inflate(float fat_coeff, bool constant_border)
270{
271 // Compute triangle center
272 Point TriangleCenter;
273 Center(TriangleCenter);
274
275 // Don't normalize?
276 // Normalize => add a constant border, regardless of triangle size
277 // Don't => add more to big triangles
278 for(udword i=0;i<3;i++)
279 {
280 Point v = mVerts[i] - TriangleCenter;
281
282 if(constant_border) v.Normalize();
283
284 mVerts[i] += v * fat_coeff;
285 }
286}
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceTriangle.h b/libraries/ode-0.9/OPCODE/Ice/IceTriangle.h
new file mode 100644
index 0000000..a984db8
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceTriangle.h
@@ -0,0 +1,68 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains a handy triangle class.
4 * \file IceTriangle.h
5 * \author Pierre Terdiman
6 * \date January, 17, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICETRIANGLE_H__
13#define __ICETRIANGLE_H__
14
15 // Forward declarations
16 class Moment;
17
18 // Partitioning values
19 enum PartVal
20 {
21 TRI_MINUS_SPACE = 0, //!< Triangle is in the negative space
22 TRI_PLUS_SPACE = 1, //!< Triangle is in the positive space
23 TRI_INTERSECT = 2, //!< Triangle intersects plane
24 TRI_ON_PLANE = 3, //!< Triangle and plane are coplanar
25
26 TRI_FORCEDWORD = 0x7fffffff
27 };
28
29 // A triangle class.
30 class ICEMATHS_API Triangle
31 {
32 public:
33 //! Constructor
34 inline_ Triangle() {}
35 //! Constructor
36 inline_ Triangle(const Point& p0, const Point& p1, const Point& p2) { mVerts[0]=p0; mVerts[1]=p1; mVerts[2]=p2; }
37 //! Copy constructor
38 inline_ Triangle(const Triangle& triangle)
39 {
40 mVerts[0] = triangle.mVerts[0];
41 mVerts[1] = triangle.mVerts[1];
42 mVerts[2] = triangle.mVerts[2];
43 }
44 //! Destructor
45 inline_ ~Triangle() {}
46 //! Vertices
47 Point mVerts[3];
48
49 // Methods
50 void Flip();
51 float Area() const;
52 float Perimeter() const;
53 float Compacity() const;
54 void Normal(Point& normal) const;
55 void DenormalizedNormal(Point& normal) const;
56 void Center(Point& center) const;
57 inline_ Plane PlaneEquation() const { return Plane(mVerts[0], mVerts[1], mVerts[2]); }
58
59 PartVal TestAgainstPlane(const Plane& plane, float epsilon) const;
60// float Distance(Point& cp, Point& cq, Tri& tri);
61 void ComputeMoment(Moment& m);
62 float MinEdgeLength() const;
63 float MaxEdgeLength() const;
64 void ComputePoint(float u, float v, Point& pt, udword* nearvtx=null) const;
65 void Inflate(float fat_coeff, bool constant_border);
66 };
67
68#endif // __ICETRIANGLE_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceTypes.h b/libraries/ode-0.9/OPCODE/Ice/IceTypes.h
new file mode 100644
index 0000000..4ff71b5
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceTypes.h
@@ -0,0 +1,171 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains custom types.
4 * \file IceTypes.h
5 * \author Pierre Terdiman
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICETYPES_H__
13#define __ICETYPES_H__
14
15///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
16// Things to help us compile on non-windows platforms
17
18#if defined(__MACOSX__) || defined(__APPLE__)
19#undef bool
20#define bool char
21#undef true
22#define true ((bool)-1)
23#undef false
24#define false ((bool)0)
25#endif // mac stuff
26
27///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
28
29 #define USE_HANDLE_MANAGER
30
31 // Constants
32 #define PI 3.1415926535897932384626433832795028841971693993751f //!< PI
33 #define HALFPI 1.57079632679489661923f //!< 0.5 * PI
34 #define TWOPI 6.28318530717958647692f //!< 2.0 * PI
35 #define INVPI 0.31830988618379067154f //!< 1.0 / PI
36
37 #define RADTODEG 57.2957795130823208768f //!< 180.0 / PI, convert radians to degrees
38 #define DEGTORAD 0.01745329251994329577f //!< PI / 180.0, convert degrees to radians
39
40 #define EXP 2.71828182845904523536f //!< e
41 #define INVLOG2 3.32192809488736234787f //!< 1.0 / log10(2)
42 #define LN2 0.693147180559945f //!< ln(2)
43 #define INVLN2 1.44269504089f //!< 1.0f / ln(2)
44
45 #define INV3 0.33333333333333333333f //!< 1/3
46 #define INV6 0.16666666666666666666f //!< 1/6
47 #define INV7 0.14285714285714285714f //!< 1/7
48 #define INV9 0.11111111111111111111f //!< 1/9
49 #define INV255 0.00392156862745098039f //!< 1/255
50
51 #define SQRT2 1.41421356237f //!< sqrt(2)
52 #define INVSQRT2 0.707106781188f //!< 1 / sqrt(2)
53
54 #define SQRT3 1.73205080757f //!< sqrt(3)
55 #define INVSQRT3 0.577350269189f //!< 1 / sqrt(3)
56
57 #define null 0 //!< our own NULL pointer
58
59 // Custom types used in ICE
60 typedef signed char sbyte; //!< sizeof(sbyte) must be 1
61 typedef unsigned char ubyte; //!< sizeof(ubyte) must be 1
62 typedef signed short sword; //!< sizeof(sword) must be 2
63 typedef unsigned short uword; //!< sizeof(uword) must be 2
64 typedef signed int sdword; //!< sizeof(sdword) must be 4
65 typedef unsigned int udword; //!< sizeof(udword) must be 4
66 typedef signed __int64 sqword; //!< sizeof(sqword) must be 8
67 typedef unsigned __int64 uqword; //!< sizeof(uqword) must be 8
68 typedef float float32; //!< sizeof(float32) must be 4
69 typedef double float64; //!< sizeof(float64) must be 4
70
71 ICE_COMPILE_TIME_ASSERT(sizeof(bool)==1); // ...otherwise things might fail with VC++ 4.2 !
72 ICE_COMPILE_TIME_ASSERT(sizeof(ubyte)==1);
73 ICE_COMPILE_TIME_ASSERT(sizeof(sbyte)==1);
74 ICE_COMPILE_TIME_ASSERT(sizeof(sword)==2);
75 ICE_COMPILE_TIME_ASSERT(sizeof(uword)==2);
76 ICE_COMPILE_TIME_ASSERT(sizeof(udword)==4);
77 ICE_COMPILE_TIME_ASSERT(sizeof(sdword)==4);
78 ICE_COMPILE_TIME_ASSERT(sizeof(uqword)==8);
79 ICE_COMPILE_TIME_ASSERT(sizeof(sqword)==8);
80
81 //! TO BE DOCUMENTED
82 #define DECLARE_ICE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
83
84 typedef udword DynID; //!< Dynamic identifier
85#ifdef USE_HANDLE_MANAGER
86 typedef udword KID; //!< Kernel ID
87// DECLARE_ICE_HANDLE(KID);
88#else
89 typedef uword KID; //!< Kernel ID
90#endif
91 typedef udword RTYPE; //!< Relationship-type (!) between owners and references
92 #define INVALID_ID 0xffffffff //!< Invalid dword ID (counterpart of null pointers)
93#ifdef USE_HANDLE_MANAGER
94 #define INVALID_KID 0xffffffff //!< Invalid Kernel ID
95#else
96 #define INVALID_KID 0xffff //!< Invalid Kernel ID
97#endif
98 #define INVALID_NUMBER 0xDEADBEEF //!< Standard junk value
99
100 // Define BOOL if needed
101 #ifndef BOOL
102 typedef int BOOL; //!< Another boolean type.
103 #endif
104
105 //! Union of a float and a sdword
106 typedef union {
107 float f; //!< The float
108 sdword d; //!< The integer
109 }scell;
110
111 //! Union of a float and a udword
112 typedef union {
113 float f; //!< The float
114 udword d; //!< The integer
115 }ucell;
116
117 // Type ranges
118 #define MAX_SBYTE 0x7f //!< max possible sbyte value
119 #define MIN_SBYTE 0x80 //!< min possible sbyte value
120 #define MAX_UBYTE 0xff //!< max possible ubyte value
121 #define MIN_UBYTE 0x00 //!< min possible ubyte value
122 #define MAX_SWORD 0x7fff //!< max possible sword value
123 #define MIN_SWORD 0x8000 //!< min possible sword value
124 #define MAX_UWORD 0xffff //!< max possible uword value
125 #define MIN_UWORD 0x0000 //!< min possible uword value
126 #define MAX_SDWORD 0x7fffffff //!< max possible sdword value
127 #define MIN_SDWORD 0x80000000 //!< min possible sdword value
128 #define MAX_UDWORD 0xffffffff //!< max possible udword value
129 #define MIN_UDWORD 0x00000000 //!< min possible udword value
130 #define MAX_FLOAT FLT_MAX //!< max possible float value
131 #define MIN_FLOAT (-FLT_MAX) //!< min possible loat value
132 #define IEEE_1_0 0x3f800000 //!< integer representation of 1.0
133 #define IEEE_255_0 0x437f0000 //!< integer representation of 255.0
134 #define IEEE_MAX_FLOAT 0x7f7fffff //!< integer representation of MAX_FLOAT
135 #define IEEE_MIN_FLOAT 0xff7fffff //!< integer representation of MIN_FLOAT
136 #define IEEE_UNDERFLOW_LIMIT 0x1a000000
137
138 #define ONE_OVER_RAND_MAX (1.0f / float(RAND_MAX)) //!< Inverse of the max possible value returned by rand()
139
140 typedef int (__stdcall* PROC)(); //!< A standard procedure call.
141 typedef bool (*ENUMERATION)(udword value, udword param, udword context); //!< ICE standard enumeration call
142 typedef void** VTABLE; //!< A V-Table.
143
144 #undef MIN
145 #undef MAX
146 #define MIN(a, b) ((a) < (b) ? (a) : (b)) //!< Returns the min value between a and b
147 #define MAX(a, b) ((a) > (b) ? (a) : (b)) //!< Returns the max value between a and b
148 #define MAXMAX(a,b,c) ((a) > (b) ? MAX (a,c) : MAX (b,c)) //!< Returns the max value between a, b and c
149
150 template<class T> inline_ const T& TMin (const T& a, const T& b) { return b < a ? b : a; }
151 template<class T> inline_ const T& TMax (const T& a, const T& b) { return a < b ? b : a; }
152 template<class T> inline_ void TSetMin (T& a, const T& b) { if(a>b) a = b; }
153 template<class T> inline_ void TSetMax (T& a, const T& b) { if(a<b) a = b; }
154
155 #define SQR(x) ((x)*(x)) //!< Returns x square
156 #define CUBE(x) ((x)*(x)*(x)) //!< Returns x cube
157
158 #define AND & //!< ...
159 #define OR | //!< ...
160 #define XOR ^ //!< ...
161
162 #define QUADRAT(x) ((x)*(x)) //!< Returns x square
163
164#ifdef _WIN32
165# define srand48(x) srand((unsigned int) (x))
166# define srandom(x) srand((unsigned int) (x))
167# define random() ((double) rand())
168# define drand48() ((double) (((double) rand()) / ((double) RAND_MAX)))
169#endif
170
171#endif // __ICETYPES_H__
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceUtils.cpp b/libraries/ode-0.9/OPCODE/Ice/IceUtils.cpp
new file mode 100644
index 0000000..29b6c57
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceUtils.cpp
@@ -0,0 +1,39 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains misc. useful macros & defines.
4 * \file IceUtils.cpp
5 * \author Pierre Terdiman (collected from various sources)
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Precompiled Header
12#include "Stdafx.h"
13
14using namespace IceCore;
15
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17/**
18 * Returns the alignment of the input address.
19 * \fn Alignment()
20 * \param address [in] address to check
21 * \return the best alignment (e.g. 1 for odd addresses, etc)
22 */
23///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
24udword IceCore::Alignment(udword address)
25{
26 // Returns 0 for null addresses
27 if(!address) return 0;
28
29 // Test all bits
30 udword Align = 1;
31 for(udword i=1;i<32;i++)
32 {
33 // Returns as soon as the alignment is broken
34 if(address&Align) return Align;
35 Align<<=1;
36 }
37 // Here all bits are null, except the highest one (else the address would be null)
38 return Align;
39}
diff --git a/libraries/ode-0.9/OPCODE/Ice/IceUtils.h b/libraries/ode-0.9/OPCODE/Ice/IceUtils.h
new file mode 100644
index 0000000..f4552ec
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Ice/IceUtils.h
@@ -0,0 +1,256 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Contains misc. useful macros & defines.
4 * \file IceUtils.h
5 * \author Pierre Terdiman (collected from various sources)
6 * \date April, 4, 2000
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11// Include Guard
12#ifndef __ICEUTILS_H__
13#define __ICEUTILS_H__
14
15 #define START_RUNONCE { static bool __RunOnce__ = false; if(!__RunOnce__){
16 #define END_RUNONCE __RunOnce__ = true;}}
17
18 //! Reverse all the bits in a 32 bit word (from Steve Baker's Cute Code Collection)
19 //! (each line can be done in any order.
20 inline_ void ReverseBits(udword& n)
21 {
22 n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
23 n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
24 n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
25 n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
26 n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000);
27 // Etc for larger intergers (64 bits in Java)
28 // NOTE: the >> operation must be unsigned! (>>> in java)
29 }
30
31 //! Count the number of '1' bits in a 32 bit word (from Steve Baker's Cute Code Collection)
32 inline_ udword CountBits(udword n)
33 {
34 // This relies of the fact that the count of n bits can NOT overflow
35 // an n bit interger. EG: 1 bit count takes a 1 bit interger, 2 bit counts
36 // 2 bit interger, 3 bit count requires only a 2 bit interger.
37 // So we add all bit pairs, then each nible, then each byte etc...
38 n = (n & 0x55555555) + ((n & 0xaaaaaaaa) >> 1);
39 n = (n & 0x33333333) + ((n & 0xcccccccc) >> 2);
40 n = (n & 0x0f0f0f0f) + ((n & 0xf0f0f0f0) >> 4);
41 n = (n & 0x00ff00ff) + ((n & 0xff00ff00) >> 8);
42 n = (n & 0x0000ffff) + ((n & 0xffff0000) >> 16);
43 // Etc for larger intergers (64 bits in Java)
44 // NOTE: the >> operation must be unsigned! (>>> in java)
45 return n;
46 }
47
48 //! Even faster?
49 inline_ udword CountBits2(udword bits)
50 {
51 bits = bits - ((bits >> 1) & 0x55555555);
52 bits = ((bits >> 2) & 0x33333333) + (bits & 0x33333333);
53 bits = ((bits >> 4) + bits) & 0x0F0F0F0F;
54 return (bits * 0x01010101) >> 24;
55 }
56
57 //! Spread out bits. EG 00001111 -> 0101010101
58 //! 00001010 -> 0100010000
59 //! This is used to interleve to intergers to produce a `Morten Key'
60 //! used in Space Filling Curves (See DrDobbs Journal, July 1999)
61 //! Order is important.
62 inline_ void SpreadBits(udword& n)
63 {
64 n = ( n & 0x0000ffff) | (( n & 0xffff0000) << 16);
65 n = ( n & 0x000000ff) | (( n & 0x0000ff00) << 8);
66 n = ( n & 0x000f000f) | (( n & 0x00f000f0) << 4);
67 n = ( n & 0x03030303) | (( n & 0x0c0c0c0c) << 2);
68 n = ( n & 0x11111111) | (( n & 0x22222222) << 1);
69 }
70
71 // Next Largest Power of 2
72 // Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm
73 // that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with
74 // the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next
75 // largest power of 2. For a 32-bit value:
76 inline_ udword nlpo2(udword x)
77 {
78 x |= (x >> 1);
79 x |= (x >> 2);
80 x |= (x >> 4);
81 x |= (x >> 8);
82 x |= (x >> 16);
83 return x+1;
84 }
85
86 //! Test to see if a number is an exact power of two (from Steve Baker's Cute Code Collection)
87 inline_ bool IsPowerOfTwo(udword n) { return ((n&(n-1))==0); }
88
89 //! Zero the least significant '1' bit in a word. (from Steve Baker's Cute Code Collection)
90 inline_ void ZeroLeastSetBit(udword& n) { n&=(n-1); }
91
92 //! Set the least significant N bits in a word. (from Steve Baker's Cute Code Collection)
93 inline_ void SetLeastNBits(udword& x, udword n) { x|=~(~0<<n); }
94
95 //! Classic XOR swap (from Steve Baker's Cute Code Collection)
96 //! x ^= y; /* x' = (x^y) */
97 //! y ^= x; /* y' = (y^(x^y)) = x */
98 //! x ^= y; /* x' = (x^y)^x = y */
99 inline_ void Swap(udword& x, udword& y) { x ^= y; y ^= x; x ^= y; }
100
101 //! Little/Big endian (from Steve Baker's Cute Code Collection)
102 //!
103 //! Extra comments by Kenny Hoff:
104 //! Determines the byte-ordering of the current machine (little or big endian)
105 //! by setting an integer value to 1 (so least significant bit is now 1); take
106 //! the address of the int and cast to a byte pointer (treat integer as an
107 //! array of four bytes); check the value of the first byte (must be 0 or 1).
108 //! If the value is 1, then the first byte least significant byte and this
109 //! implies LITTLE endian. If the value is 0, the first byte is the most
110 //! significant byte, BIG endian. Examples:
111 //! integer 1 on BIG endian: 00000000 00000000 00000000 00000001
112 //! integer 1 on LITTLE endian: 00000001 00000000 00000000 00000000
113 //!---------------------------------------------------------------------------
114 //! int IsLittleEndian() { int x=1; return ( ((char*)(&x))[0] ); }
115 inline_ char LittleEndian() { int i = 1; return *((char*)&i); }
116
117 //!< Alternative abs function
118 inline_ udword abs_(sdword x) { sdword y= x >> 31; return (x^y)-y; }
119
120 //!< Alternative min function
121 inline_ sdword min_(sdword a, sdword b) { sdword delta = b-a; return a + (delta&(delta>>31)); }
122
123 // Determine if one of the bytes in a 4 byte word is zero
124 inline_ BOOL HasNullByte(udword x) { return ((x + 0xfefefeff) & (~x) & 0x80808080); }
125
126 // To find the smallest 1 bit in a word EG: ~~~~~~10---0 => 0----010---0
127 inline_ udword LowestOneBit(udword w) { return ((w) & (~(w)+1)); }
128// inline_ udword LowestOneBit_(udword w) { return ((w) & (-(w))); }
129
130 // Most Significant 1 Bit
131 // Given a binary integer value x, the most significant 1 bit (highest numbered element of a bit set)
132 // can be computed using a SWAR algorithm that recursively "folds" the upper bits into the lower bits.
133 // This process yields a bit vector with the same most significant 1 as x, but all 1's below it.
134 // Bitwise AND of the original value with the complement of the "folded" value shifted down by one
135 // yields the most significant bit. For a 32-bit value:
136 inline_ udword msb32(udword x)
137 {
138 x |= (x >> 1);
139 x |= (x >> 2);
140 x |= (x >> 4);
141 x |= (x >> 8);
142 x |= (x >> 16);
143 return (x & ~(x >> 1));
144 }
145
146 /*
147 "Just call it repeatedly with various input values and always with the same variable as "memory".
148 The sharpness determines the degree of filtering, where 0 completely filters out the input, and 1
149 does no filtering at all.
150
151 I seem to recall from college that this is called an IIR (Infinite Impulse Response) filter. As opposed
152 to the more typical FIR (Finite Impulse Response).
153
154 Also, I'd say that you can make more intelligent and interesting filters than this, for example filters
155 that remove wrong responses from the mouse because it's being moved too fast. You'd want such a filter
156 to be applied before this one, of course."
157
158 (JCAB on Flipcode)
159 */
160 inline_ float FeedbackFilter(float val, float& memory, float sharpness)
161 {
162 ASSERT(sharpness>=0.0f && sharpness<=1.0f && "Invalid sharpness value in feedback filter");
163 if(sharpness<0.0f) sharpness = 0.0f;
164 else if(sharpness>1.0f) sharpness = 1.0f;
165 return memory = val * sharpness + memory * (1.0f - sharpness);
166 }
167
168 //! If you can guarantee that your input domain (i.e. value of x) is slightly
169 //! limited (abs(x) must be < ((1<<31u)-32767)), then you can use the
170 //! following code to clamp the resulting value into [-32768,+32767] range:
171 inline_ int ClampToInt16(int x)
172 {
173// ASSERT(abs(x) < (int)((1<<31u)-32767));
174
175 int delta = 32767 - x;
176 x += (delta>>31) & delta;
177 delta = x + 32768;
178 x -= (delta>>31) & delta;
179 return x;
180 }
181
182 // Generic functions
183 template<class Type> inline_ void TSwap(Type& a, Type& b) { const Type c = a; a = b; b = c; }
184 template<class Type> inline_ Type TClamp(const Type& x, const Type& lo, const Type& hi) { return ((x<lo) ? lo : (x>hi) ? hi : x); }
185
186 template<class Type> inline_ void TSort(Type& a, Type& b)
187 {
188 if(a>b) TSwap(a, b);
189 }
190
191 template<class Type> inline_ void TSort(Type& a, Type& b, Type& c)
192 {
193 if(a>b) TSwap(a, b);
194 if(b>c) TSwap(b, c);
195 if(a>b) TSwap(a, b);
196 if(b>c) TSwap(b, c);
197 }
198
199 // Prevent nasty user-manipulations (strategy borrowed from Charles Bloom)
200// #define PREVENT_COPY(curclass) void operator = (const curclass& object) { ASSERT(!"Bad use of operator ="); }
201 // ... actually this is better !
202 #define PREVENT_COPY(cur_class) private: cur_class(const cur_class& object); cur_class& operator=(const cur_class& object);
203
204 //! TO BE DOCUMENTED
205 #define OFFSET_OF(Class, Member) (size_t)&(((Class*)0)->Member)
206 //! TO BE DOCUMENTED
207 #define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0]))
208
209 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
210 /**
211 * Returns the alignment of the input address.
212 * \fn Alignment()
213 * \param address [in] address to check
214 * \return the best alignment (e.g. 1 for odd addresses, etc)
215 */
216 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
217 FUNCTION ICECORE_API udword Alignment(udword address);
218
219 #define IS_ALIGNED_2(x) ((x&1)==0)
220 #define IS_ALIGNED_4(x) ((x&3)==0)
221 #define IS_ALIGNED_8(x) ((x&7)==0)
222
223 inline_ void _prefetch(void const* ptr) { (void)*(char const volatile *)ptr; }
224
225 // Compute implicit coords from an index:
226 // The idea is to get back 2D coords from a 1D index.
227 // For example:
228 //
229 // 0 1 2 ... nbu-1
230 // nbu nbu+1 i ...
231 //
232 // We have i, we're looking for the equivalent (u=2, v=1) location.
233 // i = u + v*nbu
234 // <=> i/nbu = u/nbu + v
235 // Since 0 <= u < nbu, u/nbu = 0 (integer)
236 // Hence: v = i/nbu
237 // Then we simply put it back in the original equation to compute u = i - v*nbu
238 inline_ void Compute2DCoords(udword& u, udword& v, udword i, udword nbu)
239 {
240 v = i / nbu;
241 u = i - (v * nbu);
242 }
243
244 // In 3D: i = u + v*nbu + w*nbu*nbv
245 // <=> i/(nbu*nbv) = u/(nbu*nbv) + v/nbv + w
246 // u/(nbu*nbv) is null since u/nbu was null already.
247 // v/nbv is null as well for the same reason.
248 // Hence w = i/(nbu*nbv)
249 // Then we're left with a 2D problem: i' = i - w*nbu*nbv = u + v*nbu
250 inline_ void Compute3DCoords(udword& u, udword& v, udword& w, udword i, udword nbu, udword nbu_nbv)
251 {
252 w = i / (nbu_nbv);
253 Compute2DCoords(u, v, i - (w * nbu_nbv), nbu);
254 }
255
256#endif // __ICEUTILS_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_AABBCollider.cpp b/libraries/ode-0.9/OPCODE/OPC_AABBCollider.cpp
new file mode 100644
index 0000000..eaaadf1
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_AABBCollider.cpp
@@ -0,0 +1,696 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for an AABB collider.
12 * \file OPC_AABBCollider.cpp
13 * \author Pierre Terdiman
14 * \date January, 1st, 2002
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19/**
20 * Contains an AABB-vs-tree collider.
21 *
22 * \class AABBCollider
23 * \author Pierre Terdiman
24 * \version 1.3
25 * \date January, 1st, 2002
26*/
27///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
28
29///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
30// Precompiled Header
31#include "Stdafx.h"
32
33using namespace Opcode;
34
35#include "OPC_BoxBoxOverlap.h"
36#include "OPC_TriBoxOverlap.h"
37
38#define SET_CONTACT(prim_index, flag) \
39 /* Set contact status */ \
40 mFlags |= flag; \
41 mTouchedPrimitives->Add(udword(prim_index));
42
43//! AABB-triangle test
44#define AABB_PRIM(prim_index, flag) \
45 /* Request vertices from the app */ \
46 VertexPointers VP; mIMesh->GetTriangle(VP, prim_index);\
47 mLeafVerts[0] = *VP.Vertex[0]; \
48 mLeafVerts[1] = *VP.Vertex[1]; \
49 mLeafVerts[2] = *VP.Vertex[2]; \
50 /* Perform triangle-box overlap test */ \
51 if(TriBoxOverlap()) \
52 { \
53 SET_CONTACT(prim_index, flag) \
54 }
55
56///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
57/**
58 * Constructor.
59 */
60///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
61AABBCollider::AABBCollider()
62{
63}
64
65///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
66/**
67 * Destructor.
68 */
69///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
70AABBCollider::~AABBCollider()
71{
72}
73
74///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
75/**
76 * Generic collision query for generic OPCODE models. After the call, access the results:
77 * - with GetContactStatus()
78 * - with GetNbTouchedPrimitives()
79 * - with GetTouchedPrimitives()
80 *
81 * \param cache [in/out] a box cache
82 * \param box [in] collision AABB in world space
83 * \param model [in] Opcode model to collide with
84 * \return true if success
85 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
86 */
87///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
88bool AABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const Model& model)
89{
90 // Checkings
91 if(!Setup(&model)) return false;
92
93 // Init collision query
94 if(InitQuery(cache, box)) return true;
95
96 if(!model.HasLeafNodes())
97 {
98 if(model.IsQuantized())
99 {
100 const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
101
102 // Setup dequantization coeffs
103 mCenterCoeff = Tree->mCenterCoeff;
104 mExtentsCoeff = Tree->mExtentsCoeff;
105
106 // Perform collision query
107 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
108 else _Collide(Tree->GetNodes());
109 }
110 else
111 {
112 const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
113
114 // Perform collision query
115 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
116 else _Collide(Tree->GetNodes());
117 }
118 }
119 else
120 {
121 if(model.IsQuantized())
122 {
123 const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
124
125 // Setup dequantization coeffs
126 mCenterCoeff = Tree->mCenterCoeff;
127 mExtentsCoeff = Tree->mExtentsCoeff;
128
129 // Perform collision query
130 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
131 else _Collide(Tree->GetNodes());
132 }
133 else
134 {
135 const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
136
137 // Perform collision query
138 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
139 else _Collide(Tree->GetNodes());
140 }
141 }
142 return true;
143}
144
145///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
146/**
147 * Initializes a collision query :
148 * - reset stats & contact status
149 * - check temporal coherence
150 *
151 * \param cache [in/out] a box cache
152 * \param box [in] AABB in world space
153 * \return TRUE if we can return immediately
154 */
155///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
156BOOL AABBCollider::InitQuery(AABBCache& cache, const CollisionAABB& box)
157{
158 // 1) Call the base method
159 VolumeCollider::InitQuery();
160
161 // 2) Keep track of the query box
162 mBox = box;
163
164 // 3) Setup destination pointer
165 mTouchedPrimitives = &cache.TouchedPrimitives;
166
167 // 4) Special case: 1-triangle meshes [Opcode 1.3]
168 if(mCurrentModel && mCurrentModel->HasSingleNode())
169 {
170 if(!SkipPrimitiveTests())
171 {
172 // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0.
173 mTouchedPrimitives->Reset();
174
175 // Perform overlap test between the unique triangle and the box (and set contact status if needed)
176 AABB_PRIM(udword(0), OPC_CONTACT)
177
178 // Return immediately regardless of status
179 return TRUE;
180 }
181 }
182
183 // 5) Check temporal coherence :
184 if(TemporalCoherenceEnabled())
185 {
186 // Here we use temporal coherence
187 // => check results from previous frame before performing the collision query
188 if(FirstContactEnabled())
189 {
190 // We're only interested in the first contact found => test the unique previously touched face
191 if(mTouchedPrimitives->GetNbEntries())
192 {
193 // Get index of previously touched face = the first entry in the array
194 udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0);
195
196 // Then reset the array:
197 // - if the overlap test below is successful, the index we'll get added back anyway
198 // - if it isn't, then the array should be reset anyway for the normal query
199 mTouchedPrimitives->Reset();
200
201 // Perform overlap test between the cached triangle and the box (and set contact status if needed)
202 AABB_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT)
203
204 // Return immediately if possible
205 if(GetContactStatus()) return TRUE;
206 }
207 // else no face has been touched during previous query
208 // => we'll have to perform a normal query
209 }
210 else
211 {
212 // We're interested in all contacts =>test the new real box N(ew) against the previous fat box P(revious):
213 if(IsCacheValid(cache) && mBox.IsInside(cache.FatBox))
214 {
215 // - if N is included in P, return previous list
216 // => we simply leave the list (mTouchedFaces) unchanged
217
218 // Set contact status if needed
219 if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT;
220
221 // In any case we don't need to do a query
222 return TRUE;
223 }
224 else
225 {
226 // - else do the query using a fat N
227
228 // Reset cache since we'll about to perform a real query
229 mTouchedPrimitives->Reset();
230
231 // Make a fat box so that coherence will work for subsequent frames
232 mBox.mExtents *= cache.FatCoeff;
233
234 // Update cache with query data (signature for cached faces)
235 cache.FatBox = mBox;
236 }
237 }
238 }
239 else
240 {
241 // Here we don't use temporal coherence => do a normal query
242 mTouchedPrimitives->Reset();
243 }
244
245 // 5) Precompute min & max bounds if needed
246 mMin = box.mCenter - box.mExtents;
247 mMax = box.mCenter + box.mExtents;
248
249 return FALSE;
250}
251
252///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
253/**
254 * Collision query for vanilla AABB trees.
255 * \param cache [in/out] a box cache
256 * \param box [in] collision AABB in world space
257 * \param tree [in] AABB tree
258 * \return true if success
259 */
260///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
261bool AABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const AABBTree* tree)
262{
263 // This is typically called for a scene tree, full of -AABBs-, not full of triangles.
264 // So we don't really have "primitives" to deal with. Hence it doesn't work with
265 // "FirstContact" + "TemporalCoherence".
266 ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) );
267
268 // Checkings
269 if(!tree) return false;
270
271 // Init collision query
272 if(InitQuery(cache, box)) return true;
273
274 // Perform collision query
275 _Collide(tree);
276
277 return true;
278}
279
280///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
281/**
282 * Checks the AABB completely contains the box. In which case we can end the query sooner.
283 * \param bc [in] box center
284 * \param be [in] box extents
285 * \return true if the AABB contains the whole box
286 */
287///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
288inline_ BOOL AABBCollider::AABBContainsBox(const Point& bc, const Point& be)
289{
290 if(mMin.x > bc.x - be.x) return FALSE;
291 if(mMin.y > bc.y - be.y) return FALSE;
292 if(mMin.z > bc.z - be.z) return FALSE;
293
294 if(mMax.x < bc.x + be.x) return FALSE;
295 if(mMax.y < bc.y + be.y) return FALSE;
296 if(mMax.z < bc.z + be.z) return FALSE;
297
298 return TRUE;
299}
300
301#define TEST_BOX_IN_AABB(center, extents) \
302 if(AABBContainsBox(center, extents)) \
303 { \
304 /* Set contact status */ \
305 mFlags |= OPC_CONTACT; \
306 _Dump(node); \
307 return; \
308 }
309
310///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
311/**
312 * Recursive collision query for normal AABB trees.
313 * \param node [in] current collision node
314 */
315///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
316void AABBCollider::_Collide(const AABBCollisionNode* node)
317{
318 // Perform AABB-AABB overlap test
319 if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return;
320
321 TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents)
322
323 if(node->IsLeaf())
324 {
325 AABB_PRIM(node->GetPrimitive(), OPC_CONTACT)
326 }
327 else
328 {
329 _Collide(node->GetPos());
330
331 if(ContactFound()) return;
332
333 _Collide(node->GetNeg());
334 }
335}
336
337///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
338/**
339 * Recursive collision query for normal AABB trees, without primitive tests.
340 * \param node [in] current collision node
341 */
342///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
343void AABBCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node)
344{
345 // Perform AABB-AABB overlap test
346 if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return;
347
348 TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents)
349
350 if(node->IsLeaf())
351 {
352 SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
353 }
354 else
355 {
356 _CollideNoPrimitiveTest(node->GetPos());
357
358 if(ContactFound()) return;
359
360 _CollideNoPrimitiveTest(node->GetNeg());
361 }
362}
363
364///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
365/**
366 * Recursive collision query for quantized AABB trees.
367 * \param node [in] current collision node
368 */
369///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
370void AABBCollider::_Collide(const AABBQuantizedNode* node)
371{
372 // Dequantize box
373 const QuantizedAABB& Box = node->mAABB;
374 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
375 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
376
377 // Perform AABB-AABB overlap test
378 if(!AABBAABBOverlap(Extents, Center)) return;
379
380 TEST_BOX_IN_AABB(Center, Extents)
381
382 if(node->IsLeaf())
383 {
384 AABB_PRIM(node->GetPrimitive(), OPC_CONTACT)
385 }
386 else
387 {
388 _Collide(node->GetPos());
389
390 if(ContactFound()) return;
391
392 _Collide(node->GetNeg());
393 }
394}
395
396///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
397/**
398 * Recursive collision query for quantized AABB trees, without primitive tests.
399 * \param node [in] current collision node
400 */
401///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
402void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node)
403{
404 // Dequantize box
405 const QuantizedAABB& Box = node->mAABB;
406 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
407 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
408
409 // Perform AABB-AABB overlap test
410 if(!AABBAABBOverlap(Extents, Center)) return;
411
412 TEST_BOX_IN_AABB(Center, Extents)
413
414 if(node->IsLeaf())
415 {
416 SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
417 }
418 else
419 {
420 _CollideNoPrimitiveTest(node->GetPos());
421
422 if(ContactFound()) return;
423
424 _CollideNoPrimitiveTest(node->GetNeg());
425 }
426}
427
428///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
429/**
430 * Recursive collision query for no-leaf AABB trees.
431 * \param node [in] current collision node
432 */
433///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
434void AABBCollider::_Collide(const AABBNoLeafNode* node)
435{
436 // Perform AABB-AABB overlap test
437 if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return;
438
439 TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents)
440
441 if(node->HasPosLeaf()) { AABB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
442 else _Collide(node->GetPos());
443
444 if(ContactFound()) return;
445
446 if(node->HasNegLeaf()) { AABB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
447 else _Collide(node->GetNeg());
448}
449
450///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
451/**
452 * Recursive collision query for no-leaf AABB trees, without primitive tests.
453 * \param node [in] current collision node
454 */
455///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
456void AABBCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node)
457{
458 // Perform AABB-AABB overlap test
459 if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return;
460
461 TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents)
462
463 if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
464 else _CollideNoPrimitiveTest(node->GetPos());
465
466 if(ContactFound()) return;
467
468 if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
469 else _CollideNoPrimitiveTest(node->GetNeg());
470}
471
472///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
473/**
474 * Recursive collision query for quantized no-leaf AABB trees.
475 * \param node [in] current collision node
476 */
477///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
478void AABBCollider::_Collide(const AABBQuantizedNoLeafNode* node)
479{
480 // Dequantize box
481 const QuantizedAABB& Box = node->mAABB;
482 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
483 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
484
485 // Perform AABB-AABB overlap test
486 if(!AABBAABBOverlap(Extents, Center)) return;
487
488 TEST_BOX_IN_AABB(Center, Extents)
489
490 if(node->HasPosLeaf()) { AABB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
491 else _Collide(node->GetPos());
492
493 if(ContactFound()) return;
494
495 if(node->HasNegLeaf()) { AABB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
496 else _Collide(node->GetNeg());
497}
498
499///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
500/**
501 * Recursive collision query for quantized no-leaf AABB trees, without primitive tests.
502 * \param node [in] current collision node
503 */
504///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
505void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node)
506{
507 // Dequantize box
508 const QuantizedAABB& Box = node->mAABB;
509 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
510 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
511
512 // Perform AABB-AABB overlap test
513 if(!AABBAABBOverlap(Extents, Center)) return;
514
515 TEST_BOX_IN_AABB(Center, Extents)
516
517 if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
518 else _CollideNoPrimitiveTest(node->GetPos());
519
520 if(ContactFound()) return;
521
522 if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
523 else _CollideNoPrimitiveTest(node->GetNeg());
524}
525
526///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
527/**
528 * Recursive collision query for vanilla AABB trees.
529 * \param node [in] current collision node
530 */
531///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
532void AABBCollider::_Collide(const AABBTreeNode* node)
533{
534 // Perform AABB-AABB overlap test
535 Point Center, Extents;
536 node->GetAABB()->GetCenter(Center);
537 node->GetAABB()->GetExtents(Extents);
538 if(!AABBAABBOverlap(Center, Extents)) return;
539
540 if(node->IsLeaf() || AABBContainsBox(Center, Extents))
541 {
542 mFlags |= OPC_CONTACT;
543 mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives());
544 }
545 else
546 {
547 _Collide(node->GetPos());
548 _Collide(node->GetNeg());
549 }
550}
551
552
553
554
555///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
556/**
557 * Constructor.
558 */
559///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
560HybridAABBCollider::HybridAABBCollider()
561{
562}
563
564///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
565/**
566 * Destructor.
567 */
568///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
569HybridAABBCollider::~HybridAABBCollider()
570{
571}
572
573bool HybridAABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const HybridModel& model)
574{
575 // We don't want primitive tests here!
576 mFlags |= OPC_NO_PRIMITIVE_TESTS;
577
578 // Checkings
579 if(!Setup(&model)) return false;
580
581 // Init collision query
582 if(InitQuery(cache, box)) return true;
583
584 // Special case for 1-leaf trees
585 if(mCurrentModel && mCurrentModel->HasSingleNode())
586 {
587 // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles
588 udword Nb = mIMesh->GetNbTriangles();
589
590 // Loop through all triangles
591 for(udword i=0;i<Nb;i++)
592 {
593 AABB_PRIM(i, OPC_CONTACT)
594 }
595 return true;
596 }
597
598 // Override destination array since we're only going to get leaf boxes here
599 mTouchedBoxes.Reset();
600 mTouchedPrimitives = &mTouchedBoxes;
601
602 // Now, do the actual query against leaf boxes
603 if(!model.HasLeafNodes())
604 {
605 if(model.IsQuantized())
606 {
607 const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
608
609 // Setup dequantization coeffs
610 mCenterCoeff = Tree->mCenterCoeff;
611 mExtentsCoeff = Tree->mExtentsCoeff;
612
613 // Perform collision query - we don't want primitive tests here!
614 _CollideNoPrimitiveTest(Tree->GetNodes());
615 }
616 else
617 {
618 const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
619
620 // Perform collision query - we don't want primitive tests here!
621 _CollideNoPrimitiveTest(Tree->GetNodes());
622 }
623 }
624 else
625 {
626 if(model.IsQuantized())
627 {
628 const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
629
630 // Setup dequantization coeffs
631 mCenterCoeff = Tree->mCenterCoeff;
632 mExtentsCoeff = Tree->mExtentsCoeff;
633
634 // Perform collision query - we don't want primitive tests here!
635 _CollideNoPrimitiveTest(Tree->GetNodes());
636 }
637 else
638 {
639 const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
640
641 // Perform collision query - we don't want primitive tests here!
642 _CollideNoPrimitiveTest(Tree->GetNodes());
643 }
644 }
645
646 // We only have a list of boxes so far
647 if(GetContactStatus())
648 {
649 // Reset contact status, since it currently only reflects collisions with leaf boxes
650 Collider::InitQuery();
651
652 // Change dest container so that we can use built-in overlap tests and get collided primitives
653 cache.TouchedPrimitives.Reset();
654 mTouchedPrimitives = &cache.TouchedPrimitives;
655
656 // Read touched leaf boxes
657 udword Nb = mTouchedBoxes.GetNbEntries();
658 const udword* Touched = mTouchedBoxes.GetEntries();
659
660 const LeafTriangles* LT = model.GetLeafTriangles();
661 const udword* Indices = model.GetIndices();
662
663 // Loop through touched leaves
664 while(Nb--)
665 {
666 const LeafTriangles& CurrentLeaf = LT[*Touched++];
667
668 // Each leaf box has a set of triangles
669 udword NbTris = CurrentLeaf.GetNbTriangles();
670 if(Indices)
671 {
672 const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()];
673
674 // Loop through triangles and test each of them
675 while(NbTris--)
676 {
677 udword TriangleIndex = *T++;
678 AABB_PRIM(TriangleIndex, OPC_CONTACT)
679 }
680 }
681 else
682 {
683 udword BaseIndex = CurrentLeaf.GetTriangleIndex();
684
685 // Loop through triangles and test each of them
686 while(NbTris--)
687 {
688 udword TriangleIndex = BaseIndex++;
689 AABB_PRIM(TriangleIndex, OPC_CONTACT)
690 }
691 }
692 }
693 }
694
695 return true;
696}
diff --git a/libraries/ode-0.9/OPCODE/OPC_AABBCollider.h b/libraries/ode-0.9/OPCODE/OPC_AABBCollider.h
new file mode 100644
index 0000000..315d2d3
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_AABBCollider.h
@@ -0,0 +1,97 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for an AABB collider.
12 * \file OPC_AABBCollider.h
13 * \author Pierre Terdiman
14 * \date January, 1st, 2002
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_AABBCOLLIDER_H__
21#define __OPC_AABBCOLLIDER_H__
22
23 struct OPCODE_API AABBCache : VolumeCache
24 {
25 AABBCache() : FatCoeff(1.1f)
26 {
27 FatBox.mCenter.Zero();
28 FatBox.mExtents.Zero();
29 }
30
31 // Cached faces signature
32 CollisionAABB FatBox; //!< Box used when performing the query resulting in cached faces
33 // User settings
34 float FatCoeff; //!< mRadius2 multiplier used to create a fat sphere
35 };
36
37 class OPCODE_API AABBCollider : public VolumeCollider
38 {
39 public:
40 // Constructor / Destructor
41 AABBCollider();
42 virtual ~AABBCollider();
43
44 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
45 /**
46 * Generic collision query for generic OPCODE models. After the call, access the results:
47 * - with GetContactStatus()
48 * - with GetNbTouchedPrimitives()
49 * - with GetTouchedPrimitives()
50 *
51 * \param cache [in/out] a box cache
52 * \param box [in] collision AABB in world space
53 * \param model [in] Opcode model to collide with
54 * \return true if success
55 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
56 */
57 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
58 bool Collide(AABBCache& cache, const CollisionAABB& box, const Model& model);
59 //
60 bool Collide(AABBCache& cache, const CollisionAABB& box, const AABBTree* tree);
61 protected:
62 CollisionAABB mBox; //!< Query box in (center, extents) form
63 Point mMin; //!< Query box min point
64 Point mMax; //!< Query box max point
65 // Leaf description
66 Point mLeafVerts[3]; //!< Triangle vertices
67 // Internal methods
68 void _Collide(const AABBCollisionNode* node);
69 void _Collide(const AABBNoLeafNode* node);
70 void _Collide(const AABBQuantizedNode* node);
71 void _Collide(const AABBQuantizedNoLeafNode* node);
72 void _Collide(const AABBTreeNode* node);
73 void _CollideNoPrimitiveTest(const AABBCollisionNode* node);
74 void _CollideNoPrimitiveTest(const AABBNoLeafNode* node);
75 void _CollideNoPrimitiveTest(const AABBQuantizedNode* node);
76 void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node);
77 // Overlap tests
78 inline_ BOOL AABBContainsBox(const Point& bc, const Point& be);
79 inline_ BOOL AABBAABBOverlap(const Point& b, const Point& Pb);
80 inline_ BOOL TriBoxOverlap();
81 // Init methods
82 BOOL InitQuery(AABBCache& cache, const CollisionAABB& box);
83 };
84
85 class OPCODE_API HybridAABBCollider : public AABBCollider
86 {
87 public:
88 // Constructor / Destructor
89 HybridAABBCollider();
90 virtual ~HybridAABBCollider();
91
92 bool Collide(AABBCache& cache, const CollisionAABB& box, const HybridModel& model);
93 protected:
94 Container mTouchedBoxes;
95 };
96
97#endif // __OPC_AABBCOLLIDER_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_AABBTree.cpp b/libraries/ode-0.9/OPCODE/OPC_AABBTree.cpp
new file mode 100644
index 0000000..32214f4
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_AABBTree.cpp
@@ -0,0 +1,573 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for a versatile AABB tree.
12 * \file OPC_AABBTree.cpp
13 * \author Pierre Terdiman
14 * \date March, 20, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19/**
20 * Contains a generic AABB tree node.
21 *
22 * \class AABBTreeNode
23 * \author Pierre Terdiman
24 * \version 1.3
25 * \date March, 20, 2001
26*/
27///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
28
29///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
30/**
31 * Contains a generic AABB tree.
32 * This is a vanilla AABB tree, without any particular optimization. It contains anonymous references to
33 * user-provided primitives, which can theoretically be anything - triangles, boxes, etc. Each primitive
34 * is surrounded by an AABB, regardless of the primitive's nature. When the primitive is a triangle, the
35 * resulting tree can be converted into an optimized tree. If the primitive is a box, the resulting tree
36 * can be used for culling - VFC or occlusion -, assuming you cull on a mesh-by-mesh basis (modern way).
37 *
38 * \class AABBTree
39 * \author Pierre Terdiman
40 * \version 1.3
41 * \date March, 20, 2001
42*/
43///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
44
45///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
46// Precompiled Header
47#include "Stdafx.h"
48
49using namespace Opcode;
50
51///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
52/**
53 * Constructor.
54 */
55///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
56AABBTreeNode::AABBTreeNode() :
57 mPos (null),
58#ifndef OPC_NO_NEG_VANILLA_TREE
59 mNeg (null),
60#endif
61 mNbPrimitives (0),
62 mNodePrimitives (null)
63{
64#ifdef OPC_USE_TREE_COHERENCE
65 mBitmask = 0;
66#endif
67}
68
69///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
70/**
71 * Destructor.
72 */
73///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
74AABBTreeNode::~AABBTreeNode()
75{
76 // Opcode 1.3:
77 const AABBTreeNode* Pos = GetPos();
78 const AABBTreeNode* Neg = GetNeg();
79#ifndef OPC_NO_NEG_VANILLA_TREE
80 if(!(mPos&1)) DELETESINGLE(Pos);
81 if(!(mNeg&1)) DELETESINGLE(Neg);
82#else
83 if(!(mPos&1)) DELETEARRAY(Pos);
84#endif
85 mNodePrimitives = null; // This was just a shortcut to the global list => no release
86 mNbPrimitives = 0;
87}
88
89///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
90/**
91 * Splits the node along a given axis.
92 * The list of indices is reorganized according to the split values.
93 * \param axis [in] splitting axis index
94 * \param builder [in] the tree builder
95 * \return the number of primitives assigned to the first child
96 * \warning this method reorganizes the internal list of primitives
97 */
98///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
99udword AABBTreeNode::Split(udword axis, AABBTreeBuilder* builder)
100{
101 // Get node split value
102 float SplitValue = builder->GetSplittingValue(mNodePrimitives, mNbPrimitives, mBV, axis);
103
104 udword NbPos = 0;
105 // Loop through all node-related primitives. Their indices range from mNodePrimitives[0] to mNodePrimitives[mNbPrimitives-1].
106 // Those indices map the global list in the tree builder.
107 for(udword i=0;i<mNbPrimitives;i++)
108 {
109 // Get index in global list
110 udword Index = mNodePrimitives[i];
111
112 // Test against the splitting value. The primitive value is tested against the enclosing-box center.
113 // [We only need an approximate partition of the enclosing box here.]
114 float PrimitiveValue = builder->GetSplittingValue(Index, axis);
115
116 // Reorganize the list of indices in this order: positive - negative.
117 if(PrimitiveValue > SplitValue)
118 {
119 // Swap entries
120 udword Tmp = mNodePrimitives[i];
121 mNodePrimitives[i] = mNodePrimitives[NbPos];
122 mNodePrimitives[NbPos] = Tmp;
123 // Count primitives assigned to positive space
124 NbPos++;
125 }
126 }
127 return NbPos;
128}
129
130///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
131/**
132 * Subdivides the node.
133 *
134 * N
135 * / \
136 * / \
137 * N/2 N/2
138 * / \ / \
139 * N/4 N/4 N/4 N/4
140 * (etc)
141 *
142 * A well-balanced tree should have a O(log n) depth.
143 * A degenerate tree would have a O(n) depth.
144 * Note a perfectly-balanced tree is not well-suited to collision detection anyway.
145 *
146 * \param builder [in] the tree builder
147 * \return true if success
148 */
149///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
150bool AABBTreeNode::Subdivide(AABBTreeBuilder* builder)
151{
152 // Checkings
153 if(!builder) return false;
154
155 // Stop subdividing if we reach a leaf node. This is always performed here,
156 // else we could end in trouble if user overrides this.
157 if(mNbPrimitives==1) return true;
158
159 // Let the user validate the subdivision
160 if(!builder->ValidateSubdivision(mNodePrimitives, mNbPrimitives, mBV)) return true;
161
162 bool ValidSplit = true; // Optimism...
163 udword NbPos;
164 if(builder->mSettings.mRules & SPLIT_LARGEST_AXIS)
165 {
166 // Find the largest axis to split along
167 Point Extents; mBV.GetExtents(Extents); // Box extents
168 udword Axis = Extents.LargestAxis(); // Index of largest axis
169
170 // Split along the axis
171 NbPos = Split(Axis, builder);
172
173 // Check split validity
174 if(!NbPos || NbPos==mNbPrimitives) ValidSplit = false;
175 }
176 else if(builder->mSettings.mRules & SPLIT_SPLATTER_POINTS)
177 {
178 // Compute the means
179 Point Means(0.0f, 0.0f, 0.0f);
180 for(udword i=0;i<mNbPrimitives;i++)
181 {
182 udword Index = mNodePrimitives[i];
183 Means.x+=builder->GetSplittingValue(Index, 0);
184 Means.y+=builder->GetSplittingValue(Index, 1);
185 Means.z+=builder->GetSplittingValue(Index, 2);
186 }
187 Means/=float(mNbPrimitives);
188
189 // Compute variances
190 Point Vars(0.0f, 0.0f, 0.0f);
191 for(udword i=0;i<mNbPrimitives;i++)
192 {
193 udword Index = mNodePrimitives[i];
194 float Cx = builder->GetSplittingValue(Index, 0);
195 float Cy = builder->GetSplittingValue(Index, 1);
196 float Cz = builder->GetSplittingValue(Index, 2);
197 Vars.x += (Cx - Means.x)*(Cx - Means.x);
198 Vars.y += (Cy - Means.y)*(Cy - Means.y);
199 Vars.z += (Cz - Means.z)*(Cz - Means.z);
200 }
201 Vars/=float(mNbPrimitives-1);
202
203 // Choose axis with greatest variance
204 udword Axis = Vars.LargestAxis();
205
206 // Split along the axis
207 NbPos = Split(Axis, builder);
208
209 // Check split validity
210 if(!NbPos || NbPos==mNbPrimitives) ValidSplit = false;
211 }
212 else if(builder->mSettings.mRules & SPLIT_BALANCED)
213 {
214 // Test 3 axis, take the best
215 float Results[3];
216 NbPos = Split(0, builder); Results[0] = float(NbPos)/float(mNbPrimitives);
217 NbPos = Split(1, builder); Results[1] = float(NbPos)/float(mNbPrimitives);
218 NbPos = Split(2, builder); Results[2] = float(NbPos)/float(mNbPrimitives);
219 Results[0]-=0.5f; Results[0]*=Results[0];
220 Results[1]-=0.5f; Results[1]*=Results[1];
221 Results[2]-=0.5f; Results[2]*=Results[2];
222 udword Min=0;
223 if(Results[1]<Results[Min]) Min = 1;
224 if(Results[2]<Results[Min]) Min = 2;
225
226 // Split along the axis
227 NbPos = Split(Min, builder);
228
229 // Check split validity
230 if(!NbPos || NbPos==mNbPrimitives) ValidSplit = false;
231 }
232 else if(builder->mSettings.mRules & SPLIT_BEST_AXIS)
233 {
234 // Test largest, then middle, then smallest axis...
235
236 // Sort axis
237 Point Extents; mBV.GetExtents(Extents); // Box extents
238 udword SortedAxis[] = { 0, 1, 2 };
239 float* Keys = (float*)&Extents.x;
240 for(udword j=0;j<3;j++)
241 {
242 for(udword i=0;i<2;i++)
243 {
244 if(Keys[SortedAxis[i]]<Keys[SortedAxis[i+1]])
245 {
246 udword Tmp = SortedAxis[i];
247 SortedAxis[i] = SortedAxis[i+1];
248 SortedAxis[i+1] = Tmp;
249 }
250 }
251 }
252
253 // Find the largest axis to split along
254 udword CurAxis = 0;
255 ValidSplit = false;
256 while(!ValidSplit && CurAxis!=3)
257 {
258 NbPos = Split(SortedAxis[CurAxis], builder);
259 // Check the subdivision has been successful
260 if(!NbPos || NbPos==mNbPrimitives) CurAxis++;
261 else ValidSplit = true;
262 }
263 }
264 else if(builder->mSettings.mRules & SPLIT_FIFTY)
265 {
266 // Don't even bother splitting (mainly a performance test)
267 NbPos = mNbPrimitives>>1;
268 }
269 else return false; // Unknown splitting rules
270
271 // Check the subdivision has been successful
272 if(!ValidSplit)
273 {
274 // Here, all boxes lie in the same sub-space. Two strategies:
275 // - if the tree *must* be complete, make an arbitrary 50-50 split
276 // - else stop subdividing
277// if(builder->mSettings.mRules&SPLIT_COMPLETE)
278 if(builder->mSettings.mLimit==1)
279 {
280 builder->IncreaseNbInvalidSplits();
281 NbPos = mNbPrimitives>>1;
282 }
283 else return true;
284 }
285
286 // Now create children and assign their pointers.
287 if(builder->mNodeBase)
288 {
289 // We use a pre-allocated linear pool for complete trees [Opcode 1.3]
290 AABBTreeNode* Pool = (AABBTreeNode*)builder->mNodeBase;
291 udword Count = builder->GetCount() - 1; // Count begins to 1...
292 // Set last bit to tell it shouldn't be freed ### pretty ugly, find a better way. Maybe one bit in mNbPrimitives
293 ASSERT(!(udword(&Pool[Count+0])&1));
294 ASSERT(!(udword(&Pool[Count+1])&1));
295 mPos = size_t(&Pool[Count+0])|1;
296#ifndef OPC_NO_NEG_VANILLA_TREE
297 mNeg = size_t(&Pool[Count+1])|1;
298#endif
299 }
300 else
301 {
302 // Non-complete trees and/or Opcode 1.2 allocate nodes on-the-fly
303#ifndef OPC_NO_NEG_VANILLA_TREE
304 mPos = (size_t)new AABBTreeNode; CHECKALLOC(mPos);
305 mNeg = (size_t)new AABBTreeNode; CHECKALLOC(mNeg);
306#else
307 AABBTreeNode* PosNeg = new AABBTreeNode[2];
308 CHECKALLOC(PosNeg);
309 mPos = (size_t)PosNeg;
310#endif
311 }
312
313 // Update stats
314 builder->IncreaseCount(2);
315
316 // Assign children
317 AABBTreeNode* Pos = (AABBTreeNode*)GetPos();
318 AABBTreeNode* Neg = (AABBTreeNode*)GetNeg();
319 Pos->mNodePrimitives = &mNodePrimitives[0];
320 Pos->mNbPrimitives = NbPos;
321 Neg->mNodePrimitives = &mNodePrimitives[NbPos];
322 Neg->mNbPrimitives = mNbPrimitives - NbPos;
323
324 return true;
325}
326
327///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
328/**
329 * Recursive hierarchy building in a top-down fashion.
330 * \param builder [in] the tree builder
331 */
332///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
333void AABBTreeNode::_BuildHierarchy(AABBTreeBuilder* builder)
334{
335 // 1) Compute the global box for current node. The box is stored in mBV.
336 builder->ComputeGlobalBox(mNodePrimitives, mNbPrimitives, mBV);
337
338 // 2) Subdivide current node
339 Subdivide(builder);
340
341 // 3) Recurse
342 AABBTreeNode* Pos = (AABBTreeNode*)GetPos();
343 AABBTreeNode* Neg = (AABBTreeNode*)GetNeg();
344 if(Pos) Pos->_BuildHierarchy(builder);
345 if(Neg) Neg->_BuildHierarchy(builder);
346}
347
348///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
349/**
350 * Refits the tree (top-down).
351 * \param builder [in] the tree builder
352 */
353///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
354void AABBTreeNode::_Refit(AABBTreeBuilder* builder)
355{
356 // 1) Recompute the new global box for current node
357 builder->ComputeGlobalBox(mNodePrimitives, mNbPrimitives, mBV);
358
359 // 2) Recurse
360 AABBTreeNode* Pos = (AABBTreeNode*)GetPos();
361 AABBTreeNode* Neg = (AABBTreeNode*)GetNeg();
362 if(Pos) Pos->_Refit(builder);
363 if(Neg) Neg->_Refit(builder);
364}
365
366
367
368///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
369/**
370 * Constructor.
371 */
372///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
373AABBTree::AABBTree() : mIndices(null), mTotalNbNodes(0), mPool(null)
374{
375}
376
377///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
378/**
379 * Destructor.
380 */
381///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
382AABBTree::~AABBTree()
383{
384 Release();
385}
386
387///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
388/**
389 * Releases the tree.
390 */
391///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
392void AABBTree::Release()
393{
394 DELETEARRAY(mPool);
395 DELETEARRAY(mIndices);
396}
397
398///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
399/**
400 * Builds a generic AABB tree from a tree builder.
401 * \param builder [in] the tree builder
402 * \return true if success
403 */
404///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
405bool AABBTree::Build(AABBTreeBuilder* builder)
406{
407 // Checkings
408 if(!builder || !builder->mNbPrimitives) return false;
409
410 // Release previous tree
411 Release();
412
413 // Init stats
414 builder->SetCount(1);
415 builder->SetNbInvalidSplits(0);
416
417 // Initialize indices. This list will be modified during build.
418 mIndices = new udword[builder->mNbPrimitives];
419 CHECKALLOC(mIndices);
420 // Identity permutation
421 for(udword i=0;i<builder->mNbPrimitives;i++) mIndices[i] = i;
422
423 // Setup initial node. Here we have a complete permutation of the app's primitives.
424 mNodePrimitives = mIndices;
425 mNbPrimitives = builder->mNbPrimitives;
426
427 // Use a linear array for complete trees (since we can predict the final number of nodes) [Opcode 1.3]
428// if(builder->mRules&SPLIT_COMPLETE)
429 if(builder->mSettings.mLimit==1)
430 {
431 // Allocate a pool of nodes
432 mPool = new AABBTreeNode[builder->mNbPrimitives*2 - 1];
433
434 builder->mNodeBase = mPool; // ### ugly !
435 }
436
437 // Build the hierarchy
438 _BuildHierarchy(builder);
439
440 // Get back total number of nodes
441 mTotalNbNodes = builder->GetCount();
442
443 // For complete trees, check the correct number of nodes has been created [Opcode 1.3]
444 if(mPool) ASSERT(mTotalNbNodes==builder->mNbPrimitives*2 - 1);
445
446 return true;
447}
448
449///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
450/**
451 * Computes the depth of the tree.
452 * A well-balanced tree should have a log(n) depth. A degenerate tree O(n) depth.
453 * \return depth of the tree
454 */
455///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
456udword AABBTree::ComputeDepth() const
457{
458 return Walk(null, null); // Use the walking code without callback
459}
460
461///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
462/**
463 * Walks the tree, calling the user back for each node.
464 */
465///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
466udword AABBTree::Walk(WalkingCallback callback, void* user_data) const
467{
468 // Call it without callback to compute max depth
469 udword MaxDepth = 0;
470 udword CurrentDepth = 0;
471
472 struct Local
473 {
474 static void _Walk(const AABBTreeNode* current_node, udword& max_depth, udword& current_depth, WalkingCallback callback, void* user_data)
475 {
476 // Checkings
477 if(!current_node) return;
478 // Entering a new node => increase depth
479 current_depth++;
480 // Keep track of max depth
481 if(current_depth>max_depth) max_depth = current_depth;
482
483 // Callback
484 if(callback && !(callback)(current_node, current_depth, user_data)) return;
485
486 // Recurse
487 if(current_node->GetPos()) { _Walk(current_node->GetPos(), max_depth, current_depth, callback, user_data); current_depth--; }
488 if(current_node->GetNeg()) { _Walk(current_node->GetNeg(), max_depth, current_depth, callback, user_data); current_depth--; }
489 }
490 };
491 Local::_Walk(this, MaxDepth, CurrentDepth, callback, user_data);
492 return MaxDepth;
493}
494
495///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
496/**
497 * Refits the tree in a top-down way.
498 * \param builder [in] the tree builder
499 */
500///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
501bool AABBTree::Refit(AABBTreeBuilder* builder)
502{
503 if(!builder) return false;
504 _Refit(builder);
505 return true;
506}
507
508///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
509/**
510 * Refits the tree in a bottom-up way.
511 * \param builder [in] the tree builder
512 */
513///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
514bool AABBTree::Refit2(AABBTreeBuilder* builder)
515{
516 // Checkings
517 if(!builder) return false;
518
519 ASSERT(mPool);
520
521 // Bottom-up update
522 Point Min,Max;
523 Point Min_,Max_;
524 udword Index = mTotalNbNodes;
525 while(Index--)
526 {
527 AABBTreeNode& Current = mPool[Index];
528
529 if(Current.IsLeaf())
530 {
531 builder->ComputeGlobalBox(Current.GetPrimitives(), Current.GetNbPrimitives(), *(AABB*)Current.GetAABB());
532 }
533 else
534 {
535 Current.GetPos()->GetAABB()->GetMin(Min);
536 Current.GetPos()->GetAABB()->GetMax(Max);
537
538 Current.GetNeg()->GetAABB()->GetMin(Min_);
539 Current.GetNeg()->GetAABB()->GetMax(Max_);
540
541 Min.Min(Min_);
542 Max.Max(Max_);
543
544 ((AABB*)Current.GetAABB())->SetMinMax(Min, Max);
545 }
546 }
547 return true;
548}
549
550///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
551/**
552 * Computes the number of bytes used by the tree.
553 * \return number of bytes used
554 */
555///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
556udword AABBTree::GetUsedBytes() const
557{
558 udword TotalSize = mTotalNbNodes*GetNodeSize();
559 if(mIndices) TotalSize+=mNbPrimitives*sizeof(udword);
560 return TotalSize;
561}
562
563///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
564/**
565 * Checks the tree is a complete tree or not.
566 * A complete tree is made of 2*N-1 nodes, where N is the number of primitives in the tree.
567 * \return true for complete trees
568 */
569///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
570bool AABBTree::IsComplete() const
571{
572 return (GetNbNodes()==GetNbPrimitives()*2-1);
573}
diff --git a/libraries/ode-0.9/OPCODE/OPC_AABBTree.h b/libraries/ode-0.9/OPCODE/OPC_AABBTree.h
new file mode 100644
index 0000000..ee2533d
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_AABBTree.h
@@ -0,0 +1,137 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for a versatile AABB tree.
12 * \file OPC_AABBTree.h
13 * \author Pierre Terdiman
14 * \date March, 20, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_AABBTREE_H__
21#define __OPC_AABBTREE_H__
22
23#ifdef OPC_NO_NEG_VANILLA_TREE
24 //! TO BE DOCUMENTED
25 #define IMPLEMENT_TREE(base_class, volume) \
26 public: \
27 /* Constructor / Destructor */ \
28 base_class(); \
29 ~base_class(); \
30 /* Data access */ \
31 inline_ const volume* Get##volume() const { return &mBV; } \
32 /* Clear the last bit */ \
33 inline_ const base_class* GetPos() const { return (const base_class*)(mPos&~1); } \
34 inline_ const base_class* GetNeg() const { const base_class* P = GetPos(); return P ? P+1 : null;} \
35 \
36 /* We don't need to test both nodes since we can't have one without the other */ \
37 inline_ bool IsLeaf() const { return !GetPos(); } \
38 \
39 /* Stats */ \
40 inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \
41 protected: \
42 /* Tree-independent data */ \
43 /* Following data always belong to the BV-tree, regardless of what the tree actually contains.*/ \
44 /* Whatever happens we need the two children and the enclosing volume.*/ \
45 volume mBV; /* Global bounding-volume enclosing all the node-related primitives */ \
46 size_t mPos; /* "Positive" & "Negative" children */
47#else
48 //! TO BE DOCUMENTED
49 #define IMPLEMENT_TREE(base_class, volume) \
50 public: \
51 /* Constructor / Destructor */ \
52 base_class(); \
53 ~base_class(); \
54 /* Data access */ \
55 inline_ const volume* Get##volume() const { return &mBV; } \
56 /* Clear the last bit */ \
57 inline_ const base_class* GetPos() const { return (const base_class*)(mPos&~1); } \
58 inline_ const base_class* GetNeg() const { return (const base_class*)(mNeg&~1); } \
59 \
60/* inline_ bool IsLeaf() const { return (!GetPos() && !GetNeg()); } */ \
61 /* We don't need to test both nodes since we can't have one without the other */ \
62 inline_ bool IsLeaf() const { return !GetPos(); } \
63 \
64 /* Stats */ \
65 inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \
66 protected: \
67 /* Tree-independent data */ \
68 /* Following data always belong to the BV-tree, regardless of what the tree actually contains.*/ \
69 /* Whatever happens we need the two children and the enclosing volume.*/ \
70 volume mBV; /* Global bounding-volume enclosing all the node-related primitives */ \
71 size_t mPos; /* "Positive" child */ \
72 size_t mNeg; /* "Negative" child */
73#endif
74
75 typedef void (*CullingCallback) (udword nb_primitives, udword* node_primitives, BOOL need_clipping, void* user_data);
76
77 class OPCODE_API AABBTreeNode
78 {
79 IMPLEMENT_TREE(AABBTreeNode, AABB)
80 public:
81 // Data access
82 inline_ const udword* GetPrimitives() const { return mNodePrimitives; }
83 inline_ udword GetNbPrimitives() const { return mNbPrimitives; }
84
85 protected:
86 // Tree-dependent data
87 udword* mNodePrimitives; //!< Node-related primitives (shortcut to a position in mIndices below)
88 udword mNbPrimitives; //!< Number of primitives for this node
89 // Internal methods
90 udword Split(udword axis, AABBTreeBuilder* builder);
91 bool Subdivide(AABBTreeBuilder* builder);
92 void _BuildHierarchy(AABBTreeBuilder* builder);
93 void _Refit(AABBTreeBuilder* builder);
94 };
95
96 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
97 /**
98 * User-callback, called for each node by the walking code.
99 * \param current [in] current node
100 * \param depth [in] current node's depth
101 * \param user_data [in] user-defined data
102 * \return true to recurse through children, else false to bypass them
103 */
104 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
105 typedef bool (*WalkingCallback) (const AABBTreeNode* current, udword depth, void* user_data);
106
107 class OPCODE_API AABBTree : public AABBTreeNode
108 {
109 public:
110 // Constructor / Destructor
111 AABBTree();
112 ~AABBTree();
113 // Build
114 bool Build(AABBTreeBuilder* builder);
115 void Release();
116
117 // Data access
118 inline_ const udword* GetIndices() const { return mIndices; } //!< Catch the indices
119 inline_ udword GetNbNodes() const { return mTotalNbNodes; } //!< Catch the number of nodes
120
121 // Infos
122 bool IsComplete() const;
123 // Stats
124 udword ComputeDepth() const;
125 udword GetUsedBytes() const;
126 udword Walk(WalkingCallback callback, void* user_data) const;
127
128 bool Refit(AABBTreeBuilder* builder);
129 bool Refit2(AABBTreeBuilder* builder);
130 private:
131 udword* mIndices; //!< Indices in the app list. Indices are reorganized during build (permutation).
132 AABBTreeNode* mPool; //!< Linear pool of nodes for complete trees. Null otherwise. [Opcode 1.3]
133 // Stats
134 udword mTotalNbNodes; //!< Number of nodes in the tree.
135 };
136
137#endif // __OPC_AABBTREE_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_BaseModel.cpp b/libraries/ode-0.9/OPCODE/OPC_BaseModel.cpp
new file mode 100644
index 0000000..9520d9e
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_BaseModel.cpp
@@ -0,0 +1,138 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains base model interface.
12 * \file OPC_BaseModel.cpp
13 * \author Pierre Terdiman
14 * \date May, 18, 2003
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19/**
20 * The base class for collision models.
21 *
22 * \class BaseModel
23 * \author Pierre Terdiman
24 * \version 1.3
25 * \date May, 18, 2003
26*/
27///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
28
29///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
30// Precompiled Header
31#include "Stdafx.h"
32
33using namespace Opcode;
34
35///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
36/**
37 * Constructor.
38 */
39///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
40OPCODECREATE::OPCODECREATE()
41{
42 mIMesh = null;
43 mSettings.mRules = SPLIT_SPLATTER_POINTS | SPLIT_GEOM_CENTER;
44 mSettings.mLimit = 1; // Mandatory for complete trees
45 mNoLeaf = true;
46 mQuantized = true;
47#ifdef __MESHMERIZER_H__
48 mCollisionHull = false;
49#endif // __MESHMERIZER_H__
50 mKeepOriginal = false;
51 mCanRemap = false;
52}
53
54///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
55/**
56 * Constructor.
57 */
58///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
59BaseModel::BaseModel() : mIMesh(null), mModelCode(0), mSource(null), mTree(null)
60{
61}
62
63///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
64/**
65 * Destructor.
66 */
67///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
68BaseModel::~BaseModel()
69{
70 ReleaseBase();
71}
72
73///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
74/**
75 * Releases everything.
76 */
77///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
78void BaseModel::ReleaseBase()
79{
80 DELETESINGLE(mSource);
81 DELETESINGLE(mTree);
82}
83
84///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
85/**
86 * Creates an optimized tree according to user-settings, and setups mModelCode.
87 * \param no_leaf [in] true for "no leaf" tree
88 * \param quantized [in] true for quantized tree
89 * \return true if success
90 */
91///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
92bool BaseModel::CreateTree(bool no_leaf, bool quantized)
93{
94 DELETESINGLE(mTree);
95
96 // Setup model code
97 if(no_leaf) mModelCode |= OPC_NO_LEAF;
98 else mModelCode &= ~OPC_NO_LEAF;
99
100 if(quantized) mModelCode |= OPC_QUANTIZED;
101 else mModelCode &= ~OPC_QUANTIZED;
102
103 // Create the correct class
104 if(mModelCode & OPC_NO_LEAF)
105 {
106 if(mModelCode & OPC_QUANTIZED) mTree = new AABBQuantizedNoLeafTree;
107 else mTree = new AABBNoLeafTree;
108 }
109 else
110 {
111 if(mModelCode & OPC_QUANTIZED) mTree = new AABBQuantizedTree;
112 else mTree = new AABBCollisionTree;
113 }
114 CHECKALLOC(mTree);
115
116 return true;
117}
118
119///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
120/**
121 * Refits the collision model. This can be used to handle dynamic meshes. Usage is:
122 * 1. modify your mesh vertices (keep the topology constant!)
123 * 2. refit the tree (call this method)
124 * \return true if success
125 */
126///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
127bool BaseModel::Refit()
128{
129 // Refit the optimized tree
130 return mTree->Refit(mIMesh);
131
132// Old code kept for reference : refit the source tree then rebuild !
133// if(!mSource) return false;
134// // Ouch...
135// mSource->Refit(&mTB);
136// // Ouch...
137// return mTree->Build(mSource);
138}
diff --git a/libraries/ode-0.9/OPCODE/OPC_BaseModel.h b/libraries/ode-0.9/OPCODE/OPC_BaseModel.h
new file mode 100644
index 0000000..c6072db
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_BaseModel.h
@@ -0,0 +1,175 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains base model interface.
12 * \file OPC_BaseModel.h
13 * \author Pierre Terdiman
14 * \date May, 18, 2003
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_BASEMODEL_H__
21#define __OPC_BASEMODEL_H__
22
23 //! Model creation structure
24 struct OPCODE_API OPCODECREATE
25 {
26 //! Constructor
27 OPCODECREATE();
28
29 MeshInterface* mIMesh; //!< Mesh interface (access to triangles & vertices) (*)
30 BuildSettings mSettings; //!< Builder's settings
31 bool mNoLeaf; //!< true => discard leaf nodes (else use a normal tree)
32 bool mQuantized; //!< true => quantize the tree (else use a normal tree)
33#ifdef __MESHMERIZER_H__
34 bool mCollisionHull; //!< true => use convex hull + GJK
35#endif // __MESHMERIZER_H__
36 bool mKeepOriginal; //!< true => keep a copy of the original tree (debug purpose)
37 bool mCanRemap; //!< true => allows OPCODE to reorganize client arrays
38
39 // (*) This pointer is saved internally and used by OPCODE until collision structures are released,
40 // so beware of the object's lifetime.
41 };
42
43 enum ModelFlag
44 {
45 OPC_QUANTIZED = (1<<0), //!< Compressed/uncompressed tree
46 OPC_NO_LEAF = (1<<1), //!< Leaf/NoLeaf tree
47 OPC_SINGLE_NODE = (1<<2) //!< Special case for 1-node models
48 };
49
50 class OPCODE_API BaseModel
51 {
52 public:
53 // Constructor/Destructor
54 BaseModel();
55 virtual ~BaseModel();
56
57 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
58 /**
59 * Builds a collision model.
60 * \param create [in] model creation structure
61 * \return true if success
62 */
63 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
64 virtual bool Build(const OPCODECREATE& create) = 0;
65
66 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
67 /**
68 * Gets the number of bytes used by the tree.
69 * \return amount of bytes used
70 */
71 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
72 virtual udword GetUsedBytes() const = 0;
73
74 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
75 /**
76 * Refits the collision model. This can be used to handle dynamic meshes. Usage is:
77 * 1. modify your mesh vertices (keep the topology constant!)
78 * 2. refit the tree (call this method)
79 * \return true if success
80 */
81 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
82 virtual bool Refit();
83
84 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
85 /**
86 * Gets the source tree.
87 * \return generic tree
88 */
89 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
90 inline_ const AABBTree* GetSourceTree() const { return mSource; }
91
92 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
93 /**
94 * Gets the tree.
95 * \return the collision tree
96 */
97 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
98 inline_ const AABBOptimizedTree* GetTree() const { return mTree; }
99
100 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
101 /**
102 * Gets the tree.
103 * \return the collision tree
104 */
105 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
106 inline_ AABBOptimizedTree* GetTree() { return mTree; }
107
108 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
109 /**
110 * Gets the number of nodes in the tree.
111 * Should be 2*N-1 for normal trees and N-1 for optimized ones.
112 * \return number of nodes
113 */
114 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
115 inline_ udword GetNbNodes() const { return mTree->GetNbNodes(); }
116
117 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
118 /**
119 * Checks whether the tree has leaf nodes or not.
120 * \return true if the tree has leaf nodes (normal tree), else false (optimized tree)
121 */
122 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
123 inline_ BOOL HasLeafNodes() const { return !(mModelCode & OPC_NO_LEAF); }
124
125 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
126 /**
127 * Checks whether the tree is quantized or not.
128 * \return true if the tree is quantized
129 */
130 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
131 inline_ BOOL IsQuantized() const { return mModelCode & OPC_QUANTIZED; }
132
133 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
134 /**
135 * Checks whether the model has a single node or not. This special case must be handled separately.
136 * \return true if the model has only 1 node
137 */
138 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
139 inline_ BOOL HasSingleNode() const { return mModelCode & OPC_SINGLE_NODE; }
140
141 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
142 /**
143 * Gets the model's code.
144 * \return model's code
145 */
146 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
147 inline_ udword GetModelCode() const { return mModelCode; }
148
149 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
150 /**
151 * Gets the mesh interface.
152 * \return mesh interface
153 */
154 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
155 inline_ const MeshInterface* GetMeshInterface() const { return mIMesh; }
156
157 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
158 /**
159 * Sets the mesh interface.
160 * \param imesh [in] mesh interface
161 */
162 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
163 inline_ void SetMeshInterface(const MeshInterface* imesh) { mIMesh = imesh; }
164
165 protected:
166 const MeshInterface* mIMesh; //!< User-defined mesh interface
167 udword mModelCode; //!< Model code = combination of ModelFlag(s)
168 AABBTree* mSource; //!< Original source tree
169 AABBOptimizedTree* mTree; //!< Optimized tree owned by the model
170 // Internal methods
171 void ReleaseBase();
172 bool CreateTree(bool no_leaf, bool quantized);
173 };
174
175#endif //__OPC_BASEMODEL_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_BoxBoxOverlap.h b/libraries/ode-0.9/OPCODE/OPC_BoxBoxOverlap.h
new file mode 100644
index 0000000..757a17d
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_BoxBoxOverlap.h
@@ -0,0 +1,122 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * OBB-OBB overlap test using the separating axis theorem.
4 * - original code by Gomez / Gamasutra (similar to Gottschalk's one in RAPID)
5 * - optimized for AABB trees by computing the rotation matrix once (SOLID-fashion)
6 * - the fabs matrix is precomputed as well and epsilon-tweaked (RAPID-style, we found this almost mandatory)
7 * - Class III axes can be disabled... (SOLID & Intel fashion)
8 * - ...or enabled to perform some profiling
9 * - CPU comparisons used when appropriate
10 * - lazy evaluation sometimes saves some work in case of early exits (unlike SOLID)
11 *
12 * \param ea [in] extents from box A
13 * \param ca [in] center from box A
14 * \param eb [in] extents from box B
15 * \param cb [in] center from box B
16 * \return true if boxes overlap
17 */
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19inline_ BOOL AABBTreeCollider::BoxBoxOverlap(const Point& ea, const Point& ca, const Point& eb, const Point& cb)
20{
21 // Stats
22 mNbBVBVTests++;
23
24 float t,t2;
25
26 // Class I : A's basis vectors
27 float Tx = (mR1to0.m[0][0]*cb.x + mR1to0.m[1][0]*cb.y + mR1to0.m[2][0]*cb.z) + mT1to0.x - ca.x;
28 t = ea.x + eb.x*mAR.m[0][0] + eb.y*mAR.m[1][0] + eb.z*mAR.m[2][0];
29 if(GREATER(Tx, t)) return FALSE;
30
31 float Ty = (mR1to0.m[0][1]*cb.x + mR1to0.m[1][1]*cb.y + mR1to0.m[2][1]*cb.z) + mT1to0.y - ca.y;
32 t = ea.y + eb.x*mAR.m[0][1] + eb.y*mAR.m[1][1] + eb.z*mAR.m[2][1];
33 if(GREATER(Ty, t)) return FALSE;
34
35 float Tz = (mR1to0.m[0][2]*cb.x + mR1to0.m[1][2]*cb.y + mR1to0.m[2][2]*cb.z) + mT1to0.z - ca.z;
36 t = ea.z + eb.x*mAR.m[0][2] + eb.y*mAR.m[1][2] + eb.z*mAR.m[2][2];
37 if(GREATER(Tz, t)) return FALSE;
38
39 // Class II : B's basis vectors
40 t = Tx*mR1to0.m[0][0] + Ty*mR1to0.m[0][1] + Tz*mR1to0.m[0][2]; t2 = ea.x*mAR.m[0][0] + ea.y*mAR.m[0][1] + ea.z*mAR.m[0][2] + eb.x;
41 if(GREATER(t, t2)) return FALSE;
42
43 t = Tx*mR1to0.m[1][0] + Ty*mR1to0.m[1][1] + Tz*mR1to0.m[1][2]; t2 = ea.x*mAR.m[1][0] + ea.y*mAR.m[1][1] + ea.z*mAR.m[1][2] + eb.y;
44 if(GREATER(t, t2)) return FALSE;
45
46 t = Tx*mR1to0.m[2][0] + Ty*mR1to0.m[2][1] + Tz*mR1to0.m[2][2]; t2 = ea.x*mAR.m[2][0] + ea.y*mAR.m[2][1] + ea.z*mAR.m[2][2] + eb.z;
47 if(GREATER(t, t2)) return FALSE;
48
49 // Class III : 9 cross products
50 // Cool trick: always perform the full test for first level, regardless of settings.
51 // That way pathological cases (such as the pencils scene) are quickly rejected anyway !
52 if(mFullBoxBoxTest || mNbBVBVTests==1)
53 {
54 t = Tz*mR1to0.m[0][1] - Ty*mR1to0.m[0][2]; t2 = ea.y*mAR.m[0][2] + ea.z*mAR.m[0][1] + eb.y*mAR.m[2][0] + eb.z*mAR.m[1][0]; if(GREATER(t, t2)) return FALSE; // L = A0 x B0
55 t = Tz*mR1to0.m[1][1] - Ty*mR1to0.m[1][2]; t2 = ea.y*mAR.m[1][2] + ea.z*mAR.m[1][1] + eb.x*mAR.m[2][0] + eb.z*mAR.m[0][0]; if(GREATER(t, t2)) return FALSE; // L = A0 x B1
56 t = Tz*mR1to0.m[2][1] - Ty*mR1to0.m[2][2]; t2 = ea.y*mAR.m[2][2] + ea.z*mAR.m[2][1] + eb.x*mAR.m[1][0] + eb.y*mAR.m[0][0]; if(GREATER(t, t2)) return FALSE; // L = A0 x B2
57 t = Tx*mR1to0.m[0][2] - Tz*mR1to0.m[0][0]; t2 = ea.x*mAR.m[0][2] + ea.z*mAR.m[0][0] + eb.y*mAR.m[2][1] + eb.z*mAR.m[1][1]; if(GREATER(t, t2)) return FALSE; // L = A1 x B0
58 t = Tx*mR1to0.m[1][2] - Tz*mR1to0.m[1][0]; t2 = ea.x*mAR.m[1][2] + ea.z*mAR.m[1][0] + eb.x*mAR.m[2][1] + eb.z*mAR.m[0][1]; if(GREATER(t, t2)) return FALSE; // L = A1 x B1
59 t = Tx*mR1to0.m[2][2] - Tz*mR1to0.m[2][0]; t2 = ea.x*mAR.m[2][2] + ea.z*mAR.m[2][0] + eb.x*mAR.m[1][1] + eb.y*mAR.m[0][1]; if(GREATER(t, t2)) return FALSE; // L = A1 x B2
60 t = Ty*mR1to0.m[0][0] - Tx*mR1to0.m[0][1]; t2 = ea.x*mAR.m[0][1] + ea.y*mAR.m[0][0] + eb.y*mAR.m[2][2] + eb.z*mAR.m[1][2]; if(GREATER(t, t2)) return FALSE; // L = A2 x B0
61 t = Ty*mR1to0.m[1][0] - Tx*mR1to0.m[1][1]; t2 = ea.x*mAR.m[1][1] + ea.y*mAR.m[1][0] + eb.x*mAR.m[2][2] + eb.z*mAR.m[0][2]; if(GREATER(t, t2)) return FALSE; // L = A2 x B1
62 t = Ty*mR1to0.m[2][0] - Tx*mR1to0.m[2][1]; t2 = ea.x*mAR.m[2][1] + ea.y*mAR.m[2][0] + eb.x*mAR.m[1][2] + eb.y*mAR.m[0][2]; if(GREATER(t, t2)) return FALSE; // L = A2 x B2
63 }
64 return TRUE;
65}
66
67//! A dedicated version when one box is constant
68inline_ BOOL OBBCollider::BoxBoxOverlap(const Point& extents, const Point& center)
69{
70 // Stats
71 mNbVolumeBVTests++;
72
73 float t,t2;
74
75 // Class I : A's basis vectors
76 float Tx = mTBoxToModel.x - center.x; t = extents.x + mBBx1; if(GREATER(Tx, t)) return FALSE;
77 float Ty = mTBoxToModel.y - center.y; t = extents.y + mBBy1; if(GREATER(Ty, t)) return FALSE;
78 float Tz = mTBoxToModel.z - center.z; t = extents.z + mBBz1; if(GREATER(Tz, t)) return FALSE;
79
80 // Class II : B's basis vectors
81 t = Tx*mRBoxToModel.m[0][0] + Ty*mRBoxToModel.m[0][1] + Tz*mRBoxToModel.m[0][2];
82 t2 = extents.x*mAR.m[0][0] + extents.y*mAR.m[0][1] + extents.z*mAR.m[0][2] + mBoxExtents.x;
83 if(GREATER(t, t2)) return FALSE;
84
85 t = Tx*mRBoxToModel.m[1][0] + Ty*mRBoxToModel.m[1][1] + Tz*mRBoxToModel.m[1][2];
86 t2 = extents.x*mAR.m[1][0] + extents.y*mAR.m[1][1] + extents.z*mAR.m[1][2] + mBoxExtents.y;
87 if(GREATER(t, t2)) return FALSE;
88
89 t = Tx*mRBoxToModel.m[2][0] + Ty*mRBoxToModel.m[2][1] + Tz*mRBoxToModel.m[2][2];
90 t2 = extents.x*mAR.m[2][0] + extents.y*mAR.m[2][1] + extents.z*mAR.m[2][2] + mBoxExtents.z;
91 if(GREATER(t, t2)) return FALSE;
92
93 // Class III : 9 cross products
94 // Cool trick: always perform the full test for first level, regardless of settings.
95 // That way pathological cases (such as the pencils scene) are quickly rejected anyway !
96 if(mFullBoxBoxTest || mNbVolumeBVTests==1)
97 {
98 t = Tz*mRBoxToModel.m[0][1] - Ty*mRBoxToModel.m[0][2]; t2 = extents.y*mAR.m[0][2] + extents.z*mAR.m[0][1] + mBB_1; if(GREATER(t, t2)) return FALSE; // L = A0 x B0
99 t = Tz*mRBoxToModel.m[1][1] - Ty*mRBoxToModel.m[1][2]; t2 = extents.y*mAR.m[1][2] + extents.z*mAR.m[1][1] + mBB_2; if(GREATER(t, t2)) return FALSE; // L = A0 x B1
100 t = Tz*mRBoxToModel.m[2][1] - Ty*mRBoxToModel.m[2][2]; t2 = extents.y*mAR.m[2][2] + extents.z*mAR.m[2][1] + mBB_3; if(GREATER(t, t2)) return FALSE; // L = A0 x B2
101 t = Tx*mRBoxToModel.m[0][2] - Tz*mRBoxToModel.m[0][0]; t2 = extents.x*mAR.m[0][2] + extents.z*mAR.m[0][0] + mBB_4; if(GREATER(t, t2)) return FALSE; // L = A1 x B0
102 t = Tx*mRBoxToModel.m[1][2] - Tz*mRBoxToModel.m[1][0]; t2 = extents.x*mAR.m[1][2] + extents.z*mAR.m[1][0] + mBB_5; if(GREATER(t, t2)) return FALSE; // L = A1 x B1
103 t = Tx*mRBoxToModel.m[2][2] - Tz*mRBoxToModel.m[2][0]; t2 = extents.x*mAR.m[2][2] + extents.z*mAR.m[2][0] + mBB_6; if(GREATER(t, t2)) return FALSE; // L = A1 x B2
104 t = Ty*mRBoxToModel.m[0][0] - Tx*mRBoxToModel.m[0][1]; t2 = extents.x*mAR.m[0][1] + extents.y*mAR.m[0][0] + mBB_7; if(GREATER(t, t2)) return FALSE; // L = A2 x B0
105 t = Ty*mRBoxToModel.m[1][0] - Tx*mRBoxToModel.m[1][1]; t2 = extents.x*mAR.m[1][1] + extents.y*mAR.m[1][0] + mBB_8; if(GREATER(t, t2)) return FALSE; // L = A2 x B1
106 t = Ty*mRBoxToModel.m[2][0] - Tx*mRBoxToModel.m[2][1]; t2 = extents.x*mAR.m[2][1] + extents.y*mAR.m[2][0] + mBB_9; if(GREATER(t, t2)) return FALSE; // L = A2 x B2
107 }
108 return TRUE;
109}
110
111//! A special version for 2 axis-aligned boxes
112inline_ BOOL AABBCollider::AABBAABBOverlap(const Point& extents, const Point& center)
113{
114 // Stats
115 mNbVolumeBVTests++;
116
117 float tx = mBox.mCenter.x - center.x; float ex = extents.x + mBox.mExtents.x; if(GREATER(tx, ex)) return FALSE;
118 float ty = mBox.mCenter.y - center.y; float ey = extents.y + mBox.mExtents.y; if(GREATER(ty, ey)) return FALSE;
119 float tz = mBox.mCenter.z - center.z; float ez = extents.z + mBox.mExtents.z; if(GREATER(tz, ez)) return FALSE;
120
121 return TRUE;
122}
diff --git a/libraries/ode-0.9/OPCODE/OPC_BoxPruning.cpp b/libraries/ode-0.9/OPCODE/OPC_BoxPruning.cpp
new file mode 100644
index 0000000..6906160
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_BoxPruning.cpp
@@ -0,0 +1,367 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for box pruning.
12 * \file IceBoxPruning.cpp
13 * \author Pierre Terdiman
14 * \date January, 29, 2000
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18/*
19///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
20 You could use a complex sweep-and-prune as implemented in I-Collide.
21 You could use a complex hashing scheme as implemented in V-Clip or recently in ODE it seems.
22 You could use a "Recursive Dimensional Clustering" algorithm as implemented in GPG2.
23
24 Or you could use this.
25 Faster ? I don't know. Probably not. It would be a shame. But who knows ?
26 Easier ? Definitely. Enjoy the sheer simplicity.
27///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
28*/
29
30
31///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
32// Precompiled Header
33#include "Stdafx.h"
34
35using namespace Opcode;
36
37 inline_ void FindRunningIndex(udword& index, float* array, udword* sorted, int last, float max)
38 {
39 int First=index;
40 while(First<=last)
41 {
42 index = (First+last)>>1;
43
44 if(max>array[sorted[index]]) First = index+1;
45 else last = index-1;
46 }
47 }
48// ### could be log(n) !
49// and maybe use cmp integers
50
51// InsertionSort has better coherence, RadixSort is better for one-shot queries.
52#define PRUNING_SORTER RadixSort
53//#define PRUNING_SORTER InsertionSort
54
55// Static for coherence
56static PRUNING_SORTER* gCompletePruningSorter = null;
57static PRUNING_SORTER* gBipartitePruningSorter0 = null;
58static PRUNING_SORTER* gBipartitePruningSorter1 = null;
59inline_ PRUNING_SORTER* GetCompletePruningSorter()
60{
61 if(!gCompletePruningSorter) gCompletePruningSorter = new PRUNING_SORTER;
62 return gCompletePruningSorter;
63}
64inline_ PRUNING_SORTER* GetBipartitePruningSorter0()
65{
66 if(!gBipartitePruningSorter0) gBipartitePruningSorter0 = new PRUNING_SORTER;
67 return gBipartitePruningSorter0;
68}
69inline_ PRUNING_SORTER* GetBipartitePruningSorter1()
70{
71 if(!gBipartitePruningSorter1) gBipartitePruningSorter1 = new PRUNING_SORTER;
72 return gBipartitePruningSorter1;
73}
74void ReleasePruningSorters()
75{
76 DELETESINGLE(gBipartitePruningSorter1);
77 DELETESINGLE(gBipartitePruningSorter0);
78 DELETESINGLE(gCompletePruningSorter);
79}
80
81
82///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
83/**
84 * Bipartite box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set.
85 * \param nb0 [in] number of boxes in the first set
86 * \param array0 [in] array of boxes for the first set
87 * \param nb1 [in] number of boxes in the second set
88 * \param array1 [in] array of boxes for the second set
89 * \param pairs [out] array of overlapping pairs
90 * \param axes [in] projection order (0,2,1 is often best)
91 * \return true if success.
92 */
93///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
94bool Opcode::BipartiteBoxPruning(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs, const Axes& axes)
95{
96 // Checkings
97 if(!nb0 || !array0 || !nb1 || !array1) return false;
98
99 // Catch axes
100 udword Axis0 = axes.mAxis0;
101 udword Axis1 = axes.mAxis1;
102 udword Axis2 = axes.mAxis2;
103
104 // Allocate some temporary data
105 float* MinPosList0 = new float[nb0];
106 float* MinPosList1 = new float[nb1];
107
108 // 1) Build main lists using the primary axis
109 for(udword i=0;i<nb0;i++) MinPosList0[i] = array0[i]->GetMin(Axis0);
110 for(udword i=0;i<nb1;i++) MinPosList1[i] = array1[i]->GetMin(Axis0);
111
112 // 2) Sort the lists
113 PRUNING_SORTER* RS0 = GetBipartitePruningSorter0();
114 PRUNING_SORTER* RS1 = GetBipartitePruningSorter1();
115 const udword* Sorted0 = RS0->Sort(MinPosList0, nb0).GetRanks();
116 const udword* Sorted1 = RS1->Sort(MinPosList1, nb1).GetRanks();
117
118 // 3) Prune the lists
119 udword Index0, Index1;
120
121 const udword* const LastSorted0 = &Sorted0[nb0];
122 const udword* const LastSorted1 = &Sorted1[nb1];
123 const udword* RunningAddress0 = Sorted0;
124 const udword* RunningAddress1 = Sorted1;
125
126 while(RunningAddress1<LastSorted1 && Sorted0<LastSorted0)
127 {
128 Index0 = *Sorted0++;
129
130 while(RunningAddress1<LastSorted1 && MinPosList1[*RunningAddress1]<MinPosList0[Index0]) RunningAddress1++;
131
132 const udword* RunningAddress2_1 = RunningAddress1;
133
134 while(RunningAddress2_1<LastSorted1 && MinPosList1[Index1 = *RunningAddress2_1++]<=array0[Index0]->GetMax(Axis0))
135 {
136 if(array0[Index0]->Intersect(*array1[Index1], Axis1))
137 {
138 if(array0[Index0]->Intersect(*array1[Index1], Axis2))
139 {
140 pairs.AddPair(Index0, Index1);
141 }
142 }
143 }
144 }
145
146 ////
147
148 while(RunningAddress0<LastSorted0 && Sorted1<LastSorted1)
149 {
150 Index0 = *Sorted1++;
151
152 while(RunningAddress0<LastSorted0 && MinPosList0[*RunningAddress0]<=MinPosList1[Index0]) RunningAddress0++;
153
154 const udword* RunningAddress2_0 = RunningAddress0;
155
156 while(RunningAddress2_0<LastSorted0 && MinPosList0[Index1 = *RunningAddress2_0++]<=array1[Index0]->GetMax(Axis0))
157 {
158 if(array0[Index1]->Intersect(*array1[Index0], Axis1))
159 {
160 if(array0[Index1]->Intersect(*array1[Index0], Axis2))
161 {
162 pairs.AddPair(Index1, Index0);
163 }
164 }
165
166 }
167 }
168
169 DELETEARRAY(MinPosList1);
170 DELETEARRAY(MinPosList0);
171
172 return true;
173}
174
175#define ORIGINAL_VERSION
176//#define JOAKIM
177
178///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
179/**
180 * Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set.
181 * \param nb [in] number of boxes
182 * \param array [in] array of boxes
183 * \param pairs [out] array of overlapping pairs
184 * \param axes [in] projection order (0,2,1 is often best)
185 * \return true if success.
186 */
187///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
188bool Opcode::CompleteBoxPruning(udword nb, const AABB** array, Pairs& pairs, const Axes& axes)
189{
190 // Checkings
191 if(!nb || !array) return false;
192
193 // Catch axes
194 udword Axis0 = axes.mAxis0;
195 udword Axis1 = axes.mAxis1;
196 udword Axis2 = axes.mAxis2;
197
198#ifdef ORIGINAL_VERSION
199 // Allocate some temporary data
200// float* PosList = new float[nb];
201 float* PosList = new float[nb+1];
202
203 // 1) Build main list using the primary axis
204 for(udword i=0;i<nb;i++) PosList[i] = array[i]->GetMin(Axis0);
205PosList[nb++] = MAX_FLOAT;
206
207 // 2) Sort the list
208 PRUNING_SORTER* RS = GetCompletePruningSorter();
209 const udword* Sorted = RS->Sort(PosList, nb).GetRanks();
210
211 // 3) Prune the list
212 const udword* const LastSorted = &Sorted[nb];
213 const udword* RunningAddress = Sorted;
214 udword Index0, Index1;
215 while(RunningAddress<LastSorted && Sorted<LastSorted)
216 {
217 Index0 = *Sorted++;
218
219// while(RunningAddress<LastSorted && PosList[*RunningAddress++]<PosList[Index0]);
220 while(PosList[*RunningAddress++]<PosList[Index0]);
221
222 if(RunningAddress<LastSorted)
223 {
224 const udword* RunningAddress2 = RunningAddress;
225
226// while(RunningAddress2<LastSorted && PosList[Index1 = *RunningAddress2++]<=array[Index0]->GetMax(Axis0))
227 while(PosList[Index1 = *RunningAddress2++]<=array[Index0]->GetMax(Axis0))
228 {
229// if(Index0!=Index1)
230// {
231 if(array[Index0]->Intersect(*array[Index1], Axis1))
232 {
233 if(array[Index0]->Intersect(*array[Index1], Axis2))
234 {
235 pairs.AddPair(Index0, Index1);
236 }
237 }
238// }
239 }
240 }
241 }
242
243 DELETEARRAY(PosList);
244#endif
245
246#ifdef JOAKIM
247 // Allocate some temporary data
248// float* PosList = new float[nb];
249 float* MinList = new float[nb+1];
250
251 // 1) Build main list using the primary axis
252 for(udword i=0;i<nb;i++) MinList[i] = array[i]->GetMin(Axis0);
253 MinList[nb] = MAX_FLOAT;
254
255 // 2) Sort the list
256 PRUNING_SORTER* RS = GetCompletePruningSorter();
257 udword* Sorted = RS->Sort(MinList, nb+1).GetRanks();
258
259 // 3) Prune the list
260// const udword* const LastSorted = &Sorted[nb];
261// const udword* const LastSorted = &Sorted[nb-1];
262 const udword* RunningAddress = Sorted;
263 udword Index0, Index1;
264
265// while(RunningAddress<LastSorted && Sorted<LastSorted)
266// while(RunningAddress<LastSorted)
267 while(RunningAddress<&Sorted[nb])
268// while(Sorted<LastSorted)
269 {
270// Index0 = *Sorted++;
271 Index0 = *RunningAddress++;
272
273// while(RunningAddress<LastSorted && PosList[*RunningAddress++]<PosList[Index0]);
274// while(PosList[*RunningAddress++]<PosList[Index0]);
275//RunningAddress = Sorted;
276// if(RunningAddress<LastSorted)
277 {
278 const udword* RunningAddress2 = RunningAddress;
279
280// while(RunningAddress2<LastSorted && PosList[Index1 = *RunningAddress2++]<=array[Index0]->GetMax(Axis0))
281
282// float CurrentMin = array[Index0]->GetMin(Axis0);
283 float CurrentMax = array[Index0]->GetMax(Axis0);
284
285 while(MinList[Index1 = *RunningAddress2] <= CurrentMax)
286// while(PosList[Index1 = *RunningAddress] <= CurrentMax)
287 {
288// if(Index0!=Index1)
289// {
290 if(array[Index0]->Intersect(*array[Index1], Axis1))
291 {
292 if(array[Index0]->Intersect(*array[Index1], Axis2))
293 {
294 pairs.AddPair(Index0, Index1);
295 }
296 }
297// }
298
299 RunningAddress2++;
300// RunningAddress++;
301 }
302 }
303 }
304
305 DELETEARRAY(MinList);
306#endif
307
308 return true;
309}
310
311///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
312// Brute-force versions are kept:
313// - to check the optimized versions return the correct list of intersections
314// - to check the speed of the optimized code against the brute-force one
315///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
316
317///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
318/**
319 * Brute-force bipartite box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set.
320 * \param nb0 [in] number of boxes in the first set
321 * \param array0 [in] array of boxes for the first set
322 * \param nb1 [in] number of boxes in the second set
323 * \param array1 [in] array of boxes for the second set
324 * \param pairs [out] array of overlapping pairs
325 * \return true if success.
326 */
327///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
328bool Opcode::BruteForceBipartiteBoxTest(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs)
329{
330 // Checkings
331 if(!nb0 || !array0 || !nb1 || !array1) return false;
332
333 // Brute-force nb0*nb1 overlap tests
334 for(udword i=0;i<nb0;i++)
335 {
336 for(udword j=0;j<nb1;j++)
337 {
338 if(array0[i]->Intersect(*array1[j])) pairs.AddPair(i, j);
339 }
340 }
341 return true;
342}
343
344///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
345/**
346 * Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set.
347 * \param nb [in] number of boxes
348 * \param array [in] array of boxes
349 * \param pairs [out] array of overlapping pairs
350 * \return true if success.
351 */
352///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
353bool Opcode::BruteForceCompleteBoxTest(udword nb, const AABB** array, Pairs& pairs)
354{
355 // Checkings
356 if(!nb || !array) return false;
357
358 // Brute-force n(n-1)/2 overlap tests
359 for(udword i=0;i<nb;i++)
360 {
361 for(udword j=i+1;j<nb;j++)
362 {
363 if(array[i]->Intersect(*array[j])) pairs.AddPair(i, j);
364 }
365 }
366 return true;
367}
diff --git a/libraries/ode-0.9/OPCODE/OPC_BoxPruning.h b/libraries/ode-0.9/OPCODE/OPC_BoxPruning.h
new file mode 100644
index 0000000..2f77cd2
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_BoxPruning.h
@@ -0,0 +1,31 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for box pruning.
12 * \file IceBoxPruning.h
13 * \author Pierre Terdiman
14 * \date January, 29, 2000
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_BOXPRUNING_H__
21#define __OPC_BOXPRUNING_H__
22
23 // Optimized versions
24 FUNCTION OPCODE_API bool CompleteBoxPruning(udword nb, const AABB** array, Pairs& pairs, const Axes& axes);
25 FUNCTION OPCODE_API bool BipartiteBoxPruning(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs, const Axes& axes);
26
27 // Brute-force versions
28 FUNCTION OPCODE_API bool BruteForceCompleteBoxTest(udword nb, const AABB** array, Pairs& pairs);
29 FUNCTION OPCODE_API bool BruteForceBipartiteBoxTest(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs);
30
31#endif //__OPC_BOXPRUNING_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_Collider.cpp b/libraries/ode-0.9/OPCODE/OPC_Collider.cpp
new file mode 100644
index 0000000..f41fc36
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_Collider.cpp
@@ -0,0 +1,54 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains base collider class.
12 * \file OPC_Collider.cpp
13 * \author Pierre Terdiman
14 * \date June, 2, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19/**
20 * Contains the abstract class for colliders.
21 *
22 * \class Collider
23 * \author Pierre Terdiman
24 * \version 1.3
25 * \date June, 2, 2001
26*/
27///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
28
29///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
30// Precompiled Header
31#include "Stdafx.h"
32
33using namespace Opcode;
34
35///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
36/**
37 * Constructor.
38 */
39///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
40Collider::Collider() :
41 mFlags (0),
42 mCurrentModel (null),
43 mIMesh (null)
44{
45}
46
47///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
48/**
49 * Destructor.
50 */
51///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
52Collider::~Collider()
53{
54}
diff --git a/libraries/ode-0.9/OPCODE/OPC_Collider.h b/libraries/ode-0.9/OPCODE/OPC_Collider.h
new file mode 100644
index 0000000..d718e02
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_Collider.h
@@ -0,0 +1,176 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains base collider class.
12 * \file OPC_Collider.h
13 * \author Pierre Terdiman
14 * \date June, 2, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_COLLIDER_H__
21#define __OPC_COLLIDER_H__
22
23 enum CollisionFlag
24 {
25 OPC_FIRST_CONTACT = (1<<0), //!< Report all contacts (false) or only first one (true)
26 OPC_TEMPORAL_COHERENCE = (1<<1), //!< Use temporal coherence or not
27 OPC_CONTACT = (1<<2), //!< Final contact status after a collision query
28 OPC_TEMPORAL_HIT = (1<<3), //!< There has been an early exit due to temporal coherence
29 OPC_NO_PRIMITIVE_TESTS = (1<<4), //!< Keep or discard primitive-bv tests in leaf nodes (volume-mesh queries)
30
31 OPC_CONTACT_FOUND = OPC_FIRST_CONTACT | OPC_CONTACT,
32 OPC_TEMPORAL_CONTACT = OPC_TEMPORAL_HIT | OPC_CONTACT,
33
34 OPC_FORCE_DWORD = 0x7fffffff
35 };
36
37 class OPCODE_API Collider
38 {
39 public:
40 // Constructor / Destructor
41 Collider();
42 virtual ~Collider();
43
44 // Collision report
45
46 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
47 /**
48 * Gets the last collision status after a collision query.
49 * \return true if a collision occured
50 */
51 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
52 inline_ BOOL GetContactStatus() const { return mFlags & OPC_CONTACT; }
53
54 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
55 /**
56 * Gets the "first contact" mode.
57 * \return true if "first contact" mode is on
58 */
59 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
60 inline_ BOOL FirstContactEnabled() const { return mFlags & OPC_FIRST_CONTACT; }
61
62 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
63 /**
64 * Gets the temporal coherence mode.
65 * \return true if temporal coherence is on
66 */
67 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
68 inline_ BOOL TemporalCoherenceEnabled() const { return mFlags & OPC_TEMPORAL_COHERENCE; }
69
70 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
71 /**
72 * Checks a first contact has already been found.
73 * \return true if a first contact has been found and we can stop a query
74 */
75 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
76 inline_ BOOL ContactFound() const { return (mFlags&OPC_CONTACT_FOUND)==OPC_CONTACT_FOUND; }
77
78 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
79 /**
80 * Checks there's been an early exit due to temporal coherence;
81 * \return true if a temporal hit has occured
82 */
83 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
84 inline_ BOOL TemporalHit() const { return mFlags & OPC_TEMPORAL_HIT; }
85
86 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
87 /**
88 * Checks primitive tests are enabled;
89 * \return true if primitive tests must be skipped
90 */
91 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
92 inline_ BOOL SkipPrimitiveTests() const { return mFlags & OPC_NO_PRIMITIVE_TESTS; }
93
94 // Settings
95
96 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
97 /**
98 * Reports all contacts (false) or first contact only (true)
99 * \param flag [in] true for first contact, false for all contacts
100 * \see SetTemporalCoherence(bool flag)
101 * \see ValidateSettings()
102 */
103 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
104 inline_ void SetFirstContact(bool flag)
105 {
106 if(flag) mFlags |= OPC_FIRST_CONTACT;
107 else mFlags &= ~OPC_FIRST_CONTACT;
108 }
109
110 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
111 /**
112 * Enable/disable temporal coherence.
113 * \param flag [in] true to enable temporal coherence, false to discard it
114 * \see SetFirstContact(bool flag)
115 * \see ValidateSettings()
116 */
117 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
118 inline_ void SetTemporalCoherence(bool flag)
119 {
120 if(flag) mFlags |= OPC_TEMPORAL_COHERENCE;
121 else mFlags &= ~OPC_TEMPORAL_COHERENCE;
122 }
123
124 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
125 /**
126 * Enable/disable primitive tests.
127 * \param flag [in] true to enable primitive tests, false to discard them
128 */
129 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
130 inline_ void SetPrimitiveTests(bool flag)
131 {
132 if(!flag) mFlags |= OPC_NO_PRIMITIVE_TESTS;
133 else mFlags &= ~OPC_NO_PRIMITIVE_TESTS;
134 }
135
136 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
137 /**
138 * Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider.
139 * \return null if everything is ok, else a string describing the problem
140 */
141 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
142 virtual const char* ValidateSettings() = 0;
143
144 protected:
145 udword mFlags; //!< Bit flags
146 const BaseModel* mCurrentModel; //!< Current model for collision query (owner of touched faces)
147 // User mesh interface
148 const MeshInterface* mIMesh; //!< User-defined mesh interface
149
150 // Internal methods
151 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
152 /**
153 * Setups current collision model
154 * \param model [in] current collision model
155 * \return TRUE if success
156 */
157 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
158 inline_ BOOL Setup(const BaseModel* model)
159 {
160 // Keep track of current model
161 mCurrentModel = model;
162 if(!mCurrentModel) return FALSE;
163
164 mIMesh = model->GetMeshInterface();
165 return mIMesh!=null;
166 }
167
168 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
169 /**
170 * Initializes a query
171 */
172 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
173 virtual inline_ void InitQuery() { mFlags &= ~OPC_TEMPORAL_CONTACT; }
174 };
175
176#endif // __OPC_COLLIDER_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_Common.cpp b/libraries/ode-0.9/OPCODE/OPC_Common.cpp
new file mode 100644
index 0000000..5b9a9c8
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_Common.cpp
@@ -0,0 +1,48 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains common classes & defs used in OPCODE.
12 * \file OPC_Common.cpp
13 * \author Pierre Terdiman
14 * \date March, 20, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19/**
20 * An AABB dedicated to collision detection.
21 * We don't use the generic AABB class included in ICE, since it can be a Min/Max or a Center/Extents one (depends
22 * on compilation flags). Since the Center/Extents model is more efficient in collision detection, it was worth
23 * using an extra special class.
24 *
25 * \class CollisionAABB
26 * \author Pierre Terdiman
27 * \version 1.3
28 * \date March, 20, 2001
29*/
30///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
31
32///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
33/**
34 * A quantized AABB.
35 * Center/Extent model, using 16-bits integers.
36 *
37 * \class QuantizedAABB
38 * \author Pierre Terdiman
39 * \version 1.3
40 * \date March, 20, 2001
41*/
42///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
43
44///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
45// Precompiled Header
46#include "Stdafx.h"
47
48using namespace Opcode;
diff --git a/libraries/ode-0.9/OPCODE/OPC_Common.h b/libraries/ode-0.9/OPCODE/OPC_Common.h
new file mode 100644
index 0000000..f134990
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_Common.h
@@ -0,0 +1,101 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains common classes & defs used in OPCODE.
12 * \file OPC_Common.h
13 * \author Pierre Terdiman
14 * \date March, 20, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_COMMON_H__
21#define __OPC_COMMON_H__
22
23// [GOTTFRIED]: Just a small change for readability.
24#ifdef OPC_CPU_COMPARE
25 #define GREATER(x, y) AIR(x) > IR(y)
26#else
27 #define GREATER(x, y) fabsf(x) > (y)
28#endif
29
30 class OPCODE_API CollisionAABB
31 {
32 public:
33 //! Constructor
34 inline_ CollisionAABB() {}
35 //! Constructor
36 inline_ CollisionAABB(const AABB& b) { b.GetCenter(mCenter); b.GetExtents(mExtents); }
37 //! Destructor
38 inline_ ~CollisionAABB() {}
39
40 //! Get min point of the box
41 inline_ void GetMin(Point& min) const { min = mCenter - mExtents; }
42 //! Get max point of the box
43 inline_ void GetMax(Point& max) const { max = mCenter + mExtents; }
44
45 //! Get component of the box's min point along a given axis
46 inline_ float GetMin(udword axis) const { return mCenter[axis] - mExtents[axis]; }
47 //! Get component of the box's max point along a given axis
48 inline_ float GetMax(udword axis) const { return mCenter[axis] + mExtents[axis]; }
49
50 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
51 /**
52 * Setups an AABB from min & max vectors.
53 * \param min [in] the min point
54 * \param max [in] the max point
55 */
56 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
57 inline_ void SetMinMax(const Point& min, const Point& max) { mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f; }
58
59 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
60 /**
61 * Checks a box is inside another box.
62 * \param box [in] the other box
63 * \return true if current box is inside input box
64 */
65 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
66 inline_ BOOL IsInside(const CollisionAABB& box) const
67 {
68 if(box.GetMin(0)>GetMin(0)) return FALSE;
69 if(box.GetMin(1)>GetMin(1)) return FALSE;
70 if(box.GetMin(2)>GetMin(2)) return FALSE;
71 if(box.GetMax(0)<GetMax(0)) return FALSE;
72 if(box.GetMax(1)<GetMax(1)) return FALSE;
73 if(box.GetMax(2)<GetMax(2)) return FALSE;
74 return TRUE;
75 }
76
77 Point mCenter; //!< Box center
78 Point mExtents; //!< Box extents
79 };
80
81 class OPCODE_API QuantizedAABB
82 {
83 public:
84 //! Constructor
85 inline_ QuantizedAABB() {}
86 //! Destructor
87 inline_ ~QuantizedAABB() {}
88
89 sword mCenter[3]; //!< Quantized center
90 uword mExtents[3]; //!< Quantized extents
91 };
92
93 //! Quickly rotates & translates a vector
94 inline_ void TransformPoint(Point& dest, const Point& source, const Matrix3x3& rot, const Point& trans)
95 {
96 dest.x = trans.x + source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0];
97 dest.y = trans.y + source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1];
98 dest.z = trans.z + source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2];
99 }
100
101#endif //__OPC_COMMON_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_HybridModel.cpp b/libraries/ode-0.9/OPCODE/OPC_HybridModel.cpp
new file mode 100644
index 0000000..7016219
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_HybridModel.cpp
@@ -0,0 +1,466 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for hybrid models.
12 * \file OPC_HybridModel.cpp
13 * \author Pierre Terdiman
14 * \date May, 18, 2003
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19/**
20 * An hybrid collision model.
21 *
22 * The problem :
23 *
24 * Opcode really shines for mesh-mesh collision, especially when meshes are deeply overlapping
25 * (it typically outperforms RAPID in those cases).
26 *
27 * Unfortunately this is not the typical scenario in games.
28 *
29 * For close-proximity cases, especially for volume-mesh queries, it's relatively easy to run faster
30 * than Opcode, that suffers from a relatively high setup time.
31 *
32 * In particular, Opcode's "vanilla" trees in those cases -can- run faster. They can also use -less-
33 * memory than the optimized ones, when you let the system stop at ~10 triangles / leaf for example
34 * (i.e. when you don't use "complete" trees). However, those trees tend to fragment memory quite a
35 * lot, increasing cache misses : since they're not "complete", we can't predict the final number of
36 * nodes and we have to allocate nodes on-the-fly. For the same reasons we can't use Opcode's "optimized"
37 * trees here, since they rely on a known layout to perform the "optimization".
38 *
39 * Hybrid trees :
40 *
41 * Hybrid trees try to combine best of both worlds :
42 *
43 * - they use a maximum limit of 16 triangles/leaf. "16" is used so that we'll be able to save the
44 * number of triangles using 4 bits only.
45 *
46 * - they're still "complete" trees thanks to a two-passes building phase. First we create a "vanilla"
47 * AABB-tree with Opcode, limited to 16 triangles/leaf. Then we create a *second* vanilla tree, this
48 * time using the leaves of the first one. The trick is : this second tree is now "complete"... so we
49 * can further transform it into an Opcode's optimized tree.
50 *
51 * - then we run the collision queries on that standard Opcode tree. The only difference is that leaf
52 * nodes contain indices to leaf nodes of another tree. Also, we have to skip all primitive tests in
53 * Opcode optimized trees, since our leaves don't contain triangles anymore.
54 *
55 * - finally, for each collided leaf, we simply loop through 16 triangles max, and collide them with
56 * the bounding volume used in the query (we only support volume-vs-mesh queries here, not mesh-vs-mesh)
57 *
58 * All of that is wrapped in this "hybrid model" that contains the minimal data required for this to work.
59 * It's a mix between old "vanilla" trees, and old "optimized" trees.
60 *
61 * Extra advantages:
62 *
63 * - If we use them for dynamic models, we're left with a very small number of leaf nodes to refit. It
64 * might be a bit faster since we have less nodes to write back.
65 *
66 * - In rigid body simulation, using temporal coherence and sleeping objects greatly reduce the actual
67 * influence of one tree over another (i.e. the speed difference is often invisible). So memory is really
68 * the key element to consider, and in this regard hybrid trees are just better.
69 *
70 * Information to take home:
71 * - they use less ram
72 * - they're not slower (they're faster or slower depending on cases, overall there's no significant
73 * difference *as long as objects don't interpenetrate too much* - in which case Opcode's optimized trees
74 * are still notably faster)
75 *
76 * \class HybridModel
77 * \author Pierre Terdiman
78 * \version 1.3
79 * \date May, 18, 2003
80*/
81///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
82
83///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
84// Precompiled Header
85#include "Stdafx.h"
86
87using namespace Opcode;
88
89///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
90/**
91 * Constructor.
92 */
93///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
94HybridModel::HybridModel() :
95 mNbLeaves (0),
96 mNbPrimitives (0),
97 mTriangles (null),
98 mIndices (null)
99{
100}
101
102///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
103/**
104 * Destructor.
105 */
106///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
107HybridModel::~HybridModel()
108{
109 Release();
110}
111
112///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
113/**
114 * Releases everything.
115 */
116///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
117void HybridModel::Release()
118{
119 ReleaseBase();
120 DELETEARRAY(mIndices);
121 DELETEARRAY(mTriangles);
122 mNbLeaves = 0;
123 mNbPrimitives = 0;
124}
125
126 struct Internal
127 {
128 Internal()
129 {
130 mNbLeaves = 0;
131 mLeaves = null;
132 mTriangles = null;
133 mBase = null;
134 }
135 ~Internal()
136 {
137 DELETEARRAY(mLeaves);
138 }
139
140 udword mNbLeaves;
141 AABB* mLeaves;
142 LeafTriangles* mTriangles;
143 const udword* mBase;
144 };
145
146///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
147/**
148 * Builds a collision model.
149 * \param create [in] model creation structure
150 * \return true if success
151 */
152///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
153bool HybridModel::Build(const OPCODECREATE& create)
154{
155 // 1) Checkings
156 if(!create.mIMesh || !create.mIMesh->IsValid()) return false;
157
158 // Look for degenerate faces.
159 udword NbDegenerate = create.mIMesh->CheckTopology();
160 if(NbDegenerate) Log("OPCODE WARNING: found %d degenerate faces in model! Collision might report wrong results!\n", NbDegenerate);
161 // We continue nonetheless....
162
163 Release(); // Make sure previous tree has been discarded
164
165 // 1-1) Setup mesh interface automatically
166 SetMeshInterface(create.mIMesh);
167
168 bool Status = false;
169 AABBTree* LeafTree = null;
170 Internal Data;
171
172 // 2) Build a generic AABB Tree.
173 mSource = new AABBTree;
174 CHECKALLOC(mSource);
175
176 // 2-1) Setup a builder. Our primitives here are triangles from input mesh,
177 // so we use an AABBTreeOfTrianglesBuilder.....
178 {
179 AABBTreeOfTrianglesBuilder TB;
180 TB.mIMesh = create.mIMesh;
181 TB.mNbPrimitives = create.mIMesh->GetNbTriangles();
182 TB.mSettings = create.mSettings;
183 TB.mSettings.mLimit = 16; // ### Hardcoded, but maybe we could let the user choose 8 / 16 / 32 ...
184 if(!mSource->Build(&TB)) goto FreeAndExit;
185 }
186
187 // 2-2) Here's the trick : create *another* AABB tree using the leaves of the first one (which are boxes, this time)
188 struct Local
189 {
190 // A callback to count leaf nodes
191 static bool CountLeaves(const AABBTreeNode* current, udword depth, void* user_data)
192 {
193 if(current->IsLeaf())
194 {
195 Internal* Data = (Internal*)user_data;
196 Data->mNbLeaves++;
197 }
198 return true;
199 }
200
201 // A callback to setup leaf nodes in our internal structures
202 static bool SetupLeafData(const AABBTreeNode* current, udword depth, void* user_data)
203 {
204 if(current->IsLeaf())
205 {
206 Internal* Data = (Internal*)user_data;
207
208 // Get current leaf's box
209 Data->mLeaves[Data->mNbLeaves] = *current->GetAABB();
210
211 // Setup leaf data
212 udword Index = udword((size_t(current->GetPrimitives()) - size_t(Data->mBase)) / sizeof(udword));
213 Data->mTriangles[Data->mNbLeaves].SetData(current->GetNbPrimitives(), Index);
214
215 Data->mNbLeaves++;
216 }
217 return true;
218 }
219 };
220
221 // Walk the tree & count number of leaves
222 Data.mNbLeaves = 0;
223 mSource->Walk(Local::CountLeaves, &Data);
224 mNbLeaves = Data.mNbLeaves; // Keep track of it
225
226 // Special case for 1-leaf meshes
227 if(mNbLeaves==1)
228 {
229 mModelCode |= OPC_SINGLE_NODE;
230 Status = true;
231 goto FreeAndExit;
232 }
233
234 // Allocate our structures
235 Data.mLeaves = new AABB[Data.mNbLeaves]; CHECKALLOC(Data.mLeaves);
236 mTriangles = new LeafTriangles[Data.mNbLeaves]; CHECKALLOC(mTriangles);
237
238 // Walk the tree again & setup leaf data
239 Data.mTriangles = mTriangles;
240 Data.mBase = mSource->GetIndices();
241 Data.mNbLeaves = 0; // Reset for incoming walk
242 mSource->Walk(Local::SetupLeafData, &Data);
243
244 // Handle source indices
245 {
246 bool MustKeepIndices = true;
247 if(create.mCanRemap)
248 {
249 // We try to get rid of source indices (saving more ram!) by reorganizing triangle arrays...
250 // Remap can fail when we use callbacks => keep track of indices in that case (it still
251 // works, only using more memory)
252 if(create.mIMesh->RemapClient(mSource->GetNbPrimitives(), mSource->GetIndices()))
253 {
254 MustKeepIndices = false;
255 }
256 }
257
258 if(MustKeepIndices)
259 {
260 // Keep track of source indices (from vanilla tree)
261 mNbPrimitives = mSource->GetNbPrimitives();
262 mIndices = new udword[mNbPrimitives];
263 CopyMemory(mIndices, mSource->GetIndices(), mNbPrimitives*sizeof(udword));
264 }
265 }
266
267 // Now, create our optimized tree using previous leaf nodes
268 LeafTree = new AABBTree;
269 CHECKALLOC(LeafTree);
270 {
271 AABBTreeOfAABBsBuilder TB; // Now using boxes !
272 TB.mSettings = create.mSettings;
273 TB.mSettings.mLimit = 1; // We now want a complete tree so that we can "optimize" it
274 TB.mNbPrimitives = Data.mNbLeaves;
275 TB.mAABBArray = Data.mLeaves;
276 if(!LeafTree->Build(&TB)) goto FreeAndExit;
277 }
278
279 // 3) Create an optimized tree according to user-settings
280 if(!CreateTree(create.mNoLeaf, create.mQuantized)) goto FreeAndExit;
281
282 // 3-2) Create optimized tree
283 if(!mTree->Build(LeafTree)) goto FreeAndExit;
284
285 // Finally ok...
286 Status = true;
287
288FreeAndExit: // Allow me this one...
289 DELETESINGLE(LeafTree);
290
291 // 3-3) Delete generic tree if needed
292 if(!create.mKeepOriginal) DELETESINGLE(mSource);
293
294 return Status;
295}
296
297///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
298/**
299 * Gets the number of bytes used by the tree.
300 * \return amount of bytes used
301 */
302///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
303udword HybridModel::GetUsedBytes() const
304{
305 udword UsedBytes = 0;
306 if(mTree) UsedBytes += mTree->GetUsedBytes();
307 if(mIndices) UsedBytes += mNbPrimitives * sizeof(udword); // mIndices
308 if(mTriangles) UsedBytes += mNbLeaves * sizeof(LeafTriangles); // mTriangles
309 return UsedBytes;
310}
311
312inline_ void ComputeMinMax(Point& min, Point& max, const VertexPointers& vp)
313{
314 // Compute triangle's AABB = a leaf box
315#ifdef OPC_USE_FCOMI // a 15% speedup on my machine, not much
316 min.x = FCMin3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x);
317 max.x = FCMax3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x);
318
319 min.y = FCMin3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y);
320 max.y = FCMax3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y);
321
322 min.z = FCMin3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z);
323 max.z = FCMax3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z);
324#else
325 min = *vp.Vertex[0];
326 max = *vp.Vertex[0];
327 min.Min(*vp.Vertex[1]);
328 max.Max(*vp.Vertex[1]);
329 min.Min(*vp.Vertex[2]);
330 max.Max(*vp.Vertex[2]);
331#endif
332}
333
334///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
335/**
336 * Refits the collision model. This can be used to handle dynamic meshes. Usage is:
337 * 1. modify your mesh vertices (keep the topology constant!)
338 * 2. refit the tree (call this method)
339 * \return true if success
340 */
341///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
342bool HybridModel::Refit()
343{
344 if(!mIMesh) return false;
345 if(!mTree) return false;
346
347 if(IsQuantized()) return false;
348 if(HasLeafNodes()) return false;
349
350 const LeafTriangles* LT = GetLeafTriangles();
351 const udword* Indices = GetIndices();
352
353 // Bottom-up update
354 VertexPointers VP;
355 Point Min,Max;
356 Point Min_,Max_;
357 udword Index = mTree->GetNbNodes();
358 AABBNoLeafNode* Nodes = (AABBNoLeafNode*)((AABBNoLeafTree*)mTree)->GetNodes();
359 while(Index--)
360 {
361 AABBNoLeafNode& Current = Nodes[Index];
362
363 if(Current.HasPosLeaf())
364 {
365 const LeafTriangles& CurrentLeaf = LT[Current.GetPosPrimitive()];
366
367 Min.SetPlusInfinity();
368 Max.SetMinusInfinity();
369
370 Point TmpMin, TmpMax;
371
372 // Each leaf box has a set of triangles
373 udword NbTris = CurrentLeaf.GetNbTriangles();
374 if(Indices)
375 {
376 const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()];
377
378 // Loop through triangles and test each of them
379 while(NbTris--)
380 {
381 mIMesh->GetTriangle(VP, *T++);
382 ComputeMinMax(TmpMin, TmpMax, VP);
383 Min.Min(TmpMin);
384 Max.Max(TmpMax);
385 }
386 }
387 else
388 {
389 udword BaseIndex = CurrentLeaf.GetTriangleIndex();
390
391 // Loop through triangles and test each of them
392 while(NbTris--)
393 {
394 mIMesh->GetTriangle(VP, BaseIndex++);
395 ComputeMinMax(TmpMin, TmpMax, VP);
396 Min.Min(TmpMin);
397 Max.Max(TmpMax);
398 }
399 }
400 }
401 else
402 {
403 const CollisionAABB& CurrentBox = Current.GetPos()->mAABB;
404 CurrentBox.GetMin(Min);
405 CurrentBox.GetMax(Max);
406 }
407
408 if(Current.HasNegLeaf())
409 {
410 const LeafTriangles& CurrentLeaf = LT[Current.GetNegPrimitive()];
411
412 Min_.SetPlusInfinity();
413 Max_.SetMinusInfinity();
414
415 Point TmpMin, TmpMax;
416
417 // Each leaf box has a set of triangles
418 udword NbTris = CurrentLeaf.GetNbTriangles();
419 if(Indices)
420 {
421 const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()];
422
423 // Loop through triangles and test each of them
424 while(NbTris--)
425 {
426 mIMesh->GetTriangle(VP, *T++);
427 ComputeMinMax(TmpMin, TmpMax, VP);
428 Min_.Min(TmpMin);
429 Max_.Max(TmpMax);
430 }
431 }
432 else
433 {
434 udword BaseIndex = CurrentLeaf.GetTriangleIndex();
435
436 // Loop through triangles and test each of them
437 while(NbTris--)
438 {
439 mIMesh->GetTriangle(VP, BaseIndex++);
440 ComputeMinMax(TmpMin, TmpMax, VP);
441 Min_.Min(TmpMin);
442 Max_.Max(TmpMax);
443 }
444 }
445 }
446 else
447 {
448 const CollisionAABB& CurrentBox = Current.GetNeg()->mAABB;
449 CurrentBox.GetMin(Min_);
450 CurrentBox.GetMax(Max_);
451 }
452#ifdef OPC_USE_FCOMI
453 Min.x = FCMin2(Min.x, Min_.x);
454 Max.x = FCMax2(Max.x, Max_.x);
455 Min.y = FCMin2(Min.y, Min_.y);
456 Max.y = FCMax2(Max.y, Max_.y);
457 Min.z = FCMin2(Min.z, Min_.z);
458 Max.z = FCMax2(Max.z, Max_.z);
459#else
460 Min.Min(Min_);
461 Max.Max(Max_);
462#endif
463 Current.mAABB.SetMinMax(Min, Max);
464 }
465 return true;
466}
diff --git a/libraries/ode-0.9/OPCODE/OPC_HybridModel.h b/libraries/ode-0.9/OPCODE/OPC_HybridModel.h
new file mode 100644
index 0000000..c7eb59d
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_HybridModel.h
@@ -0,0 +1,106 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for hybrid models.
12 * \file OPC_HybridModel.h
13 * \author Pierre Terdiman
14 * \date May, 18, 2003
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_HYBRIDMODEL_H__
21#define __OPC_HYBRIDMODEL_H__
22
23 //! Leaf descriptor
24 struct LeafTriangles
25 {
26 udword Data; //!< Packed data
27
28 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
29 /**
30 * Gets number of triangles in the leaf.
31 * \return number of triangles N, with 0 < N <= 16
32 */
33 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
34 inline_ udword GetNbTriangles() const { return (Data & 15)+1; }
35
36 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
37 /**
38 * Gets triangle index for this leaf. Indexed model's array of indices retrieved with HybridModel::GetIndices()
39 * \return triangle index
40 */
41 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
42 inline_ udword GetTriangleIndex() const { return Data>>4; }
43 inline_ void SetData(udword nb, udword index) { ASSERT(nb>0 && nb<=16); nb--; Data = (index<<4)|(nb&15); }
44 };
45
46 class OPCODE_API HybridModel : public BaseModel
47 {
48 public:
49 // Constructor/Destructor
50 HybridModel();
51 virtual ~HybridModel();
52
53 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
54 /**
55 * Builds a collision model.
56 * \param create [in] model creation structure
57 * \return true if success
58 */
59 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
60 override(BaseModel) bool Build(const OPCODECREATE& create);
61
62 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
63 /**
64 * Gets the number of bytes used by the tree.
65 * \return amount of bytes used
66 */
67 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
68 override(BaseModel) udword GetUsedBytes() const;
69
70 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
71 /**
72 * Refits the collision model. This can be used to handle dynamic meshes. Usage is:
73 * 1. modify your mesh vertices (keep the topology constant!)
74 * 2. refit the tree (call this method)
75 * \return true if success
76 */
77 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
78 override(BaseModel) bool Refit();
79
80 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
81 /**
82 * Gets array of triangles.
83 * \return array of triangles
84 */
85 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
86 inline_ const LeafTriangles* GetLeafTriangles() const { return mTriangles; }
87
88 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
89 /**
90 * Gets array of indices.
91 * \return array of indices
92 */
93 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
94 inline_ const udword* GetIndices() const { return mIndices; }
95
96 private:
97 udword mNbLeaves; //!< Number of leaf nodes in the model
98 LeafTriangles* mTriangles; //!< Array of mNbLeaves leaf descriptors
99 udword mNbPrimitives; //!< Number of primitives in the model
100 udword* mIndices; //!< Array of primitive indices
101
102 // Internal methods
103 void Release();
104 };
105
106#endif // __OPC_HYBRIDMODEL_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_IceHook.h b/libraries/ode-0.9/OPCODE/OPC_IceHook.h
new file mode 100644
index 0000000..62343b8
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_IceHook.h
@@ -0,0 +1,70 @@
1
2// Should be included by Opcode.h if needed
3
4 #define ICE_DONT_CHECK_COMPILER_OPTIONS
5
6 // From Windows...
7 typedef int BOOL;
8 #ifndef FALSE
9 #define FALSE 0
10 #endif
11
12 #ifndef TRUE
13 #define TRUE 1
14 #endif
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <assert.h>
19 #include <string.h>
20 #include <float.h>
21 #include <math.h>
22
23 #ifndef ASSERT
24 #define ASSERT(exp) {}
25 #endif
26 #define ICE_COMPILE_TIME_ASSERT(exp) extern char ICE_Dummy[ (exp) ? 1 : -1 ]
27
28 #define Log {}
29 #define SetIceError(a,b) false
30 #define EC_OUTOFMEMORY "Out of memory"
31
32 #include "Ice/IcePreprocessor.h"
33
34 #undef ICECORE_API
35 #define ICECORE_API OPCODE_API
36
37 #include "Ice/IceTypes.h"
38 #include "Ice/IceFPU.h"
39 #include "Ice/IceMemoryMacros.h"
40
41 namespace IceCore
42 {
43 #include "Ice/IceUtils.h"
44 #include "Ice/IceContainer.h"
45 #include "Ice/IcePairs.h"
46 #include "Ice/IceRevisitedRadix.h"
47 #include "Ice/IceRandom.h"
48 }
49 using namespace IceCore;
50
51 #define ICEMATHS_API OPCODE_API
52 namespace IceMaths
53 {
54 #include "Ice/IceAxes.h"
55 #include "Ice/IcePoint.h"
56 #include "Ice/IceHPoint.h"
57 #include "Ice/IceMatrix3x3.h"
58 #include "Ice/IceMatrix4x4.h"
59 #include "Ice/IcePlane.h"
60 #include "Ice/IceRay.h"
61 #include "Ice/IceIndexedTriangle.h"
62 #include "Ice/IceTriangle.h"
63 #include "Ice/IceTriList.h"
64 #include "Ice/IceAABB.h"
65 #include "Ice/IceOBB.h"
66 #include "Ice/IceBoundingSphere.h"
67 #include "Ice/IceSegment.h"
68 #include "Ice/IceLSS.h"
69 }
70 using namespace IceMaths;
diff --git a/libraries/ode-0.9/OPCODE/OPC_LSSAABBOverlap.h b/libraries/ode-0.9/OPCODE/OPC_LSSAABBOverlap.h
new file mode 100644
index 0000000..5cc50b5
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_LSSAABBOverlap.h
@@ -0,0 +1,523 @@
1
2// Following code from Magic-Software (http://www.magic-software.com/)
3// A bit modified for Opcode
4
5inline_ float OPC_PointAABBSqrDist(const Point& point, const Point& center, const Point& extents)
6{
7 // Compute coordinates of point in box coordinate system
8 Point Closest = point - center;
9
10 float SqrDistance = 0.0f;
11
12 if(Closest.x < -extents.x)
13 {
14 float Delta = Closest.x + extents.x;
15 SqrDistance += Delta*Delta;
16 }
17 else if(Closest.x > extents.x)
18 {
19 float Delta = Closest.x - extents.x;
20 SqrDistance += Delta*Delta;
21 }
22
23 if(Closest.y < -extents.y)
24 {
25 float Delta = Closest.y + extents.y;
26 SqrDistance += Delta*Delta;
27 }
28 else if(Closest.y > extents.y)
29 {
30 float Delta = Closest.y - extents.y;
31 SqrDistance += Delta*Delta;
32 }
33
34 if(Closest.z < -extents.z)
35 {
36 float Delta = Closest.z + extents.z;
37 SqrDistance += Delta*Delta;
38 }
39 else if(Closest.z > extents.z)
40 {
41 float Delta = Closest.z - extents.z;
42 SqrDistance += Delta*Delta;
43 }
44 return SqrDistance;
45}
46
47static void Face(int i0, int i1, int i2, Point& rkPnt, const Point& rkDir, const Point& extents, const Point& rkPmE, float* pfLParam, float& rfSqrDistance)
48{
49 Point kPpE;
50 float fLSqr, fInv, fTmp, fParam, fT, fDelta;
51
52 kPpE[i1] = rkPnt[i1] + extents[i1];
53 kPpE[i2] = rkPnt[i2] + extents[i2];
54 if(rkDir[i0]*kPpE[i1] >= rkDir[i1]*rkPmE[i0])
55 {
56 if(rkDir[i0]*kPpE[i2] >= rkDir[i2]*rkPmE[i0])
57 {
58 // v[i1] >= -e[i1], v[i2] >= -e[i2] (distance = 0)
59 if(pfLParam)
60 {
61 rkPnt[i0] = extents[i0];
62 fInv = 1.0f/rkDir[i0];
63 rkPnt[i1] -= rkDir[i1]*rkPmE[i0]*fInv;
64 rkPnt[i2] -= rkDir[i2]*rkPmE[i0]*fInv;
65 *pfLParam = -rkPmE[i0]*fInv;
66 }
67 }
68 else
69 {
70 // v[i1] >= -e[i1], v[i2] < -e[i2]
71 fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i2]*rkDir[i2];
72 fTmp = fLSqr*kPpE[i1] - rkDir[i1]*(rkDir[i0]*rkPmE[i0] + rkDir[i2]*kPpE[i2]);
73 if(fTmp <= 2.0f*fLSqr*extents[i1])
74 {
75 fT = fTmp/fLSqr;
76 fLSqr += rkDir[i1]*rkDir[i1];
77 fTmp = kPpE[i1] - fT;
78 fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*fTmp + rkDir[i2]*kPpE[i2];
79 fParam = -fDelta/fLSqr;
80 rfSqrDistance += rkPmE[i0]*rkPmE[i0] + fTmp*fTmp + kPpE[i2]*kPpE[i2] + fDelta*fParam;
81
82 if(pfLParam)
83 {
84 *pfLParam = fParam;
85 rkPnt[i0] = extents[i0];
86 rkPnt[i1] = fT - extents[i1];
87 rkPnt[i2] = -extents[i2];
88 }
89 }
90 else
91 {
92 fLSqr += rkDir[i1]*rkDir[i1];
93 fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*rkPmE[i1] + rkDir[i2]*kPpE[i2];
94 fParam = -fDelta/fLSqr;
95 rfSqrDistance += rkPmE[i0]*rkPmE[i0] + rkPmE[i1]*rkPmE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam;
96
97 if(pfLParam)
98 {
99 *pfLParam = fParam;
100 rkPnt[i0] = extents[i0];
101 rkPnt[i1] = extents[i1];
102 rkPnt[i2] = -extents[i2];
103 }
104 }
105 }
106 }
107 else
108 {
109 if ( rkDir[i0]*kPpE[i2] >= rkDir[i2]*rkPmE[i0] )
110 {
111 // v[i1] < -e[i1], v[i2] >= -e[i2]
112 fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1];
113 fTmp = fLSqr*kPpE[i2] - rkDir[i2]*(rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1]);
114 if(fTmp <= 2.0f*fLSqr*extents[i2])
115 {
116 fT = fTmp/fLSqr;
117 fLSqr += rkDir[i2]*rkDir[i2];
118 fTmp = kPpE[i2] - fT;
119 fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*fTmp;
120 fParam = -fDelta/fLSqr;
121 rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + fTmp*fTmp + fDelta*fParam;
122
123 if(pfLParam)
124 {
125 *pfLParam = fParam;
126 rkPnt[i0] = extents[i0];
127 rkPnt[i1] = -extents[i1];
128 rkPnt[i2] = fT - extents[i2];
129 }
130 }
131 else
132 {
133 fLSqr += rkDir[i2]*rkDir[i2];
134 fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*rkPmE[i2];
135 fParam = -fDelta/fLSqr;
136 rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + rkPmE[i2]*rkPmE[i2] + fDelta*fParam;
137
138 if(pfLParam)
139 {
140 *pfLParam = fParam;
141 rkPnt[i0] = extents[i0];
142 rkPnt[i1] = -extents[i1];
143 rkPnt[i2] = extents[i2];
144 }
145 }
146 }
147 else
148 {
149 // v[i1] < -e[i1], v[i2] < -e[i2]
150 fLSqr = rkDir[i0]*rkDir[i0]+rkDir[i2]*rkDir[i2];
151 fTmp = fLSqr*kPpE[i1] - rkDir[i1]*(rkDir[i0]*rkPmE[i0] + rkDir[i2]*kPpE[i2]);
152 if(fTmp >= 0.0f)
153 {
154 // v[i1]-edge is closest
155 if ( fTmp <= 2.0f*fLSqr*extents[i1] )
156 {
157 fT = fTmp/fLSqr;
158 fLSqr += rkDir[i1]*rkDir[i1];
159 fTmp = kPpE[i1] - fT;
160 fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*fTmp + rkDir[i2]*kPpE[i2];
161 fParam = -fDelta/fLSqr;
162 rfSqrDistance += rkPmE[i0]*rkPmE[i0] + fTmp*fTmp + kPpE[i2]*kPpE[i2] + fDelta*fParam;
163
164 if(pfLParam)
165 {
166 *pfLParam = fParam;
167 rkPnt[i0] = extents[i0];
168 rkPnt[i1] = fT - extents[i1];
169 rkPnt[i2] = -extents[i2];
170 }
171 }
172 else
173 {
174 fLSqr += rkDir[i1]*rkDir[i1];
175 fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*rkPmE[i1] + rkDir[i2]*kPpE[i2];
176 fParam = -fDelta/fLSqr;
177 rfSqrDistance += rkPmE[i0]*rkPmE[i0] + rkPmE[i1]*rkPmE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam;
178
179 if(pfLParam)
180 {
181 *pfLParam = fParam;
182 rkPnt[i0] = extents[i0];
183 rkPnt[i1] = extents[i1];
184 rkPnt[i2] = -extents[i2];
185 }
186 }
187 return;
188 }
189
190 fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1];
191 fTmp = fLSqr*kPpE[i2] - rkDir[i2]*(rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1]);
192 if(fTmp >= 0.0f)
193 {
194 // v[i2]-edge is closest
195 if(fTmp <= 2.0f*fLSqr*extents[i2])
196 {
197 fT = fTmp/fLSqr;
198 fLSqr += rkDir[i2]*rkDir[i2];
199 fTmp = kPpE[i2] - fT;
200 fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*fTmp;
201 fParam = -fDelta/fLSqr;
202 rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + fTmp*fTmp + fDelta*fParam;
203
204 if(pfLParam)
205 {
206 *pfLParam = fParam;
207 rkPnt[i0] = extents[i0];
208 rkPnt[i1] = -extents[i1];
209 rkPnt[i2] = fT - extents[i2];
210 }
211 }
212 else
213 {
214 fLSqr += rkDir[i2]*rkDir[i2];
215 fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*rkPmE[i2];
216 fParam = -fDelta/fLSqr;
217 rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + rkPmE[i2]*rkPmE[i2] + fDelta*fParam;
218
219 if(pfLParam)
220 {
221 *pfLParam = fParam;
222 rkPnt[i0] = extents[i0];
223 rkPnt[i1] = -extents[i1];
224 rkPnt[i2] = extents[i2];
225 }
226 }
227 return;
228 }
229
230 // (v[i1],v[i2])-corner is closest
231 fLSqr += rkDir[i2]*rkDir[i2];
232 fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*kPpE[i2];
233 fParam = -fDelta/fLSqr;
234 rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam;
235
236 if(pfLParam)
237 {
238 *pfLParam = fParam;
239 rkPnt[i0] = extents[i0];
240 rkPnt[i1] = -extents[i1];
241 rkPnt[i2] = -extents[i2];
242 }
243 }
244 }
245}
246
247static void CaseNoZeros(Point& rkPnt, const Point& rkDir, const Point& extents, float* pfLParam, float& rfSqrDistance)
248{
249 Point kPmE(rkPnt.x - extents.x, rkPnt.y - extents.y, rkPnt.z - extents.z);
250
251 float fProdDxPy, fProdDyPx, fProdDzPx, fProdDxPz, fProdDzPy, fProdDyPz;
252
253 fProdDxPy = rkDir.x*kPmE.y;
254 fProdDyPx = rkDir.y*kPmE.x;
255 if(fProdDyPx >= fProdDxPy)
256 {
257 fProdDzPx = rkDir.z*kPmE.x;
258 fProdDxPz = rkDir.x*kPmE.z;
259 if(fProdDzPx >= fProdDxPz)
260 {
261 // line intersects x = e0
262 Face(0, 1, 2, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance);
263 }
264 else
265 {
266 // line intersects z = e2
267 Face(2, 0, 1, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance);
268 }
269 }
270 else
271 {
272 fProdDzPy = rkDir.z*kPmE.y;
273 fProdDyPz = rkDir.y*kPmE.z;
274 if(fProdDzPy >= fProdDyPz)
275 {
276 // line intersects y = e1
277 Face(1, 2, 0, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance);
278 }
279 else
280 {
281 // line intersects z = e2
282 Face(2, 0, 1, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance);
283 }
284 }
285}
286
287static void Case0(int i0, int i1, int i2, Point& rkPnt, const Point& rkDir, const Point& extents, float* pfLParam, float& rfSqrDistance)
288{
289 float fPmE0 = rkPnt[i0] - extents[i0];
290 float fPmE1 = rkPnt[i1] - extents[i1];
291 float fProd0 = rkDir[i1]*fPmE0;
292 float fProd1 = rkDir[i0]*fPmE1;
293 float fDelta, fInvLSqr, fInv;
294
295 if(fProd0 >= fProd1)
296 {
297 // line intersects P[i0] = e[i0]
298 rkPnt[i0] = extents[i0];
299
300 float fPpE1 = rkPnt[i1] + extents[i1];
301 fDelta = fProd0 - rkDir[i0]*fPpE1;
302 if(fDelta >= 0.0f)
303 {
304 fInvLSqr = 1.0f/(rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]);
305 rfSqrDistance += fDelta*fDelta*fInvLSqr;
306 if(pfLParam)
307 {
308 rkPnt[i1] = -extents[i1];
309 *pfLParam = -(rkDir[i0]*fPmE0+rkDir[i1]*fPpE1)*fInvLSqr;
310 }
311 }
312 else
313 {
314 if(pfLParam)
315 {
316 fInv = 1.0f/rkDir[i0];
317 rkPnt[i1] -= fProd0*fInv;
318 *pfLParam = -fPmE0*fInv;
319 }
320 }
321 }
322 else
323 {
324 // line intersects P[i1] = e[i1]
325 rkPnt[i1] = extents[i1];
326
327 float fPpE0 = rkPnt[i0] + extents[i0];
328 fDelta = fProd1 - rkDir[i1]*fPpE0;
329 if(fDelta >= 0.0f)
330 {
331 fInvLSqr = 1.0f/(rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]);
332 rfSqrDistance += fDelta*fDelta*fInvLSqr;
333 if(pfLParam)
334 {
335 rkPnt[i0] = -extents[i0];
336 *pfLParam = -(rkDir[i0]*fPpE0+rkDir[i1]*fPmE1)*fInvLSqr;
337 }
338 }
339 else
340 {
341 if(pfLParam)
342 {
343 fInv = 1.0f/rkDir[i1];
344 rkPnt[i0] -= fProd1*fInv;
345 *pfLParam = -fPmE1*fInv;
346 }
347 }
348 }
349
350 if(rkPnt[i2] < -extents[i2])
351 {
352 fDelta = rkPnt[i2] + extents[i2];
353 rfSqrDistance += fDelta*fDelta;
354 rkPnt[i2] = -extents[i2];
355 }
356 else if ( rkPnt[i2] > extents[i2] )
357 {
358 fDelta = rkPnt[i2] - extents[i2];
359 rfSqrDistance += fDelta*fDelta;
360 rkPnt[i2] = extents[i2];
361 }
362}
363
364static void Case00(int i0, int i1, int i2, Point& rkPnt, const Point& rkDir, const Point& extents, float* pfLParam, float& rfSqrDistance)
365{
366 float fDelta;
367
368 if(pfLParam)
369 *pfLParam = (extents[i0] - rkPnt[i0])/rkDir[i0];
370
371 rkPnt[i0] = extents[i0];
372
373 if(rkPnt[i1] < -extents[i1])
374 {
375 fDelta = rkPnt[i1] + extents[i1];
376 rfSqrDistance += fDelta*fDelta;
377 rkPnt[i1] = -extents[i1];
378 }
379 else if(rkPnt[i1] > extents[i1])
380 {
381 fDelta = rkPnt[i1] - extents[i1];
382 rfSqrDistance += fDelta*fDelta;
383 rkPnt[i1] = extents[i1];
384 }
385
386 if(rkPnt[i2] < -extents[i2])
387 {
388 fDelta = rkPnt[i2] + extents[i2];
389 rfSqrDistance += fDelta*fDelta;
390 rkPnt[i1] = -extents[i2];
391 }
392 else if(rkPnt[i2] > extents[i2])
393 {
394 fDelta = rkPnt[i2] - extents[i2];
395 rfSqrDistance += fDelta*fDelta;
396 rkPnt[i2] = extents[i2];
397 }
398}
399
400static void Case000(Point& rkPnt, const Point& extents, float& rfSqrDistance)
401{
402 float fDelta;
403
404 if(rkPnt.x < -extents.x)
405 {
406 fDelta = rkPnt.x + extents.x;
407 rfSqrDistance += fDelta*fDelta;
408 rkPnt.x = -extents.x;
409 }
410 else if(rkPnt.x > extents.x)
411 {
412 fDelta = rkPnt.x - extents.x;
413 rfSqrDistance += fDelta*fDelta;
414 rkPnt.x = extents.x;
415 }
416
417 if(rkPnt.y < -extents.y)
418 {
419 fDelta = rkPnt.y + extents.y;
420 rfSqrDistance += fDelta*fDelta;
421 rkPnt.y = -extents.y;
422 }
423 else if(rkPnt.y > extents.y)
424 {
425 fDelta = rkPnt.y - extents.y;
426 rfSqrDistance += fDelta*fDelta;
427 rkPnt.y = extents.y;
428 }
429
430 if(rkPnt.z < -extents.z)
431 {
432 fDelta = rkPnt.z + extents.z;
433 rfSqrDistance += fDelta*fDelta;
434 rkPnt.z = -extents.z;
435 }
436 else if(rkPnt.z > extents.z)
437 {
438 fDelta = rkPnt.z - extents.z;
439 rfSqrDistance += fDelta*fDelta;
440 rkPnt.z = extents.z;
441 }
442}
443
444static float SqrDistance(const Ray& rkLine, const Point& center, const Point& extents, float* pfLParam)
445{
446 // compute coordinates of line in box coordinate system
447 Point kDiff = rkLine.mOrig - center;
448 Point kPnt = kDiff;
449 Point kDir = rkLine.mDir;
450
451 // Apply reflections so that direction vector has nonnegative components.
452 bool bReflect[3];
453 for(int i=0;i<3;i++)
454 {
455 if(kDir[i]<0.0f)
456 {
457 kPnt[i] = -kPnt[i];
458 kDir[i] = -kDir[i];
459 bReflect[i] = true;
460 }
461 else
462 {
463 bReflect[i] = false;
464 }
465 }
466
467 float fSqrDistance = 0.0f;
468
469 if(kDir.x>0.0f)
470 {
471 if(kDir.y>0.0f)
472 {
473 if(kDir.z>0.0f) CaseNoZeros(kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,+,+)
474 else Case0(0, 1, 2, kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,+,0)
475 }
476 else
477 {
478 if(kDir.z>0.0f) Case0(0, 2, 1, kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,0,+)
479 else Case00(0, 1, 2, kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,0,0)
480 }
481 }
482 else
483 {
484 if(kDir.y>0.0f)
485 {
486 if(kDir.z>0.0f) Case0(1, 2, 0, kPnt, kDir, extents, pfLParam, fSqrDistance); // (0,+,+)
487 else Case00(1, 0, 2, kPnt, kDir, extents, pfLParam, fSqrDistance); // (0,+,0)
488 }
489 else
490 {
491 if(kDir.z>0.0f) Case00(2, 0, 1, kPnt, kDir, extents, pfLParam, fSqrDistance); // (0,0,+)
492 else
493 {
494 Case000(kPnt, extents, fSqrDistance); // (0,0,0)
495 if(pfLParam) *pfLParam = 0.0f;
496 }
497 }
498 }
499 return fSqrDistance;
500}
501
502inline_ float OPC_SegmentOBBSqrDist(const Segment& segment, const Point& c0, const Point& e0)
503{
504 float fLP;
505 float fSqrDistance = SqrDistance(Ray(segment.GetOrigin(), segment.ComputeDirection()), c0, e0, &fLP);
506 if(fLP>=0.0f)
507 {
508 if(fLP<=1.0f) return fSqrDistance;
509 else return OPC_PointAABBSqrDist(segment.mP1, c0, e0);
510 }
511 else return OPC_PointAABBSqrDist(segment.mP0, c0, e0);
512}
513
514inline_ BOOL LSSCollider::LSSAABBOverlap(const Point& center, const Point& extents)
515{
516 // Stats
517 mNbVolumeBVTests++;
518
519 float s2 = OPC_SegmentOBBSqrDist(mSeg, center, extents);
520 if(s2<mRadius2) return TRUE;
521
522 return FALSE;
523}
diff --git a/libraries/ode-0.9/OPCODE/OPC_LSSCollider.cpp b/libraries/ode-0.9/OPCODE/OPC_LSSCollider.cpp
new file mode 100644
index 0000000..458c0a2
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_LSSCollider.cpp
@@ -0,0 +1,725 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for an LSS collider.
12 * \file OPC_LSSCollider.cpp
13 * \author Pierre Terdiman
14 * \date December, 28, 2002
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19/**
20 * Contains a lss-vs-tree collider.
21 *
22 * \class LSSCollider
23 * \author Pierre Terdiman
24 * \version 1.3
25 * \date December, 28, 2002
26*/
27///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
28
29///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
30// Precompiled Header
31#include "Stdafx.h"
32
33using namespace Opcode;
34
35#include "OPC_LSSAABBOverlap.h"
36#include "OPC_LSSTriOverlap.h"
37
38#define SET_CONTACT(prim_index, flag) \
39 /* Set contact status */ \
40 mFlags |= flag; \
41 mTouchedPrimitives->Add(udword(prim_index));
42
43//! LSS-triangle overlap test
44#define LSS_PRIM(prim_index, flag) \
45 /* Request vertices from the app */ \
46 VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \
47 \
48 /* Perform LSS-tri overlap test */ \
49 if(LSSTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \
50 { \
51 SET_CONTACT(prim_index, flag) \
52 }
53
54///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
55/**
56 * Constructor.
57 */
58///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
59LSSCollider::LSSCollider()
60{
61// mCenter.Zero();
62// mRadius2 = 0.0f;
63}
64
65///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
66/**
67 * Destructor.
68 */
69///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
70LSSCollider::~LSSCollider()
71{
72}
73
74///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
75/**
76 * Generic collision query for generic OPCODE models. After the call, access the results:
77 * - with GetContactStatus()
78 * - with GetNbTouchedPrimitives()
79 * - with GetTouchedPrimitives()
80 *
81 * \param cache [in/out] an lss cache
82 * \param lss [in] collision lss in local space
83 * \param model [in] Opcode model to collide with
84 * \param worldl [in] lss world matrix, or null
85 * \param worldm [in] model's world matrix, or null
86 * \return true if success
87 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
88 */
89///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
90bool LSSCollider::Collide(LSSCache& cache, const LSS& lss, const Model& model, const Matrix4x4* worldl, const Matrix4x4* worldm)
91{
92 // Checkings
93 if(!Setup(&model)) return false;
94
95 // Init collision query
96 if(InitQuery(cache, lss, worldl, worldm)) return true;
97
98 if(!model.HasLeafNodes())
99 {
100 if(model.IsQuantized())
101 {
102 const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
103
104 // Setup dequantization coeffs
105 mCenterCoeff = Tree->mCenterCoeff;
106 mExtentsCoeff = Tree->mExtentsCoeff;
107
108 // Perform collision query
109 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
110 else _Collide(Tree->GetNodes());
111 }
112 else
113 {
114 const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
115
116 // Perform collision query
117 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
118 else _Collide(Tree->GetNodes());
119 }
120 }
121 else
122 {
123 if(model.IsQuantized())
124 {
125 const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
126
127 // Setup dequantization coeffs
128 mCenterCoeff = Tree->mCenterCoeff;
129 mExtentsCoeff = Tree->mExtentsCoeff;
130
131 // Perform collision query
132 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
133 else _Collide(Tree->GetNodes());
134 }
135 else
136 {
137 const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
138
139 // Perform collision query
140 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
141 else _Collide(Tree->GetNodes());
142 }
143 }
144
145 return true;
146}
147
148///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
149/**
150 * Initializes a collision query :
151 * - reset stats & contact status
152 * - setup matrices
153 * - check temporal coherence
154 *
155 * \param cache [in/out] an lss cache
156 * \param lss [in] lss in local space
157 * \param worldl [in] lss world matrix, or null
158 * \param worldm [in] model's world matrix, or null
159 * \return TRUE if we can return immediately
160 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
161 */
162///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
163BOOL LSSCollider::InitQuery(LSSCache& cache, const LSS& lss, const Matrix4x4* worldl, const Matrix4x4* worldm)
164{
165 // 1) Call the base method
166 VolumeCollider::InitQuery();
167
168 // 2) Compute LSS in model space:
169 // - Precompute R^2
170 mRadius2 = lss.mRadius * lss.mRadius;
171 // - Compute segment
172 mSeg.mP0 = lss.mP0;
173 mSeg.mP1 = lss.mP1;
174 // -> to world space
175 if(worldl)
176 {
177 mSeg.mP0 *= *worldl;
178 mSeg.mP1 *= *worldl;
179 }
180 // -> to model space
181 if(worldm)
182 {
183 // Invert model matrix
184 Matrix4x4 InvWorldM;
185 InvertPRMatrix(InvWorldM, *worldm);
186
187 mSeg.mP0 *= InvWorldM;
188 mSeg.mP1 *= InvWorldM;
189 }
190
191 // 3) Setup destination pointer
192 mTouchedPrimitives = &cache.TouchedPrimitives;
193
194 // 4) Special case: 1-triangle meshes [Opcode 1.3]
195 if(mCurrentModel && mCurrentModel->HasSingleNode())
196 {
197 if(!SkipPrimitiveTests())
198 {
199 // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0.
200 mTouchedPrimitives->Reset();
201
202 // Perform overlap test between the unique triangle and the LSS (and set contact status if needed)
203 LSS_PRIM(udword(0), OPC_CONTACT)
204
205 // Return immediately regardless of status
206 return TRUE;
207 }
208 }
209
210 // 5) Check temporal coherence :
211 if(TemporalCoherenceEnabled())
212 {
213 // Here we use temporal coherence
214 // => check results from previous frame before performing the collision query
215 if(FirstContactEnabled())
216 {
217 // We're only interested in the first contact found => test the unique previously touched face
218 if(mTouchedPrimitives->GetNbEntries())
219 {
220 // Get index of previously touched face = the first entry in the array
221 udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0);
222
223 // Then reset the array:
224 // - if the overlap test below is successful, the index we'll get added back anyway
225 // - if it isn't, then the array should be reset anyway for the normal query
226 mTouchedPrimitives->Reset();
227
228 // Perform overlap test between the cached triangle and the LSS (and set contact status if needed)
229 LSS_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT)
230
231 // Return immediately if possible
232 if(GetContactStatus()) return TRUE;
233 }
234 // else no face has been touched during previous query
235 // => we'll have to perform a normal query
236 }
237 else
238 {
239 // We're interested in all contacts =>test the new real LSS N(ew) against the previous fat LSS P(revious):
240
241 // ### rewrite this
242
243 LSS Test(mSeg, lss.mRadius); // in model space
244 LSS Previous(cache.Previous, sqrtf(cache.Previous.mRadius));
245
246// if(cache.Previous.Contains(Test))
247 if(IsCacheValid(cache) && Previous.Contains(Test))
248 {
249 // - if N is included in P, return previous list
250 // => we simply leave the list (mTouchedFaces) unchanged
251
252 // Set contact status if needed
253 if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT;
254
255 // In any case we don't need to do a query
256 return TRUE;
257 }
258 else
259 {
260 // - else do the query using a fat N
261
262 // Reset cache since we'll about to perform a real query
263 mTouchedPrimitives->Reset();
264
265 // Make a fat sphere so that coherence will work for subsequent frames
266 mRadius2 *= cache.FatCoeff;
267// mRadius2 = (lss.mRadius * cache.FatCoeff)*(lss.mRadius * cache.FatCoeff);
268
269
270 // Update cache with query data (signature for cached faces)
271 cache.Previous.mP0 = mSeg.mP0;
272 cache.Previous.mP1 = mSeg.mP1;
273 cache.Previous.mRadius = mRadius2;
274 }
275 }
276 }
277 else
278 {
279 // Here we don't use temporal coherence => do a normal query
280 mTouchedPrimitives->Reset();
281 }
282
283 return FALSE;
284}
285
286///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
287/**
288 * Collision query for vanilla AABB trees.
289 * \param cache [in/out] an lss cache
290 * \param lss [in] collision lss in world space
291 * \param tree [in] AABB tree
292 * \return true if success
293 */
294///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
295bool LSSCollider::Collide(LSSCache& cache, const LSS& lss, const AABBTree* tree)
296{
297 // This is typically called for a scene tree, full of -AABBs-, not full of triangles.
298 // So we don't really have "primitives" to deal with. Hence it doesn't work with
299 // "FirstContact" + "TemporalCoherence".
300 ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) );
301
302 // Checkings
303 if(!tree) return false;
304
305 // Init collision query
306 if(InitQuery(cache, lss)) return true;
307
308 // Perform collision query
309 _Collide(tree);
310
311 return true;
312}
313
314///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
315/**
316 * Checks the LSS completely contains the box. In which case we can end the query sooner.
317 * \param bc [in] box center
318 * \param be [in] box extents
319 * \return true if the LSS contains the whole box
320 */
321///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
322inline_ BOOL LSSCollider::LSSContainsBox(const Point& bc, const Point& be)
323{
324 // Not implemented
325 return FALSE;
326}
327
328#define TEST_BOX_IN_LSS(center, extents) \
329 if(LSSContainsBox(center, extents)) \
330 { \
331 /* Set contact status */ \
332 mFlags |= OPC_CONTACT; \
333 _Dump(node); \
334 return; \
335 }
336
337///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
338/**
339 * Recursive collision query for normal AABB trees.
340 * \param node [in] current collision node
341 */
342///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
343void LSSCollider::_Collide(const AABBCollisionNode* node)
344{
345 // Perform LSS-AABB overlap test
346 if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
347
348 TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents)
349
350 if(node->IsLeaf())
351 {
352 LSS_PRIM(node->GetPrimitive(), OPC_CONTACT)
353 }
354 else
355 {
356 _Collide(node->GetPos());
357
358 if(ContactFound()) return;
359
360 _Collide(node->GetNeg());
361 }
362}
363
364///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
365/**
366 * Recursive collision query for normal AABB trees, without primitive tests.
367 * \param node [in] current collision node
368 */
369///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
370void LSSCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node)
371{
372 // Perform LSS-AABB overlap test
373 if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
374
375 TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents)
376
377 if(node->IsLeaf())
378 {
379 SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
380 }
381 else
382 {
383 _CollideNoPrimitiveTest(node->GetPos());
384
385 if(ContactFound()) return;
386
387 _CollideNoPrimitiveTest(node->GetNeg());
388 }
389}
390
391///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
392/**
393 * Recursive collision query for quantized AABB trees.
394 * \param node [in] current collision node
395 */
396///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
397void LSSCollider::_Collide(const AABBQuantizedNode* node)
398{
399 // Dequantize box
400 const QuantizedAABB& Box = node->mAABB;
401 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
402 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
403
404 // Perform LSS-AABB overlap test
405 if(!LSSAABBOverlap(Center, Extents)) return;
406
407 TEST_BOX_IN_LSS(Center, Extents)
408
409 if(node->IsLeaf())
410 {
411 LSS_PRIM(node->GetPrimitive(), OPC_CONTACT)
412 }
413 else
414 {
415 _Collide(node->GetPos());
416
417 if(ContactFound()) return;
418
419 _Collide(node->GetNeg());
420 }
421}
422
423///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
424/**
425 * Recursive collision query for quantized AABB trees, without primitive tests.
426 * \param node [in] current collision node
427 */
428///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
429void LSSCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node)
430{
431 // Dequantize box
432 const QuantizedAABB& Box = node->mAABB;
433 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
434 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
435
436 // Perform LSS-AABB overlap test
437 if(!LSSAABBOverlap(Center, Extents)) return;
438
439 TEST_BOX_IN_LSS(Center, Extents)
440
441 if(node->IsLeaf())
442 {
443 SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
444 }
445 else
446 {
447 _CollideNoPrimitiveTest(node->GetPos());
448
449 if(ContactFound()) return;
450
451 _CollideNoPrimitiveTest(node->GetNeg());
452 }
453}
454
455///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
456/**
457 * Recursive collision query for no-leaf AABB trees.
458 * \param node [in] current collision node
459 */
460///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
461void LSSCollider::_Collide(const AABBNoLeafNode* node)
462{
463 // Perform LSS-AABB overlap test
464 if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
465
466 TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents)
467
468 if(node->HasPosLeaf()) { LSS_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
469 else _Collide(node->GetPos());
470
471 if(ContactFound()) return;
472
473 if(node->HasNegLeaf()) { LSS_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
474 else _Collide(node->GetNeg());
475}
476
477///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
478/**
479 * Recursive collision query for no-leaf AABB trees, without primitive tests.
480 * \param node [in] current collision node
481 */
482///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
483void LSSCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node)
484{
485 // Perform LSS-AABB overlap test
486 if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
487
488 TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents)
489
490 if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
491 else _CollideNoPrimitiveTest(node->GetPos());
492
493 if(ContactFound()) return;
494
495 if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
496 else _CollideNoPrimitiveTest(node->GetNeg());
497}
498
499///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
500/**
501 * Recursive collision query for quantized no-leaf AABB trees.
502 * \param node [in] current collision node
503 */
504///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
505void LSSCollider::_Collide(const AABBQuantizedNoLeafNode* node)
506{
507 // Dequantize box
508 const QuantizedAABB& Box = node->mAABB;
509 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
510 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
511
512 // Perform LSS-AABB overlap test
513 if(!LSSAABBOverlap(Center, Extents)) return;
514
515 TEST_BOX_IN_LSS(Center, Extents)
516
517 if(node->HasPosLeaf()) { LSS_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
518 else _Collide(node->GetPos());
519
520 if(ContactFound()) return;
521
522 if(node->HasNegLeaf()) { LSS_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
523 else _Collide(node->GetNeg());
524}
525
526///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
527/**
528 * Recursive collision query for quantized no-leaf AABB trees, without primitive tests.
529 * \param node [in] current collision node
530 */
531///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
532void LSSCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node)
533{
534 // Dequantize box
535 const QuantizedAABB& Box = node->mAABB;
536 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
537 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
538
539 // Perform LSS-AABB overlap test
540 if(!LSSAABBOverlap(Center, Extents)) return;
541
542 TEST_BOX_IN_LSS(Center, Extents)
543
544 if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
545 else _CollideNoPrimitiveTest(node->GetPos());
546
547 if(ContactFound()) return;
548
549 if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
550 else _CollideNoPrimitiveTest(node->GetNeg());
551}
552
553///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
554/**
555 * Recursive collision query for vanilla AABB trees.
556 * \param node [in] current collision node
557 */
558///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
559void LSSCollider::_Collide(const AABBTreeNode* node)
560{
561 // Perform LSS-AABB overlap test
562 Point Center, Extents;
563 node->GetAABB()->GetCenter(Center);
564 node->GetAABB()->GetExtents(Extents);
565 if(!LSSAABBOverlap(Center, Extents)) return;
566
567 if(node->IsLeaf() || LSSContainsBox(Center, Extents))
568 {
569 mFlags |= OPC_CONTACT;
570 mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives());
571 }
572 else
573 {
574 _Collide(node->GetPos());
575 _Collide(node->GetNeg());
576 }
577}
578
579
580
581
582
583
584///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
585/**
586 * Constructor.
587 */
588///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
589HybridLSSCollider::HybridLSSCollider()
590{
591}
592
593///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
594/**
595 * Destructor.
596 */
597///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
598HybridLSSCollider::~HybridLSSCollider()
599{
600}
601
602bool HybridLSSCollider::Collide(LSSCache& cache, const LSS& lss, const HybridModel& model, const Matrix4x4* worldl, const Matrix4x4* worldm)
603{
604 // We don't want primitive tests here!
605 mFlags |= OPC_NO_PRIMITIVE_TESTS;
606
607 // Checkings
608 if(!Setup(&model)) return false;
609
610 // Init collision query
611 if(InitQuery(cache, lss, worldl, worldm)) return true;
612
613 // Special case for 1-leaf trees
614 if(mCurrentModel && mCurrentModel->HasSingleNode())
615 {
616 // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles
617 udword Nb = mIMesh->GetNbTriangles();
618
619 // Loop through all triangles
620 for(udword i=0;i<Nb;i++)
621 {
622 LSS_PRIM(i, OPC_CONTACT)
623 }
624 return true;
625 }
626
627 // Override destination array since we're only going to get leaf boxes here
628 mTouchedBoxes.Reset();
629 mTouchedPrimitives = &mTouchedBoxes;
630
631 // Now, do the actual query against leaf boxes
632 if(!model.HasLeafNodes())
633 {
634 if(model.IsQuantized())
635 {
636 const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
637
638 // Setup dequantization coeffs
639 mCenterCoeff = Tree->mCenterCoeff;
640 mExtentsCoeff = Tree->mExtentsCoeff;
641
642 // Perform collision query - we don't want primitive tests here!
643 _CollideNoPrimitiveTest(Tree->GetNodes());
644 }
645 else
646 {
647 const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
648
649 // Perform collision query - we don't want primitive tests here!
650 _CollideNoPrimitiveTest(Tree->GetNodes());
651 }
652 }
653 else
654 {
655 if(model.IsQuantized())
656 {
657 const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
658
659 // Setup dequantization coeffs
660 mCenterCoeff = Tree->mCenterCoeff;
661 mExtentsCoeff = Tree->mExtentsCoeff;
662
663 // Perform collision query - we don't want primitive tests here!
664 _CollideNoPrimitiveTest(Tree->GetNodes());
665 }
666 else
667 {
668 const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
669
670 // Perform collision query - we don't want primitive tests here!
671 _CollideNoPrimitiveTest(Tree->GetNodes());
672 }
673 }
674
675 // We only have a list of boxes so far
676 if(GetContactStatus())
677 {
678 // Reset contact status, since it currently only reflects collisions with leaf boxes
679 Collider::InitQuery();
680
681 // Change dest container so that we can use built-in overlap tests and get collided primitives
682 cache.TouchedPrimitives.Reset();
683 mTouchedPrimitives = &cache.TouchedPrimitives;
684
685 // Read touched leaf boxes
686 udword Nb = mTouchedBoxes.GetNbEntries();
687 const udword* Touched = mTouchedBoxes.GetEntries();
688
689 const LeafTriangles* LT = model.GetLeafTriangles();
690 const udword* Indices = model.GetIndices();
691
692 // Loop through touched leaves
693 while(Nb--)
694 {
695 const LeafTriangles& CurrentLeaf = LT[*Touched++];
696
697 // Each leaf box has a set of triangles
698 udword NbTris = CurrentLeaf.GetNbTriangles();
699 if(Indices)
700 {
701 const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()];
702
703 // Loop through triangles and test each of them
704 while(NbTris--)
705 {
706 udword TriangleIndex = *T++;
707 LSS_PRIM(TriangleIndex, OPC_CONTACT)
708 }
709 }
710 else
711 {
712 udword BaseIndex = CurrentLeaf.GetTriangleIndex();
713
714 // Loop through triangles and test each of them
715 while(NbTris--)
716 {
717 udword TriangleIndex = BaseIndex++;
718 LSS_PRIM(TriangleIndex, OPC_CONTACT)
719 }
720 }
721 }
722 }
723
724 return true;
725}
diff --git a/libraries/ode-0.9/OPCODE/OPC_LSSCollider.h b/libraries/ode-0.9/OPCODE/OPC_LSSCollider.h
new file mode 100644
index 0000000..b4d0893
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_LSSCollider.h
@@ -0,0 +1,99 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for an LSS collider.
12 * \file OPC_LSSCollider.h
13 * \author Pierre Terdiman
14 * \date December, 28, 2002
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_LSSCOLLIDER_H__
21#define __OPC_LSSCOLLIDER_H__
22
23 struct OPCODE_API LSSCache : VolumeCache
24 {
25 LSSCache()
26 {
27 Previous.mP0 = Point(0.0f, 0.0f, 0.0f);
28 Previous.mP1 = Point(0.0f, 0.0f, 0.0f);
29 Previous.mRadius = 0.0f;
30 FatCoeff = 1.1f;
31 }
32
33 // Cached faces signature
34 LSS Previous; //!< LSS used when performing the query resulting in cached faces
35 // User settings
36 float FatCoeff; //!< mRadius2 multiplier used to create a fat LSS
37 };
38
39 class OPCODE_API LSSCollider : public VolumeCollider
40 {
41 public:
42 // Constructor / Destructor
43 LSSCollider();
44 virtual ~LSSCollider();
45
46 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
47 /**
48 * Generic collision query for generic OPCODE models. After the call, access the results:
49 * - with GetContactStatus()
50 * - with GetNbTouchedPrimitives()
51 * - with GetTouchedPrimitives()
52 *
53 * \param cache [in/out] an lss cache
54 * \param lss [in] collision lss in local space
55 * \param model [in] Opcode model to collide with
56 * \param worldl [in] lss world matrix, or null
57 * \param worldm [in] model's world matrix, or null
58 * \return true if success
59 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
60 */
61 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
62 bool Collide(LSSCache& cache, const LSS& lss, const Model& model, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null);
63 //
64 bool Collide(LSSCache& cache, const LSS& lss, const AABBTree* tree);
65 protected:
66 // LSS in model space
67 Segment mSeg; //!< Segment
68 float mRadius2; //!< LSS radius squared
69 // Internal methods
70 void _Collide(const AABBCollisionNode* node);
71 void _Collide(const AABBNoLeafNode* node);
72 void _Collide(const AABBQuantizedNode* node);
73 void _Collide(const AABBQuantizedNoLeafNode* node);
74 void _Collide(const AABBTreeNode* node);
75 void _CollideNoPrimitiveTest(const AABBCollisionNode* node);
76 void _CollideNoPrimitiveTest(const AABBNoLeafNode* node);
77 void _CollideNoPrimitiveTest(const AABBQuantizedNode* node);
78 void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node);
79 // Overlap tests
80 inline_ BOOL LSSContainsBox(const Point& bc, const Point& be);
81 inline_ BOOL LSSAABBOverlap(const Point& center, const Point& extents);
82 inline_ BOOL LSSTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2);
83 // Init methods
84 BOOL InitQuery(LSSCache& cache, const LSS& lss, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null);
85 };
86
87 class OPCODE_API HybridLSSCollider : public LSSCollider
88 {
89 public:
90 // Constructor / Destructor
91 HybridLSSCollider();
92 virtual ~HybridLSSCollider();
93
94 bool Collide(LSSCache& cache, const LSS& lss, const HybridModel& model, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null);
95 protected:
96 Container mTouchedBoxes;
97 };
98
99#endif // __OPC_LSSCOLLIDER_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_LSSTriOverlap.h b/libraries/ode-0.9/OPCODE/OPC_LSSTriOverlap.h
new file mode 100644
index 0000000..f1d17e4
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_LSSTriOverlap.h
@@ -0,0 +1,679 @@
1// Following code from Magic-Software (http://www.magic-software.com/)
2// A bit modified for Opcode
3
4static const float gs_fTolerance = 1e-05f;
5
6static float OPC_PointTriangleSqrDist(const Point& point, const Point& p0, const Point& p1, const Point& p2)
7{
8 // Hook
9 Point TriEdge0 = p1 - p0;
10 Point TriEdge1 = p2 - p0;
11
12 Point kDiff = p0 - point;
13 float fA00 = TriEdge0.SquareMagnitude();
14 float fA01 = TriEdge0 | TriEdge1;
15 float fA11 = TriEdge1.SquareMagnitude();
16 float fB0 = kDiff | TriEdge0;
17 float fB1 = kDiff | TriEdge1;
18 float fC = kDiff.SquareMagnitude();
19 float fDet = fabsf(fA00*fA11 - fA01*fA01);
20 float fS = fA01*fB1-fA11*fB0;
21 float fT = fA01*fB0-fA00*fB1;
22 float fSqrDist;
23
24 if(fS + fT <= fDet)
25 {
26 if(fS < 0.0f)
27 {
28 if(fT < 0.0f) // region 4
29 {
30 if(fB0 < 0.0f)
31 {
32 if(-fB0 >= fA00) fSqrDist = fA00+2.0f*fB0+fC;
33 else fSqrDist = fB0*(-fB0/fA00)+fC;
34 }
35 else
36 {
37 if(fB1 >= 0.0f) fSqrDist = fC;
38 else if(-fB1 >= fA11) fSqrDist = fA11+2.0f*fB1+fC;
39 else fSqrDist = fB1*(-fB1/fA11)+fC;
40 }
41 }
42 else // region 3
43 {
44 if(fB1 >= 0.0f) fSqrDist = fC;
45 else if(-fB1 >= fA11) fSqrDist = fA11+2.0f*fB1+fC;
46 else fSqrDist = fB1*(-fB1/fA11)+fC;
47 }
48 }
49 else if(fT < 0.0f) // region 5
50 {
51 if(fB0 >= 0.0f) fSqrDist = fC;
52 else if(-fB0 >= fA00) fSqrDist = fA00+2.0f*fB0+fC;
53 else fSqrDist = fB0*(-fB0/fA00)+fC;
54 }
55 else // region 0
56 {
57 // minimum at interior point
58 if(fDet==0.0f)
59 {
60 fSqrDist = MAX_FLOAT;
61 }
62 else
63 {
64 float fInvDet = 1.0f/fDet;
65 fS *= fInvDet;
66 fT *= fInvDet;
67 fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC;
68 }
69 }
70 }
71 else
72 {
73 float fTmp0, fTmp1, fNumer, fDenom;
74
75 if(fS < 0.0f) // region 2
76 {
77 fTmp0 = fA01 + fB0;
78 fTmp1 = fA11 + fB1;
79 if(fTmp1 > fTmp0)
80 {
81 fNumer = fTmp1 - fTmp0;
82 fDenom = fA00-2.0f*fA01+fA11;
83 if(fNumer >= fDenom)
84 {
85 fSqrDist = fA00+2.0f*fB0+fC;
86 }
87 else
88 {
89 fS = fNumer/fDenom;
90 fT = 1.0f - fS;
91 fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC;
92 }
93 }
94 else
95 {
96 if(fTmp1 <= 0.0f) fSqrDist = fA11+2.0f*fB1+fC;
97 else if(fB1 >= 0.0f) fSqrDist = fC;
98 else fSqrDist = fB1*(-fB1/fA11)+fC;
99 }
100 }
101 else if(fT < 0.0f) // region 6
102 {
103 fTmp0 = fA01 + fB1;
104 fTmp1 = fA00 + fB0;
105 if(fTmp1 > fTmp0)
106 {
107 fNumer = fTmp1 - fTmp0;
108 fDenom = fA00-2.0f*fA01+fA11;
109 if(fNumer >= fDenom)
110 {
111 fSqrDist = fA11+2.0f*fB1+fC;
112 }
113 else
114 {
115 fT = fNumer/fDenom;
116 fS = 1.0f - fT;
117 fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC;
118 }
119 }
120 else
121 {
122 if(fTmp1 <= 0.0f) fSqrDist = fA00+2.0f*fB0+fC;
123 else if(fB0 >= 0.0f) fSqrDist = fC;
124 else fSqrDist = fB0*(-fB0/fA00)+fC;
125 }
126 }
127 else // region 1
128 {
129 fNumer = fA11 + fB1 - fA01 - fB0;
130 if(fNumer <= 0.0f)
131 {
132 fSqrDist = fA11+2.0f*fB1+fC;
133 }
134 else
135 {
136 fDenom = fA00-2.0f*fA01+fA11;
137 if(fNumer >= fDenom)
138 {
139 fSqrDist = fA00+2.0f*fB0+fC;
140 }
141 else
142 {
143 fS = fNumer/fDenom;
144 fT = 1.0f - fS;
145 fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC;
146 }
147 }
148 }
149 }
150 return fabsf(fSqrDist);
151}
152
153static float OPC_SegmentSegmentSqrDist(const Segment& rkSeg0, const Segment& rkSeg1)
154{
155 // Hook
156 Point rkSeg0Direction = rkSeg0.ComputeDirection();
157 Point rkSeg1Direction = rkSeg1.ComputeDirection();
158
159 Point kDiff = rkSeg0.mP0 - rkSeg1.mP0;
160 float fA00 = rkSeg0Direction.SquareMagnitude();
161 float fA01 = -rkSeg0Direction.Dot(rkSeg1Direction);
162 float fA11 = rkSeg1Direction.SquareMagnitude();
163 float fB0 = kDiff.Dot(rkSeg0Direction);
164 float fC = kDiff.SquareMagnitude();
165 float fDet = fabsf(fA00*fA11-fA01*fA01);
166
167 float fB1, fS, fT, fSqrDist, fTmp;
168
169 if(fDet>=gs_fTolerance)
170 {
171 // line segments are not parallel
172 fB1 = -kDiff.Dot(rkSeg1Direction);
173 fS = fA01*fB1-fA11*fB0;
174 fT = fA01*fB0-fA00*fB1;
175
176 if(fS >= 0.0f)
177 {
178 if(fS <= fDet)
179 {
180 if(fT >= 0.0f)
181 {
182 if(fT <= fDet) // region 0 (interior)
183 {
184 // minimum at two interior points of 3D lines
185 float fInvDet = 1.0f/fDet;
186 fS *= fInvDet;
187 fT *= fInvDet;
188 fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC;
189 }
190 else // region 3 (side)
191 {
192 fTmp = fA01+fB0;
193 if(fTmp>=0.0f) fSqrDist = fA11+2.0f*fB1+fC;
194 else if(-fTmp>=fA00) fSqrDist = fA00+fA11+fC+2.0f*(fB1+fTmp);
195 else fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC;
196 }
197 }
198 else // region 7 (side)
199 {
200 if(fB0>=0.0f) fSqrDist = fC;
201 else if(-fB0>=fA00) fSqrDist = fA00+2.0f*fB0+fC;
202 else fSqrDist = fB0*(-fB0/fA00)+fC;
203 }
204 }
205 else
206 {
207 if ( fT >= 0.0 )
208 {
209 if ( fT <= fDet ) // region 1 (side)
210 {
211 fTmp = fA01+fB1;
212 if(fTmp>=0.0f) fSqrDist = fA00+2.0f*fB0+fC;
213 else if(-fTmp>=fA11) fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp);
214 else fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC;
215 }
216 else // region 2 (corner)
217 {
218 fTmp = fA01+fB0;
219 if ( -fTmp <= fA00 )
220 {
221 if(fTmp>=0.0f) fSqrDist = fA11+2.0f*fB1+fC;
222 else fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC;
223 }
224 else
225 {
226 fTmp = fA01+fB1;
227 if(fTmp>=0.0f) fSqrDist = fA00+2.0f*fB0+fC;
228 else if(-fTmp>=fA11) fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp);
229 else fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC;
230 }
231 }
232 }
233 else // region 8 (corner)
234 {
235 if ( -fB0 < fA00 )
236 {
237 if(fB0>=0.0f) fSqrDist = fC;
238 else fSqrDist = fB0*(-fB0/fA00)+fC;
239 }
240 else
241 {
242 fTmp = fA01+fB1;
243 if(fTmp>=0.0f) fSqrDist = fA00+2.0f*fB0+fC;
244 else if(-fTmp>=fA11) fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp);
245 else fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC;
246 }
247 }
248 }
249 }
250 else
251 {
252 if ( fT >= 0.0f )
253 {
254 if ( fT <= fDet ) // region 5 (side)
255 {
256 if(fB1>=0.0f) fSqrDist = fC;
257 else if(-fB1>=fA11) fSqrDist = fA11+2.0f*fB1+fC;
258 else fSqrDist = fB1*(-fB1/fA11)+fC;
259 }
260 else // region 4 (corner)
261 {
262 fTmp = fA01+fB0;
263 if ( fTmp < 0.0f )
264 {
265 if(-fTmp>=fA00) fSqrDist = fA00+fA11+fC+2.0f*(fB1+fTmp);
266 else fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC;
267 }
268 else
269 {
270 if(fB1>=0.0f) fSqrDist = fC;
271 else if(-fB1>=fA11) fSqrDist = fA11+2.0f*fB1+fC;
272 else fSqrDist = fB1*(-fB1/fA11)+fC;
273 }
274 }
275 }
276 else // region 6 (corner)
277 {
278 if ( fB0 < 0.0f )
279 {
280 if(-fB0>=fA00) fSqrDist = fA00+2.0f*fB0+fC;
281 else fSqrDist = fB0*(-fB0/fA00)+fC;
282 }
283 else
284 {
285 if(fB1>=0.0f) fSqrDist = fC;
286 else if(-fB1>=fA11) fSqrDist = fA11+2.0f*fB1+fC;
287 else fSqrDist = fB1*(-fB1/fA11)+fC;
288 }
289 }
290 }
291 }
292 else
293 {
294 // line segments are parallel
295 if ( fA01 > 0.0f )
296 {
297 // direction vectors form an obtuse angle
298 if ( fB0 >= 0.0f )
299 {
300 fSqrDist = fC;
301 }
302 else if ( -fB0 <= fA00 )
303 {
304 fSqrDist = fB0*(-fB0/fA00)+fC;
305 }
306 else
307 {
308 fB1 = -kDiff.Dot(rkSeg1Direction);
309 fTmp = fA00+fB0;
310 if ( -fTmp >= fA01 )
311 {
312 fSqrDist = fA00+fA11+fC+2.0f*(fA01+fB0+fB1);
313 }
314 else
315 {
316 fT = -fTmp/fA01;
317 fSqrDist = fA00+2.0f*fB0+fC+fT*(fA11*fT+2.0f*(fA01+fB1));
318 }
319 }
320 }
321 else
322 {
323 // direction vectors form an acute angle
324 if ( -fB0 >= fA00 )
325 {
326 fSqrDist = fA00+2.0f*fB0+fC;
327 }
328 else if ( fB0 <= 0.0f )
329 {
330 fSqrDist = fB0*(-fB0/fA00)+fC;
331 }
332 else
333 {
334 fB1 = -kDiff.Dot(rkSeg1Direction);
335 if ( fB0 >= -fA01 )
336 {
337 fSqrDist = fA11+2.0f*fB1+fC;
338 }
339 else
340 {
341 fT = -fB0/fA01;
342 fSqrDist = fC+fT*(2.0f*fB1+fA11*fT);
343 }
344 }
345 }
346 }
347 return fabsf(fSqrDist);
348}
349
350inline_ float OPC_SegmentRaySqrDist(const Segment& rkSeg0, const Ray& rkSeg1)
351{
352 return OPC_SegmentSegmentSqrDist(rkSeg0, Segment(rkSeg1.mOrig, rkSeg1.mOrig + rkSeg1.mDir));
353}
354
355static float OPC_SegmentTriangleSqrDist(const Segment& segment, const Point& p0, const Point& p1, const Point& p2)
356{
357 // Hook
358 const Point TriEdge0 = p1 - p0;
359 const Point TriEdge1 = p2 - p0;
360
361 const Point& rkSegOrigin = segment.GetOrigin();
362 Point rkSegDirection = segment.ComputeDirection();
363
364 Point kDiff = p0 - rkSegOrigin;
365 float fA00 = rkSegDirection.SquareMagnitude();
366 float fA01 = -rkSegDirection.Dot(TriEdge0);
367 float fA02 = -rkSegDirection.Dot(TriEdge1);
368 float fA11 = TriEdge0.SquareMagnitude();
369 float fA12 = TriEdge0.Dot(TriEdge1);
370 float fA22 = TriEdge1.Dot(TriEdge1);
371 float fB0 = -kDiff.Dot(rkSegDirection);
372 float fB1 = kDiff.Dot(TriEdge0);
373 float fB2 = kDiff.Dot(TriEdge1);
374 float fCof00 = fA11*fA22-fA12*fA12;
375 float fCof01 = fA02*fA12-fA01*fA22;
376 float fCof02 = fA01*fA12-fA02*fA11;
377 float fDet = fA00*fCof00+fA01*fCof01+fA02*fCof02;
378
379 Ray kTriSeg;
380 Point kPt;
381 float fSqrDist, fSqrDist0;
382
383 if(fabsf(fDet)>=gs_fTolerance)
384 {
385 float fCof11 = fA00*fA22-fA02*fA02;
386 float fCof12 = fA02*fA01-fA00*fA12;
387 float fCof22 = fA00*fA11-fA01*fA01;
388 float fInvDet = 1.0f/fDet;
389 float fRhs0 = -fB0*fInvDet;
390 float fRhs1 = -fB1*fInvDet;
391 float fRhs2 = -fB2*fInvDet;
392
393 float fR = fCof00*fRhs0+fCof01*fRhs1+fCof02*fRhs2;
394 float fS = fCof01*fRhs0+fCof11*fRhs1+fCof12*fRhs2;
395 float fT = fCof02*fRhs0+fCof12*fRhs1+fCof22*fRhs2;
396
397 if ( fR < 0.0f )
398 {
399 if ( fS+fT <= 1.0f )
400 {
401 if ( fS < 0.0f )
402 {
403 if ( fT < 0.0f ) // region 4m
404 {
405 // min on face s=0 or t=0 or r=0
406 kTriSeg.mOrig = p0;
407 kTriSeg.mDir = TriEdge1;
408 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
409 kTriSeg.mOrig = p0;
410 kTriSeg.mDir = TriEdge0;
411 fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
412 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
413 fSqrDist0 = OPC_PointTriangleSqrDist(rkSegOrigin, p0, p1, p2);
414 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
415 }
416 else // region 3m
417 {
418 // min on face s=0 or r=0
419 kTriSeg.mOrig = p0;
420 kTriSeg.mDir = TriEdge1;
421 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
422 fSqrDist0 = OPC_PointTriangleSqrDist(rkSegOrigin, p0, p1, p2);
423 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
424 }
425 }
426 else if ( fT < 0.0f ) // region 5m
427 {
428 // min on face t=0 or r=0
429 kTriSeg.mOrig = p0;
430 kTriSeg.mDir = TriEdge0;
431 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
432 fSqrDist0 = OPC_PointTriangleSqrDist(rkSegOrigin, p0, p1, p2);
433 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
434 }
435 else // region 0m
436 {
437 // min on face r=0
438 fSqrDist = OPC_PointTriangleSqrDist(rkSegOrigin, p0, p1, p2);
439 }
440 }
441 else
442 {
443 if ( fS < 0.0f ) // region 2m
444 {
445 // min on face s=0 or s+t=1 or r=0
446 kTriSeg.mOrig = p0;
447 kTriSeg.mDir = TriEdge1;
448 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
449 kTriSeg.mOrig = p1;
450 kTriSeg.mDir = TriEdge1-TriEdge0;
451 fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
452 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
453 fSqrDist0 = OPC_PointTriangleSqrDist(rkSegOrigin, p0, p1, p2);
454 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
455 }
456 else if ( fT < 0.0f ) // region 6m
457 {
458 // min on face t=0 or s+t=1 or r=0
459 kTriSeg.mOrig = p0;
460 kTriSeg.mDir = TriEdge0;
461 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
462 kTriSeg.mOrig = p1;
463 kTriSeg.mDir = TriEdge1-TriEdge0;
464 fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
465 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
466 fSqrDist0 = OPC_PointTriangleSqrDist(rkSegOrigin, p0, p1, p2);
467 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
468 }
469 else // region 1m
470 {
471 // min on face s+t=1 or r=0
472 kTriSeg.mOrig = p1;
473 kTriSeg.mDir = TriEdge1-TriEdge0;
474 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
475 fSqrDist0 = OPC_PointTriangleSqrDist(rkSegOrigin, p0, p1, p2);
476 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
477 }
478 }
479 }
480 else if ( fR <= 1.0f )
481 {
482 if ( fS+fT <= 1.0f )
483 {
484 if ( fS < 0.0f )
485 {
486 if ( fT < 0.0f ) // region 4
487 {
488 // min on face s=0 or t=0
489 kTriSeg.mOrig = p0;
490 kTriSeg.mDir = TriEdge1;
491 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
492 kTriSeg.mOrig = p0;
493 kTriSeg.mDir = TriEdge0;
494 fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
495 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
496 }
497 else // region 3
498 {
499 // min on face s=0
500 kTriSeg.mOrig = p0;
501 kTriSeg.mDir = TriEdge1;
502 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
503 }
504 }
505 else if ( fT < 0.0f ) // region 5
506 {
507 // min on face t=0
508 kTriSeg.mOrig = p0;
509 kTriSeg.mDir = TriEdge0;
510 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
511 }
512 else // region 0
513 {
514 // global minimum is interior, done
515 fSqrDist = fR*(fA00*fR+fA01*fS+fA02*fT+2.0f*fB0)
516 +fS*(fA01*fR+fA11*fS+fA12*fT+2.0f*fB1)
517 +fT*(fA02*fR+fA12*fS+fA22*fT+2.0f*fB2)
518 +kDiff.SquareMagnitude();
519 }
520 }
521 else
522 {
523 if ( fS < 0.0f ) // region 2
524 {
525 // min on face s=0 or s+t=1
526 kTriSeg.mOrig = p0;
527 kTriSeg.mDir = TriEdge1;
528 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
529 kTriSeg.mOrig = p1;
530 kTriSeg.mDir = TriEdge1-TriEdge0;
531 fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
532 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
533 }
534 else if ( fT < 0.0f ) // region 6
535 {
536 // min on face t=0 or s+t=1
537 kTriSeg.mOrig = p0;
538 kTriSeg.mDir = TriEdge0;
539 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
540 kTriSeg.mOrig = p1;
541 kTriSeg.mDir = TriEdge1-TriEdge0;
542 fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
543 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
544 }
545 else // region 1
546 {
547 // min on face s+t=1
548 kTriSeg.mOrig = p1;
549 kTriSeg.mDir = TriEdge1-TriEdge0;
550 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
551 }
552 }
553 }
554 else // fR > 1
555 {
556 if ( fS+fT <= 1.0f )
557 {
558 if ( fS < 0.0f )
559 {
560 if ( fT < 0.0f ) // region 4p
561 {
562 // min on face s=0 or t=0 or r=1
563 kTriSeg.mOrig = p0;
564 kTriSeg.mDir = TriEdge1;
565 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
566 kTriSeg.mOrig = p0;
567 kTriSeg.mDir = TriEdge0;
568 fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
569 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
570 kPt = rkSegOrigin+rkSegDirection;
571 fSqrDist0 = OPC_PointTriangleSqrDist(kPt, p0, p1, p2);
572 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
573 }
574 else // region 3p
575 {
576 // min on face s=0 or r=1
577 kTriSeg.mOrig = p0;
578 kTriSeg.mDir = TriEdge1;
579 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
580 kPt = rkSegOrigin+rkSegDirection;
581 fSqrDist0 = OPC_PointTriangleSqrDist(kPt, p0, p1, p2);
582 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
583 }
584 }
585 else if ( fT < 0.0f ) // region 5p
586 {
587 // min on face t=0 or r=1
588 kTriSeg.mOrig = p0;
589 kTriSeg.mDir = TriEdge0;
590 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
591 kPt = rkSegOrigin+rkSegDirection;
592 fSqrDist0 = OPC_PointTriangleSqrDist(kPt, p0, p1, p2);
593 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
594 }
595 else // region 0p
596 {
597 // min face on r=1
598 kPt = rkSegOrigin+rkSegDirection;
599 fSqrDist = OPC_PointTriangleSqrDist(kPt, p0, p1, p2);
600 }
601 }
602 else
603 {
604 if ( fS < 0.0f ) // region 2p
605 {
606 // min on face s=0 or s+t=1 or r=1
607 kTriSeg.mOrig = p0;
608 kTriSeg.mDir = TriEdge1;
609 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
610 kTriSeg.mOrig = p1;
611 kTriSeg.mDir = TriEdge1-TriEdge0;
612 fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
613 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
614 kPt = rkSegOrigin+rkSegDirection;
615 fSqrDist0 = OPC_PointTriangleSqrDist(kPt, p0, p1, p2);
616 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
617 }
618 else if ( fT < 0.0f ) // region 6p
619 {
620 // min on face t=0 or s+t=1 or r=1
621 kTriSeg.mOrig = p0;
622 kTriSeg.mDir = TriEdge0;
623 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
624 kTriSeg.mOrig = p1;
625 kTriSeg.mDir = TriEdge1-TriEdge0;
626 fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
627 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
628 kPt = rkSegOrigin+rkSegDirection;
629 fSqrDist0 = OPC_PointTriangleSqrDist(kPt, p0, p1, p2);
630 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
631 }
632 else // region 1p
633 {
634 // min on face s+t=1 or r=1
635 kTriSeg.mOrig = p1;
636 kTriSeg.mDir = TriEdge1-TriEdge0;
637 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
638 kPt = rkSegOrigin+rkSegDirection;
639 fSqrDist0 = OPC_PointTriangleSqrDist(kPt, p0, p1, p2);
640 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
641 }
642 }
643 }
644 }
645 else
646 {
647 // segment and triangle are parallel
648 kTriSeg.mOrig = p0;
649 kTriSeg.mDir = TriEdge0;
650 fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
651
652 kTriSeg.mDir = TriEdge1;
653 fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
654 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
655
656 kTriSeg.mOrig = p1;
657 kTriSeg.mDir = TriEdge1 - TriEdge0;
658 fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
659 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
660
661 fSqrDist0 = OPC_PointTriangleSqrDist(rkSegOrigin, p0, p1, p2);
662 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
663
664 kPt = rkSegOrigin+rkSegDirection;
665 fSqrDist0 = OPC_PointTriangleSqrDist(kPt, p0, p1, p2);
666 if(fSqrDist0<fSqrDist) fSqrDist = fSqrDist0;
667 }
668 return fabsf(fSqrDist);
669}
670
671inline_ BOOL LSSCollider::LSSTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2)
672{
673 // Stats
674 mNbVolumePrimTests++;
675
676 float s2 = OPC_SegmentTriangleSqrDist(mSeg, vert0, vert1, vert2);
677 if(s2<mRadius2) return TRUE;
678 return FALSE;
679}
diff --git a/libraries/ode-0.9/OPCODE/OPC_MeshInterface.cpp b/libraries/ode-0.9/OPCODE/OPC_MeshInterface.cpp
new file mode 100644
index 0000000..b962764
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_MeshInterface.cpp
@@ -0,0 +1,303 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains a mesh interface.
12 * \file OPC_MeshInterface.cpp
13 * \author Pierre Terdiman
14 * \date November, 27, 2002
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19/**
20 * This structure holds 3 vertex-pointers. It's mainly used by collision callbacks so that the app doesn't have
21 * to return 3 vertices to OPCODE (36 bytes) but only 3 pointers (12 bytes). It seems better but I never profiled
22 * the alternative.
23 *
24 * \class VertexPointers
25 * \author Pierre Terdiman
26 * \version 1.3
27 * \date March, 20, 2001
28*/
29///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
30
31///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
32/**
33 * This class is an interface between us and user-defined meshes. Meshes can be defined in a lot of ways, and here we
34 * try to support most of them.
35 *
36 * Basically you have two options:
37 * - callbacks, if OPC_USE_CALLBACKS is defined in OPC_Settings.h.
38 * - else pointers.
39 *
40 * If using pointers, you can also use strides or not. Strides are used when OPC_USE_STRIDE is defined.
41 *
42 *
43 * CALLBACKS:
44 *
45 * Using callbacks is the most generic way to feed OPCODE with your meshes. Indeed, you just have to give
46 * access to three vertices at the end of the day. It's up to you to fetch them from your database, using
47 * whatever method you want. Hence your meshes can lie in system memory or AGP, be indexed or not, use 16
48 * or 32-bits indices, you can decompress them on-the-fly if needed, etc. On the other hand, a callback is
49 * called each time OPCODE needs access to a particular triangle, so there might be a slight overhead.
50 *
51 * To make things clear: geometry & topology are NOT stored in the collision system,
52 * in order to save some ram. So, when the system needs them to perform accurate intersection
53 * tests, you're requested to provide the triangle-vertices corresponding to a given face index.
54 *
55 * Ex:
56 *
57 * \code
58 * static void ColCallback(udword triangle_index, VertexPointers& triangle, udword user_data)
59 * {
60 * // Get back Mesh0 or Mesh1 (you also can use 2 different callbacks)
61 * Mesh* MyMesh = (Mesh*)user_data;
62 * // Get correct triangle in the app-controlled database
63 * const Triangle* Tri = MyMesh->GetTriangle(triangle_index);
64 * // Setup pointers to vertices for the collision system
65 * triangle.Vertex[0] = MyMesh->GetVertex(Tri->mVRef[0]);
66 * triangle.Vertex[1] = MyMesh->GetVertex(Tri->mVRef[1]);
67 * triangle.Vertex[2] = MyMesh->GetVertex(Tri->mVRef[2]);
68 * }
69 *
70 * // Setup callbacks
71 * MeshInterface0->SetCallback(ColCallback, udword(Mesh0));
72 * MeshInterface1->SetCallback(ColCallback, udword(Mesh1));
73 * \endcode
74 *
75 * Of course, you should make this callback as fast as possible. And you're also not supposed
76 * to modify the geometry *after* the collision trees have been built. The alternative was to
77 * store the geometry & topology in the collision system as well (as in RAPID) but we have found
78 * this approach to waste a lot of ram in many cases.
79 *
80 *
81 * POINTERS:
82 *
83 * If you're internally using the following canonical structures:
84 * - a vertex made of three 32-bits floating point values
85 * - a triangle made of three 32-bits integer vertex references
86 * ...then you may want to use pointers instead of callbacks. This is the same, except OPCODE will directly
87 * use provided pointers to access the topology and geometry, without using a callback. It might be faster,
88 * but probably not as safe. Pointers have been introduced in OPCODE 1.2.
89 *
90 * Ex:
91 *
92 * \code
93 * // Setup pointers
94 * MeshInterface0->SetPointers(Mesh0->GetFaces(), Mesh0->GetVerts());
95 * MeshInterface1->SetPointers(Mesh1->GetFaces(), Mesh1->GetVerts());
96 * \endcode
97 *
98 *
99 * STRIDES:
100 *
101 * If your vertices are D3D-like entities interleaving a position, a normal and/or texture coordinates
102 * (i.e. if your vertices are FVFs), you might want to use a vertex stride to skip extra data OPCODE
103 * doesn't need. Using a stride shouldn't be notably slower than not using it, but it might increase
104 * cache misses. Please also note that you *shouldn't* read from AGP or video-memory buffers !
105 *
106 *
107 * In any case, compilation flags are here to select callbacks/pointers/strides at compile time, so
108 * choose what's best for your application. All of this has been wrapped into this MeshInterface.
109 *
110 * \class MeshInterface
111 * \author Pierre Terdiman
112 * \version 1.3
113 * \date November, 27, 2002
114*/
115///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
116
117///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
118// Precompiled Header
119#include "Stdafx.h"
120
121using namespace Opcode;
122
123Point MeshInterface::VertexCache[3];
124
125///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
126/**
127 * Constructor.
128 */
129///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
130MeshInterface::MeshInterface() :
131#ifdef OPC_USE_CALLBACKS
132 mUserData (null),
133 mObjCallback (null),
134#else
135 mTris (null),
136 mVerts (null),
137 #ifdef OPC_USE_STRIDE
138 mTriStride (sizeof(IndexedTriangle)),
139 mVertexStride (sizeof(Point)),
140 #endif
141#endif
142 mNbTris (0),
143 mNbVerts (0),
144
145 Single(true)
146{
147}
148
149///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
150/**
151 * Destructor.
152 */
153///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
154MeshInterface::~MeshInterface()
155{
156}
157
158///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
159/**
160 * Checks the mesh interface is valid, i.e. things have been setup correctly.
161 * \return true if valid
162 */
163///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
164bool MeshInterface::IsValid() const
165{
166 if(!mNbTris || !mNbVerts) return false;
167#ifdef OPC_USE_CALLBACKS
168 if(!mObjCallback) return false;
169#else
170 if(!mTris || !mVerts) return false;
171#endif
172 return true;
173}
174
175///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
176/**
177 * Checks the mesh itself is valid.
178 * Currently we only look for degenerate faces.
179 * \return number of degenerate faces
180 */
181///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
182udword MeshInterface::CheckTopology() const
183{
184 // Check topology. If the model contains degenerate faces, collision report can be wrong in some cases.
185 // e.g. it happens with the standard MAX teapot. So clean your meshes first... If you don't have a mesh cleaner
186 // you can try this: www.codercorner.com/Consolidation.zip
187
188 udword NbDegenerate = 0;
189
190 VertexPointers VP;
191
192 // Using callbacks, we don't have access to vertex indices. Nevertheless we still can check for
193 // redundant vertex pointers, which cover all possibilities (callbacks/pointers/strides).
194 for(udword i=0;i<mNbTris;i++)
195 {
196 GetTriangle(VP, i);
197
198 if( (VP.Vertex[0]==VP.Vertex[1])
199 || (VP.Vertex[1]==VP.Vertex[2])
200 || (VP.Vertex[2]==VP.Vertex[0])) NbDegenerate++;
201 }
202
203 return NbDegenerate;
204}
205
206#ifdef OPC_USE_CALLBACKS
207///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
208/**
209 * Callback control: setups object callback. Must provide triangle-vertices for a given triangle index.
210 * \param callback [in] user-defined callback
211 * \param user_data [in] user-defined data
212 * \return true if success
213 */
214///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
215bool MeshInterface::SetCallback(RequestCallback callback, void* user_data)
216{
217 if(!callback) return SetIceError("MeshInterface::SetCallback: callback pointer is null");
218
219 mObjCallback = callback;
220 mUserData = user_data;
221 return true;
222}
223#else
224///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
225/**
226 * Pointers control: setups object pointers. Must provide access to faces and vertices for a given object.
227 * \param tris [in] pointer to triangles
228 * \param verts [in] pointer to vertices
229 * \return true if success
230 */
231///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
232bool MeshInterface::SetPointers(const IndexedTriangle* tris, const Point* verts)
233{
234 if(!tris || !verts) return SetIceError("MeshInterface::SetPointers: pointer is null", null);
235
236 mTris = tris;
237 mVerts = verts;
238 return true;
239}
240#ifdef OPC_USE_STRIDE
241///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
242/**
243 * Strides control
244 * \param tri_stride [in] size of a triangle in bytes. The first sizeof(IndexedTriangle) bytes are used to get vertex indices.
245 * \param vertex_stride [in] size of a vertex in bytes. The first sizeof(Point) bytes are used to get vertex position.
246 * \return true if success
247 */
248///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
249bool MeshInterface::SetStrides(udword tri_stride, udword vertex_stride)
250{
251 if(tri_stride<sizeof(IndexedTriangle)) return SetIceError("MeshInterface::SetStrides: invalid triangle stride", null);
252 if(vertex_stride<sizeof(Point)) return SetIceError("MeshInterface::SetStrides: invalid vertex stride", null);
253
254 mTriStride = tri_stride;
255 mVertexStride = vertex_stride;
256 return true;
257}
258#endif
259#endif
260
261///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
262/**
263 * Remaps client's mesh according to a permutation.
264 * \param nb_indices [in] number of indices in the permutation (will be checked against number of triangles)
265 * \param permutation [in] list of triangle indices
266 * \return true if success
267 */
268///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
269bool MeshInterface::RemapClient(udword nb_indices, const udword* permutation) const
270{
271 // Checkings
272 if(!nb_indices || !permutation) return false;
273 if(nb_indices!=mNbTris) return false;
274
275#ifdef OPC_USE_CALLBACKS
276 // We can't really do that using callbacks
277 return false;
278#else
279 IndexedTriangle* Tmp = new IndexedTriangle[mNbTris];
280 CHECKALLOC(Tmp);
281
282 #ifdef OPC_USE_STRIDE
283 udword Stride = mTriStride;
284 #else
285 udword Stride = sizeof(IndexedTriangle);
286 #endif
287
288 for(udword i=0;i<mNbTris;i++)
289 {
290 const IndexedTriangle* T = (const IndexedTriangle*)(((ubyte*)mTris) + i * Stride);
291 Tmp[i] = *T;
292 }
293
294 for(udword i=0;i<mNbTris;i++)
295 {
296 IndexedTriangle* T = (IndexedTriangle*)(((ubyte*)mTris) + i * Stride);
297 *T = Tmp[permutation[i]];
298 }
299
300 DELETEARRAY(Tmp);
301#endif
302 return true;
303}
diff --git a/libraries/ode-0.9/OPCODE/OPC_MeshInterface.h b/libraries/ode-0.9/OPCODE/OPC_MeshInterface.h
new file mode 100644
index 0000000..61142cf
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_MeshInterface.h
@@ -0,0 +1,199 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains a mesh interface.
12 * \file OPC_MeshInterface.h
13 * \author Pierre Terdiman
14 * \date November, 27, 2002
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_MESHINTERFACE_H__
21#define __OPC_MESHINTERFACE_H__
22
23 struct VertexPointers
24 {
25 const Point* Vertex[3];
26
27 bool BackfaceCulling(const Point& source)
28 {
29 const Point& p0 = *Vertex[0];
30 const Point& p1 = *Vertex[1];
31 const Point& p2 = *Vertex[2];
32
33 // Compute normal direction
34 Point Normal = (p2 - p1)^(p0 - p1);
35
36 // Backface culling
37 return (Normal | (source - p0)) >= 0.0f;
38 }
39 };
40
41#ifdef OPC_USE_CALLBACKS
42 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
43 /**
44 * User-callback, called by OPCODE to request vertices from the app.
45 * \param triangle_index [in] face index for which the system is requesting the vertices
46 * \param triangle [out] triangle's vertices (must be provided by the user)
47 * \param user_data [in] user-defined data from SetCallback()
48 */
49 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
50 typedef void (*RequestCallback) (udword triangle_index, VertexPointers& triangle, void* user_data);
51#endif
52
53 class OPCODE_API MeshInterface
54 {
55 public:
56 // Constructor / Destructor
57 MeshInterface();
58 ~MeshInterface();
59 // Common settings
60 inline_ udword GetNbTriangles() const { return mNbTris; }
61 inline_ udword GetNbVertices() const { return mNbVerts; }
62 inline_ void SetNbTriangles(udword nb) { mNbTris = nb; }
63 inline_ void SetNbVertices(udword nb) { mNbVerts = nb; }
64
65#ifdef OPC_USE_CALLBACKS
66 // Callback settings
67
68 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
69 /**
70 * Callback control: setups object callback. Must provide triangle-vertices for a given triangle index.
71 * \param callback [in] user-defined callback
72 * \param user_data [in] user-defined data
73 * \return true if success
74 */
75 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
76 bool SetCallback(RequestCallback callback, void* user_data);
77 inline_ void* GetUserData() const { return mUserData; }
78 inline_ RequestCallback GetCallback() const { return mObjCallback; }
79#else
80 // Pointers settings
81
82 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
83 /**
84 * Pointers control: setups object pointers. Must provide access to faces and vertices for a given object.
85 * \param tris [in] pointer to triangles
86 * \param verts [in] pointer to vertices
87 * \return true if success
88 */
89 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
90 bool SetPointers(const IndexedTriangle* tris, const Point* verts);
91 inline_ const IndexedTriangle* GetTris() const { return mTris; }
92 inline_ const Point* GetVerts() const { return mVerts; }
93
94 #ifdef OPC_USE_STRIDE
95 // Strides settings
96
97 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
98 /**
99 * Strides control
100 * \param tri_stride [in] size of a triangle in bytes. The first sizeof(IndexedTriangle) bytes are used to get vertex indices.
101 * \param vertex_stride [in] size of a vertex in bytes. The first sizeof(Point) bytes are used to get vertex position.
102 * \return true if success
103 */
104 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
105 bool SetStrides(udword tri_stride=sizeof(IndexedTriangle), udword vertex_stride=sizeof(Point));
106 inline_ udword GetTriStride() const { return mTriStride; }
107 inline_ udword GetVertexStride() const { return mVertexStride; }
108 #endif
109#endif
110
111 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
112 /**
113 * Fetches a triangle given a triangle index.
114 * \param vp [out] required triangle's vertex pointers
115 * \param index [in] triangle index
116 */
117 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
118 inline_ void GetTriangle(VertexPointers& vp, udword index) const
119 {
120#ifdef OPC_USE_CALLBACKS
121 (mObjCallback)(index, vp, mUserData);
122#else
123 #ifdef OPC_USE_STRIDE
124 const IndexedTriangle* T = (const IndexedTriangle*)(((ubyte*)mTris) + index * mTriStride);
125
126 if (Single){
127 vp.Vertex[0] = (const Point*)(((ubyte*)mVerts) + T->mVRef[0] * mVertexStride);
128 vp.Vertex[1] = (const Point*)(((ubyte*)mVerts) + T->mVRef[1] * mVertexStride);
129 vp.Vertex[2] = (const Point*)(((ubyte*)mVerts) + T->mVRef[2] * mVertexStride);
130 }
131 else{
132 for (int i = 0; i < 3; i++){
133 const double* v = (const double*)(((ubyte*)mVerts) + T->mVRef[i] * mVertexStride);
134
135 VertexCache[i].x = (float)v[0];
136 VertexCache[i].y = (float)v[1];
137 VertexCache[i].z = (float)v[2];
138 vp.Vertex[i] = &VertexCache[i];
139 }
140 }
141 #else
142 const IndexedTriangle* T = &mTris[index];
143 vp.Vertex[0] = &mVerts[T->mVRef[0]];
144 vp.Vertex[1] = &mVerts[T->mVRef[1]];
145 vp.Vertex[2] = &mVerts[T->mVRef[2]];
146 #endif
147#endif
148 }
149
150 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
151 /**
152 * Remaps client's mesh according to a permutation.
153 * \param nb_indices [in] number of indices in the permutation (will be checked against number of triangles)
154 * \param permutation [in] list of triangle indices
155 * \return true if success
156 */
157 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
158 bool RemapClient(udword nb_indices, const udword* permutation) const;
159
160 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
161 /**
162 * Checks the mesh interface is valid, i.e. things have been setup correctly.
163 * \return true if valid
164 */
165 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
166 bool IsValid() const;
167
168 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
169 /**
170 * Checks the mesh itself is valid.
171 * Currently we only look for degenerate faces.
172 * \return number of degenerate faces
173 */
174 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
175 udword CheckTopology() const;
176 private:
177
178 udword mNbTris; //!< Number of triangles in the input model
179 udword mNbVerts; //!< Number of vertices in the input model
180#ifdef OPC_USE_CALLBACKS
181 // User callback
182 void* mUserData; //!< User-defined data sent to callback
183 RequestCallback mObjCallback; //!< Object callback
184#else
185 // User pointers
186 const IndexedTriangle* mTris; //!< Array of indexed triangles
187 const Point* mVerts; //!< Array of vertices
188 #ifdef OPC_USE_STRIDE
189 udword mTriStride; //!< Possible triangle stride in bytes [Opcode 1.3]
190 udword mVertexStride; //!< Possible vertex stride in bytes [Opcode 1.3]
191 #endif
192 public:
193 bool Single; //!< Use single or double precision vertices
194 private:
195 static Point VertexCache[3];
196#endif
197 };
198
199#endif //__OPC_MESHINTERFACE_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_Model.cpp b/libraries/ode-0.9/OPCODE/OPC_Model.cpp
new file mode 100644
index 0000000..8b71fb1
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_Model.cpp
@@ -0,0 +1,222 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for OPCODE models.
12 * \file OPC_Model.cpp
13 * \author Pierre Terdiman
14 * \date March, 20, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
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)
25 *
26 * Usage:
27 *
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.
31 *
32 * 2) Build a Model using a creation structure:
33 *
34 * \code
35 * Model Sample;
36 *
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
45 *
46 * 3) Create a tree collider and set it up:
47 *
48 * \code
49 * AABBTreeCollider TC;
50 * TC.SetFirstContact(...);
51 * TC.SetFullBoxBoxTest(...);
52 * TC.SetFullPrimBoxTest(...);
53 * TC.SetTemporalCoherence(...);
54 * \endcode
55 *
56 * 4) Perform a collision query
57 *
58 * \code
59 * // Setup cache
60 * static BVTCache ColCache;
61 * ColCache.Model0 = &Model0;
62 * ColCache.Model1 = &Model1;
63 *
64 * // Collision query
65 * bool IsOk = TC.Collide(ColCache, World0, World1);
66 *
67 * // Get collision status => if true, objects overlap
68 * BOOL Status = TC.GetContactStatus();
69 *
70 * // Number of colliding pairs and list of pairs
71 * udword NbPairs = TC.GetNbPairs();
72 * const Pair* p = TC.GetPairs()
73 * \endcode
74 *
75 * 5) Stats
76 *
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
83 *
84 * \class Model
85 * \author Pierre Terdiman
86 * \version 1.3
87 * \date March, 20, 2001
88*/
89///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
90
91///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
92// Precompiled Header
93#include "Stdafx.h"
94
95using namespace Opcode;
96
97///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
98/**
99 * Constructor.
100 */
101///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
102Model::Model()
103{
104#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE !
105 mHull = null;
106#endif // __MESHMERIZER_H__
107}
108
109///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
110/**
111 * Destructor.
112 */
113///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
114Model::~Model()
115{
116 Release();
117}
118
119///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
120/**
121 * Releases the model.
122 */
123///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
124void Model::Release()
125{
126 ReleaseBase();
127#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE !
128 DELETESINGLE(mHull);
129#endif // __MESHMERIZER_H__
130}
131
132///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
133/**
134 * Builds a collision model.
135 * \param create [in] model creation structure
136 * \return true if success
137 */
138///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
139bool Model::Build(const OPCODECREATE& create)
140{
141 // 1) Checkings
142 if(!create.mIMesh || !create.mIMesh->IsValid()) return false;
143
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);
146
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....
151
152 Release(); // Make sure previous tree has been discarded [Opcode 1.3, thanks Adam]
153
154 // 1-1) Setup mesh interface automatically [Opcode 1.3]
155 SetMeshInterface(create.mIMesh);
156
157 // Special case for 1-triangle meshes [Opcode 1.3]
158 udword NbTris = create.mIMesh->GetNbTriangles();
159 if(NbTris==1)
160 {
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;
165 }
166
167 // 2) Build a generic AABB Tree.
168 mSource = new AABBTree;
169 CHECKALLOC(mSource);
170
171 // 2-1) Setup a builder. Our primitives here are triangles from input mesh,
172 // so we use an AABBTreeOfTrianglesBuilder.....
173 {
174 AABBTreeOfTrianglesBuilder TB;
175 TB.mIMesh = create.mIMesh;
176 TB.mSettings = create.mSettings;
177 TB.mNbPrimitives = NbTris;
178 if(!mSource->Build(&TB)) return false;
179 }
180
181 // 3) Create an optimized tree according to user-settings
182 if(!CreateTree(create.mNoLeaf, create.mQuantized)) return false;
183
184 // 3-2) Create optimized tree
185 if(!mTree->Build(mSource)) return false;
186
187 // 3-3) Delete generic tree if needed
188 if(!create.mKeepOriginal) DELETESINGLE(mSource);
189
190#ifdef __MESHMERIZER_H__
191 // 4) Convex hull
192 if(create.mCollisionHull)
193 {
194 // Create hull
195 mHull = new CollisionHull;
196 CHECKALLOC(mHull);
197
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);
206 }
207#endif // __MESHMERIZER_H__
208
209 return true;
210}
211
212///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
213/**
214 * Gets the number of bytes used by the tree.
215 * \return amount of bytes used
216 */
217///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
218udword Model::GetUsedBytes() const
219{
220 if(!mTree) return 0;
221 return mTree->GetUsedBytes();
222}
diff --git a/libraries/ode-0.9/OPCODE/OPC_Model.h b/libraries/ode-0.9/OPCODE/OPC_Model.h
new file mode 100644
index 0000000..98dee56
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_Model.h
@@ -0,0 +1,65 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for OPCODE models.
12 * \file OPC_Model.h
13 * \author Pierre Terdiman
14 * \date March, 20, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_MODEL_H__
21#define __OPC_MODEL_H__
22
23 class OPCODE_API Model : public BaseModel
24 {
25 public:
26 // Constructor/Destructor
27 Model();
28 virtual ~Model();
29
30 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
31 /**
32 * Builds a collision model.
33 * \param create [in] model creation structure
34 * \return true if success
35 */
36 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
37 override(BaseModel) bool Build(const OPCODECREATE& create);
38
39#ifdef __MESHMERIZER_H__
40 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
41 /**
42 * Gets the collision hull.
43 * \return the collision hull if it exists
44 */
45 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
46 inline_ const CollisionHull* GetHull() const { return mHull; }
47#endif // __MESHMERIZER_H__
48
49 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
50 /**
51 * Gets the number of bytes used by the tree.
52 * \return amount of bytes used
53 */
54 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
55 override(BaseModel) udword GetUsedBytes() const;
56
57 private:
58#ifdef __MESHMERIZER_H__
59 CollisionHull* mHull; //!< Possible convex hull
60#endif // __MESHMERIZER_H__
61 // Internal methods
62 void Release();
63 };
64
65#endif //__OPC_MODEL_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_OBBCollider.cpp b/libraries/ode-0.9/OPCODE/OPC_OBBCollider.cpp
new file mode 100644
index 0000000..028d000
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_OBBCollider.cpp
@@ -0,0 +1,767 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for an OBB collider.
12 * \file OPC_OBBCollider.cpp
13 * \author Pierre Terdiman
14 * \date January, 1st, 2002
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19/**
20 * Contains an OBB-vs-tree collider.
21 *
22 * \class OBBCollider
23 * \author Pierre Terdiman
24 * \version 1.3
25 * \date January, 1st, 2002
26*/
27///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
28
29///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
30// Precompiled Header
31#include "Stdafx.h"
32
33using namespace Opcode;
34
35#include "OPC_BoxBoxOverlap.h"
36#include "OPC_TriBoxOverlap.h"
37
38#define SET_CONTACT(prim_index, flag) \
39 /* Set contact status */ \
40 mFlags |= flag; \
41 mTouchedPrimitives->Add(udword(prim_index));
42
43//! OBB-triangle test
44#define OBB_PRIM(prim_index, flag) \
45 /* Request vertices from the app */ \
46 VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \
47 /* Transform them in a common space */ \
48 TransformPoint(mLeafVerts[0], *VP.Vertex[0], mRModelToBox, mTModelToBox); \
49 TransformPoint(mLeafVerts[1], *VP.Vertex[1], mRModelToBox, mTModelToBox); \
50 TransformPoint(mLeafVerts[2], *VP.Vertex[2], mRModelToBox, mTModelToBox); \
51 /* Perform triangle-box overlap test */ \
52 if(TriBoxOverlap()) \
53 { \
54 SET_CONTACT(prim_index, flag) \
55 }
56
57///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
58/**
59 * Constructor.
60 */
61///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
62OBBCollider::OBBCollider() : mFullBoxBoxTest(true)
63{
64}
65
66///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
67/**
68 * Destructor.
69 */
70///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
71OBBCollider::~OBBCollider()
72{
73}
74
75///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
76/**
77 * Validates current settings. You should call this method after all the settings and callbacks have been defined.
78 * \return null if everything is ok, else a string describing the problem
79 */
80///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
81const char* OBBCollider::ValidateSettings()
82{
83 if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!";
84
85 return VolumeCollider::ValidateSettings();
86}
87
88///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
89/**
90 * Generic collision query for generic OPCODE models. After the call, access the results:
91 * - with GetContactStatus()
92 * - with GetNbTouchedPrimitives()
93 * - with GetTouchedPrimitives()
94 *
95 * \param cache [in/out] a box cache
96 * \param box [in] collision OBB in local space
97 * \param model [in] Opcode model to collide with
98 * \param worldb [in] OBB's world matrix, or null
99 * \param worldm [in] model's world matrix, or null
100 * \return true if success
101 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
102 */
103///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
104bool OBBCollider::Collide(OBBCache& cache, const OBB& box, const Model& model, const Matrix4x4* worldb, const Matrix4x4* worldm)
105{
106 // Checkings
107 if(!Setup(&model)) return false;
108
109 // Init collision query
110 if(InitQuery(cache, box, worldb, worldm)) return true;
111
112 if(!model.HasLeafNodes())
113 {
114 if(model.IsQuantized())
115 {
116 const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
117
118 // Setup dequantization coeffs
119 mCenterCoeff = Tree->mCenterCoeff;
120 mExtentsCoeff = Tree->mExtentsCoeff;
121
122 // Perform collision query
123 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
124 else _Collide(Tree->GetNodes());
125 }
126 else
127 {
128 const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
129
130 // Perform collision query
131 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
132 else _Collide(Tree->GetNodes());
133 }
134 }
135 else
136 {
137 if(model.IsQuantized())
138 {
139 const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
140
141 // Setup dequantization coeffs
142 mCenterCoeff = Tree->mCenterCoeff;
143 mExtentsCoeff = Tree->mExtentsCoeff;
144
145 // Perform collision query
146 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
147 else _Collide(Tree->GetNodes());
148 }
149 else
150 {
151 const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
152
153 // Perform collision query
154 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
155 else _Collide(Tree->GetNodes());
156 }
157 }
158
159 return true;
160}
161
162///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
163/**
164 * Initializes a collision query :
165 * - reset stats & contact status
166 * - setup matrices
167 * - check temporal coherence
168 *
169 * \param cache [in/out] a box cache
170 * \param box [in] obb in local space
171 * \param worldb [in] obb's world matrix, or null
172 * \param worldm [in] model's world matrix, or null
173 * \return TRUE if we can return immediately
174 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
175 */
176///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
177BOOL OBBCollider::InitQuery(OBBCache& cache, const OBB& box, const Matrix4x4* worldb, const Matrix4x4* worldm)
178{
179 // 1) Call the base method
180 VolumeCollider::InitQuery();
181
182 // 2) Compute obb in world space
183 mBoxExtents = box.mExtents;
184
185 Matrix4x4 WorldB;
186
187 if(worldb)
188 {
189 WorldB = Matrix4x4( box.mRot * Matrix3x3(*worldb) );
190 WorldB.SetTrans(box.mCenter * *worldb);
191 }
192 else
193 {
194 WorldB = box.mRot;
195 WorldB.SetTrans(box.mCenter);
196 }
197
198 // Setup matrices
199 Matrix4x4 InvWorldB;
200 InvertPRMatrix(InvWorldB, WorldB);
201
202 if(worldm)
203 {
204 Matrix4x4 InvWorldM;
205 InvertPRMatrix(InvWorldM, *worldm);
206
207 Matrix4x4 WorldBtoM = WorldB * InvWorldM;
208 Matrix4x4 WorldMtoB = *worldm * InvWorldB;
209
210 mRModelToBox = WorldMtoB; WorldMtoB.GetTrans(mTModelToBox);
211 mRBoxToModel = WorldBtoM; WorldBtoM.GetTrans(mTBoxToModel);
212 }
213 else
214 {
215 mRModelToBox = InvWorldB; InvWorldB.GetTrans(mTModelToBox);
216 mRBoxToModel = WorldB; WorldB.GetTrans(mTBoxToModel);
217 }
218
219 // 3) Setup destination pointer
220 mTouchedPrimitives = &cache.TouchedPrimitives;
221
222 // 4) Special case: 1-triangle meshes [Opcode 1.3]
223 if(mCurrentModel && mCurrentModel->HasSingleNode())
224 {
225 if(!SkipPrimitiveTests())
226 {
227 // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0.
228 mTouchedPrimitives->Reset();
229
230 // Perform overlap test between the unique triangle and the box (and set contact status if needed)
231 OBB_PRIM(udword(0), OPC_CONTACT)
232
233 // Return immediately regardless of status
234 return TRUE;
235 }
236 }
237
238 // 5) Check temporal coherence:
239 if(TemporalCoherenceEnabled())
240 {
241 // Here we use temporal coherence
242 // => check results from previous frame before performing the collision query
243 if(FirstContactEnabled())
244 {
245 // We're only interested in the first contact found => test the unique previously touched face
246 if(mTouchedPrimitives->GetNbEntries())
247 {
248 // Get index of previously touched face = the first entry in the array
249 udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0);
250
251 // Then reset the array:
252 // - if the overlap test below is successful, the index we'll get added back anyway
253 // - if it isn't, then the array should be reset anyway for the normal query
254 mTouchedPrimitives->Reset();
255
256 // Perform overlap test between the cached triangle and the box (and set contact status if needed)
257 OBB_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT)
258
259 // Return immediately if possible
260 if(GetContactStatus()) return TRUE;
261 }
262 // else no face has been touched during previous query
263 // => we'll have to perform a normal query
264 }
265 else
266 {
267 // ### rewrite this
268 OBB TestBox(mTBoxToModel, mBoxExtents, mRBoxToModel);
269
270 // We're interested in all contacts =>test the new real box N(ew) against the previous fat box P(revious):
271 if(IsCacheValid(cache) && TestBox.IsInside(cache.FatBox))
272 {
273 // - if N is included in P, return previous list
274 // => we simply leave the list (mTouchedFaces) unchanged
275
276 // Set contact status if needed
277 if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT;
278
279 // In any case we don't need to do a query
280 return TRUE;
281 }
282 else
283 {
284 // - else do the query using a fat N
285
286 // Reset cache since we'll about to perform a real query
287 mTouchedPrimitives->Reset();
288
289 // Make a fat box so that coherence will work for subsequent frames
290 TestBox.mExtents *= cache.FatCoeff;
291 mBoxExtents *= cache.FatCoeff;
292
293 // Update cache with query data (signature for cached faces)
294 cache.FatBox = TestBox;
295 }
296 }
297 }
298 else
299 {
300 // Here we don't use temporal coherence => do a normal query
301 mTouchedPrimitives->Reset();
302 }
303
304 // Now we can precompute box-box data
305
306 // Precompute absolute box-to-model rotation matrix
307 for(udword i=0;i<3;i++)
308 {
309 for(udword j=0;j<3;j++)
310 {
311 // Epsilon value prevents floating-point inaccuracies (strategy borrowed from RAPID)
312 mAR.m[i][j] = 1e-6f + fabsf(mRBoxToModel.m[i][j]);
313 }
314 }
315
316 // Precompute bounds for box-in-box test
317 mB0 = mBoxExtents - mTModelToBox;
318 mB1 = - mBoxExtents - mTModelToBox;
319
320 // Precompute box-box data - Courtesy of Erwin de Vries
321 mBBx1 = mBoxExtents.x*mAR.m[0][0] + mBoxExtents.y*mAR.m[1][0] + mBoxExtents.z*mAR.m[2][0];
322 mBBy1 = mBoxExtents.x*mAR.m[0][1] + mBoxExtents.y*mAR.m[1][1] + mBoxExtents.z*mAR.m[2][1];
323 mBBz1 = mBoxExtents.x*mAR.m[0][2] + mBoxExtents.y*mAR.m[1][2] + mBoxExtents.z*mAR.m[2][2];
324
325 mBB_1 = mBoxExtents.y*mAR.m[2][0] + mBoxExtents.z*mAR.m[1][0];
326 mBB_2 = mBoxExtents.x*mAR.m[2][0] + mBoxExtents.z*mAR.m[0][0];
327 mBB_3 = mBoxExtents.x*mAR.m[1][0] + mBoxExtents.y*mAR.m[0][0];
328 mBB_4 = mBoxExtents.y*mAR.m[2][1] + mBoxExtents.z*mAR.m[1][1];
329 mBB_5 = mBoxExtents.x*mAR.m[2][1] + mBoxExtents.z*mAR.m[0][1];
330 mBB_6 = mBoxExtents.x*mAR.m[1][1] + mBoxExtents.y*mAR.m[0][1];
331 mBB_7 = mBoxExtents.y*mAR.m[2][2] + mBoxExtents.z*mAR.m[1][2];
332 mBB_8 = mBoxExtents.x*mAR.m[2][2] + mBoxExtents.z*mAR.m[0][2];
333 mBB_9 = mBoxExtents.x*mAR.m[1][2] + mBoxExtents.y*mAR.m[0][2];
334
335 return FALSE;
336}
337
338///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
339/**
340 * Checks the OBB completely contains the box. In which case we can end the query sooner.
341 * \param bc [in] box center
342 * \param be [in] box extents
343 * \return true if the OBB contains the whole box
344 */
345///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
346inline_ BOOL OBBCollider::OBBContainsBox(const Point& bc, const Point& be)
347{
348 // I assume if all 8 box vertices are inside the OBB, so does the whole box.
349 // Sounds ok but maybe there's a better way?
350/*
351#define TEST_PT(a,b,c) \
352 p.x=a; p.y=b; p.z=c; p+=bc; \
353 f = p.x * mRModelToBox.m[0][0] + p.y * mRModelToBox.m[1][0] + p.z * mRModelToBox.m[2][0]; if(f>mB0.x || f<mB1.x) return FALSE;\
354 f = p.x * mRModelToBox.m[0][1] + p.y * mRModelToBox.m[1][1] + p.z * mRModelToBox.m[2][1]; if(f>mB0.y || f<mB1.y) return FALSE;\
355 f = p.x * mRModelToBox.m[0][2] + p.y * mRModelToBox.m[1][2] + p.z * mRModelToBox.m[2][2]; if(f>mB0.z || f<mB1.z) return FALSE;
356
357 Point p;
358 float f;
359
360 TEST_PT(be.x, be.y, be.z)
361 TEST_PT(-be.x, be.y, be.z)
362 TEST_PT(be.x, -be.y, be.z)
363 TEST_PT(-be.x, -be.y, be.z)
364 TEST_PT(be.x, be.y, -be.z)
365 TEST_PT(-be.x, be.y, -be.z)
366 TEST_PT(be.x, -be.y, -be.z)
367 TEST_PT(-be.x, -be.y, -be.z)
368
369 return TRUE;
370*/
371
372 // Yes there is:
373 // - compute model-box's AABB in OBB space
374 // - test AABB-in-AABB
375 float NCx = bc.x * mRModelToBox.m[0][0] + bc.y * mRModelToBox.m[1][0] + bc.z * mRModelToBox.m[2][0];
376 float NEx = fabsf(mRModelToBox.m[0][0] * be.x) + fabsf(mRModelToBox.m[1][0] * be.y) + fabsf(mRModelToBox.m[2][0] * be.z);
377
378 if(mB0.x < NCx+NEx) return FALSE;
379 if(mB1.x > NCx-NEx) return FALSE;
380
381 float NCy = bc.x * mRModelToBox.m[0][1] + bc.y * mRModelToBox.m[1][1] + bc.z * mRModelToBox.m[2][1];
382 float NEy = fabsf(mRModelToBox.m[0][1] * be.x) + fabsf(mRModelToBox.m[1][1] * be.y) + fabsf(mRModelToBox.m[2][1] * be.z);
383
384 if(mB0.y < NCy+NEy) return FALSE;
385 if(mB1.y > NCy-NEy) return FALSE;
386
387 float NCz = bc.x * mRModelToBox.m[0][2] + bc.y * mRModelToBox.m[1][2] + bc.z * mRModelToBox.m[2][2];
388 float NEz = fabsf(mRModelToBox.m[0][2] * be.x) + fabsf(mRModelToBox.m[1][2] * be.y) + fabsf(mRModelToBox.m[2][2] * be.z);
389
390 if(mB0.z < NCz+NEz) return FALSE;
391 if(mB1.z > NCz-NEz) return FALSE;
392
393 return TRUE;
394}
395
396#define TEST_BOX_IN_OBB(center, extents) \
397 if(OBBContainsBox(center, extents)) \
398 { \
399 /* Set contact status */ \
400 mFlags |= OPC_CONTACT; \
401 _Dump(node); \
402 return; \
403 }
404
405///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
406/**
407 * Recursive collision query for normal AABB trees.
408 * \param node [in] current collision node
409 */
410///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
411void OBBCollider::_Collide(const AABBCollisionNode* node)
412{
413 // Perform OBB-AABB overlap test
414 if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return;
415
416 TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents)
417
418 if(node->IsLeaf())
419 {
420 OBB_PRIM(node->GetPrimitive(), OPC_CONTACT)
421 }
422 else
423 {
424 _Collide(node->GetPos());
425
426 if(ContactFound()) return;
427
428 _Collide(node->GetNeg());
429 }
430}
431
432///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
433/**
434 * Recursive collision query for normal AABB trees, without primitive tests.
435 * \param node [in] current collision node
436 */
437///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
438void OBBCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node)
439{
440 // Perform OBB-AABB overlap test
441 if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return;
442
443 TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents)
444
445 if(node->IsLeaf())
446 {
447 SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
448 }
449 else
450 {
451 _CollideNoPrimitiveTest(node->GetPos());
452
453 if(ContactFound()) return;
454
455 _CollideNoPrimitiveTest(node->GetNeg());
456 }
457}
458
459///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
460/**
461 * Recursive collision query for quantized AABB trees.
462 * \param node [in] current collision node
463 */
464///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
465void OBBCollider::_Collide(const AABBQuantizedNode* node)
466{
467 // Dequantize box
468 const QuantizedAABB& Box = node->mAABB;
469 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
470 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
471
472 // Perform OBB-AABB overlap test
473 if(!BoxBoxOverlap(Extents, Center)) return;
474
475 TEST_BOX_IN_OBB(Center, Extents)
476
477 if(node->IsLeaf())
478 {
479 OBB_PRIM(node->GetPrimitive(), OPC_CONTACT)
480 }
481 else
482 {
483 _Collide(node->GetPos());
484
485 if(ContactFound()) return;
486
487 _Collide(node->GetNeg());
488 }
489}
490
491///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
492/**
493 * Recursive collision query for quantized AABB trees, without primitive tests.
494 * \param node [in] current collision node
495 */
496///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
497void OBBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node)
498{
499 // Dequantize box
500 const QuantizedAABB& Box = node->mAABB;
501 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
502 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
503
504 // Perform OBB-AABB overlap test
505 if(!BoxBoxOverlap(Extents, Center)) return;
506
507 TEST_BOX_IN_OBB(Center, Extents)
508
509 if(node->IsLeaf())
510 {
511 SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
512 }
513 else
514 {
515 _CollideNoPrimitiveTest(node->GetPos());
516
517 if(ContactFound()) return;
518
519 _CollideNoPrimitiveTest(node->GetNeg());
520 }
521}
522
523///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
524/**
525 * Recursive collision query for no-leaf AABB trees.
526 * \param node [in] current collision node
527 */
528///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
529void OBBCollider::_Collide(const AABBNoLeafNode* node)
530{
531 // Perform OBB-AABB overlap test
532 if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return;
533
534 TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents)
535
536 if(node->HasPosLeaf()) { OBB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
537 else _Collide(node->GetPos());
538
539 if(ContactFound()) return;
540
541 if(node->HasNegLeaf()) { OBB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
542 else _Collide(node->GetNeg());
543}
544
545///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
546/**
547 * Recursive collision query for no-leaf AABB trees, without primitive tests.
548 * \param node [in] current collision node
549 */
550///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
551void OBBCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node)
552{
553 // Perform OBB-AABB overlap test
554 if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return;
555
556 TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents)
557
558 if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
559 else _CollideNoPrimitiveTest(node->GetPos());
560
561 if(ContactFound()) return;
562
563 if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
564 else _CollideNoPrimitiveTest(node->GetNeg());
565}
566
567///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
568/**
569 * Recursive collision query for quantized no-leaf AABB trees.
570 * \param node [in] current collision node
571 */
572///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
573void OBBCollider::_Collide(const AABBQuantizedNoLeafNode* node)
574{
575 // Dequantize box
576 const QuantizedAABB& Box = node->mAABB;
577 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
578 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
579
580 // Perform OBB-AABB overlap test
581 if(!BoxBoxOverlap(Extents, Center)) return;
582
583 TEST_BOX_IN_OBB(Center, Extents)
584
585 if(node->HasPosLeaf()) { OBB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
586 else _Collide(node->GetPos());
587
588 if(ContactFound()) return;
589
590 if(node->HasNegLeaf()) { OBB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
591 else _Collide(node->GetNeg());
592}
593
594///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
595/**
596 * Recursive collision query for quantized no-leaf AABB trees, without primitive tests.
597 * \param node [in] current collision node
598 */
599///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
600void OBBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node)
601{
602 // Dequantize box
603 const QuantizedAABB& Box = node->mAABB;
604 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
605 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
606
607 // Perform OBB-AABB overlap test
608 if(!BoxBoxOverlap(Extents, Center)) return;
609
610 TEST_BOX_IN_OBB(Center, Extents)
611
612 if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
613 else _CollideNoPrimitiveTest(node->GetPos());
614
615 if(ContactFound()) return;
616
617 if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
618 else _CollideNoPrimitiveTest(node->GetNeg());
619}
620
621
622
623
624
625
626///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
627/**
628 * Constructor.
629 */
630///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
631HybridOBBCollider::HybridOBBCollider()
632{
633}
634
635///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
636/**
637 * Destructor.
638 */
639///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
640HybridOBBCollider::~HybridOBBCollider()
641{
642}
643
644bool HybridOBBCollider::Collide(OBBCache& cache, const OBB& box, const HybridModel& model, const Matrix4x4* worldb, const Matrix4x4* worldm)
645{
646 // We don't want primitive tests here!
647 mFlags |= OPC_NO_PRIMITIVE_TESTS;
648
649 // Checkings
650 if(!Setup(&model)) return false;
651
652 // Init collision query
653 if(InitQuery(cache, box, worldb, worldm)) return true;
654
655 // Special case for 1-leaf trees
656 if(mCurrentModel && mCurrentModel->HasSingleNode())
657 {
658 // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles
659 udword Nb = mIMesh->GetNbTriangles();
660
661 // Loop through all triangles
662 for(udword i=0;i<Nb;i++)
663 {
664 OBB_PRIM(i, OPC_CONTACT)
665 }
666 return true;
667 }
668
669 // Override destination array since we're only going to get leaf boxes here
670 mTouchedBoxes.Reset();
671 mTouchedPrimitives = &mTouchedBoxes;
672
673 // Now, do the actual query against leaf boxes
674 if(!model.HasLeafNodes())
675 {
676 if(model.IsQuantized())
677 {
678 const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
679
680 // Setup dequantization coeffs
681 mCenterCoeff = Tree->mCenterCoeff;
682 mExtentsCoeff = Tree->mExtentsCoeff;
683
684 // Perform collision query - we don't want primitive tests here!
685 _CollideNoPrimitiveTest(Tree->GetNodes());
686 }
687 else
688 {
689 const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
690
691 // Perform collision query - we don't want primitive tests here!
692 _CollideNoPrimitiveTest(Tree->GetNodes());
693 }
694 }
695 else
696 {
697 if(model.IsQuantized())
698 {
699 const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
700
701 // Setup dequantization coeffs
702 mCenterCoeff = Tree->mCenterCoeff;
703 mExtentsCoeff = Tree->mExtentsCoeff;
704
705 // Perform collision query - we don't want primitive tests here!
706 _CollideNoPrimitiveTest(Tree->GetNodes());
707 }
708 else
709 {
710 const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
711
712 // Perform collision query - we don't want primitive tests here!
713 _CollideNoPrimitiveTest(Tree->GetNodes());
714 }
715 }
716
717 // We only have a list of boxes so far
718 if(GetContactStatus())
719 {
720 // Reset contact status, since it currently only reflects collisions with leaf boxes
721 Collider::InitQuery();
722
723 // Change dest container so that we can use built-in overlap tests and get collided primitives
724 cache.TouchedPrimitives.Reset();
725 mTouchedPrimitives = &cache.TouchedPrimitives;
726
727 // Read touched leaf boxes
728 udword Nb = mTouchedBoxes.GetNbEntries();
729 const udword* Touched = mTouchedBoxes.GetEntries();
730
731 const LeafTriangles* LT = model.GetLeafTriangles();
732 const udword* Indices = model.GetIndices();
733
734 // Loop through touched leaves
735 while(Nb--)
736 {
737 const LeafTriangles& CurrentLeaf = LT[*Touched++];
738
739 // Each leaf box has a set of triangles
740 udword NbTris = CurrentLeaf.GetNbTriangles();
741 if(Indices)
742 {
743 const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()];
744
745 // Loop through triangles and test each of them
746 while(NbTris--)
747 {
748 udword TriangleIndex = *T++;
749 OBB_PRIM(TriangleIndex, OPC_CONTACT)
750 }
751 }
752 else
753 {
754 udword BaseIndex = CurrentLeaf.GetTriangleIndex();
755
756 // Loop through triangles and test each of them
757 while(NbTris--)
758 {
759 udword TriangleIndex = BaseIndex++;
760 OBB_PRIM(TriangleIndex, OPC_CONTACT)
761 }
762 }
763 }
764 }
765
766 return true;
767}
diff --git a/libraries/ode-0.9/OPCODE/OPC_OBBCollider.h b/libraries/ode-0.9/OPCODE/OPC_OBBCollider.h
new file mode 100644
index 0000000..a050118
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_OBBCollider.h
@@ -0,0 +1,142 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for an OBB collider.
12 * \file OPC_OBBCollider.h
13 * \author Pierre Terdiman
14 * \date January, 1st, 2002
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_OBBCOLLIDER_H__
21#define __OPC_OBBCOLLIDER_H__
22
23 struct OPCODE_API OBBCache : VolumeCache
24 {
25 OBBCache() : FatCoeff(1.1f)
26 {
27 FatBox.mCenter.Zero();
28 FatBox.mExtents.Zero();
29 FatBox.mRot.Identity();
30 }
31
32 // Cached faces signature
33 OBB FatBox; //!< Box used when performing the query resulting in cached faces
34 // User settings
35 float FatCoeff; //!< extents multiplier used to create a fat box
36 };
37
38 class OPCODE_API OBBCollider : public VolumeCollider
39 {
40 public:
41 // Constructor / Destructor
42 OBBCollider();
43 virtual ~OBBCollider();
44
45 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
46 /**
47 * Generic collision query for generic OPCODE models. After the call, access the results:
48 * - with GetContactStatus()
49 * - with GetNbTouchedPrimitives()
50 * - with GetTouchedPrimitives()
51 *
52 * \param cache [in/out] a box cache
53 * \param box [in] collision OBB in local space
54 * \param model [in] Opcode model to collide with
55 * \param worldb [in] OBB's world matrix, or null
56 * \param worldm [in] model's world matrix, or null
57 * \return true if success
58 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
59 */
60 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
61 bool Collide(OBBCache& cache, const OBB& box, const Model& model, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null);
62
63 // Settings
64
65 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
66 /**
67 * Settings: select between full box-box tests or "SAT-lite" tests (where Class III axes are discarded)
68 * \param flag [in] true for full tests, false for coarse tests
69 */
70 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
71 inline_ void SetFullBoxBoxTest(bool flag) { mFullBoxBoxTest = flag; }
72
73 // Settings
74
75 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
76 /**
77 * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider.
78 * \return null if everything is ok, else a string describing the problem
79 */
80 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
81 override(Collider) const char* ValidateSettings();
82
83 protected:
84 // Precomputed data
85 Matrix3x3 mAR; //!< Absolute rotation matrix
86 Matrix3x3 mRModelToBox; //!< Rotation from model space to obb space
87 Matrix3x3 mRBoxToModel; //!< Rotation from obb space to model space
88 Point mTModelToBox; //!< Translation from model space to obb space
89 Point mTBoxToModel; //!< Translation from obb space to model space
90
91 Point mBoxExtents;
92 Point mB0; //!< - mTModelToBox + mBoxExtents
93 Point mB1; //!< - mTModelToBox - mBoxExtents
94
95 float mBBx1;
96 float mBBy1;
97 float mBBz1;
98
99 float mBB_1;
100 float mBB_2;
101 float mBB_3;
102 float mBB_4;
103 float mBB_5;
104 float mBB_6;
105 float mBB_7;
106 float mBB_8;
107 float mBB_9;
108
109 // Leaf description
110 Point mLeafVerts[3]; //!< Triangle vertices
111 // Settings
112 bool mFullBoxBoxTest; //!< Perform full BV-BV tests (true) or SAT-lite tests (false)
113 // Internal methods
114 void _Collide(const AABBCollisionNode* node);
115 void _Collide(const AABBNoLeafNode* node);
116 void _Collide(const AABBQuantizedNode* node);
117 void _Collide(const AABBQuantizedNoLeafNode* node);
118 void _CollideNoPrimitiveTest(const AABBCollisionNode* node);
119 void _CollideNoPrimitiveTest(const AABBNoLeafNode* node);
120 void _CollideNoPrimitiveTest(const AABBQuantizedNode* node);
121 void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node);
122 // Overlap tests
123 inline_ BOOL OBBContainsBox(const Point& bc, const Point& be);
124 inline_ BOOL BoxBoxOverlap(const Point& extents, const Point& center);
125 inline_ BOOL TriBoxOverlap();
126 // Init methods
127 BOOL InitQuery(OBBCache& cache, const OBB& box, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null);
128 };
129
130 class OPCODE_API HybridOBBCollider : public OBBCollider
131 {
132 public:
133 // Constructor / Destructor
134 HybridOBBCollider();
135 virtual ~HybridOBBCollider();
136
137 bool Collide(OBBCache& cache, const OBB& box, const HybridModel& model, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null);
138 protected:
139 Container mTouchedBoxes;
140 };
141
142#endif // __OPC_OBBCOLLIDER_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_OptimizedTree.cpp b/libraries/ode-0.9/OPCODE/OPC_OptimizedTree.cpp
new file mode 100644
index 0000000..11b92f9
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_OptimizedTree.cpp
@@ -0,0 +1,782 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for optimized trees. Implements 4 trees:
12 * - normal
13 * - no leaf
14 * - quantized
15 * - no leaf / quantized
16 *
17 * \file OPC_OptimizedTree.cpp
18 * \author Pierre Terdiman
19 * \date March, 20, 2001
20 */
21///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
22
23///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
24/**
25 * A standard AABB tree.
26 *
27 * \class AABBCollisionTree
28 * \author Pierre Terdiman
29 * \version 1.3
30 * \date March, 20, 2001
31*/
32///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
33
34///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
35/**
36 * A no-leaf AABB tree.
37 *
38 * \class AABBNoLeafTree
39 * \author Pierre Terdiman
40 * \version 1.3
41 * \date March, 20, 2001
42*/
43///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
44
45///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
46/**
47 * A quantized AABB tree.
48 *
49 * \class AABBQuantizedTree
50 * \author Pierre Terdiman
51 * \version 1.3
52 * \date March, 20, 2001
53*/
54///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
55
56///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
57/**
58 * A quantized no-leaf AABB tree.
59 *
60 * \class AABBQuantizedNoLeafTree
61 * \author Pierre Terdiman
62 * \version 1.3
63 * \date March, 20, 2001
64*/
65///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
66
67///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
68// Precompiled Header
69#include "Stdafx.h"
70
71using namespace Opcode;
72
73//! Compilation flag:
74//! - true to fix quantized boxes (i.e. make sure they enclose the original ones)
75//! - false to see the effects of quantization errors (faster, but wrong results in some cases)
76static bool gFixQuantized = true;
77
78///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
79/**
80 * Builds an implicit tree from a standard one. An implicit tree is a complete tree (2*N-1 nodes) whose negative
81 * box pointers and primitive pointers have been made implicit, hence packing 3 pointers in one.
82 *
83 * Layout for implicit trees:
84 * Node:
85 * - box
86 * - data (32-bits value)
87 *
88 * if data's LSB = 1 => remaining bits are a primitive pointer
89 * else remaining bits are a P-node pointer, and N = P + 1
90 *
91 * \relates AABBCollisionNode
92 * \fn _BuildCollisionTree(AABBCollisionNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node)
93 * \param linear [in] base address of destination nodes
94 * \param box_id [in] index of destination node
95 * \param current_id [in] current running index
96 * \param current_node [in] current node from input tree
97 */
98///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
99static void _BuildCollisionTree(AABBCollisionNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node)
100{
101 // Current node from input tree is "current_node". Must be flattened into "linear[boxid]".
102
103 // Store the AABB
104 current_node->GetAABB()->GetCenter(linear[box_id].mAABB.mCenter);
105 current_node->GetAABB()->GetExtents(linear[box_id].mAABB.mExtents);
106 // Store remaining info
107 if(current_node->IsLeaf())
108 {
109 // The input tree must be complete => i.e. one primitive/leaf
110 ASSERT(current_node->GetNbPrimitives()==1);
111 // Get the primitive index from the input tree
112 udword PrimitiveIndex = current_node->GetPrimitives()[0];
113 // Setup box data as the primitive index, marked as leaf
114 linear[box_id].mData = (PrimitiveIndex<<1)|1;
115 }
116 else
117 {
118 // To make the negative one implicit, we must store P and N in successive order
119 udword PosID = current_id++; // Get a new id for positive child
120 udword NegID = current_id++; // Get a new id for negative child
121 // Setup box data as the forthcoming new P pointer
122 linear[box_id].mData = (size_t)&linear[PosID];
123 // Make sure it's not marked as leaf
124 ASSERT(!(linear[box_id].mData&1));
125 // Recurse with new IDs
126 _BuildCollisionTree(linear, PosID, current_id, current_node->GetPos());
127 _BuildCollisionTree(linear, NegID, current_id, current_node->GetNeg());
128 }
129}
130
131///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
132/**
133 * Builds a "no-leaf" tree from a standard one. This is a tree whose leaf nodes have been removed.
134 *
135 * Layout for no-leaf trees:
136 *
137 * Node:
138 * - box
139 * - P pointer => a node (LSB=0) or a primitive (LSB=1)
140 * - N pointer => a node (LSB=0) or a primitive (LSB=1)
141 *
142 * \relates AABBNoLeafNode
143 * \fn _BuildNoLeafTree(AABBNoLeafNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node)
144 * \param linear [in] base address of destination nodes
145 * \param box_id [in] index of destination node
146 * \param current_id [in] current running index
147 * \param current_node [in] current node from input tree
148 */
149///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
150static void _BuildNoLeafTree(AABBNoLeafNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node)
151{
152 const AABBTreeNode* P = current_node->GetPos();
153 const AABBTreeNode* N = current_node->GetNeg();
154 // Leaf nodes here?!
155 ASSERT(P);
156 ASSERT(N);
157 // Internal node => keep the box
158 current_node->GetAABB()->GetCenter(linear[box_id].mAABB.mCenter);
159 current_node->GetAABB()->GetExtents(linear[box_id].mAABB.mExtents);
160
161 if(P->IsLeaf())
162 {
163 // The input tree must be complete => i.e. one primitive/leaf
164 ASSERT(P->GetNbPrimitives()==1);
165 // Get the primitive index from the input tree
166 udword PrimitiveIndex = P->GetPrimitives()[0];
167 // Setup prev box data as the primitive index, marked as leaf
168 linear[box_id].mPosData = (PrimitiveIndex<<1)|1;
169 }
170 else
171 {
172 // Get a new id for positive child
173 udword PosID = current_id++;
174 // Setup box data
175 linear[box_id].mPosData = (size_t)&linear[PosID];
176 // Make sure it's not marked as leaf
177 ASSERT(!(linear[box_id].mPosData&1));
178 // Recurse
179 _BuildNoLeafTree(linear, PosID, current_id, P);
180 }
181
182 if(N->IsLeaf())
183 {
184 // The input tree must be complete => i.e. one primitive/leaf
185 ASSERT(N->GetNbPrimitives()==1);
186 // Get the primitive index from the input tree
187 udword PrimitiveIndex = N->GetPrimitives()[0];
188 // Setup prev box data as the primitive index, marked as leaf
189 linear[box_id].mNegData = (PrimitiveIndex<<1)|1;
190 }
191 else
192 {
193 // Get a new id for negative child
194 udword NegID = current_id++;
195 // Setup box data
196 linear[box_id].mNegData = (size_t)&linear[NegID];
197 // Make sure it's not marked as leaf
198 ASSERT(!(linear[box_id].mNegData&1));
199 // Recurse
200 _BuildNoLeafTree(linear, NegID, current_id, N);
201 }
202}
203
204///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
205/**
206 * Constructor.
207 */
208///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
209AABBCollisionTree::AABBCollisionTree() : mNodes(null)
210{
211}
212
213///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
214/**
215 * Destructor.
216 */
217///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
218AABBCollisionTree::~AABBCollisionTree()
219{
220 DELETEARRAY(mNodes);
221}
222
223///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
224/**
225 * Builds the collision tree from a generic AABB tree.
226 * \param tree [in] generic AABB tree
227 * \return true if success
228 */
229///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
230bool AABBCollisionTree::Build(AABBTree* tree)
231{
232 // Checkings
233 if(!tree) return false;
234 // Check the input tree is complete
235 udword NbTriangles = tree->GetNbPrimitives();
236 udword NbNodes = tree->GetNbNodes();
237 if(NbNodes!=NbTriangles*2-1) return false;
238
239 // Get nodes
240 if(mNbNodes!=NbNodes) // Same number of nodes => keep moving
241 {
242 mNbNodes = NbNodes;
243 DELETEARRAY(mNodes);
244 mNodes = new AABBCollisionNode[mNbNodes];
245 CHECKALLOC(mNodes);
246 }
247
248 // Build the tree
249 udword CurID = 1;
250 _BuildCollisionTree(mNodes, 0, CurID, tree);
251 ASSERT(CurID==mNbNodes);
252
253 return true;
254}
255
256///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
257/**
258 * Refits the collision tree after vertices have been modified.
259 * \param mesh_interface [in] mesh interface for current model
260 * \return true if success
261 */
262///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
263bool AABBCollisionTree::Refit(const MeshInterface* mesh_interface)
264{
265 ASSERT(!"Not implemented since AABBCollisionTrees have twice as more nodes to refit as AABBNoLeafTrees!");
266 return false;
267}
268
269///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
270/**
271 * Walks the tree and call the user back for each node.
272 * \param callback [in] walking callback
273 * \param user_data [in] callback's user data
274 * \return true if success
275 */
276///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
277bool AABBCollisionTree::Walk(GenericWalkingCallback callback, void* user_data) const
278{
279 if(!callback) return false;
280
281 struct Local
282 {
283 static void _Walk(const AABBCollisionNode* current_node, GenericWalkingCallback callback, void* user_data)
284 {
285 if(!current_node || !(callback)(current_node, user_data)) return;
286
287 if(!current_node->IsLeaf())
288 {
289 _Walk(current_node->GetPos(), callback, user_data);
290 _Walk(current_node->GetNeg(), callback, user_data);
291 }
292 }
293 };
294 Local::_Walk(mNodes, callback, user_data);
295 return true;
296}
297
298
299///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
300/**
301 * Constructor.
302 */
303///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
304AABBNoLeafTree::AABBNoLeafTree() : mNodes(null)
305{
306}
307
308///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
309/**
310 * Destructor.
311 */
312///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
313AABBNoLeafTree::~AABBNoLeafTree()
314{
315 DELETEARRAY(mNodes);
316}
317
318///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
319/**
320 * Builds the collision tree from a generic AABB tree.
321 * \param tree [in] generic AABB tree
322 * \return true if success
323 */
324///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
325bool AABBNoLeafTree::Build(AABBTree* tree)
326{
327 // Checkings
328 if(!tree) return false;
329 // Check the input tree is complete
330 udword NbTriangles = tree->GetNbPrimitives();
331 udword NbNodes = tree->GetNbNodes();
332 if(NbNodes!=NbTriangles*2-1) return false;
333
334 // Get nodes
335 if(mNbNodes!=NbTriangles-1) // Same number of nodes => keep moving
336 {
337 mNbNodes = NbTriangles-1;
338 DELETEARRAY(mNodes);
339 mNodes = new AABBNoLeafNode[mNbNodes];
340 CHECKALLOC(mNodes);
341 }
342
343 // Build the tree
344 udword CurID = 1;
345 _BuildNoLeafTree(mNodes, 0, CurID, tree);
346 ASSERT(CurID==mNbNodes);
347
348 return true;
349}
350
351inline_ void ComputeMinMax(Point& min, Point& max, const VertexPointers& vp)
352{
353 // Compute triangle's AABB = a leaf box
354#ifdef OPC_USE_FCOMI // a 15% speedup on my machine, not much
355 min.x = FCMin3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x);
356 max.x = FCMax3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x);
357
358 min.y = FCMin3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y);
359 max.y = FCMax3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y);
360
361 min.z = FCMin3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z);
362 max.z = FCMax3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z);
363#else
364 min = *vp.Vertex[0];
365 max = *vp.Vertex[0];
366 min.Min(*vp.Vertex[1]);
367 max.Max(*vp.Vertex[1]);
368 min.Min(*vp.Vertex[2]);
369 max.Max(*vp.Vertex[2]);
370#endif
371}
372
373///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
374/**
375 * Refits the collision tree after vertices have been modified.
376 * \param mesh_interface [in] mesh interface for current model
377 * \return true if success
378 */
379///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
380bool AABBNoLeafTree::Refit(const MeshInterface* mesh_interface)
381{
382 // Checkings
383 if(!mesh_interface) return false;
384
385 // Bottom-up update
386 VertexPointers VP;
387 Point Min,Max;
388 Point Min_,Max_;
389 udword Index = mNbNodes;
390 while(Index--)
391 {
392 AABBNoLeafNode& Current = mNodes[Index];
393
394 if(Current.HasPosLeaf())
395 {
396 mesh_interface->GetTriangle(VP, Current.GetPosPrimitive());
397 ComputeMinMax(Min, Max, VP);
398 }
399 else
400 {
401 const CollisionAABB& CurrentBox = Current.GetPos()->mAABB;
402 CurrentBox.GetMin(Min);
403 CurrentBox.GetMax(Max);
404 }
405
406 if(Current.HasNegLeaf())
407 {
408 mesh_interface->GetTriangle(VP, Current.GetNegPrimitive());
409 ComputeMinMax(Min_, Max_, VP);
410 }
411 else
412 {
413 const CollisionAABB& CurrentBox = Current.GetNeg()->mAABB;
414 CurrentBox.GetMin(Min_);
415 CurrentBox.GetMax(Max_);
416 }
417#ifdef OPC_USE_FCOMI
418 Min.x = FCMin2(Min.x, Min_.x);
419 Max.x = FCMax2(Max.x, Max_.x);
420 Min.y = FCMin2(Min.y, Min_.y);
421 Max.y = FCMax2(Max.y, Max_.y);
422 Min.z = FCMin2(Min.z, Min_.z);
423 Max.z = FCMax2(Max.z, Max_.z);
424#else
425 Min.Min(Min_);
426 Max.Max(Max_);
427#endif
428 Current.mAABB.SetMinMax(Min, Max);
429 }
430 return true;
431}
432
433///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
434/**
435 * Walks the tree and call the user back for each node.
436 * \param callback [in] walking callback
437 * \param user_data [in] callback's user data
438 * \return true if success
439 */
440///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
441bool AABBNoLeafTree::Walk(GenericWalkingCallback callback, void* user_data) const
442{
443 if(!callback) return false;
444
445 struct Local
446 {
447 static void _Walk(const AABBNoLeafNode* current_node, GenericWalkingCallback callback, void* user_data)
448 {
449 if(!current_node || !(callback)(current_node, user_data)) return;
450
451 if(!current_node->HasPosLeaf()) _Walk(current_node->GetPos(), callback, user_data);
452 if(!current_node->HasNegLeaf()) _Walk(current_node->GetNeg(), callback, user_data);
453 }
454 };
455 Local::_Walk(mNodes, callback, user_data);
456 return true;
457}
458
459// Quantization notes:
460// - We could use the highest bits of mData to store some more quantized bits. Dequantization code
461// would be slightly more complex, but number of overlap tests would be reduced (and anyhow those
462// bits are currently wasted). Of course it's not possible if we move to 16 bits mData.
463// - Something like "16 bits floats" could be tested, to bypass the int-to-float conversion.
464// - A dedicated BV-BV test could be used, dequantizing while testing for overlap. (i.e. it's some
465// lazy-dequantization which may save some work in case of early exits). At the very least some
466// muls could be saved by precomputing several more matrices. But maybe not worth the pain.
467// - Do we need to dequantize anyway? Not doing the extents-related muls only implies the box has
468// been scaled, for example.
469// - The deeper we move into the hierarchy, the smaller the extents should be. May not need a fixed
470// number of quantization bits. Even better, could probably be best delta-encoded.
471
472
473// Find max values. Some people asked why I wasn't simply using the first node. Well, I can't.
474// I'm not looking for (min, max) values like in a standard AABB, I'm looking for the extremal
475// centers/extents in order to quantize them. The first node would only give a single center and
476// a single extents. While extents would be the biggest, the center wouldn't.
477#define FIND_MAX_VALUES \
478 /* Get max values */ \
479 Point CMax(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); \
480 Point EMax(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); \
481 for(udword i=0;i<mNbNodes;i++) \
482 { \
483 if(fabsf(Nodes[i].mAABB.mCenter.x)>CMax.x) CMax.x = fabsf(Nodes[i].mAABB.mCenter.x); \
484 if(fabsf(Nodes[i].mAABB.mCenter.y)>CMax.y) CMax.y = fabsf(Nodes[i].mAABB.mCenter.y); \
485 if(fabsf(Nodes[i].mAABB.mCenter.z)>CMax.z) CMax.z = fabsf(Nodes[i].mAABB.mCenter.z); \
486 if(fabsf(Nodes[i].mAABB.mExtents.x)>EMax.x) EMax.x = fabsf(Nodes[i].mAABB.mExtents.x); \
487 if(fabsf(Nodes[i].mAABB.mExtents.y)>EMax.y) EMax.y = fabsf(Nodes[i].mAABB.mExtents.y); \
488 if(fabsf(Nodes[i].mAABB.mExtents.z)>EMax.z) EMax.z = fabsf(Nodes[i].mAABB.mExtents.z); \
489 }
490
491#define INIT_QUANTIZATION \
492 udword nbc=15; /* Keep one bit for sign */ \
493 udword nbe=15; /* Keep one bit for fix */ \
494 if(!gFixQuantized) nbe++; \
495 \
496 /* Compute quantization coeffs */ \
497 Point CQuantCoeff, EQuantCoeff; \
498 CQuantCoeff.x = CMax.x!=0.0f ? float((1<<nbc)-1)/CMax.x : 0.0f; \
499 CQuantCoeff.y = CMax.y!=0.0f ? float((1<<nbc)-1)/CMax.y : 0.0f; \
500 CQuantCoeff.z = CMax.z!=0.0f ? float((1<<nbc)-1)/CMax.z : 0.0f; \
501 EQuantCoeff.x = EMax.x!=0.0f ? float((1<<nbe)-1)/EMax.x : 0.0f; \
502 EQuantCoeff.y = EMax.y!=0.0f ? float((1<<nbe)-1)/EMax.y : 0.0f; \
503 EQuantCoeff.z = EMax.z!=0.0f ? float((1<<nbe)-1)/EMax.z : 0.0f; \
504 /* Compute and save dequantization coeffs */ \
505 mCenterCoeff.x = CQuantCoeff.x!=0.0f ? 1.0f / CQuantCoeff.x : 0.0f; \
506 mCenterCoeff.y = CQuantCoeff.y!=0.0f ? 1.0f / CQuantCoeff.y : 0.0f; \
507 mCenterCoeff.z = CQuantCoeff.z!=0.0f ? 1.0f / CQuantCoeff.z : 0.0f; \
508 mExtentsCoeff.x = EQuantCoeff.x!=0.0f ? 1.0f / EQuantCoeff.x : 0.0f; \
509 mExtentsCoeff.y = EQuantCoeff.y!=0.0f ? 1.0f / EQuantCoeff.y : 0.0f; \
510 mExtentsCoeff.z = EQuantCoeff.z!=0.0f ? 1.0f / EQuantCoeff.z : 0.0f; \
511
512#define PERFORM_QUANTIZATION \
513 /* Quantize */ \
514 mNodes[i].mAABB.mCenter[0] = sword(Nodes[i].mAABB.mCenter.x * CQuantCoeff.x); \
515 mNodes[i].mAABB.mCenter[1] = sword(Nodes[i].mAABB.mCenter.y * CQuantCoeff.y); \
516 mNodes[i].mAABB.mCenter[2] = sword(Nodes[i].mAABB.mCenter.z * CQuantCoeff.z); \
517 mNodes[i].mAABB.mExtents[0] = uword(Nodes[i].mAABB.mExtents.x * EQuantCoeff.x); \
518 mNodes[i].mAABB.mExtents[1] = uword(Nodes[i].mAABB.mExtents.y * EQuantCoeff.y); \
519 mNodes[i].mAABB.mExtents[2] = uword(Nodes[i].mAABB.mExtents.z * EQuantCoeff.z); \
520 /* Fix quantized boxes */ \
521 if(gFixQuantized) \
522 { \
523 /* Make sure the quantized box is still valid */ \
524 Point Max = Nodes[i].mAABB.mCenter + Nodes[i].mAABB.mExtents; \
525 Point Min = Nodes[i].mAABB.mCenter - Nodes[i].mAABB.mExtents; \
526 /* For each axis */ \
527 for(udword j=0;j<3;j++) \
528 { /* Dequantize the box center */ \
529 float qc = float(mNodes[i].mAABB.mCenter[j]) * mCenterCoeff[j]; \
530 bool FixMe=true; \
531 do \
532 { /* Dequantize the box extent */ \
533 float qe = float(mNodes[i].mAABB.mExtents[j]) * mExtentsCoeff[j]; \
534 /* Compare real & dequantized values */ \
535 if(qc+qe<Max[j] || qc-qe>Min[j]) mNodes[i].mAABB.mExtents[j]++; \
536 else FixMe=false; \
537 /* Prevent wrapping */ \
538 if(!mNodes[i].mAABB.mExtents[j]) \
539 { \
540 mNodes[i].mAABB.mExtents[j]=0xffff; \
541 FixMe=false; \
542 } \
543 }while(FixMe); \
544 } \
545 }
546
547#define REMAP_DATA(member) \
548 /* Fix data */ \
549 Data = Nodes[i].member; \
550 if(!(Data&1)) \
551 { \
552 /* Compute box number */ \
553 size_t Nb = (Data - size_t(Nodes))/Nodes[i].GetNodeSize(); \
554 Data = (size_t) &mNodes[Nb]; \
555 } \
556 /* ...remapped */ \
557 mNodes[i].member = Data;
558
559///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
560/**
561 * Constructor.
562 */
563///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
564AABBQuantizedTree::AABBQuantizedTree() : mNodes(null)
565{
566}
567
568///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
569/**
570 * Destructor.
571 */
572///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
573AABBQuantizedTree::~AABBQuantizedTree()
574{
575 DELETEARRAY(mNodes);
576}
577
578///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
579/**
580 * Builds the collision tree from a generic AABB tree.
581 * \param tree [in] generic AABB tree
582 * \return true if success
583 */
584///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
585bool AABBQuantizedTree::Build(AABBTree* tree)
586{
587 // Checkings
588 if(!tree) return false;
589 // Check the input tree is complete
590 udword NbTriangles = tree->GetNbPrimitives();
591 udword NbNodes = tree->GetNbNodes();
592 if(NbNodes!=NbTriangles*2-1) return false;
593
594 // Get nodes
595 mNbNodes = NbNodes;
596 DELETEARRAY(mNodes);
597 AABBCollisionNode* Nodes = new AABBCollisionNode[mNbNodes];
598 CHECKALLOC(Nodes);
599
600 // Build the tree
601 udword CurID = 1;
602 _BuildCollisionTree(Nodes, 0, CurID, tree);
603
604 // Quantize
605 {
606 mNodes = new AABBQuantizedNode[mNbNodes];
607 CHECKALLOC(mNodes);
608
609 // Get max values
610 FIND_MAX_VALUES
611
612 // Quantization
613 INIT_QUANTIZATION
614
615 // Quantize
616 size_t Data;
617 for(udword i=0;i<mNbNodes;i++)
618 {
619 PERFORM_QUANTIZATION
620 REMAP_DATA(mData)
621 }
622
623 DELETEARRAY(Nodes);
624 }
625
626 return true;
627}
628
629///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
630/**
631 * Refits the collision tree after vertices have been modified.
632 * \param mesh_interface [in] mesh interface for current model
633 * \return true if success
634 */
635///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
636bool AABBQuantizedTree::Refit(const MeshInterface* mesh_interface)
637{
638 ASSERT(!"Not implemented since requantizing is painful !");
639 return false;
640}
641
642///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
643/**
644 * Walks the tree and call the user back for each node.
645 * \param callback [in] walking callback
646 * \param user_data [in] callback's user data
647 * \return true if success
648 */
649///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
650bool AABBQuantizedTree::Walk(GenericWalkingCallback callback, void* user_data) const
651{
652 if(!callback) return false;
653
654 struct Local
655 {
656 static void _Walk(const AABBQuantizedNode* current_node, GenericWalkingCallback callback, void* user_data)
657 {
658 if(!current_node || !(callback)(current_node, user_data)) return;
659
660 if(!current_node->IsLeaf())
661 {
662 _Walk(current_node->GetPos(), callback, user_data);
663 _Walk(current_node->GetNeg(), callback, user_data);
664 }
665 }
666 };
667 Local::_Walk(mNodes, callback, user_data);
668 return true;
669}
670
671
672
673///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
674/**
675 * Constructor.
676 */
677///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
678AABBQuantizedNoLeafTree::AABBQuantizedNoLeafTree() : mNodes(null)
679{
680}
681
682///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
683/**
684 * Destructor.
685 */
686///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
687AABBQuantizedNoLeafTree::~AABBQuantizedNoLeafTree()
688{
689 DELETEARRAY(mNodes);
690}
691
692///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
693/**
694 * Builds the collision tree from a generic AABB tree.
695 * \param tree [in] generic AABB tree
696 * \return true if success
697 */
698///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
699bool AABBQuantizedNoLeafTree::Build(AABBTree* tree)
700{
701 // Checkings
702 if(!tree) return false;
703 // Check the input tree is complete
704 udword NbTriangles = tree->GetNbPrimitives();
705 udword NbNodes = tree->GetNbNodes();
706 if(NbNodes!=NbTriangles*2-1) return false;
707
708 // Get nodes
709 mNbNodes = NbTriangles-1;
710 DELETEARRAY(mNodes);
711 AABBNoLeafNode* Nodes = new AABBNoLeafNode[mNbNodes];
712 CHECKALLOC(Nodes);
713
714 // Build the tree
715 udword CurID = 1;
716 _BuildNoLeafTree(Nodes, 0, CurID, tree);
717 ASSERT(CurID==mNbNodes);
718
719 // Quantize
720 {
721 mNodes = new AABBQuantizedNoLeafNode[mNbNodes];
722 CHECKALLOC(mNodes);
723
724 // Get max values
725 FIND_MAX_VALUES
726
727 // Quantization
728 INIT_QUANTIZATION
729
730 // Quantize
731 size_t Data;
732 for(udword i=0;i<mNbNodes;i++)
733 {
734 PERFORM_QUANTIZATION
735 REMAP_DATA(mPosData)
736 REMAP_DATA(mNegData)
737 }
738
739 DELETEARRAY(Nodes);
740 }
741
742 return true;
743}
744
745///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
746/**
747 * Refits the collision tree after vertices have been modified.
748 * \param mesh_interface [in] mesh interface for current model
749 * \return true if success
750 */
751///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
752bool AABBQuantizedNoLeafTree::Refit(const MeshInterface* mesh_interface)
753{
754 ASSERT(!"Not implemented since requantizing is painful !");
755 return false;
756}
757
758///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
759/**
760 * Walks the tree and call the user back for each node.
761 * \param callback [in] walking callback
762 * \param user_data [in] callback's user data
763 * \return true if success
764 */
765///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
766bool AABBQuantizedNoLeafTree::Walk(GenericWalkingCallback callback, void* user_data) const
767{
768 if(!callback) return false;
769
770 struct Local
771 {
772 static void _Walk(const AABBQuantizedNoLeafNode* current_node, GenericWalkingCallback callback, void* user_data)
773 {
774 if(!current_node || !(callback)(current_node, user_data)) return;
775
776 if(!current_node->HasPosLeaf()) _Walk(current_node->GetPos(), callback, user_data);
777 if(!current_node->HasNegLeaf()) _Walk(current_node->GetNeg(), callback, user_data);
778 }
779 };
780 Local::_Walk(mNodes, callback, user_data);
781 return true;
782}
diff --git a/libraries/ode-0.9/OPCODE/OPC_OptimizedTree.h b/libraries/ode-0.9/OPCODE/OPC_OptimizedTree.h
new file mode 100644
index 0000000..36aea07
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_OptimizedTree.h
@@ -0,0 +1,206 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for optimized trees.
12 * \file OPC_OptimizedTree.h
13 * \author Pierre Terdiman
14 * \date March, 20, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_OPTIMIZEDTREE_H__
21#define __OPC_OPTIMIZEDTREE_H__
22
23 //! Common interface for a node of an implicit tree
24 #define IMPLEMENT_IMPLICIT_NODE(base_class, volume) \
25 public: \
26 /* Constructor / Destructor */ \
27 inline_ base_class() : mData(0) {} \
28 inline_ ~base_class() {} \
29 /* Leaf test */ \
30 inline_ BOOL IsLeaf() const { return (mData&1)!=0; } \
31 /* Data access */ \
32 inline_ const base_class* GetPos() const { return (base_class*)mData; } \
33 inline_ const base_class* GetNeg() const { return ((base_class*)mData)+1; } \
34 inline_ size_t GetPrimitive() const { return (mData>>1); } \
35 /* Stats */ \
36 inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \
37 \
38 volume mAABB; \
39 size_t mData;
40
41 //! Common interface for a node of a no-leaf tree
42 #define IMPLEMENT_NOLEAF_NODE(base_class, volume) \
43 public: \
44 /* Constructor / Destructor */ \
45 inline_ base_class() : mPosData(0), mNegData(0) {} \
46 inline_ ~base_class() {} \
47 /* Leaf tests */ \
48 inline_ BOOL HasPosLeaf() const { return (mPosData&1)!=0; } \
49 inline_ BOOL HasNegLeaf() const { return (mNegData&1)!=0; } \
50 /* Data access */ \
51 inline_ const base_class* GetPos() const { return (base_class*)mPosData; } \
52 inline_ const base_class* GetNeg() const { return (base_class*)mNegData; } \
53 inline_ size_t GetPosPrimitive() const { return (mPosData>>1); } \
54 inline_ size_t GetNegPrimitive() const { return (mNegData>>1); } \
55 /* Stats */ \
56 inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \
57 \
58 volume mAABB; \
59 size_t mPosData; \
60 size_t mNegData;
61
62 class OPCODE_API AABBCollisionNode
63 {
64 IMPLEMENT_IMPLICIT_NODE(AABBCollisionNode, CollisionAABB)
65
66 inline_ float GetVolume() const { return mAABB.mExtents.x * mAABB.mExtents.y * mAABB.mExtents.z; }
67 inline_ float GetSize() const { return mAABB.mExtents.SquareMagnitude(); }
68 inline_ udword GetRadius() const
69 {
70 udword* Bits = (udword*)&mAABB.mExtents.x;
71 udword Max = Bits[0];
72 if(Bits[1]>Max) Max = Bits[1];
73 if(Bits[2]>Max) Max = Bits[2];
74 return Max;
75 }
76
77 // NB: using the square-magnitude or the true volume of the box, seems to yield better results
78 // (assuming UNC-like informed traversal methods). I borrowed this idea from PQP. The usual "size"
79 // otherwise, is the largest box extent. In SOLID that extent is computed on-the-fly each time it's
80 // needed (the best approach IMHO). In RAPID the rotation matrix is permuted so that Extent[0] is
81 // always the greatest, which saves looking for it at runtime. On the other hand, it yields matrices
82 // whose determinant is not 1, i.e. you can't encode them anymore as unit quaternions. Not a very
83 // good strategy.
84 };
85
86 class OPCODE_API AABBQuantizedNode
87 {
88 IMPLEMENT_IMPLICIT_NODE(AABBQuantizedNode, QuantizedAABB)
89
90 inline_ uword GetSize() const
91 {
92 const uword* Bits = mAABB.mExtents;
93 uword Max = Bits[0];
94 if(Bits[1]>Max) Max = Bits[1];
95 if(Bits[2]>Max) Max = Bits[2];
96 return Max;
97 }
98 // NB: for quantized nodes I don't feel like computing a square-magnitude with integers all
99 // over the place.......!
100 };
101
102 class OPCODE_API AABBNoLeafNode
103 {
104 IMPLEMENT_NOLEAF_NODE(AABBNoLeafNode, CollisionAABB)
105 };
106
107 class OPCODE_API AABBQuantizedNoLeafNode
108 {
109 IMPLEMENT_NOLEAF_NODE(AABBQuantizedNoLeafNode, QuantizedAABB)
110 };
111
112 //! Common interface for a collision tree
113 #define IMPLEMENT_COLLISION_TREE(base_class, node) \
114 public: \
115 /* Constructor / Destructor */ \
116 base_class(); \
117 virtual ~base_class(); \
118 /* Builds from a standard tree */ \
119 override(AABBOptimizedTree) bool Build(AABBTree* tree); \
120 /* Refits the tree */ \
121 override(AABBOptimizedTree) bool Refit(const MeshInterface* mesh_interface); \
122 /* Walks the tree */ \
123 override(AABBOptimizedTree) bool Walk(GenericWalkingCallback callback, void* user_data) const; \
124 /* Data access */ \
125 inline_ const node* GetNodes() const { return mNodes; } \
126 /* Stats */ \
127 override(AABBOptimizedTree) udword GetUsedBytes() const { return mNbNodes*sizeof(node); } \
128 private: \
129 node* mNodes;
130
131 typedef bool (*GenericWalkingCallback) (const void* current, void* user_data);
132
133 class OPCODE_API AABBOptimizedTree
134 {
135 public:
136 // Constructor / Destructor
137 AABBOptimizedTree() :
138 mNbNodes (0)
139 {}
140 virtual ~AABBOptimizedTree() {}
141
142 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
143 /**
144 * Builds the collision tree from a generic AABB tree.
145 * \param tree [in] generic AABB tree
146 * \return true if success
147 */
148 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
149 virtual bool Build(AABBTree* tree) = 0;
150
151 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
152 /**
153 * Refits the collision tree after vertices have been modified.
154 * \param mesh_interface [in] mesh interface for current model
155 * \return true if success
156 */
157 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
158 virtual bool Refit(const MeshInterface* mesh_interface) = 0;
159
160 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
161 /**
162 * Walks the tree and call the user back for each node.
163 * \param callback [in] walking callback
164 * \param user_data [in] callback's user data
165 * \return true if success
166 */
167 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
168 virtual bool Walk(GenericWalkingCallback callback, void* user_data) const = 0;
169
170 // Data access
171 virtual udword GetUsedBytes() const = 0;
172 inline_ udword GetNbNodes() const { return mNbNodes; }
173
174 protected:
175 udword mNbNodes;
176 };
177
178 class OPCODE_API AABBCollisionTree : public AABBOptimizedTree
179 {
180 IMPLEMENT_COLLISION_TREE(AABBCollisionTree, AABBCollisionNode)
181 };
182
183 class OPCODE_API AABBNoLeafTree : public AABBOptimizedTree
184 {
185 IMPLEMENT_COLLISION_TREE(AABBNoLeafTree, AABBNoLeafNode)
186 };
187
188 class OPCODE_API AABBQuantizedTree : public AABBOptimizedTree
189 {
190 IMPLEMENT_COLLISION_TREE(AABBQuantizedTree, AABBQuantizedNode)
191
192 public:
193 Point mCenterCoeff;
194 Point mExtentsCoeff;
195 };
196
197 class OPCODE_API AABBQuantizedNoLeafTree : public AABBOptimizedTree
198 {
199 IMPLEMENT_COLLISION_TREE(AABBQuantizedNoLeafTree, AABBQuantizedNoLeafNode)
200
201 public:
202 Point mCenterCoeff;
203 Point mExtentsCoeff;
204 };
205
206#endif // __OPC_OPTIMIZEDTREE_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_Picking.cpp b/libraries/ode-0.9/OPCODE/OPC_Picking.cpp
new file mode 100644
index 0000000..3b53774
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_Picking.cpp
@@ -0,0 +1,182 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code to perform "picking".
12 * \file OPC_Picking.cpp
13 * \author Pierre Terdiman
14 * \date March, 20, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Precompiled Header
20#include "Stdafx.h"
21
22using namespace Opcode;
23
24#ifdef OPC_RAYHIT_CALLBACK
25
26/*
27 Possible RayCollider usages:
28 - boolean query (shadow feeler)
29 - closest hit
30 - all hits
31 - number of intersection (boolean)
32
33*/
34
35bool Opcode::SetupAllHits(RayCollider& collider, CollisionFaces& contacts)
36{
37 struct Local
38 {
39 static void AllContacts(const CollisionFace& hit, void* user_data)
40 {
41 CollisionFaces* CF = (CollisionFaces*)user_data;
42 CF->AddFace(hit);
43 }
44 };
45
46 collider.SetFirstContact(false);
47 collider.SetHitCallback(Local::AllContacts);
48 collider.SetUserData(&contacts);
49 return true;
50}
51
52bool Opcode::SetupClosestHit(RayCollider& collider, CollisionFace& closest_contact)
53{
54 struct Local
55 {
56 static void ClosestContact(const CollisionFace& hit, void* user_data)
57 {
58 CollisionFace* CF = (CollisionFace*)user_data;
59 if(hit.mDistance<CF->mDistance) *CF = hit;
60 }
61 };
62
63 collider.SetFirstContact(false);
64 collider.SetHitCallback(Local::ClosestContact);
65 collider.SetUserData(&closest_contact);
66 closest_contact.mDistance = MAX_FLOAT;
67 return true;
68}
69
70bool Opcode::SetupShadowFeeler(RayCollider& collider)
71{
72 collider.SetFirstContact(true);
73 collider.SetHitCallback(null);
74 return true;
75}
76
77bool Opcode::SetupInOutTest(RayCollider& collider)
78{
79 collider.SetFirstContact(false);
80 collider.SetHitCallback(null);
81 // Results with collider.GetNbIntersections()
82 return true;
83}
84
85bool Opcode::Picking(
86CollisionFace& picked_face,
87const Ray& world_ray, const Model& model, const Matrix4x4* world,
88float min_dist, float max_dist, const Point& view_point, CullModeCallback callback, void* user_data)
89{
90 struct Local
91 {
92 struct CullData
93 {
94 CollisionFace* Closest;
95 float MinLimit;
96 CullModeCallback Callback;
97 void* UserData;
98 Point ViewPoint;
99 const MeshInterface* IMesh;
100 };
101
102 // Called for each stabbed face
103 static void RenderCullingCallback(const CollisionFace& hit, void* user_data)
104 {
105 CullData* Data = (CullData*)user_data;
106
107 // Discard face if we already have a closer hit
108 if(hit.mDistance>=Data->Closest->mDistance) return;
109
110 // Discard face if hit point is smaller than min limit. This mainly happens when the face is in front
111 // of the near clip plane (or straddles it). If we keep the face nonetheless, the user can select an
112 // object that he may not even be able to see, which is very annoying.
113 if(hit.mDistance<=Data->MinLimit) return;
114
115 // This is the index of currently stabbed triangle.
116 udword StabbedFaceIndex = hit.mFaceID;
117
118 // We may keep it or not, depending on backface culling
119 bool KeepIt = true;
120
121 // Catch *render* cull mode for this face
122 CullMode CM = (Data->Callback)(StabbedFaceIndex, Data->UserData);
123
124 if(CM!=CULLMODE_NONE) // Don't even compute culling for double-sided triangles
125 {
126 // Compute backface culling for current face
127
128 VertexPointers VP;
129 Data->IMesh->GetTriangle(VP, StabbedFaceIndex);
130 if(VP.BackfaceCulling(Data->ViewPoint))
131 {
132 if(CM==CULLMODE_CW) KeepIt = false;
133 }
134 else
135 {
136 if(CM==CULLMODE_CCW) KeepIt = false;
137 }
138 }
139
140 if(KeepIt) *Data->Closest = hit;
141 }
142 };
143
144 RayCollider RC;
145 RC.SetMaxDist(max_dist);
146 RC.SetTemporalCoherence(false);
147 RC.SetCulling(false); // We need all faces since some of them can be double-sided
148 RC.SetFirstContact(false);
149 RC.SetHitCallback(Local::RenderCullingCallback);
150
151 picked_face.mFaceID = INVALID_ID;
152 picked_face.mDistance = MAX_FLOAT;
153 picked_face.mU = 0.0f;
154 picked_face.mV = 0.0f;
155
156 Local::CullData Data;
157 Data.Closest = &picked_face;
158 Data.MinLimit = min_dist;
159 Data.Callback = callback;
160 Data.UserData = user_data;
161 Data.ViewPoint = view_point;
162 Data.IMesh = model.GetMeshInterface();
163
164 if(world)
165 {
166 // Get matrices
167 Matrix4x4 InvWorld;
168 InvertPRMatrix(InvWorld, *world);
169
170 // Compute camera position in mesh space
171 Data.ViewPoint *= InvWorld;
172 }
173
174 RC.SetUserData(&Data);
175 if(RC.Collide(world_ray, model, world))
176 {
177 return picked_face.mFaceID!=INVALID_ID;
178 }
179 return false;
180}
181
182#endif
diff --git a/libraries/ode-0.9/OPCODE/OPC_Picking.h b/libraries/ode-0.9/OPCODE/OPC_Picking.h
new file mode 100644
index 0000000..d22fa38
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_Picking.h
@@ -0,0 +1,45 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code to perform "picking".
12 * \file OPC_Picking.h
13 * \author Pierre Terdiman
14 * \date March, 20, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_PICKING_H__
21#define __OPC_PICKING_H__
22
23#ifdef OPC_RAYHIT_CALLBACK
24
25 enum CullMode
26 {
27 CULLMODE_NONE = 0,
28 CULLMODE_CW = 1,
29 CULLMODE_CCW = 2
30 };
31
32 typedef CullMode (*CullModeCallback)(udword triangle_index, void* user_data);
33
34 OPCODE_API bool SetupAllHits (RayCollider& collider, CollisionFaces& contacts);
35 OPCODE_API bool SetupClosestHit (RayCollider& collider, CollisionFace& closest_contact);
36 OPCODE_API bool SetupShadowFeeler (RayCollider& collider);
37 OPCODE_API bool SetupInOutTest (RayCollider& collider);
38
39 OPCODE_API bool Picking(
40 CollisionFace& picked_face,
41 const Ray& world_ray, const Model& model, const Matrix4x4* world,
42 float min_dist, float max_dist, const Point& view_point, CullModeCallback callback, void* user_data);
43#endif
44
45#endif //__OPC_PICKING_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_PlanesAABBOverlap.h b/libraries/ode-0.9/OPCODE/OPC_PlanesAABBOverlap.h
new file mode 100644
index 0000000..5d7576e
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_PlanesAABBOverlap.h
@@ -0,0 +1,50 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Planes-AABB overlap test.
4 * - original code by Ville Miettinen, from Umbra/dPVS (released on the GD-Algorithms mailing list)
5 * - almost used "as-is", I even left the comments (hence the frustum-related notes)
6 *
7 * \param center [in] box center
8 * \param extents [in] box extents
9 * \param out_clip_mask [out] bitmask for active planes
10 * \param in_clip_mask [in] bitmask for active planes
11 * \return TRUE if boxes overlap planes
12 */
13///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
14inline_ BOOL PlanesCollider::PlanesAABBOverlap(const Point& center, const Point& extents, udword& out_clip_mask, udword in_clip_mask)
15{
16 // Stats
17 mNbVolumeBVTests++;
18
19 const Plane* p = mPlanes;
20
21 // Evaluate through all active frustum planes. We determine the relation
22 // between the AABB and a plane by using the concept of "near" and "far"
23 // vertices originally described by Zhang (and later by Möller). Our
24 // variant here uses 3 fabs ops, 6 muls, 7 adds and two floating point
25 // comparisons per plane. The routine early-exits if the AABB is found
26 // to be outside any of the planes. The loop also constructs a new output
27 // clip mask. Most FPUs have a native single-cycle fabsf() operation.
28
29 udword Mask = 1; // current mask index (1,2,4,8,..)
30 udword TmpOutClipMask = 0; // initialize output clip mask into empty.
31
32 while(Mask<=in_clip_mask) // keep looping while we have active planes left...
33 {
34 if(in_clip_mask & Mask) // if clip plane is active, process it..
35 {
36 float NP = extents.x*fabsf(p->n.x) + extents.y*fabsf(p->n.y) + extents.z*fabsf(p->n.z); // ### fabsf could be precomputed
37 float MP = center.x*p->n.x + center.y*p->n.y + center.z*p->n.z + p->d;
38
39 if(NP < MP) // near vertex behind the clip plane...
40 return FALSE; // .. so there is no intersection..
41 if((-NP) < MP) // near and far vertices on different sides of plane..
42 TmpOutClipMask |= Mask; // .. so update the clip mask...
43 }
44 Mask+=Mask; // mk = (1<<plane)
45 p++; // advance to next plane
46 }
47
48 out_clip_mask = TmpOutClipMask; // copy output value (temp used to resolve aliasing!)
49 return TRUE; // indicate that AABB intersects frustum
50}
diff --git a/libraries/ode-0.9/OPCODE/OPC_PlanesCollider.cpp b/libraries/ode-0.9/OPCODE/OPC_PlanesCollider.cpp
new file mode 100644
index 0000000..60d7f9c
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_PlanesCollider.cpp
@@ -0,0 +1,653 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for a planes collider.
12 * \file OPC_PlanesCollider.cpp
13 * \author Pierre Terdiman
14 * \date January, 1st, 2002
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19/**
20 * Contains a Planes-vs-tree collider.
21 *
22 * \class PlanesCollider
23 * \author Pierre Terdiman
24 * \version 1.3
25 * \date January, 1st, 2002
26*/
27///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
28
29///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
30// Precompiled Header
31#include "Stdafx.h"
32
33using namespace Opcode;
34
35#include "OPC_PlanesAABBOverlap.h"
36#include "OPC_PlanesTriOverlap.h"
37
38#define SET_CONTACT(prim_index, flag) \
39 /* Set contact status */ \
40 mFlags |= flag; \
41 mTouchedPrimitives->Add(udword(prim_index));
42
43//! Planes-triangle test
44#define PLANES_PRIM(prim_index, flag) \
45 /* Request vertices from the app */ \
46 mIMesh->GetTriangle(mVP, prim_index); \
47 /* Perform triangle-box overlap test */ \
48 if(PlanesTriOverlap(clip_mask)) \
49 { \
50 SET_CONTACT(prim_index, flag) \
51 }
52
53///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
54/**
55 * Constructor.
56 */
57///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
58PlanesCollider::PlanesCollider() :
59 mPlanes (null),
60 mNbPlanes (0)
61{
62}
63
64///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
65/**
66 * Destructor.
67 */
68///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
69PlanesCollider::~PlanesCollider()
70{
71 DELETEARRAY(mPlanes);
72}
73
74///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
75/**
76 * Validates current settings. You should call this method after all the settings and callbacks have been defined.
77 * \return null if everything is ok, else a string describing the problem
78 */
79///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
80const char* PlanesCollider::ValidateSettings()
81{
82 if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!";
83
84 return VolumeCollider::ValidateSettings();
85}
86
87///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
88/**
89 * Generic collision query for generic OPCODE models. After the call, access the results:
90 * - with GetContactStatus()
91 * - with GetNbTouchedPrimitives()
92 * - with GetTouchedPrimitives()
93 *
94 * \param cache [in/out] a planes cache
95 * \param planes [in] list of planes in world space
96 * \param nb_planes [in] number of planes
97 * \param model [in] Opcode model to collide with
98 * \param worldm [in] model's world matrix, or null
99 * \return true if success
100 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
101 */
102///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
103bool PlanesCollider::Collide(PlanesCache& cache, const Plane* planes, udword nb_planes, const Model& model, const Matrix4x4* worldm)
104{
105 // Checkings
106 if(!Setup(&model)) return false;
107
108 // Init collision query
109 if(InitQuery(cache, planes, nb_planes, worldm)) return true;
110
111 udword PlaneMask = (1<<nb_planes)-1;
112
113 if(!model.HasLeafNodes())
114 {
115 if(model.IsQuantized())
116 {
117 const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
118
119 // Setup dequantization coeffs
120 mCenterCoeff = Tree->mCenterCoeff;
121 mExtentsCoeff = Tree->mExtentsCoeff;
122
123 // Perform collision query
124 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
125 else _Collide(Tree->GetNodes(), PlaneMask);
126 }
127 else
128 {
129 const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
130
131 // Perform collision query
132 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
133 else _Collide(Tree->GetNodes(), PlaneMask);
134 }
135 }
136 else
137 {
138 if(model.IsQuantized())
139 {
140 const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
141
142 // Setup dequantization coeffs
143 mCenterCoeff = Tree->mCenterCoeff;
144 mExtentsCoeff = Tree->mExtentsCoeff;
145
146 // Perform collision query
147 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
148 else _Collide(Tree->GetNodes(), PlaneMask);
149 }
150 else
151 {
152 const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
153
154 // Perform collision query
155 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
156 else _Collide(Tree->GetNodes(), PlaneMask);
157 }
158 }
159 return true;
160}
161
162///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
163/**
164 * Initializes a collision query :
165 * - reset stats & contact status
166 * - compute planes in model space
167 * - check temporal coherence
168 *
169 * \param cache [in/out] a planes cache
170 * \param planes [in] list of planes
171 * \param nb_planes [in] number of planes
172 * \param worldm [in] model's world matrix, or null
173 * \return TRUE if we can return immediately
174 * \warning SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only.
175 */
176///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
177BOOL PlanesCollider::InitQuery(PlanesCache& cache, const Plane* planes, udword nb_planes, const Matrix4x4* worldm)
178{
179 // 1) Call the base method
180 VolumeCollider::InitQuery();
181
182 // 2) Compute planes in model space
183 if(nb_planes>mNbPlanes)
184 {
185 DELETEARRAY(mPlanes);
186 mPlanes = new Plane[nb_planes];
187 }
188 mNbPlanes = nb_planes;
189
190 if(worldm)
191 {
192 Matrix4x4 InvWorldM;
193 InvertPRMatrix(InvWorldM, *worldm);
194
195// for(udword i=0;i<nb_planes;i++) mPlanes[i] = planes[i] * InvWorldM;
196 for(udword i=0;i<nb_planes;i++) TransformPlane(mPlanes[i], planes[i], InvWorldM);
197 }
198 else CopyMemory(mPlanes, planes, nb_planes*sizeof(Plane));
199
200 // 3) Setup destination pointer
201 mTouchedPrimitives = &cache.TouchedPrimitives;
202
203 // 4) Special case: 1-triangle meshes [Opcode 1.3]
204 if(mCurrentModel && mCurrentModel->HasSingleNode())
205 {
206 if(!SkipPrimitiveTests())
207 {
208 // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0.
209 mTouchedPrimitives->Reset();
210
211 // Perform overlap test between the unique triangle and the planes (and set contact status if needed)
212 udword clip_mask = (1<<mNbPlanes)-1;
213 PLANES_PRIM(udword(0), OPC_CONTACT)
214
215 // Return immediately regardless of status
216 return TRUE;
217 }
218 }
219
220 // 4) Check temporal coherence:
221 if(TemporalCoherenceEnabled())
222 {
223 // Here we use temporal coherence
224 // => check results from previous frame before performing the collision query
225 if(FirstContactEnabled())
226 {
227 // We're only interested in the first contact found => test the unique previously touched face
228 if(mTouchedPrimitives->GetNbEntries())
229 {
230 // Get index of previously touched face = the first entry in the array
231 udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0);
232
233 // Then reset the array:
234 // - if the overlap test below is successful, the index we'll get added back anyway
235 // - if it isn't, then the array should be reset anyway for the normal query
236 mTouchedPrimitives->Reset();
237
238 // Perform overlap test between the cached triangle and the planes (and set contact status if needed)
239 udword clip_mask = (1<<mNbPlanes)-1;
240 PLANES_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT)
241
242 // Return immediately if possible
243 if(GetContactStatus()) return TRUE;
244 }
245 // else no face has been touched during previous query
246 // => we'll have to perform a normal query
247 }
248 else mTouchedPrimitives->Reset();
249 }
250 else
251 {
252 // Here we don't use temporal coherence => do a normal query
253 mTouchedPrimitives->Reset();
254 }
255
256 return FALSE;
257}
258
259#define TEST_CLIP_MASK \
260 /* If the box is completely included, so are its children. We don't need to do extra tests, we */ \
261 /* can immediately output a list of visible children. Those ones won't need to be clipped. */ \
262 if(!OutClipMask) \
263 { \
264 /* Set contact status */ \
265 mFlags |= OPC_CONTACT; \
266 _Dump(node); \
267 return; \
268 }
269
270///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
271/**
272 * Recursive collision query for normal AABB trees.
273 * \param node [in] current collision node
274 */
275///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
276void PlanesCollider::_Collide(const AABBCollisionNode* node, udword clip_mask)
277{
278 // Test the box against the planes. If the box is completely culled, so are its children, hence we exit.
279 udword OutClipMask;
280 if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return;
281
282 TEST_CLIP_MASK
283
284 // Else the box straddles one or several planes, so we need to recurse down the tree.
285 if(node->IsLeaf())
286 {
287 PLANES_PRIM(node->GetPrimitive(), OPC_CONTACT)
288 }
289 else
290 {
291 _Collide(node->GetPos(), OutClipMask);
292
293 if(ContactFound()) return;
294
295 _Collide(node->GetNeg(), OutClipMask);
296 }
297}
298
299///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
300/**
301 * Recursive collision query for normal AABB trees.
302 * \param node [in] current collision node
303 */
304///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
305void PlanesCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node, udword clip_mask)
306{
307 // Test the box against the planes. If the box is completely culled, so are its children, hence we exit.
308 udword OutClipMask;
309 if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return;
310
311 TEST_CLIP_MASK
312
313 // Else the box straddles one or several planes, so we need to recurse down the tree.
314 if(node->IsLeaf())
315 {
316 SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
317 }
318 else
319 {
320 _CollideNoPrimitiveTest(node->GetPos(), OutClipMask);
321
322 if(ContactFound()) return;
323
324 _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask);
325 }
326}
327
328///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
329/**
330 * Recursive collision query for quantized AABB trees.
331 * \param node [in] current collision node
332 */
333///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
334void PlanesCollider::_Collide(const AABBQuantizedNode* node, udword clip_mask)
335{
336 // Dequantize box
337 const QuantizedAABB& Box = node->mAABB;
338 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
339 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
340
341 // Test the box against the planes. If the box is completely culled, so are its children, hence we exit.
342 udword OutClipMask;
343 if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return;
344
345 TEST_CLIP_MASK
346
347 // Else the box straddles one or several planes, so we need to recurse down the tree.
348 if(node->IsLeaf())
349 {
350 PLANES_PRIM(node->GetPrimitive(), OPC_CONTACT)
351 }
352 else
353 {
354 _Collide(node->GetPos(), OutClipMask);
355
356 if(ContactFound()) return;
357
358 _Collide(node->GetNeg(), OutClipMask);
359 }
360}
361
362///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
363/**
364 * Recursive collision query for quantized AABB trees.
365 * \param node [in] current collision node
366 */
367///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
368void PlanesCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node, udword clip_mask)
369{
370 // Dequantize box
371 const QuantizedAABB& Box = node->mAABB;
372 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
373 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
374
375 // Test the box against the planes. If the box is completely culled, so are its children, hence we exit.
376 udword OutClipMask;
377 if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return;
378
379 TEST_CLIP_MASK
380
381 // Else the box straddles one or several planes, so we need to recurse down the tree.
382 if(node->IsLeaf())
383 {
384 SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
385 }
386 else
387 {
388 _CollideNoPrimitiveTest(node->GetPos(), OutClipMask);
389
390 if(ContactFound()) return;
391
392 _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask);
393 }
394}
395
396///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
397/**
398 * Recursive collision query for no-leaf AABB trees.
399 * \param node [in] current collision node
400 */
401///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
402void PlanesCollider::_Collide(const AABBNoLeafNode* node, udword clip_mask)
403{
404 // Test the box against the planes. If the box is completely culled, so are its children, hence we exit.
405 udword OutClipMask;
406 if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return;
407
408 TEST_CLIP_MASK
409
410 // Else the box straddles one or several planes, so we need to recurse down the tree.
411 if(node->HasPosLeaf()) { PLANES_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
412 else _Collide(node->GetPos(), OutClipMask);
413
414 if(ContactFound()) return;
415
416 if(node->HasNegLeaf()) { PLANES_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
417 else _Collide(node->GetNeg(), OutClipMask);
418}
419
420///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
421/**
422 * Recursive collision query for no-leaf AABB trees.
423 * \param node [in] current collision node
424 */
425///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
426void PlanesCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node, udword clip_mask)
427{
428 // Test the box against the planes. If the box is completely culled, so are its children, hence we exit.
429 udword OutClipMask;
430 if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return;
431
432 TEST_CLIP_MASK
433
434 // Else the box straddles one or several planes, so we need to recurse down the tree.
435 if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
436 else _CollideNoPrimitiveTest(node->GetPos(), OutClipMask);
437
438 if(ContactFound()) return;
439
440 if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
441 else _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask);
442}
443
444///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
445/**
446 * Recursive collision query for quantized no-leaf AABB trees.
447 * \param node [in] current collision node
448 */
449///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
450void PlanesCollider::_Collide(const AABBQuantizedNoLeafNode* node, udword clip_mask)
451{
452 // Dequantize box
453 const QuantizedAABB& Box = node->mAABB;
454 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
455 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
456
457 // Test the box against the planes. If the box is completely culled, so are its children, hence we exit.
458 udword OutClipMask;
459 if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return;
460
461 TEST_CLIP_MASK
462
463 // Else the box straddles one or several planes, so we need to recurse down the tree.
464 if(node->HasPosLeaf()) { PLANES_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
465 else _Collide(node->GetPos(), OutClipMask);
466
467 if(ContactFound()) return;
468
469 if(node->HasNegLeaf()) { PLANES_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
470 else _Collide(node->GetNeg(), OutClipMask);
471}
472
473///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
474/**
475 * Recursive collision query for quantized no-leaf AABB trees.
476 * \param node [in] current collision node
477 */
478///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
479void PlanesCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node, udword clip_mask)
480{
481 // Dequantize box
482 const QuantizedAABB& Box = node->mAABB;
483 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
484 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
485
486 // Test the box against the planes. If the box is completely culled, so are its children, hence we exit.
487 udword OutClipMask;
488 if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return;
489
490 TEST_CLIP_MASK
491
492 // Else the box straddles one or several planes, so we need to recurse down the tree.
493 if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
494 else _CollideNoPrimitiveTest(node->GetPos(), OutClipMask);
495
496 if(ContactFound()) return;
497
498 if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
499 else _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask);
500}
501
502
503
504
505
506
507
508///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
509/**
510 * Constructor.
511 */
512///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
513HybridPlanesCollider::HybridPlanesCollider()
514{
515}
516
517///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
518/**
519 * Destructor.
520 */
521///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
522HybridPlanesCollider::~HybridPlanesCollider()
523{
524}
525
526bool HybridPlanesCollider::Collide(PlanesCache& cache, const Plane* planes, udword nb_planes, const HybridModel& model, const Matrix4x4* worldm)
527{
528 // We don't want primitive tests here!
529 mFlags |= OPC_NO_PRIMITIVE_TESTS;
530
531 // Checkings
532 if(!Setup(&model)) return false;
533
534 // Init collision query
535 if(InitQuery(cache, planes, nb_planes, worldm)) return true;
536
537 // Special case for 1-leaf trees
538 if(mCurrentModel && mCurrentModel->HasSingleNode())
539 {
540 // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles
541 udword Nb = mIMesh->GetNbTriangles();
542
543 // Loop through all triangles
544 udword clip_mask = (1<<mNbPlanes)-1;
545 for(udword i=0;i<Nb;i++)
546 {
547 PLANES_PRIM(i, OPC_CONTACT)
548 }
549 return true;
550 }
551
552 // Override destination array since we're only going to get leaf boxes here
553 mTouchedBoxes.Reset();
554 mTouchedPrimitives = &mTouchedBoxes;
555
556 udword PlaneMask = (1<<nb_planes)-1;
557
558 // Now, do the actual query against leaf boxes
559 if(!model.HasLeafNodes())
560 {
561 if(model.IsQuantized())
562 {
563 const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
564
565 // Setup dequantization coeffs
566 mCenterCoeff = Tree->mCenterCoeff;
567 mExtentsCoeff = Tree->mExtentsCoeff;
568
569 // Perform collision query - we don't want primitive tests here!
570 _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
571 }
572 else
573 {
574 const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
575
576 // Perform collision query - we don't want primitive tests here!
577 _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
578 }
579 }
580 else
581 {
582 if(model.IsQuantized())
583 {
584 const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
585
586 // Setup dequantization coeffs
587 mCenterCoeff = Tree->mCenterCoeff;
588 mExtentsCoeff = Tree->mExtentsCoeff;
589
590 // Perform collision query - we don't want primitive tests here!
591 _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
592 }
593 else
594 {
595 const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
596
597 // Perform collision query - we don't want primitive tests here!
598 _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
599 }
600 }
601
602 // We only have a list of boxes so far
603 if(GetContactStatus())
604 {
605 // Reset contact status, since it currently only reflects collisions with leaf boxes
606 Collider::InitQuery();
607
608 // Change dest container so that we can use built-in overlap tests and get collided primitives
609 cache.TouchedPrimitives.Reset();
610 mTouchedPrimitives = &cache.TouchedPrimitives;
611
612 // Read touched leaf boxes
613 udword Nb = mTouchedBoxes.GetNbEntries();
614 const udword* Touched = mTouchedBoxes.GetEntries();
615
616 const LeafTriangles* LT = model.GetLeafTriangles();
617 const udword* Indices = model.GetIndices();
618
619 // Loop through touched leaves
620 udword clip_mask = (1<<mNbPlanes)-1;
621 while(Nb--)
622 {
623 const LeafTriangles& CurrentLeaf = LT[*Touched++];
624
625 // Each leaf box has a set of triangles
626 udword NbTris = CurrentLeaf.GetNbTriangles();
627 if(Indices)
628 {
629 const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()];
630
631 // Loop through triangles and test each of them
632 while(NbTris--)
633 {
634 udword TriangleIndex = *T++;
635 PLANES_PRIM(TriangleIndex, OPC_CONTACT)
636 }
637 }
638 else
639 {
640 udword BaseIndex = CurrentLeaf.GetTriangleIndex();
641
642 // Loop through triangles and test each of them
643 while(NbTris--)
644 {
645 udword TriangleIndex = BaseIndex++;
646 PLANES_PRIM(TriangleIndex, OPC_CONTACT)
647 }
648 }
649 }
650 }
651
652 return true;
653}
diff --git a/libraries/ode-0.9/OPCODE/OPC_PlanesCollider.h b/libraries/ode-0.9/OPCODE/OPC_PlanesCollider.h
new file mode 100644
index 0000000..35de28a
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_PlanesCollider.h
@@ -0,0 +1,121 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for a planes collider.
12 * \file OPC_PlanesCollider.h
13 * \author Pierre Terdiman
14 * \date January, 1st, 2002
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_PLANESCOLLIDER_H__
21#define __OPC_PLANESCOLLIDER_H__
22
23 struct OPCODE_API PlanesCache : VolumeCache
24 {
25 PlanesCache()
26 {
27 }
28 };
29
30 class OPCODE_API PlanesCollider : public VolumeCollider
31 {
32 public:
33 // Constructor / Destructor
34 PlanesCollider();
35 virtual ~PlanesCollider();
36
37 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
38 /**
39 * Generic collision query for generic OPCODE models. After the call, access the results:
40 * - with GetContactStatus()
41 * - with GetNbTouchedPrimitives()
42 * - with GetTouchedPrimitives()
43 *
44 * \param cache [in/out] a planes cache
45 * \param planes [in] list of planes in world space
46 * \param nb_planes [in] number of planes
47 * \param model [in] Opcode model to collide with
48 * \param worldm [in] model's world matrix, or null
49 * \return true if success
50 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
51 */
52 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
53 bool Collide(PlanesCache& cache, const Plane* planes, udword nb_planes, const Model& model, const Matrix4x4* worldm=null);
54
55 // Mutant box-with-planes collision queries
56 inline_ bool Collide(PlanesCache& cache, const OBB& box, const Model& model, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null)
57 {
58 Plane PL[6];
59
60 if(worldb)
61 {
62 // Create a new OBB in world space
63 OBB WorldBox;
64 box.Rotate(*worldb, WorldBox);
65 // Compute planes from the sides of the box
66 WorldBox.ComputePlanes(PL);
67 }
68 else
69 {
70 // Compute planes from the sides of the box
71 box.ComputePlanes(PL);
72 }
73
74 // Collide with box planes
75 return Collide(cache, PL, 6, model, worldm);
76 }
77 // Settings
78
79 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
80 /**
81 * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider.
82 * \return null if everything is ok, else a string describing the problem
83 */
84 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
85 override(Collider) const char* ValidateSettings();
86
87 protected:
88 // Planes in model space
89 udword mNbPlanes;
90 Plane* mPlanes;
91 // Leaf description
92 VertexPointers mVP;
93 // Internal methods
94 void _Collide(const AABBCollisionNode* node, udword clip_mask);
95 void _Collide(const AABBNoLeafNode* node, udword clip_mask);
96 void _Collide(const AABBQuantizedNode* node, udword clip_mask);
97 void _Collide(const AABBQuantizedNoLeafNode* node, udword clip_mask);
98 void _CollideNoPrimitiveTest(const AABBCollisionNode* node, udword clip_mask);
99 void _CollideNoPrimitiveTest(const AABBNoLeafNode* node, udword clip_mask);
100 void _CollideNoPrimitiveTest(const AABBQuantizedNode* node, udword clip_mask);
101 void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node, udword clip_mask);
102 // Overlap tests
103 inline_ BOOL PlanesAABBOverlap(const Point& center, const Point& extents, udword& out_clip_mask, udword in_clip_mask);
104 inline_ BOOL PlanesTriOverlap(udword in_clip_mask);
105 // Init methods
106 BOOL InitQuery(PlanesCache& cache, const Plane* planes, udword nb_planes, const Matrix4x4* worldm=null);
107 };
108
109 class OPCODE_API HybridPlanesCollider : public PlanesCollider
110 {
111 public:
112 // Constructor / Destructor
113 HybridPlanesCollider();
114 virtual ~HybridPlanesCollider();
115
116 bool Collide(PlanesCache& cache, const Plane* planes, udword nb_planes, const HybridModel& model, const Matrix4x4* worldm=null);
117 protected:
118 Container mTouchedBoxes;
119 };
120
121#endif // __OPC_PLANESCOLLIDER_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_PlanesTriOverlap.h b/libraries/ode-0.9/OPCODE/OPC_PlanesTriOverlap.h
new file mode 100644
index 0000000..3f9b39f
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_PlanesTriOverlap.h
@@ -0,0 +1,40 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Planes-triangle overlap test.
4 * \param in_clip_mask [in] bitmask for active planes
5 * \return TRUE if triangle overlap planes
6 * \warning THIS IS A CONSERVATIVE TEST !! Some triangles will be returned as intersecting, while they're not!
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9inline_ BOOL PlanesCollider::PlanesTriOverlap(udword in_clip_mask)
10{
11 // Stats
12 mNbVolumePrimTests++;
13
14 const Plane* p = mPlanes;
15 udword Mask = 1;
16
17 while(Mask<=in_clip_mask)
18 {
19 if(in_clip_mask & Mask)
20 {
21 float d0 = p->Distance(*mVP.Vertex[0]);
22 float d1 = p->Distance(*mVP.Vertex[1]);
23 float d2 = p->Distance(*mVP.Vertex[2]);
24 if(d0>0.0f && d1>0.0f && d2>0.0f) return FALSE;
25// if(!(IR(d0)&SIGN_BITMASK) && !(IR(d1)&SIGN_BITMASK) && !(IR(d2)&SIGN_BITMASK)) return FALSE;
26 }
27 Mask+=Mask;
28 p++;
29 }
30/*
31 for(udword i=0;i<6;i++)
32 {
33 float d0 = p[i].Distance(mLeafVerts[0]);
34 float d1 = p[i].Distance(mLeafVerts[1]);
35 float d2 = p[i].Distance(mLeafVerts[2]);
36 if(d0>0.0f && d1>0.0f && d2>0.0f) return false;
37 }
38*/
39 return TRUE;
40}
diff --git a/libraries/ode-0.9/OPCODE/OPC_RayAABBOverlap.h b/libraries/ode-0.9/OPCODE/OPC_RayAABBOverlap.h
new file mode 100644
index 0000000..a8162bf
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_RayAABBOverlap.h
@@ -0,0 +1,63 @@
1// Opcode 1.1: ray-AABB overlap tests based on Woo's code
2// Opcode 1.2: ray-AABB overlap tests based on the separating axis theorem
3//
4// The point of intersection is not computed anymore. The distance to impact is not needed anymore
5// since we now have two different queries for segments or rays.
6
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8/**
9 * Computes a segment-AABB overlap test using the separating axis theorem. Segment is cached within the class.
10 * \param center [in] AABB center
11 * \param extents [in] AABB extents
12 * \return true on overlap
13 */
14///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
15inline_ BOOL RayCollider::SegmentAABBOverlap(const Point& center, const Point& extents)
16{
17 // Stats
18 mNbRayBVTests++;
19
20 float Dx = mData2.x - center.x; if(fabsf(Dx) > extents.x + mFDir.x) return FALSE;
21 float Dy = mData2.y - center.y; if(fabsf(Dy) > extents.y + mFDir.y) return FALSE;
22 float Dz = mData2.z - center.z; if(fabsf(Dz) > extents.z + mFDir.z) return FALSE;
23
24 float f;
25 f = mData.y * Dz - mData.z * Dy; if(fabsf(f) > extents.y*mFDir.z + extents.z*mFDir.y) return FALSE;
26 f = mData.z * Dx - mData.x * Dz; if(fabsf(f) > extents.x*mFDir.z + extents.z*mFDir.x) return FALSE;
27 f = mData.x * Dy - mData.y * Dx; if(fabsf(f) > extents.x*mFDir.y + extents.y*mFDir.x) return FALSE;
28
29 return TRUE;
30}
31
32///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
33/**
34 * Computes a ray-AABB overlap test using the separating axis theorem. Ray is cached within the class.
35 * \param center [in] AABB center
36 * \param extents [in] AABB extents
37 * \return true on overlap
38 */
39///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
40inline_ BOOL RayCollider::RayAABBOverlap(const Point& center, const Point& extents)
41{
42 // Stats
43 mNbRayBVTests++;
44
45// float Dx = mOrigin.x - center.x; if(fabsf(Dx) > extents.x && Dx*mDir.x>=0.0f) return FALSE;
46// float Dy = mOrigin.y - center.y; if(fabsf(Dy) > extents.y && Dy*mDir.y>=0.0f) return FALSE;
47// float Dz = mOrigin.z - center.z; if(fabsf(Dz) > extents.z && Dz*mDir.z>=0.0f) return FALSE;
48
49 float Dx = mOrigin.x - center.x; if(GREATER(Dx, extents.x) && Dx*mDir.x>=0.0f) return FALSE;
50 float Dy = mOrigin.y - center.y; if(GREATER(Dy, extents.y) && Dy*mDir.y>=0.0f) return FALSE;
51 float Dz = mOrigin.z - center.z; if(GREATER(Dz, extents.z) && Dz*mDir.z>=0.0f) return FALSE;
52
53// float Dx = mOrigin.x - center.x; if(GREATER(Dx, extents.x) && ((SIR(Dx)-1)^SIR(mDir.x))>=0.0f) return FALSE;
54// float Dy = mOrigin.y - center.y; if(GREATER(Dy, extents.y) && ((SIR(Dy)-1)^SIR(mDir.y))>=0.0f) return FALSE;
55// float Dz = mOrigin.z - center.z; if(GREATER(Dz, extents.z) && ((SIR(Dz)-1)^SIR(mDir.z))>=0.0f) return FALSE;
56
57 float f;
58 f = mDir.y * Dz - mDir.z * Dy; if(fabsf(f) > extents.y*mFDir.z + extents.z*mFDir.y) return FALSE;
59 f = mDir.z * Dx - mDir.x * Dz; if(fabsf(f) > extents.x*mFDir.z + extents.z*mFDir.x) return FALSE;
60 f = mDir.x * Dy - mDir.y * Dx; if(fabsf(f) > extents.x*mFDir.y + extents.y*mFDir.x) return FALSE;
61
62 return TRUE;
63}
diff --git a/libraries/ode-0.9/OPCODE/OPC_RayCollider.cpp b/libraries/ode-0.9/OPCODE/OPC_RayCollider.cpp
new file mode 100644
index 0000000..5828ce4
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_RayCollider.cpp
@@ -0,0 +1,762 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for a ray collider.
12 * \file OPC_RayCollider.cpp
13 * \author Pierre Terdiman
14 * \date June, 2, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19/**
20 * Contains a ray-vs-tree collider.
21 * This class performs a stabbing query on an AABB tree, i.e. does a ray-mesh collision.
22 *
23 * HIGHER DISTANCE BOUND:
24 *
25 * If P0 and P1 are two 3D points, let's define:
26 * - d = distance between P0 and P1
27 * - Origin = P0
28 * - Direction = (P1 - P0) / d = normalized direction vector
29 * - A parameter t such as a point P on the line (P0,P1) is P = Origin + t * Direction
30 * - t = 0 --> P = P0
31 * - t = d --> P = P1
32 *
33 * Then we can define a general "ray" as:
34 *
35 * struct Ray
36 * {
37 * Point Origin;
38 * Point Direction;
39 * };
40 *
41 * But it actually maps three different things:
42 * - a segment, when 0 <= t <= d
43 * - a half-line, when 0 <= t < +infinity, or -infinity < t <= d
44 * - a line, when -infinity < t < +infinity
45 *
46 * In Opcode, we support segment queries, which yield half-line queries by setting d = +infinity.
47 * We don't support line-queries. If you need them, shift the origin along the ray by an appropriate margin.
48 *
49 * In short, the lower bound is always 0, and you can setup the higher bound "d" with RayCollider::SetMaxDist().
50 *
51 * Query |segment |half-line |line
52 * --------|-------------------|---------------|----------------
53 * Usages |-shadow feelers |-raytracing |-
54 * |-sweep tests |-in/out tests |
55 *
56 * FIRST CONTACT:
57 *
58 * - You can setup "first contact" mode or "all contacts" mode with RayCollider::SetFirstContact().
59 * - In "first contact" mode we return as soon as the ray hits one face. If can be useful e.g. for shadow feelers, where
60 * you want to know whether the path to the light is free or not (a boolean answer is enough).
61 * - In "all contacts" mode we return all faces hit by the ray.
62 *
63 * TEMPORAL COHERENCE:
64 *
65 * - You can enable or disable temporal coherence with RayCollider::SetTemporalCoherence().
66 * - It currently only works in "first contact" mode.
67 * - If temporal coherence is enabled, the previously hit triangle is cached during the first query. Then, next queries
68 * start by colliding the ray against the cached triangle. If they still collide, we return immediately.
69 *
70 * CLOSEST HIT:
71 *
72 * - You can enable or disable "closest hit" with RayCollider::SetClosestHit().
73 * - It currently only works in "all contacts" mode.
74 * - If closest hit is enabled, faces are sorted by distance on-the-fly and the closest one only is reported.
75 *
76 * BACKFACE CULLING:
77 *
78 * - You can enable or disable backface culling with RayCollider::SetCulling().
79 * - If culling is enabled, ray will not hit back faces (only front faces).
80 *
81 *
82 *
83 * \class RayCollider
84 * \author Pierre Terdiman
85 * \version 1.3
86 * \date June, 2, 2001
87*/
88///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
89
90///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
91/**
92 * This class describes a face hit by a ray or segment.
93 * This is a particular class dedicated to stabbing queries.
94 *
95 * \class CollisionFace
96 * \author Pierre Terdiman
97 * \version 1.3
98 * \date March, 20, 2001
99*/
100///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
101
102///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
103/**
104 * This class is a dedicated collection of CollisionFace.
105 *
106 * \class CollisionFaces
107 * \author Pierre Terdiman
108 * \version 1.3
109 * \date March, 20, 2001
110*/
111///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
112
113///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
114// Precompiled Header
115#include "Stdafx.h"
116
117using namespace Opcode;
118
119#include "OPC_RayAABBOverlap.h"
120#include "OPC_RayTriOverlap.h"
121
122#define SET_CONTACT(prim_index, flag) \
123 mNbIntersections++; \
124 /* Set contact status */ \
125 mFlags |= flag; \
126 /* In any case the contact has been found and recorded in mStabbedFace */ \
127 mStabbedFace.mFaceID = prim_index;
128
129#ifdef OPC_RAYHIT_CALLBACK
130
131 #define HANDLE_CONTACT(prim_index, flag) \
132 SET_CONTACT(prim_index, flag) \
133 \
134 if(mHitCallback) (mHitCallback)(mStabbedFace, mUserData);
135
136 #define UPDATE_CACHE \
137 if(cache && GetContactStatus()) \
138 { \
139 *cache = mStabbedFace.mFaceID; \
140 }
141#else
142
143 #define HANDLE_CONTACT(prim_index, flag) \
144 SET_CONTACT(prim_index, flag) \
145 \
146 /* Now we can also record it in mStabbedFaces if available */ \
147 if(mStabbedFaces) \
148 { \
149 /* If we want all faces or if that's the first one we hit */ \
150 if(!mClosestHit || !mStabbedFaces->GetNbFaces()) \
151 { \
152 mStabbedFaces->AddFace(mStabbedFace); \
153 } \
154 else \
155 { \
156 /* We only keep closest hit */ \
157 CollisionFace* Current = const_cast<CollisionFace*>(mStabbedFaces->GetFaces()); \
158 if(Current && mStabbedFace.mDistance<Current->mDistance) \
159 { \
160 *Current = mStabbedFace; \
161 } \
162 } \
163 }
164
165 #define UPDATE_CACHE \
166 if(cache && GetContactStatus() && mStabbedFaces) \
167 { \
168 const CollisionFace* Current = mStabbedFaces->GetFaces(); \
169 if(Current) *cache = Current->mFaceID; \
170 else *cache = INVALID_ID; \
171 }
172#endif
173
174#define SEGMENT_PRIM(prim_index, flag) \
175 /* Request vertices from the app */ \
176 VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \
177 \
178 /* Perform ray-tri overlap test and return */ \
179 if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \
180 { \
181 /* Intersection point is valid if dist < segment's length */ \
182 /* We know dist>0 so we can use integers */ \
183 if(IR(mStabbedFace.mDistance)<IR(mMaxDist)) \
184 { \
185 HANDLE_CONTACT(prim_index, flag) \
186 } \
187 }
188
189#define RAY_PRIM(prim_index, flag) \
190 /* Request vertices from the app */ \
191 VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \
192 \
193 /* Perform ray-tri overlap test and return */ \
194 if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \
195 { \
196 HANDLE_CONTACT(prim_index, flag) \
197 }
198
199
200///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
201/**
202 * Constructor.
203 */
204///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
205RayCollider::RayCollider() :
206 mNbRayBVTests (0),
207 mNbRayPrimTests (0),
208 mNbIntersections (0),
209 mCulling (true),
210#ifdef OPC_RAYHIT_CALLBACK
211 mHitCallback (null),
212 mUserData (0),
213#else
214 mClosestHit (false),
215 mStabbedFaces (null),
216#endif
217 mMaxDist (MAX_FLOAT)
218{
219}
220
221///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
222/**
223 * Destructor.
224 */
225///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
226RayCollider::~RayCollider()
227{
228}
229
230///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
231/**
232 * Validates current settings. You should call this method after all the settings and callbacks have been defined.
233 * \return null if everything is ok, else a string describing the problem
234 */
235///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
236const char* RayCollider::ValidateSettings()
237{
238 if(mMaxDist<0.0f) return "Higher distance bound must be positive!";
239 if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!";
240#ifndef OPC_RAYHIT_CALLBACK
241 if(mClosestHit && FirstContactEnabled()) return "Closest hit doesn't work with ""First contact"" mode!";
242 if(TemporalCoherenceEnabled() && mClosestHit) return "Temporal coherence can't guarantee to report closest hit!";
243#endif
244 if(SkipPrimitiveTests()) return "SkipPrimitiveTests not possible for RayCollider ! (not implemented)";
245 return null;
246}
247
248///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
249/**
250 * Generic stabbing query for generic OPCODE models. After the call, access the results:
251 * - with GetContactStatus()
252 * - in the user-provided destination array
253 *
254 * \param world_ray [in] stabbing ray in world space
255 * \param model [in] Opcode model to collide with
256 * \param world [in] model's world matrix, or null
257 * \param cache [in] a possibly cached face index, or null
258 * \return true if success
259 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
260 */
261///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
262bool RayCollider::Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world, udword* cache)
263{
264 // Checkings
265 if(!Setup(&model)) return false;
266
267 // Init collision query
268 if(InitQuery(world_ray, world, cache)) return true;
269
270 if(!model.HasLeafNodes())
271 {
272 if(model.IsQuantized())
273 {
274 const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
275
276 // Setup dequantization coeffs
277 mCenterCoeff = Tree->mCenterCoeff;
278 mExtentsCoeff = Tree->mExtentsCoeff;
279
280 // Perform stabbing query
281 if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes());
282 else _RayStab(Tree->GetNodes());
283 }
284 else
285 {
286 const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
287
288 // Perform stabbing query
289 if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes());
290 else _RayStab(Tree->GetNodes());
291 }
292 }
293 else
294 {
295 if(model.IsQuantized())
296 {
297 const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
298
299 // Setup dequantization coeffs
300 mCenterCoeff = Tree->mCenterCoeff;
301 mExtentsCoeff = Tree->mExtentsCoeff;
302
303 // Perform stabbing query
304 if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes());
305 else _RayStab(Tree->GetNodes());
306 }
307 else
308 {
309 const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
310
311 // Perform stabbing query
312 if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes());
313 else _RayStab(Tree->GetNodes());
314 }
315 }
316
317 // Update cache if needed
318 UPDATE_CACHE
319 return true;
320}
321
322
323///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
324/**
325 * Initializes a stabbing query :
326 * - reset stats & contact status
327 * - compute ray in local space
328 * - check temporal coherence
329 *
330 * \param world_ray [in] stabbing ray in world space
331 * \param world [in] object's world matrix, or null
332 * \param face_id [in] index of previously stabbed triangle
333 * \return TRUE if we can return immediately
334 * \warning SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only.
335 */
336///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
337BOOL RayCollider::InitQuery(const Ray& world_ray, const Matrix4x4* world, udword* face_id)
338{
339 // Reset stats & contact status
340 Collider::InitQuery();
341 mNbRayBVTests = 0;
342 mNbRayPrimTests = 0;
343 mNbIntersections = 0;
344#ifndef OPC_RAYHIT_CALLBACK
345 if(mStabbedFaces) mStabbedFaces->Reset();
346#endif
347
348 // Compute ray in local space
349 // The (Origin/Dir) form is needed for the ray-triangle test anyway (even for segment tests)
350 if(world)
351 {
352 Matrix3x3 InvWorld = *world;
353 mDir = InvWorld * world_ray.mDir;
354
355 Matrix4x4 World;
356 InvertPRMatrix(World, *world);
357 mOrigin = world_ray.mOrig * World;
358 }
359 else
360 {
361 mDir = world_ray.mDir;
362 mOrigin = world_ray.mOrig;
363 }
364
365 // 4) Special case: 1-triangle meshes [Opcode 1.3]
366 if(mCurrentModel && mCurrentModel->HasSingleNode())
367 {
368 // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0.
369 if(!SkipPrimitiveTests())
370 {
371 // Perform overlap test between the unique triangle and the ray (and set contact status if needed)
372 SEGMENT_PRIM(udword(0), OPC_CONTACT)
373
374 // Return immediately regardless of status
375 return TRUE;
376 }
377 }
378
379 // Check temporal coherence :
380
381 // Test previously colliding primitives first
382 if(TemporalCoherenceEnabled() && FirstContactEnabled() && face_id && *face_id!=INVALID_ID)
383 {
384#ifdef OLD_CODE
385#ifndef OPC_RAYHIT_CALLBACK
386 if(!mClosestHit)
387#endif
388 {
389 // Request vertices from the app
390 VertexPointers VP;
391 mIMesh->GetTriangle(VP, *face_id);
392 // Perform ray-cached tri overlap test
393 if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2]))
394 {
395 // Intersection point is valid if:
396 // - distance is positive (else it can just be a face behind the orig point)
397 // - distance is smaller than a given max distance (useful for shadow feelers)
398// if(mStabbedFace.mDistance>0.0f && mStabbedFace.mDistance<mMaxDist)
399 if(IR(mStabbedFace.mDistance)<IR(mMaxDist)) // The other test is already performed in RayTriOverlap
400 {
401 // Set contact status
402 mFlags |= OPC_TEMPORAL_CONTACT;
403
404 mStabbedFace.mFaceID = *face_id;
405
406#ifndef OPC_RAYHIT_CALLBACK
407 if(mStabbedFaces) mStabbedFaces->AddFace(mStabbedFace);
408#endif
409 return TRUE;
410 }
411 }
412 }
413#else
414 // New code
415 // We handle both Segment/ray queries with the same segment code, and a possible infinite limit
416 SEGMENT_PRIM(*face_id, OPC_TEMPORAL_CONTACT)
417
418 // Return immediately if possible
419 if(GetContactStatus()) return TRUE;
420#endif
421 }
422
423 // Precompute data (moved after temporal coherence since only needed for ray-AABB)
424 if(IR(mMaxDist)!=IEEE_MAX_FLOAT)
425 {
426 // For Segment-AABB overlap
427 mData = 0.5f * mDir * mMaxDist;
428 mData2 = mOrigin + mData;
429
430 // Precompute mFDir;
431 mFDir.x = fabsf(mData.x);
432 mFDir.y = fabsf(mData.y);
433 mFDir.z = fabsf(mData.z);
434 }
435 else
436 {
437 // For Ray-AABB overlap
438// udword x = SIR(mDir.x)-1;
439// udword y = SIR(mDir.y)-1;
440// udword z = SIR(mDir.z)-1;
441// mData.x = FR(x);
442// mData.y = FR(y);
443// mData.z = FR(z);
444
445 // Precompute mFDir;
446 mFDir.x = fabsf(mDir.x);
447 mFDir.y = fabsf(mDir.y);
448 mFDir.z = fabsf(mDir.z);
449 }
450
451 return FALSE;
452}
453
454///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
455/**
456 * Stabbing query for vanilla AABB trees.
457 * \param world_ray [in] stabbing ray in world space
458 * \param tree [in] AABB tree
459 * \param box_indices [out] indices of stabbed boxes
460 * \return true if success
461 */
462///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
463bool RayCollider::Collide(const Ray& world_ray, const AABBTree* tree, Container& box_indices)
464{
465 // ### bad design here
466
467 // This is typically called for a scene tree, full of -AABBs-, not full of triangles.
468 // So we don't really have "primitives" to deal with. Hence it doesn't work with
469 // "FirstContact" + "TemporalCoherence".
470 ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) );
471
472 // Checkings
473 if(!tree) return false;
474
475 // Init collision query
476 // Basically this is only called to initialize precomputed data
477 if(InitQuery(world_ray)) return true;
478
479 // Perform stabbing query
480 if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(tree, box_indices);
481 else _RayStab(tree, box_indices);
482
483 return true;
484}
485
486
487///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
488/**
489 * Recursive stabbing query for normal AABB trees.
490 * \param node [in] current collision node
491 */
492///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
493void RayCollider::_SegmentStab(const AABBCollisionNode* node)
494{
495 // Perform Segment-AABB overlap test
496 if(!SegmentAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
497
498 if(node->IsLeaf())
499 {
500 SEGMENT_PRIM(node->GetPrimitive(), OPC_CONTACT)
501 }
502 else
503 {
504 _SegmentStab(node->GetPos());
505
506 if(ContactFound()) return;
507
508 _SegmentStab(node->GetNeg());
509 }
510}
511
512///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
513/**
514 * Recursive stabbing query for quantized AABB trees.
515 * \param node [in] current collision node
516 */
517///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
518void RayCollider::_SegmentStab(const AABBQuantizedNode* node)
519{
520 // Dequantize box
521 const QuantizedAABB& Box = node->mAABB;
522 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
523 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
524
525 // Perform Segment-AABB overlap test
526 if(!SegmentAABBOverlap(Center, Extents)) return;
527
528 if(node->IsLeaf())
529 {
530 SEGMENT_PRIM(node->GetPrimitive(), OPC_CONTACT)
531 }
532 else
533 {
534 _SegmentStab(node->GetPos());
535
536 if(ContactFound()) return;
537
538 _SegmentStab(node->GetNeg());
539 }
540}
541
542///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
543/**
544 * Recursive stabbing query for no-leaf AABB trees.
545 * \param node [in] current collision node
546 */
547///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
548void RayCollider::_SegmentStab(const AABBNoLeafNode* node)
549{
550 // Perform Segment-AABB overlap test
551 if(!SegmentAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
552
553 if(node->HasPosLeaf())
554 {
555 SEGMENT_PRIM(node->GetPosPrimitive(), OPC_CONTACT)
556 }
557 else _SegmentStab(node->GetPos());
558
559 if(ContactFound()) return;
560
561 if(node->HasNegLeaf())
562 {
563 SEGMENT_PRIM(node->GetNegPrimitive(), OPC_CONTACT)
564 }
565 else _SegmentStab(node->GetNeg());
566}
567
568///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
569/**
570 * Recursive stabbing query for quantized no-leaf AABB trees.
571 * \param node [in] current collision node
572 */
573///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
574void RayCollider::_SegmentStab(const AABBQuantizedNoLeafNode* node)
575{
576 // Dequantize box
577 const QuantizedAABB& Box = node->mAABB;
578 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
579 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
580
581 // Perform Segment-AABB overlap test
582 if(!SegmentAABBOverlap(Center, Extents)) return;
583
584 if(node->HasPosLeaf())
585 {
586 SEGMENT_PRIM(node->GetPosPrimitive(), OPC_CONTACT)
587 }
588 else _SegmentStab(node->GetPos());
589
590 if(ContactFound()) return;
591
592 if(node->HasNegLeaf())
593 {
594 SEGMENT_PRIM(node->GetNegPrimitive(), OPC_CONTACT)
595 }
596 else _SegmentStab(node->GetNeg());
597}
598
599///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
600/**
601 * Recursive stabbing query for vanilla AABB trees.
602 * \param node [in] current collision node
603 * \param box_indices [out] indices of stabbed boxes
604 */
605///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
606void RayCollider::_SegmentStab(const AABBTreeNode* node, Container& box_indices)
607{
608 // Test the box against the segment
609 Point Center, Extents;
610 node->GetAABB()->GetCenter(Center);
611 node->GetAABB()->GetExtents(Extents);
612 if(!SegmentAABBOverlap(Center, Extents)) return;
613
614 if(node->IsLeaf())
615 {
616 box_indices.Add(node->GetPrimitives(), node->GetNbPrimitives());
617 }
618 else
619 {
620 _SegmentStab(node->GetPos(), box_indices);
621 _SegmentStab(node->GetNeg(), box_indices);
622 }
623}
624
625///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
626/**
627 * Recursive stabbing query for normal AABB trees.
628 * \param node [in] current collision node
629 */
630///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
631void RayCollider::_RayStab(const AABBCollisionNode* node)
632{
633 // Perform Ray-AABB overlap test
634 if(!RayAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
635
636 if(node->IsLeaf())
637 {
638 RAY_PRIM(node->GetPrimitive(), OPC_CONTACT)
639 }
640 else
641 {
642 _RayStab(node->GetPos());
643
644 if(ContactFound()) return;
645
646 _RayStab(node->GetNeg());
647 }
648}
649
650///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
651/**
652 * Recursive stabbing query for quantized AABB trees.
653 * \param node [in] current collision node
654 */
655///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
656void RayCollider::_RayStab(const AABBQuantizedNode* node)
657{
658 // Dequantize box
659 const QuantizedAABB& Box = node->mAABB;
660 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
661 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
662
663 // Perform Ray-AABB overlap test
664 if(!RayAABBOverlap(Center, Extents)) return;
665
666 if(node->IsLeaf())
667 {
668 RAY_PRIM(node->GetPrimitive(), OPC_CONTACT)
669 }
670 else
671 {
672 _RayStab(node->GetPos());
673
674 if(ContactFound()) return;
675
676 _RayStab(node->GetNeg());
677 }
678}
679
680///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
681/**
682 * Recursive stabbing query for no-leaf AABB trees.
683 * \param node [in] current collision node
684 */
685///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
686void RayCollider::_RayStab(const AABBNoLeafNode* node)
687{
688 // Perform Ray-AABB overlap test
689 if(!RayAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
690
691 if(node->HasPosLeaf())
692 {
693 RAY_PRIM(node->GetPosPrimitive(), OPC_CONTACT)
694 }
695 else _RayStab(node->GetPos());
696
697 if(ContactFound()) return;
698
699 if(node->HasNegLeaf())
700 {
701 RAY_PRIM(node->GetNegPrimitive(), OPC_CONTACT)
702 }
703 else _RayStab(node->GetNeg());
704}
705
706///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
707/**
708 * Recursive stabbing query for quantized no-leaf AABB trees.
709 * \param node [in] current collision node
710 */
711///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
712void RayCollider::_RayStab(const AABBQuantizedNoLeafNode* node)
713{
714 // Dequantize box
715 const QuantizedAABB& Box = node->mAABB;
716 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
717 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
718
719 // Perform Ray-AABB overlap test
720 if(!RayAABBOverlap(Center, Extents)) return;
721
722 if(node->HasPosLeaf())
723 {
724 RAY_PRIM(node->GetPosPrimitive(), OPC_CONTACT)
725 }
726 else _RayStab(node->GetPos());
727
728 if(ContactFound()) return;
729
730 if(node->HasNegLeaf())
731 {
732 RAY_PRIM(node->GetNegPrimitive(), OPC_CONTACT)
733 }
734 else _RayStab(node->GetNeg());
735}
736
737///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
738/**
739 * Recursive stabbing query for vanilla AABB trees.
740 * \param node [in] current collision node
741 * \param box_indices [out] indices of stabbed boxes
742 */
743///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
744void RayCollider::_RayStab(const AABBTreeNode* node, Container& box_indices)
745{
746 // Test the box against the ray
747 Point Center, Extents;
748 node->GetAABB()->GetCenter(Center);
749 node->GetAABB()->GetExtents(Extents);
750 if(!RayAABBOverlap(Center, Extents)) return;
751
752 if(node->IsLeaf())
753 {
754 mFlags |= OPC_CONTACT;
755 box_indices.Add(node->GetPrimitives(), node->GetNbPrimitives());
756 }
757 else
758 {
759 _RayStab(node->GetPos(), box_indices);
760 _RayStab(node->GetNeg(), box_indices);
761 }
762}
diff --git a/libraries/ode-0.9/OPCODE/OPC_RayCollider.h b/libraries/ode-0.9/OPCODE/OPC_RayCollider.h
new file mode 100644
index 0000000..3fd8381
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_RayCollider.h
@@ -0,0 +1,225 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for a ray collider.
12 * \file OPC_RayCollider.h
13 * \author Pierre Terdiman
14 * \date June, 2, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_RAYCOLLIDER_H__
21#define __OPC_RAYCOLLIDER_H__
22
23 class OPCODE_API CollisionFace
24 {
25 public:
26 //! Constructor
27 inline_ CollisionFace() {}
28 //! Destructor
29 inline_ ~CollisionFace() {}
30
31 udword mFaceID; //!< Index of touched face
32 float mDistance; //!< Distance from collider to hitpoint
33 float mU, mV; //!< Impact barycentric coordinates
34 };
35
36 class OPCODE_API CollisionFaces : public Container
37 {
38 public:
39 //! Constructor
40 CollisionFaces() {}
41 //! Destructor
42 ~CollisionFaces() {}
43
44 inline_ udword GetNbFaces() const { return GetNbEntries()>>2; }
45 inline_ const CollisionFace* GetFaces() const { return (const CollisionFace*)GetEntries(); }
46
47 inline_ void Reset() { Container::Reset(); }
48
49 inline_ void AddFace(const CollisionFace& face) { Add(face.mFaceID).Add(face.mDistance).Add(face.mU).Add(face.mV); }
50 };
51
52#ifdef OPC_RAYHIT_CALLBACK
53 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
54 /**
55 * User-callback, called by OPCODE to record a hit.
56 * \param hit [in] current hit
57 * \param user_data [in] user-defined data from SetCallback()
58 */
59 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
60 typedef void (*HitCallback) (const CollisionFace& hit, void* user_data);
61#endif
62
63 class OPCODE_API RayCollider : public Collider
64 {
65 public:
66 // Constructor / Destructor
67 RayCollider();
68 virtual ~RayCollider();
69
70 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
71 /**
72 * Generic stabbing query for generic OPCODE models. After the call, access the results:
73 * - with GetContactStatus()
74 * - in the user-provided destination array
75 *
76 * \param world_ray [in] stabbing ray in world space
77 * \param model [in] Opcode model to collide with
78 * \param world [in] model's world matrix, or null
79 * \param cache [in] a possibly cached face index, or null
80 * \return true if success
81 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
82 */
83 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
84 bool Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world=null, udword* cache=null);
85 //
86 bool Collide(const Ray& world_ray, const AABBTree* tree, Container& box_indices);
87 // Settings
88
89#ifndef OPC_RAYHIT_CALLBACK
90 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
91 /**
92 * Settings: enable or disable "closest hit" mode.
93 * \param flag [in] true to report closest hit only
94 * \see SetCulling(bool flag)
95 * \see SetMaxDist(float max_dist)
96 * \see SetDestination(StabbedFaces* sf)
97 */
98 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
99 inline_ void SetClosestHit(bool flag) { mClosestHit = flag; }
100#endif
101 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
102 /**
103 * Settings: enable or disable backface culling.
104 * \param flag [in] true to enable backface culling
105 * \see SetClosestHit(bool flag)
106 * \see SetMaxDist(float max_dist)
107 * \see SetDestination(StabbedFaces* sf)
108 */
109 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
110 inline_ void SetCulling(bool flag) { mCulling = flag; }
111
112 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
113 /**
114 * Settings: sets the higher distance bound.
115 * \param max_dist [in] higher distance bound. Default = maximal value, for ray queries (else segment)
116 * \see SetClosestHit(bool flag)
117 * \see SetCulling(bool flag)
118 * \see SetDestination(StabbedFaces* sf)
119 */
120 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
121 inline_ void SetMaxDist(float max_dist=MAX_FLOAT) { mMaxDist = max_dist; }
122
123#ifdef OPC_RAYHIT_CALLBACK
124 inline_ void SetHitCallback(HitCallback cb) { mHitCallback = cb; }
125 inline_ void SetUserData(void* user_data) { mUserData = user_data; }
126#else
127 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
128 /**
129 * Settings: sets the destination array for stabbed faces.
130 * \param cf [in] destination array, filled during queries
131 * \see SetClosestHit(bool flag)
132 * \see SetCulling(bool flag)
133 * \see SetMaxDist(float max_dist)
134 */
135 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
136 inline_ void SetDestination(CollisionFaces* cf) { mStabbedFaces = cf; }
137#endif
138 // Stats
139 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
140 /**
141 * Stats: gets the number of Ray-BV overlap tests after a collision query.
142 * \see GetNbRayPrimTests()
143 * \see GetNbIntersections()
144 * \return the number of Ray-BV tests performed during last query
145 */
146 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
147 inline_ udword GetNbRayBVTests() const { return mNbRayBVTests; }
148
149 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
150 /**
151 * Stats: gets the number of Ray-Triangle overlap tests after a collision query.
152 * \see GetNbRayBVTests()
153 * \see GetNbIntersections()
154 * \return the number of Ray-Triangle tests performed during last query
155 */
156 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
157 inline_ udword GetNbRayPrimTests() const { return mNbRayPrimTests; }
158
159 // In-out test
160 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
161 /**
162 * Stats: gets the number of intersection found after a collision query. Can be used for in/out tests.
163 * \see GetNbRayBVTests()
164 * \see GetNbRayPrimTests()
165 * \return the number of valid intersections during last query
166 */
167 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
168 inline_ udword GetNbIntersections() const { return mNbIntersections; }
169
170 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
171 /**
172 * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider.
173 * \return null if everything is ok, else a string describing the problem
174 */
175 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
176 override(Collider) const char* ValidateSettings();
177
178 protected:
179 // Ray in local space
180 Point mOrigin; //!< Ray origin
181 Point mDir; //!< Ray direction (normalized)
182 Point mFDir; //!< fabsf(mDir)
183 Point mData, mData2;
184 // Stabbed faces
185 CollisionFace mStabbedFace; //!< Current stabbed face
186#ifdef OPC_RAYHIT_CALLBACK
187 HitCallback mHitCallback; //!< Callback used to record a hit
188 void* mUserData; //!< User-defined data
189#else
190 CollisionFaces* mStabbedFaces; //!< List of stabbed faces
191#endif
192 // Stats
193 udword mNbRayBVTests; //!< Number of Ray-BV tests
194 udword mNbRayPrimTests; //!< Number of Ray-Primitive tests
195 // In-out test
196 udword mNbIntersections; //!< Number of valid intersections
197 // Dequantization coeffs
198 Point mCenterCoeff;
199 Point mExtentsCoeff;
200 // Settings
201 float mMaxDist; //!< Valid segment on the ray
202#ifndef OPC_RAYHIT_CALLBACK
203 bool mClosestHit; //!< Report closest hit only
204#endif
205 bool mCulling; //!< Stab culled faces or not
206 // Internal methods
207 void _SegmentStab(const AABBCollisionNode* node);
208 void _SegmentStab(const AABBNoLeafNode* node);
209 void _SegmentStab(const AABBQuantizedNode* node);
210 void _SegmentStab(const AABBQuantizedNoLeafNode* node);
211 void _SegmentStab(const AABBTreeNode* node, Container& box_indices);
212 void _RayStab(const AABBCollisionNode* node);
213 void _RayStab(const AABBNoLeafNode* node);
214 void _RayStab(const AABBQuantizedNode* node);
215 void _RayStab(const AABBQuantizedNoLeafNode* node);
216 void _RayStab(const AABBTreeNode* node, Container& box_indices);
217 // Overlap tests
218 inline_ BOOL RayAABBOverlap(const Point& center, const Point& extents);
219 inline_ BOOL SegmentAABBOverlap(const Point& center, const Point& extents);
220 inline_ BOOL RayTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2);
221 // Init methods
222 BOOL InitQuery(const Ray& world_ray, const Matrix4x4* world=null, udword* face_id=null);
223 };
224
225#endif // __OPC_RAYCOLLIDER_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_RayTriOverlap.h b/libraries/ode-0.9/OPCODE/OPC_RayTriOverlap.h
new file mode 100644
index 0000000..7fe37c9
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_RayTriOverlap.h
@@ -0,0 +1,89 @@
1#define LOCAL_EPSILON 0.000001f
2
3///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4/**
5 * Computes a ray-triangle intersection test.
6 * Original code from Tomas Möller's "Fast Minimum Storage Ray-Triangle Intersection".
7 * It's been optimized a bit with integer code, and modified to return a non-intersection if distance from
8 * ray origin to triangle is negative.
9 *
10 * \param vert0 [in] triangle vertex
11 * \param vert1 [in] triangle vertex
12 * \param vert2 [in] triangle vertex
13 * \return true on overlap. mStabbedFace is filled with relevant info.
14 */
15///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
16inline_ BOOL RayCollider::RayTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2)
17{
18 // Stats
19 mNbRayPrimTests++;
20
21 // Find vectors for two edges sharing vert0
22 Point edge1 = vert1 - vert0;
23 Point edge2 = vert2 - vert0;
24
25 // Begin calculating determinant - also used to calculate U parameter
26 Point pvec = mDir^edge2;
27
28 // If determinant is near zero, ray lies in plane of triangle
29 float det = edge1|pvec;
30
31 if(mCulling)
32 {
33 if(det<LOCAL_EPSILON) return FALSE;
34 // From here, det is > 0. So we can use integer cmp.
35
36 // Calculate distance from vert0 to ray origin
37 Point tvec = mOrigin - vert0;
38
39 // Calculate U parameter and test bounds
40 mStabbedFace.mU = tvec|pvec;
41// if(IR(u)&0x80000000 || u>det) return FALSE;
42 if(IS_NEGATIVE_FLOAT(mStabbedFace.mU) || IR(mStabbedFace.mU)>IR(det)) return FALSE;
43
44 // Prepare to test V parameter
45 Point qvec = tvec^edge1;
46
47 // Calculate V parameter and test bounds
48 mStabbedFace.mV = mDir|qvec;
49 if(IS_NEGATIVE_FLOAT(mStabbedFace.mV) || mStabbedFace.mU+mStabbedFace.mV>det) return FALSE;
50
51 // Calculate t, scale parameters, ray intersects triangle
52 mStabbedFace.mDistance = edge2|qvec;
53 // Det > 0 so we can early exit here
54 // Intersection point is valid if distance is positive (else it can just be a face behind the orig point)
55 if(IS_NEGATIVE_FLOAT(mStabbedFace.mDistance)) return FALSE;
56 // Else go on
57 float OneOverDet = 1.0f / det;
58 mStabbedFace.mDistance *= OneOverDet;
59 mStabbedFace.mU *= OneOverDet;
60 mStabbedFace.mV *= OneOverDet;
61 }
62 else
63 {
64 // the non-culling branch
65 if(det>-LOCAL_EPSILON && det<LOCAL_EPSILON) return FALSE;
66 float OneOverDet = 1.0f / det;
67
68 // Calculate distance from vert0 to ray origin
69 Point tvec = mOrigin - vert0;
70
71 // Calculate U parameter and test bounds
72 mStabbedFace.mU = (tvec|pvec) * OneOverDet;
73// if(IR(u)&0x80000000 || u>1.0f) return FALSE;
74 if(IS_NEGATIVE_FLOAT(mStabbedFace.mU) || IR(mStabbedFace.mU)>IEEE_1_0) return FALSE;
75
76 // prepare to test V parameter
77 Point qvec = tvec^edge1;
78
79 // Calculate V parameter and test bounds
80 mStabbedFace.mV = (mDir|qvec) * OneOverDet;
81 if(IS_NEGATIVE_FLOAT(mStabbedFace.mV) || mStabbedFace.mU+mStabbedFace.mV>1.0f) return FALSE;
82
83 // Calculate t, ray intersects triangle
84 mStabbedFace.mDistance = (edge2|qvec) * OneOverDet;
85 // Intersection point is valid if distance is positive (else it can just be a face behind the orig point)
86 if(IS_NEGATIVE_FLOAT(mStabbedFace.mDistance)) return FALSE;
87 }
88 return TRUE;
89}
diff --git a/libraries/ode-0.9/OPCODE/OPC_Settings.h b/libraries/ode-0.9/OPCODE/OPC_Settings.h
new file mode 100644
index 0000000..1841a2b
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_Settings.h
@@ -0,0 +1,49 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains compilation flags.
12 * \file OPC_Settings.h
13 * \author Pierre Terdiman
14 * \date May, 12, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_SETTINGS_H__
21#define __OPC_SETTINGS_H__
22
23 //! Use CPU comparisons (comment that line to use standard FPU compares)
24 #define OPC_CPU_COMPARE
25
26 //! Use FCOMI / FCMOV on Pentium-Pro based processors (comment that line to use plain C++)
27 #define OPC_USE_FCOMI
28
29 //! Use epsilon value in tri-tri overlap test
30 #define OPC_TRITRI_EPSILON_TEST
31
32 //! Use tree-coherence or not [not implemented yet]
33// #define OPC_USE_TREE_COHERENCE
34
35 //! Use callbacks or direct pointers. Using callbacks might be a bit slower (but probably not much)
36// #define OPC_USE_CALLBACKS
37
38 //! Support triangle and vertex strides or not. Using strides might be a bit slower (but probably not much)
39 #define OPC_USE_STRIDE
40
41 //! Discard negative pointer in vanilla trees
42 #define OPC_NO_NEG_VANILLA_TREE
43
44 //! Use a callback in the ray collider
45 //#define OPC_RAYHIT_CALLBACK
46
47 // NB: no compilation flag to enable/disable stats since they're actually needed in the box/box overlap test
48
49#endif //__OPC_SETTINGS_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_SphereAABBOverlap.h b/libraries/ode-0.9/OPCODE/OPC_SphereAABBOverlap.h
new file mode 100644
index 0000000..2278bc0
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_SphereAABBOverlap.h
@@ -0,0 +1,128 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/**
3 * Sphere-AABB overlap test, based on Jim Arvo's code.
4 * \param center [in] box center
5 * \param extents [in] box extents
6 * \return TRUE on overlap
7 */
8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9inline_ BOOL SphereCollider::SphereAABBOverlap(const Point& center, const Point& extents)
10{
11 // Stats
12 mNbVolumeBVTests++;
13
14 float d = 0.0f;
15
16 //find the square of the distance
17 //from the sphere to the box
18#ifdef OLDIES
19 for(udword i=0;i<3;i++)
20 {
21 float tmp = mCenter[i] - center[i];
22 float s = tmp + extents[i];
23
24 if(s<0.0f) d += s*s;
25 else
26 {
27 s = tmp - extents[i];
28 if(s>0.0f) d += s*s;
29 }
30 }
31#endif
32
33//#ifdef NEW_TEST
34
35// float tmp = mCenter.x - center.x;
36// float s = tmp + extents.x;
37
38 float tmp,s;
39
40 tmp = mCenter.x - center.x;
41 s = tmp + extents.x;
42
43 if(s<0.0f)
44 {
45 d += s*s;
46 if(d>mRadius2) return FALSE;
47 }
48 else
49 {
50 s = tmp - extents.x;
51 if(s>0.0f)
52 {
53 d += s*s;
54 if(d>mRadius2) return FALSE;
55 }
56 }
57
58 tmp = mCenter.y - center.y;
59 s = tmp + extents.y;
60
61 if(s<0.0f)
62 {
63 d += s*s;
64 if(d>mRadius2) return FALSE;
65 }
66 else
67 {
68 s = tmp - extents.y;
69 if(s>0.0f)
70 {
71 d += s*s;
72 if(d>mRadius2) return FALSE;
73 }
74 }
75
76 tmp = mCenter.z - center.z;
77 s = tmp + extents.z;
78
79 if(s<0.0f)
80 {
81 d += s*s;
82 if(d>mRadius2) return FALSE;
83 }
84 else
85 {
86 s = tmp - extents.z;
87 if(s>0.0f)
88 {
89 d += s*s;
90 if(d>mRadius2) return FALSE;
91 }
92 }
93//#endif
94
95#ifdef OLDIES
96// Point Min = center - extents;
97// Point Max = center + extents;
98
99 float d = 0.0f;
100
101 //find the square of the distance
102 //from the sphere to the box
103 for(udword i=0;i<3;i++)
104 {
105float Min = center[i] - extents[i];
106
107// if(mCenter[i]<Min[i])
108 if(mCenter[i]<Min)
109 {
110// float s = mCenter[i] - Min[i];
111 float s = mCenter[i] - Min;
112 d += s*s;
113 }
114 else
115 {
116float Max = center[i] + extents[i];
117
118// if(mCenter[i]>Max[i])
119 if(mCenter[i]>Max)
120 {
121 float s = mCenter[i] - Max;
122 d += s*s;
123 }
124 }
125 }
126#endif
127 return d <= mRadius2;
128}
diff --git a/libraries/ode-0.9/OPCODE/OPC_SphereCollider.cpp b/libraries/ode-0.9/OPCODE/OPC_SphereCollider.cpp
new file mode 100644
index 0000000..65350b7
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_SphereCollider.cpp
@@ -0,0 +1,739 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for a sphere collider.
12 * \file OPC_SphereCollider.cpp
13 * \author Pierre Terdiman
14 * \date June, 2, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19/**
20 * Contains a sphere-vs-tree collider.
21 * This class performs a collision test between a sphere and an AABB tree. You can use this to do a standard player vs world collision,
22 * in a Nettle/Telemachos way. It doesn't suffer from all reported bugs in those two classic codes - the "new" one by Paul Nettle is a
23 * debuggued version I think. Collision response can be driven by reported collision data - it works extremely well for me. In sake of
24 * efficiency, all meshes (that is, all AABB trees) should of course also be kept in an extra hierarchical structure (octree, whatever).
25 *
26 * \class SphereCollider
27 * \author Pierre Terdiman
28 * \version 1.3
29 * \date June, 2, 2001
30*/
31///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
32
33///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
34// Precompiled Header
35#include "Stdafx.h"
36
37using namespace Opcode;
38
39#include "OPC_SphereAABBOverlap.h"
40#include "OPC_SphereTriOverlap.h"
41
42#define SET_CONTACT(prim_index, flag) \
43 /* Set contact status */ \
44 mFlags |= flag; \
45 mTouchedPrimitives->Add(udword(prim_index));
46
47//! Sphere-triangle overlap test
48#define SPHERE_PRIM(prim_index, flag) \
49 /* Request vertices from the app */ \
50 VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \
51 \
52 /* Perform sphere-tri overlap test */ \
53 if(SphereTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \
54 { \
55 SET_CONTACT(prim_index, flag) \
56 }
57
58///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
59/**
60 * Constructor.
61 */
62///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
63SphereCollider::SphereCollider()
64{
65 mCenter.Zero();
66 mRadius2 = 0.0f;
67}
68
69///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
70/**
71 * Destructor.
72 */
73///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
74SphereCollider::~SphereCollider()
75{
76}
77
78///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
79/**
80 * Generic collision query for generic OPCODE models. After the call, access the results:
81 * - with GetContactStatus()
82 * - with GetNbTouchedPrimitives()
83 * - with GetTouchedPrimitives()
84 *
85 * \param cache [in/out] a sphere cache
86 * \param sphere [in] collision sphere in local space
87 * \param model [in] Opcode model to collide with
88 * \param worlds [in] sphere's world matrix, or null
89 * \param worldm [in] model's world matrix, or null
90 * \return true if success
91 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
92 */
93///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
94bool SphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const Model& model, const Matrix4x4* worlds, const Matrix4x4* worldm)
95{
96 // Checkings
97 if(!Setup(&model)) return false;
98
99 // Init collision query
100 if(InitQuery(cache, sphere, worlds, worldm)) return true;
101
102 // Special case for 1-leaf trees
103 if(mCurrentModel && mCurrentModel->HasSingleNode())
104 {
105 // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles
106 udword Nb = mIMesh->GetNbTriangles();
107 // Loop through all triangles
108 for(udword i=0;i<Nb;i++)
109 {
110 SPHERE_PRIM(i, OPC_CONTACT)
111 }
112 return true;
113 }
114
115 if(!model.HasLeafNodes())
116 {
117 if(model.IsQuantized())
118 {
119 const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
120
121 // Setup dequantization coeffs
122 mCenterCoeff = Tree->mCenterCoeff;
123 mExtentsCoeff = Tree->mExtentsCoeff;
124
125 // Perform collision query
126 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
127 else _Collide(Tree->GetNodes());
128 }
129 else
130 {
131 const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
132
133 // Perform collision query
134 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
135 else _Collide(Tree->GetNodes());
136 }
137 }
138 else
139 {
140 if(model.IsQuantized())
141 {
142 const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
143
144 // Setup dequantization coeffs
145 mCenterCoeff = Tree->mCenterCoeff;
146 mExtentsCoeff = Tree->mExtentsCoeff;
147
148 // Perform collision query
149 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
150 else _Collide(Tree->GetNodes());
151 }
152 else
153 {
154 const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
155
156 // Perform collision query
157 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
158 else _Collide(Tree->GetNodes());
159 }
160 }
161 return true;
162}
163
164///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
165/**
166 * Initializes a collision query :
167 * - reset stats & contact status
168 * - setup matrices
169 * - check temporal coherence
170 *
171 * \param cache [in/out] a sphere cache
172 * \param sphere [in] sphere in local space
173 * \param worlds [in] sphere's world matrix, or null
174 * \param worldm [in] model's world matrix, or null
175 * \return TRUE if we can return immediately
176 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
177 */
178///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
179BOOL SphereCollider::InitQuery(SphereCache& cache, const Sphere& sphere, const Matrix4x4* worlds, const Matrix4x4* worldm)
180{
181 // 1) Call the base method
182 VolumeCollider::InitQuery();
183
184 // 2) Compute sphere in model space:
185 // - Precompute R^2
186 mRadius2 = sphere.mRadius * sphere.mRadius;
187 // - Compute center position
188 mCenter = sphere.mCenter;
189 // -> to world space
190 if(worlds) mCenter *= *worlds;
191 // -> to model space
192 if(worldm)
193 {
194 // Invert model matrix
195 Matrix4x4 InvWorldM;
196 InvertPRMatrix(InvWorldM, *worldm);
197
198 mCenter *= InvWorldM;
199 }
200
201 // 3) Setup destination pointer
202 mTouchedPrimitives = &cache.TouchedPrimitives;
203
204 // 4) Special case: 1-triangle meshes [Opcode 1.3]
205 if(mCurrentModel && mCurrentModel->HasSingleNode())
206 {
207 if(!SkipPrimitiveTests())
208 {
209 // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0.
210 mTouchedPrimitives->Reset();
211
212 // Perform overlap test between the unique triangle and the sphere (and set contact status if needed)
213 SPHERE_PRIM(udword(0), OPC_CONTACT)
214
215 // Return immediately regardless of status
216 return TRUE;
217 }
218 }
219
220 // 5) Check temporal coherence :
221 if(TemporalCoherenceEnabled())
222 {
223 // Here we use temporal coherence
224 // => check results from previous frame before performing the collision query
225 if(FirstContactEnabled())
226 {
227 // We're only interested in the first contact found => test the unique previously touched face
228 if(mTouchedPrimitives->GetNbEntries())
229 {
230 // Get index of previously touched face = the first entry in the array
231 udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0);
232
233 // Then reset the array:
234 // - if the overlap test below is successful, the index we'll get added back anyway
235 // - if it isn't, then the array should be reset anyway for the normal query
236 mTouchedPrimitives->Reset();
237
238 // Perform overlap test between the cached triangle and the sphere (and set contact status if needed)
239 SPHERE_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT)
240
241 // Return immediately if possible
242 if(GetContactStatus()) return TRUE;
243 }
244 // else no face has been touched during previous query
245 // => we'll have to perform a normal query
246 }
247 else
248 {
249 // We're interested in all contacts =>test the new real sphere N(ew) against the previous fat sphere P(revious):
250 float r = sqrtf(cache.FatRadius2) - sphere.mRadius;
251 if(IsCacheValid(cache) && cache.Center.SquareDistance(mCenter) < r*r)
252 {
253 // - if N is included in P, return previous list
254 // => we simply leave the list (mTouchedFaces) unchanged
255
256 // Set contact status if needed
257 if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT;
258
259 // In any case we don't need to do a query
260 return TRUE;
261 }
262 else
263 {
264 // - else do the query using a fat N
265
266 // Reset cache since we'll about to perform a real query
267 mTouchedPrimitives->Reset();
268
269 // Make a fat sphere so that coherence will work for subsequent frames
270 mRadius2 *= cache.FatCoeff;
271// mRadius2 = (sphere.mRadius * cache.FatCoeff)*(sphere.mRadius * cache.FatCoeff);
272
273 // Update cache with query data (signature for cached faces)
274 cache.Center = mCenter;
275 cache.FatRadius2 = mRadius2;
276 }
277 }
278 }
279 else
280 {
281 // Here we don't use temporal coherence => do a normal query
282 mTouchedPrimitives->Reset();
283 }
284
285 return FALSE;
286}
287
288///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
289/**
290 * Collision query for vanilla AABB trees.
291 * \param cache [in/out] a sphere cache
292 * \param sphere [in] collision sphere in world space
293 * \param tree [in] AABB tree
294 * \return true if success
295 */
296///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
297bool SphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const AABBTree* tree)
298{
299 // This is typically called for a scene tree, full of -AABBs-, not full of triangles.
300 // So we don't really have "primitives" to deal with. Hence it doesn't work with
301 // "FirstContact" + "TemporalCoherence".
302 ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) );
303
304 // Checkings
305 if(!tree) return false;
306
307 // Init collision query
308 if(InitQuery(cache, sphere)) return true;
309
310 // Perform collision query
311 _Collide(tree);
312
313 return true;
314}
315
316///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
317/**
318 * Checks the sphere completely contains the box. In which case we can end the query sooner.
319 * \param bc [in] box center
320 * \param be [in] box extents
321 * \return true if the sphere contains the whole box
322 */
323///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
324inline_ BOOL SphereCollider::SphereContainsBox(const Point& bc, const Point& be)
325{
326 // I assume if all 8 box vertices are inside the sphere, so does the whole box.
327 // Sounds ok but maybe there's a better way?
328 Point p;
329 p.x=bc.x+be.x; p.y=bc.y+be.y; p.z=bc.z+be.z; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
330 p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
331 p.x=bc.x+be.x; p.y=bc.y-be.y; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
332 p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
333 p.x=bc.x+be.x; p.y=bc.y+be.y; p.z=bc.z-be.z; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
334 p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
335 p.x=bc.x+be.x; p.y=bc.y-be.y; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
336 p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
337
338 return TRUE;
339}
340
341#define TEST_BOX_IN_SPHERE(center, extents) \
342 if(SphereContainsBox(center, extents)) \
343 { \
344 /* Set contact status */ \
345 mFlags |= OPC_CONTACT; \
346 _Dump(node); \
347 return; \
348 }
349
350///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
351/**
352 * Recursive collision query for normal AABB trees.
353 * \param node [in] current collision node
354 */
355///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
356void SphereCollider::_Collide(const AABBCollisionNode* node)
357{
358 // Perform Sphere-AABB overlap test
359 if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
360
361 TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents)
362
363 if(node->IsLeaf())
364 {
365 SPHERE_PRIM(node->GetPrimitive(), OPC_CONTACT)
366 }
367 else
368 {
369 _Collide(node->GetPos());
370
371 if(ContactFound()) return;
372
373 _Collide(node->GetNeg());
374 }
375}
376
377///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
378/**
379 * Recursive collision query for normal AABB trees, without primitive tests.
380 * \param node [in] current collision node
381 */
382///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
383void SphereCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node)
384{
385 // Perform Sphere-AABB overlap test
386 if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
387
388 TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents)
389
390 if(node->IsLeaf())
391 {
392 SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
393 }
394 else
395 {
396 _CollideNoPrimitiveTest(node->GetPos());
397
398 if(ContactFound()) return;
399
400 _CollideNoPrimitiveTest(node->GetNeg());
401 }
402}
403
404///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
405/**
406 * Recursive collision query for quantized AABB trees.
407 * \param node [in] current collision node
408 */
409///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
410void SphereCollider::_Collide(const AABBQuantizedNode* node)
411{
412 // Dequantize box
413 const QuantizedAABB& Box = node->mAABB;
414 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
415 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
416
417 // Perform Sphere-AABB overlap test
418 if(!SphereAABBOverlap(Center, Extents)) return;
419
420 TEST_BOX_IN_SPHERE(Center, Extents)
421
422 if(node->IsLeaf())
423 {
424 SPHERE_PRIM(node->GetPrimitive(), OPC_CONTACT)
425 }
426 else
427 {
428 _Collide(node->GetPos());
429
430 if(ContactFound()) return;
431
432 _Collide(node->GetNeg());
433 }
434}
435
436///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
437/**
438 * Recursive collision query for quantized AABB trees, without primitive tests.
439 * \param node [in] current collision node
440 */
441///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
442void SphereCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node)
443{
444 // Dequantize box
445 const QuantizedAABB& Box = node->mAABB;
446 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
447 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
448
449 // Perform Sphere-AABB overlap test
450 if(!SphereAABBOverlap(Center, Extents)) return;
451
452 TEST_BOX_IN_SPHERE(Center, Extents)
453
454 if(node->IsLeaf())
455 {
456 SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
457 }
458 else
459 {
460 _CollideNoPrimitiveTest(node->GetPos());
461
462 if(ContactFound()) return;
463
464 _CollideNoPrimitiveTest(node->GetNeg());
465 }
466}
467
468///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
469/**
470 * Recursive collision query for no-leaf AABB trees.
471 * \param node [in] current collision node
472 */
473///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
474void SphereCollider::_Collide(const AABBNoLeafNode* node)
475{
476 // Perform Sphere-AABB overlap test
477 if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
478
479 TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents)
480
481 if(node->HasPosLeaf()) { SPHERE_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
482 else _Collide(node->GetPos());
483
484 if(ContactFound()) return;
485
486 if(node->HasNegLeaf()) { SPHERE_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
487 else _Collide(node->GetNeg());
488}
489
490///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
491/**
492 * Recursive collision query for no-leaf AABB trees, without primitive tests.
493 * \param node [in] current collision node
494 */
495///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
496void SphereCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node)
497{
498 // Perform Sphere-AABB overlap test
499 if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
500
501 TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents)
502
503 if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
504 else _CollideNoPrimitiveTest(node->GetPos());
505
506 if(ContactFound()) return;
507
508 if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
509 else _CollideNoPrimitiveTest(node->GetNeg());
510}
511
512///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
513/**
514 * Recursive collision query for quantized no-leaf AABB trees.
515 * \param node [in] current collision node
516 */
517///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
518void SphereCollider::_Collide(const AABBQuantizedNoLeafNode* node)
519{
520 // Dequantize box
521 const QuantizedAABB& Box = node->mAABB;
522 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
523 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
524
525 // Perform Sphere-AABB overlap test
526 if(!SphereAABBOverlap(Center, Extents)) return;
527
528 TEST_BOX_IN_SPHERE(Center, Extents)
529
530 if(node->HasPosLeaf()) { SPHERE_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
531 else _Collide(node->GetPos());
532
533 if(ContactFound()) return;
534
535 if(node->HasNegLeaf()) { SPHERE_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
536 else _Collide(node->GetNeg());
537}
538
539///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
540/**
541 * Recursive collision query for quantized no-leaf AABB trees, without primitive tests.
542 * \param node [in] current collision node
543 */
544///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
545void SphereCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node)
546{
547 // Dequantize box
548 const QuantizedAABB& Box = node->mAABB;
549 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
550 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
551
552 // Perform Sphere-AABB overlap test
553 if(!SphereAABBOverlap(Center, Extents)) return;
554
555 TEST_BOX_IN_SPHERE(Center, Extents)
556
557 if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
558 else _CollideNoPrimitiveTest(node->GetPos());
559
560 if(ContactFound()) return;
561
562 if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
563 else _CollideNoPrimitiveTest(node->GetNeg());
564}
565
566///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
567/**
568 * Recursive collision query for vanilla AABB trees.
569 * \param node [in] current collision node
570 */
571///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
572void SphereCollider::_Collide(const AABBTreeNode* node)
573{
574 // Perform Sphere-AABB overlap test
575 Point Center, Extents;
576 node->GetAABB()->GetCenter(Center);
577 node->GetAABB()->GetExtents(Extents);
578 if(!SphereAABBOverlap(Center, Extents)) return;
579
580 if(node->IsLeaf() || SphereContainsBox(Center, Extents))
581 {
582 mFlags |= OPC_CONTACT;
583 mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives());
584 }
585 else
586 {
587 _Collide(node->GetPos());
588 _Collide(node->GetNeg());
589 }
590}
591
592
593
594
595
596
597
598///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
599/**
600 * Constructor.
601 */
602///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
603HybridSphereCollider::HybridSphereCollider()
604{
605}
606
607///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
608/**
609 * Destructor.
610 */
611///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
612HybridSphereCollider::~HybridSphereCollider()
613{
614}
615
616bool HybridSphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const HybridModel& model, const Matrix4x4* worlds, const Matrix4x4* worldm)
617{
618 // We don't want primitive tests here!
619 mFlags |= OPC_NO_PRIMITIVE_TESTS;
620
621 // Checkings
622 if(!Setup(&model)) return false;
623
624 // Init collision query
625 if(InitQuery(cache, sphere, worlds, worldm)) return true;
626
627 // Special case for 1-leaf trees
628 if(mCurrentModel && mCurrentModel->HasSingleNode())
629 {
630 // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles
631 udword Nb = mIMesh->GetNbTriangles();
632
633 // Loop through all triangles
634 for(udword i=0;i<Nb;i++)
635 {
636 SPHERE_PRIM(i, OPC_CONTACT)
637 }
638 return true;
639 }
640
641 // Override destination array since we're only going to get leaf boxes here
642 mTouchedBoxes.Reset();
643 mTouchedPrimitives = &mTouchedBoxes;
644
645 // Now, do the actual query against leaf boxes
646 if(!model.HasLeafNodes())
647 {
648 if(model.IsQuantized())
649 {
650 const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
651
652 // Setup dequantization coeffs
653 mCenterCoeff = Tree->mCenterCoeff;
654 mExtentsCoeff = Tree->mExtentsCoeff;
655
656 // Perform collision query - we don't want primitive tests here!
657 _CollideNoPrimitiveTest(Tree->GetNodes());
658 }
659 else
660 {
661 const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
662
663 // Perform collision query - we don't want primitive tests here!
664 _CollideNoPrimitiveTest(Tree->GetNodes());
665 }
666 }
667 else
668 {
669 if(model.IsQuantized())
670 {
671 const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
672
673 // Setup dequantization coeffs
674 mCenterCoeff = Tree->mCenterCoeff;
675 mExtentsCoeff = Tree->mExtentsCoeff;
676
677 // Perform collision query - we don't want primitive tests here!
678 _CollideNoPrimitiveTest(Tree->GetNodes());
679 }
680 else
681 {
682 const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
683
684 // Perform collision query - we don't want primitive tests here!
685 _CollideNoPrimitiveTest(Tree->GetNodes());
686 }
687 }
688
689 // We only have a list of boxes so far
690 if(GetContactStatus())
691 {
692 // Reset contact status, since it currently only reflects collisions with leaf boxes
693 Collider::InitQuery();
694
695 // Change dest container so that we can use built-in overlap tests and get collided primitives
696 cache.TouchedPrimitives.Reset();
697 mTouchedPrimitives = &cache.TouchedPrimitives;
698
699 // Read touched leaf boxes
700 udword Nb = mTouchedBoxes.GetNbEntries();
701 const udword* Touched = mTouchedBoxes.GetEntries();
702
703 const LeafTriangles* LT = model.GetLeafTriangles();
704 const udword* Indices = model.GetIndices();
705
706 // Loop through touched leaves
707 while(Nb--)
708 {
709 const LeafTriangles& CurrentLeaf = LT[*Touched++];
710
711 // Each leaf box has a set of triangles
712 udword NbTris = CurrentLeaf.GetNbTriangles();
713 if(Indices)
714 {
715 const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()];
716
717 // Loop through triangles and test each of them
718 while(NbTris--)
719 {
720 udword TriangleIndex = *T++;
721 SPHERE_PRIM(TriangleIndex, OPC_CONTACT)
722 }
723 }
724 else
725 {
726 udword BaseIndex = CurrentLeaf.GetTriangleIndex();
727
728 // Loop through triangles and test each of them
729 while(NbTris--)
730 {
731 udword TriangleIndex = BaseIndex++;
732 SPHERE_PRIM(TriangleIndex, OPC_CONTACT)
733 }
734 }
735 }
736 }
737
738 return true;
739}
diff --git a/libraries/ode-0.9/OPCODE/OPC_SphereCollider.h b/libraries/ode-0.9/OPCODE/OPC_SphereCollider.h
new file mode 100644
index 0000000..ac6495e
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_SphereCollider.h
@@ -0,0 +1,96 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for a sphere collider.
12 * \file OPC_SphereCollider.h
13 * \author Pierre Terdiman
14 * \date June, 2, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_SPHERECOLLIDER_H__
21#define __OPC_SPHERECOLLIDER_H__
22
23 struct OPCODE_API SphereCache : VolumeCache
24 {
25 SphereCache() : Center(0.0f,0.0f,0.0f), FatRadius2(0.0f), FatCoeff(1.1f) {}
26 ~SphereCache() {}
27
28 // Cached faces signature
29 Point Center; //!< Sphere used when performing the query resulting in cached faces
30 float FatRadius2; //!< Sphere used when performing the query resulting in cached faces
31 // User settings
32 float FatCoeff; //!< mRadius2 multiplier used to create a fat sphere
33 };
34
35 class OPCODE_API SphereCollider : public VolumeCollider
36 {
37 public:
38 // Constructor / Destructor
39 SphereCollider();
40 virtual ~SphereCollider();
41
42 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
43 /**
44 * Generic collision query for generic OPCODE models. After the call, access the results:
45 * - with GetContactStatus()
46 * - with GetNbTouchedPrimitives()
47 * - with GetTouchedPrimitives()
48 *
49 * \param cache [in/out] a sphere cache
50 * \param sphere [in] collision sphere in local space
51 * \param model [in] Opcode model to collide with
52 * \param worlds [in] sphere's world matrix, or null
53 * \param worldm [in] model's world matrix, or null
54 * \return true if success
55 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
56 */
57 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
58 bool Collide(SphereCache& cache, const Sphere& sphere, const Model& model, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null);
59
60 //
61 bool Collide(SphereCache& cache, const Sphere& sphere, const AABBTree* tree);
62 protected:
63 // Sphere in model space
64 Point mCenter; //!< Sphere center
65 float mRadius2; //!< Sphere radius squared
66 // Internal methods
67 void _Collide(const AABBCollisionNode* node);
68 void _Collide(const AABBNoLeafNode* node);
69 void _Collide(const AABBQuantizedNode* node);
70 void _Collide(const AABBQuantizedNoLeafNode* node);
71 void _Collide(const AABBTreeNode* node);
72 void _CollideNoPrimitiveTest(const AABBCollisionNode* node);
73 void _CollideNoPrimitiveTest(const AABBNoLeafNode* node);
74 void _CollideNoPrimitiveTest(const AABBQuantizedNode* node);
75 void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node);
76 // Overlap tests
77 inline_ BOOL SphereContainsBox(const Point& bc, const Point& be);
78 inline_ BOOL SphereAABBOverlap(const Point& center, const Point& extents);
79 BOOL SphereTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2);
80 // Init methods
81 BOOL InitQuery(SphereCache& cache, const Sphere& sphere, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null);
82 };
83
84 class OPCODE_API HybridSphereCollider : public SphereCollider
85 {
86 public:
87 // Constructor / Destructor
88 HybridSphereCollider();
89 virtual ~HybridSphereCollider();
90
91 bool Collide(SphereCache& cache, const Sphere& sphere, const HybridModel& model, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null);
92 protected:
93 Container mTouchedBoxes;
94 };
95
96#endif // __OPC_SPHERECOLLIDER_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_SphereTriOverlap.h b/libraries/ode-0.9/OPCODE/OPC_SphereTriOverlap.h
new file mode 100644
index 0000000..77e59f3
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_SphereTriOverlap.h
@@ -0,0 +1,187 @@
1
2// This is collision detection. If you do another distance test for collision *response*,
3// if might be useful to simply *skip* the test below completely, and report a collision.
4// - if sphere-triangle overlap, result is ok
5// - if they don't, we'll discard them during collision response with a similar test anyway
6// Overall this approach should run faster.
7
8// Original code by David Eberly in Magic.
9BOOL SphereCollider::SphereTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2)
10{
11 // Stats
12 mNbVolumePrimTests++;
13
14 // Early exit if one of the vertices is inside the sphere
15 Point kDiff = vert2 - mCenter;
16 float fC = kDiff.SquareMagnitude();
17 if(fC <= mRadius2) return TRUE;
18
19 kDiff = vert1 - mCenter;
20 fC = kDiff.SquareMagnitude();
21 if(fC <= mRadius2) return TRUE;
22
23 kDiff = vert0 - mCenter;
24 fC = kDiff.SquareMagnitude();
25 if(fC <= mRadius2) return TRUE;
26
27 // Else do the full distance test
28 Point TriEdge0 = vert1 - vert0;
29 Point TriEdge1 = vert2 - vert0;
30
31//Point kDiff = vert0 - mCenter;
32 float fA00 = TriEdge0.SquareMagnitude();
33 float fA01 = TriEdge0 | TriEdge1;
34 float fA11 = TriEdge1.SquareMagnitude();
35 float fB0 = kDiff | TriEdge0;
36 float fB1 = kDiff | TriEdge1;
37//float fC = kDiff.SquareMagnitude();
38 float fDet = fabsf(fA00*fA11 - fA01*fA01);
39 float u = fA01*fB1-fA11*fB0;
40 float v = fA01*fB0-fA00*fB1;
41 float SqrDist;
42
43 if(u + v <= fDet)
44 {
45 if(u < 0.0f)
46 {
47 if(v < 0.0f) // region 4
48 {
49 if(fB0 < 0.0f)
50 {
51// v = 0.0f;
52 if(-fB0>=fA00) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; }
53 else { u = -fB0/fA00; SqrDist = fB0*u+fC; }
54 }
55 else
56 {
57// u = 0.0f;
58 if(fB1>=0.0f) { /*v = 0.0f;*/ SqrDist = fC; }
59 else if(-fB1>=fA11) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; }
60 else { v = -fB1/fA11; SqrDist = fB1*v+fC; }
61 }
62 }
63 else // region 3
64 {
65// u = 0.0f;
66 if(fB1>=0.0f) { /*v = 0.0f;*/ SqrDist = fC; }
67 else if(-fB1>=fA11) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; }
68 else { v = -fB1/fA11; SqrDist = fB1*v+fC; }
69 }
70 }
71 else if(v < 0.0f) // region 5
72 {
73// v = 0.0f;
74 if(fB0>=0.0f) { /*u = 0.0f;*/ SqrDist = fC; }
75 else if(-fB0>=fA00) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; }
76 else { u = -fB0/fA00; SqrDist = fB0*u+fC; }
77 }
78 else // region 0
79 {
80 // minimum at interior point
81 if(fDet==0.0f)
82 {
83// u = 0.0f;
84// v = 0.0f;
85 SqrDist = MAX_FLOAT;
86 }
87 else
88 {
89 float fInvDet = 1.0f/fDet;
90 u *= fInvDet;
91 v *= fInvDet;
92 SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC;
93 }
94 }
95 }
96 else
97 {
98 float fTmp0, fTmp1, fNumer, fDenom;
99
100 if(u < 0.0f) // region 2
101 {
102 fTmp0 = fA01 + fB0;
103 fTmp1 = fA11 + fB1;
104 if(fTmp1 > fTmp0)
105 {
106 fNumer = fTmp1 - fTmp0;
107 fDenom = fA00-2.0f*fA01+fA11;
108 if(fNumer >= fDenom)
109 {
110// u = 1.0f;
111// v = 0.0f;
112 SqrDist = fA00+2.0f*fB0+fC;
113 }
114 else
115 {
116 u = fNumer/fDenom;
117 v = 1.0f - u;
118 SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC;
119 }
120 }
121 else
122 {
123// u = 0.0f;
124 if(fTmp1 <= 0.0f) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; }
125 else if(fB1 >= 0.0f) { /*v = 0.0f;*/ SqrDist = fC; }
126 else { v = -fB1/fA11; SqrDist = fB1*v+fC; }
127 }
128 }
129 else if(v < 0.0f) // region 6
130 {
131 fTmp0 = fA01 + fB1;
132 fTmp1 = fA00 + fB0;
133 if(fTmp1 > fTmp0)
134 {
135 fNumer = fTmp1 - fTmp0;
136 fDenom = fA00-2.0f*fA01+fA11;
137 if(fNumer >= fDenom)
138 {
139// v = 1.0f;
140// u = 0.0f;
141 SqrDist = fA11+2.0f*fB1+fC;
142 }
143 else
144 {
145 v = fNumer/fDenom;
146 u = 1.0f - v;
147 SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC;
148 }
149 }
150 else
151 {
152// v = 0.0f;
153 if(fTmp1 <= 0.0f) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; }
154 else if(fB0 >= 0.0f) { /*u = 0.0f;*/ SqrDist = fC; }
155 else { u = -fB0/fA00; SqrDist = fB0*u+fC; }
156 }
157 }
158 else // region 1
159 {
160 fNumer = fA11 + fB1 - fA01 - fB0;
161 if(fNumer <= 0.0f)
162 {
163// u = 0.0f;
164// v = 1.0f;
165 SqrDist = fA11+2.0f*fB1+fC;
166 }
167 else
168 {
169 fDenom = fA00-2.0f*fA01+fA11;
170 if(fNumer >= fDenom)
171 {
172// u = 1.0f;
173// v = 0.0f;
174 SqrDist = fA00+2.0f*fB0+fC;
175 }
176 else
177 {
178 u = fNumer/fDenom;
179 v = 1.0f - u;
180 SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC;
181 }
182 }
183 }
184 }
185
186 return fabsf(SqrDist) < mRadius2;
187}
diff --git a/libraries/ode-0.9/OPCODE/OPC_SweepAndPrune.cpp b/libraries/ode-0.9/OPCODE/OPC_SweepAndPrune.cpp
new file mode 100644
index 0000000..7f1a8f3
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_SweepAndPrune.cpp
@@ -0,0 +1,664 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains an implementation of the sweep-and-prune algorithm (moved from Z-Collide)
12 * \file OPC_SweepAndPrune.cpp
13 * \author Pierre Terdiman
14 * \date January, 29, 2000
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Precompiled Header
20#include "Stdafx.h"
21
22using namespace Opcode;
23
24inline_ void Sort(udword& id0, udword& id1)
25{
26 if(id0>id1) Swap(id0, id1);
27}
28
29 class Opcode::SAP_Element
30 {
31 public:
32 inline_ SAP_Element() {}
33 inline_ SAP_Element(udword id, SAP_Element* next) : mID(id), mNext(next) {}
34 inline_ ~SAP_Element() {}
35
36 udword mID;
37 SAP_Element* mNext;
38 };
39
40 class Opcode::SAP_Box
41 {
42 public:
43 SAP_EndPoint* Min[3];
44 SAP_EndPoint* Max[3];
45 };
46
47 class Opcode::SAP_EndPoint
48 {
49 public:
50 float Value; // Min or Max value
51 SAP_EndPoint* Previous; // Previous EndPoint whose Value is smaller than ours (or null)
52 SAP_EndPoint* Next; // Next EndPoint whose Value is greater than ours (or null)
53 udword Data; // Parent box ID *2 | MinMax flag
54
55 inline_ void SetData(udword box_id, BOOL is_max) { Data = (box_id<<1)|is_max; }
56 inline_ BOOL IsMax() const { return Data & 1; }
57 inline_ udword GetBoxID() const { return Data>>1; }
58
59 inline_ void InsertAfter(SAP_EndPoint* element)
60 {
61 if(this!=element && this!=element->Next)
62 {
63 // Remove
64 if(Previous) Previous->Next = Next;
65 if(Next) Next->Previous = Previous;
66
67 // Insert
68 Next = element->Next;
69 if(Next) Next->Previous = this;
70
71 element->Next = this;
72 Previous = element;
73 }
74 }
75
76 inline_ void InsertBefore(SAP_EndPoint* element)
77 {
78 if(this!=element && this!=element->Previous)
79 {
80 // Remove
81 if(Previous) Previous->Next = Next;
82 if(Next) Next->Previous = Previous;
83
84 // Insert
85 Previous = element->Previous;
86 element->Previous = this;
87
88 Next = element;
89 if(Previous) Previous->Next = this;
90 }
91 }
92 };
93
94
95
96
97
98
99
100
101
102
103///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
104/**
105 * Constructor.
106 */
107///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
108SAP_PairData::SAP_PairData() :
109 mNbElements (0),
110 mNbUsedElements (0),
111 mElementPool (null),
112 mFirstFree (null),
113 mNbObjects (0),
114 mArray (null)
115{
116}
117
118///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
119/**
120 * Destructor.
121 */
122///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
123SAP_PairData::~SAP_PairData()
124{
125 Release();
126}
127
128void SAP_PairData::Release()
129{
130 mNbElements = 0;
131 mNbUsedElements = 0;
132 mNbObjects = 0;
133 DELETEARRAY(mElementPool);
134 DELETEARRAY(mArray);
135}
136
137///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
138/**
139 * Initializes.
140 * \param nb_objects [in]
141 * \return true if success
142 */
143///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
144bool SAP_PairData::Init(udword nb_objects)
145{
146 // Make sure everything has been released
147 Release();
148 if(!nb_objects) return false;
149
150 mArray = new SAP_Element*[nb_objects];
151 CHECKALLOC(mArray);
152 ZeroMemory(mArray, nb_objects*sizeof(SAP_Element*));
153 mNbObjects = nb_objects;
154
155 return true;
156}
157
158///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
159/**
160 * Remaps a pointer when pool gets resized.
161 * \param element [in/out] remapped element
162 * \param delta [in] offset in bytes
163 */
164///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
165inline_ void Remap(SAP_Element*& element, size_t delta)
166{
167 if(element) element = (SAP_Element*)(size_t(element) + delta);
168}
169
170///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
171/**
172 * Gets a free element in the pool.
173 * \param id [in] element id
174 * \param next [in] next element
175 * \param remap [out] possible remapping offset
176 * \return the new element
177 */
178///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
179SAP_Element* SAP_PairData::GetFreeElem(udword id, SAP_Element* next, udword* remap)
180{
181 if(remap) *remap = 0;
182
183 SAP_Element* FreeElem;
184 if(mFirstFree)
185 {
186 // Recycle
187 FreeElem = mFirstFree;
188 mFirstFree = mFirstFree->mNext; // First free = next free (or null)
189 }
190 else
191 {
192 if(mNbUsedElements==mNbElements)
193 {
194 // Resize
195 mNbElements = mNbElements ? (mNbElements<<1) : 2;
196
197 SAP_Element* NewElems = new SAP_Element[mNbElements];
198
199 if(mNbUsedElements) CopyMemory(NewElems, mElementPool, mNbUsedElements*sizeof(SAP_Element));
200
201 // Remap everything
202 {
203 size_t Delta = size_t(NewElems) - size_t(mElementPool);
204
205 for(udword i=0;i<mNbUsedElements;i++) Remap(NewElems[i].mNext, Delta);
206 for(udword i=0;i<mNbObjects;i++) Remap(mArray[i], Delta);
207
208 Remap(mFirstFree, Delta);
209 Remap(next, Delta);
210
211 if(remap) *remap = Delta;
212 }
213
214 DELETEARRAY(mElementPool);
215 mElementPool = NewElems;
216 }
217
218 FreeElem = &mElementPool[mNbUsedElements++];
219 }
220
221 FreeElem->mID = id;
222 FreeElem->mNext = next;
223
224 return FreeElem;
225}
226
227///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
228/**
229 * Frees an element of the pool.
230 * \param elem [in] element to free/recycle
231 */
232///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
233inline_ void SAP_PairData::FreeElem(SAP_Element* elem)
234{
235 elem->mNext = mFirstFree; // Next free
236 mFirstFree = elem;
237}
238
239// Add a pair to the set.
240void SAP_PairData::AddPair(udword id1, udword id2)
241{
242 // Order the ids
243 Sort(id1, id2);
244
245 ASSERT(id1<mNbObjects);
246 if(id1>=mNbObjects) return;
247
248 // Select the right list from "mArray".
249 SAP_Element* Current = mArray[id1];
250
251 if(!Current)
252 {
253 // Empty slot => create new element
254 mArray[id1] = GetFreeElem(id2, null);
255 }
256 else if(Current->mID>id2)
257 {
258 // The list is not empty but all elements are greater than id2 => insert id2 in the front.
259 mArray[id1] = GetFreeElem(id2, mArray[id1]);
260 }
261 else
262 {
263 // Else find the correct location in the sorted list (ascending order) and insert id2 there.
264 while(Current->mNext)
265 {
266 if(Current->mNext->mID > id2) break;
267
268 Current = Current->mNext;
269 }
270
271 if(Current->mID==id2) return; // The pair already exists
272
273// Current->mNext = GetFreeElem(id2, Current->mNext);
274 udword Delta;
275 SAP_Element* E = GetFreeElem(id2, Current->mNext, &Delta);
276 if(Delta) Remap(Current, Delta);
277 Current->mNext = E;
278 }
279}
280
281// Delete a pair from the set.
282void SAP_PairData::RemovePair(udword id1, udword id2)
283{
284 // Order the ids.
285 Sort(id1, id2);
286
287 // Exit if the pair doesn't exist in the set
288 if(id1>=mNbObjects) return;
289
290 // Otherwise, select the correct list.
291 SAP_Element* Current = mArray[id1];
292
293 // If this list is empty, the pair doesn't exist.
294 if(!Current) return;
295
296 // Otherwise, if id2 is the first element, delete it.
297 if(Current->mID==id2)
298 {
299 mArray[id1] = Current->mNext;
300 FreeElem(Current);
301 }
302 else
303 {
304 // If id2 is not the first element, start traversing the sorted list.
305 while(Current->mNext)
306 {
307 // If we have moved too far away without hitting id2, then the pair doesn't exist
308 if(Current->mNext->mID > id2) return;
309
310 // Otherwise, delete id2.
311 if(Current->mNext->mID == id2)
312 {
313 SAP_Element* Temp = Current->mNext;
314 Current->mNext = Temp->mNext;
315 FreeElem(Temp);
316 return;
317 }
318 Current = Current->mNext;
319 }
320 }
321}
322
323void SAP_PairData::DumpPairs(Pairs& pairs) const
324{
325 // ### Ugly and slow
326 for(udword i=0;i<mNbObjects;i++)
327 {
328 SAP_Element* Current = mArray[i];
329 while(Current)
330 {
331 ASSERT(Current->mID<mNbObjects);
332
333 pairs.AddPair(i, Current->mID);
334 Current = Current->mNext;
335 }
336 }
337}
338
339void SAP_PairData::DumpPairs(PairCallback callback, void* user_data) const
340{
341 if(!callback) return;
342
343 // ### Ugly and slow
344 for(udword i=0;i<mNbObjects;i++)
345 {
346 SAP_Element* Current = mArray[i];
347 while(Current)
348 {
349 ASSERT(Current->mID<mNbObjects);
350
351 if(!(callback)(i, Current->mID, user_data)) return;
352 Current = Current->mNext;
353 }
354 }
355}
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
385/**
386 * Constructor.
387 */
388///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
389SweepAndPrune::SweepAndPrune()
390{
391}
392
393///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
394/**
395 * Destructor.
396 */
397///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
398SweepAndPrune::~SweepAndPrune()
399{
400}
401
402void SweepAndPrune::GetPairs(Pairs& pairs) const
403{
404 mPairs.DumpPairs(pairs);
405}
406
407void SweepAndPrune::GetPairs(PairCallback callback, void* user_data) const
408{
409 mPairs.DumpPairs(callback, user_data);
410}
411
412bool SweepAndPrune::Init(udword nb_objects, const AABB** boxes)
413{
414 // 1) Create sorted lists
415 mNbObjects = nb_objects;
416
417 mBoxes = new SAP_Box[nb_objects];
418// for(udword i=0;i<nb_objects;i++) mBoxes[i].Box = *boxes[i];
419
420 float* Data = new float[nb_objects*2];
421
422 for(udword Axis=0;Axis<3;Axis++)
423 {
424 mList[Axis] = new SAP_EndPoint[nb_objects*2];
425
426 for(udword i=0;i<nb_objects;i++)
427 {
428 Data[i*2+0] = boxes[i]->GetMin(Axis);
429 Data[i*2+1] = boxes[i]->GetMax(Axis);
430 }
431 RadixSort RS;
432 const udword* Sorted = RS.Sort(Data, nb_objects*2).GetRanks();
433
434 SAP_EndPoint* PreviousEndPoint = null;
435
436 for(udword i=0;i<nb_objects*2;i++)
437 {
438 udword SortedIndex = *Sorted++;
439 float SortedCoord = Data[SortedIndex];
440 udword BoxIndex = SortedIndex>>1;
441
442 ASSERT(BoxIndex<nb_objects);
443
444 SAP_EndPoint* CurrentEndPoint = &mList[Axis][SortedIndex];
445 CurrentEndPoint->Value = SortedCoord;
446// CurrentEndPoint->IsMax = SortedIndex&1; // ### could be implicit ?
447// CurrentEndPoint->ID = BoxIndex; // ### could be implicit ?
448 CurrentEndPoint->SetData(BoxIndex, SortedIndex&1); // ### could be implicit ?
449 CurrentEndPoint->Previous = PreviousEndPoint;
450 CurrentEndPoint->Next = null;
451 if(PreviousEndPoint) PreviousEndPoint->Next = CurrentEndPoint;
452
453 if(CurrentEndPoint->IsMax()) mBoxes[BoxIndex].Max[Axis] = CurrentEndPoint;
454 else mBoxes[BoxIndex].Min[Axis] = CurrentEndPoint;
455
456 PreviousEndPoint = CurrentEndPoint;
457 }
458 }
459
460 DELETEARRAY(Data);
461
462 CheckListsIntegrity();
463
464 // 2) Quickly find starting pairs
465
466 mPairs.Init(nb_objects);
467
468 {
469 Pairs P;
470 CompleteBoxPruning(nb_objects, boxes, P, Axes(AXES_XZY));
471 for(udword i=0;i<P.GetNbPairs();i++)
472 {
473 const Pair* PP = P.GetPair(i);
474
475 udword id0 = PP->id0;
476 udword id1 = PP->id1;
477
478 if(id0!=id1 && boxes[id0]->Intersect(*boxes[id1]))
479 {
480 mPairs.AddPair(id0, id1);
481 }
482 else ASSERT(0);
483 }
484 }
485
486 return true;
487}
488
489bool SweepAndPrune::CheckListsIntegrity()
490{
491 for(udword Axis=0;Axis<3;Axis++)
492 {
493 // Find list head
494 SAP_EndPoint* Current = mList[Axis];
495 while(Current->Previous) Current = Current->Previous;
496
497 udword Nb = 0;
498
499 SAP_EndPoint* Previous = null;
500 while(Current)
501 {
502 Nb++;
503
504 if(Previous)
505 {
506 ASSERT(Previous->Value <= Current->Value);
507 if(Previous->Value > Current->Value) return false;
508 }
509
510 ASSERT(Current->Previous==Previous);
511 if(Current->Previous!=Previous) return false;
512
513 Previous = Current;
514 Current = Current->Next;
515 }
516
517 ASSERT(Nb==mNbObjects*2);
518 }
519 return true;
520}
521
522inline_ BOOL Intersect(const AABB& a, const SAP_Box& b)
523{
524 if(b.Max[0]->Value < a.GetMin(0) || a.GetMax(0) < b.Min[0]->Value
525 || b.Max[1]->Value < a.GetMin(1) || a.GetMax(1) < b.Min[1]->Value
526 || b.Max[2]->Value < a.GetMin(2) || a.GetMax(2) < b.Min[2]->Value) return FALSE;
527
528 return TRUE;
529}
530
531
532
533bool SweepAndPrune::UpdateObject(udword i, const AABB& box)
534{
535 for(udword Axis=0;Axis<3;Axis++)
536 {
537// udword Base = (udword)&mList[Axis][0];
538
539 // Update min
540 {
541 SAP_EndPoint* const CurrentMin = mBoxes[i].Min[Axis];
542 ASSERT(!CurrentMin->IsMax());
543
544 const float Limit = box.GetMin(Axis);
545 if(Limit == CurrentMin->Value)
546 {
547 }
548 else if(Limit < CurrentMin->Value)
549 {
550 CurrentMin->Value = Limit;
551
552 // Min is moving left:
553 SAP_EndPoint* NewPos = CurrentMin;
554 ASSERT(NewPos);
555
556 SAP_EndPoint* tmp;
557 while((tmp = NewPos->Previous) && tmp->Value > Limit)
558 {
559 NewPos = tmp;
560
561 if(NewPos->IsMax())
562 {
563 // Our min passed a max => start overlap
564 //udword SortedIndex = (udword(CurrentMin) - Base)/sizeof(NS_EndPoint);
565 const udword id0 = CurrentMin->GetBoxID();
566 const udword id1 = NewPos->GetBoxID();
567
568 if(id0!=id1 && Intersect(box, mBoxes[id1])) mPairs.AddPair(id0, id1);
569 }
570 }
571
572 CurrentMin->InsertBefore(NewPos);
573 }
574 else// if(Limit > CurrentMin->Value)
575 {
576 CurrentMin->Value = Limit;
577
578 // Min is moving right:
579 SAP_EndPoint* NewPos = CurrentMin;
580 ASSERT(NewPos);
581
582 SAP_EndPoint* tmp;
583 while((tmp = NewPos->Next) && tmp->Value < Limit)
584 {
585 NewPos = tmp;
586
587 if(NewPos->IsMax())
588 {
589 // Our min passed a max => stop overlap
590 const udword id0 = CurrentMin->GetBoxID();
591 const udword id1 = NewPos->GetBoxID();
592
593 if(id0!=id1) mPairs.RemovePair(id0, id1);
594 }
595 }
596
597 CurrentMin->InsertAfter(NewPos);
598 }
599 }
600
601 // Update max
602 {
603 SAP_EndPoint* const CurrentMax = mBoxes[i].Max[Axis];
604 ASSERT(CurrentMax->IsMax());
605
606 const float Limit = box.GetMax(Axis);
607 if(Limit == CurrentMax->Value)
608 {
609 }
610 else if(Limit > CurrentMax->Value)
611 {
612 CurrentMax->Value = Limit;
613
614 // Max is moving right:
615 SAP_EndPoint* NewPos = CurrentMax;
616 ASSERT(NewPos);
617
618 SAP_EndPoint* tmp;
619 while((tmp = NewPos->Next) && tmp->Value < Limit)
620 {
621 NewPos = tmp;
622
623 if(!NewPos->IsMax())
624 {
625 // Our max passed a min => start overlap
626 const udword id0 = CurrentMax->GetBoxID();
627 const udword id1 = NewPos->GetBoxID();
628
629 if(id0!=id1 && Intersect(box, mBoxes[id1])) mPairs.AddPair(id0, id1);
630 }
631 }
632
633 CurrentMax->InsertAfter(NewPos);
634 }
635 else// if(Limit < CurrentMax->Value)
636 {
637 CurrentMax->Value = Limit;
638
639 // Max is moving left:
640 SAP_EndPoint* NewPos = CurrentMax;
641 ASSERT(NewPos);
642
643 SAP_EndPoint* tmp;
644 while((tmp = NewPos->Previous) && tmp->Value > Limit)
645 {
646 NewPos = tmp;
647
648 if(!NewPos->IsMax())
649 {
650 // Our max passed a min => stop overlap
651 const udword id0 = CurrentMax->GetBoxID();
652 const udword id1 = NewPos->GetBoxID();
653
654 if(id0!=id1) mPairs.RemovePair(id0, id1);
655 }
656 }
657
658 CurrentMax->InsertBefore(NewPos);
659 }
660 }
661 }
662
663 return true;
664}
diff --git a/libraries/ode-0.9/OPCODE/OPC_SweepAndPrune.h b/libraries/ode-0.9/OPCODE/OPC_SweepAndPrune.h
new file mode 100644
index 0000000..2cbbb7e
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_SweepAndPrune.h
@@ -0,0 +1,86 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains an implementation of the sweep-and-prune algorithm (moved from Z-Collide)
12 * \file OPC_SweepAndPrune.h
13 * \author Pierre Terdiman
14 * \date January, 29, 2000
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_SWEEPANDPRUNE_H__
21#define __OPC_SWEEPANDPRUNE_H__
22
23 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
24 /**
25 * User-callback, called by OPCODE for each colliding pairs.
26 * \param id0 [in] id of colliding object
27 * \param id1 [in] id of colliding object
28 * \param user_data [in] user-defined data
29 * \return TRUE to continue enumeration
30 */
31 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
32 typedef BOOL (*PairCallback) (udword id0, udword id1, void* user_data);
33
34 class SAP_Element;
35 class SAP_EndPoint;
36 class SAP_Box;
37
38 class OPCODE_API SAP_PairData
39 {
40 public:
41 SAP_PairData();
42 ~SAP_PairData();
43
44 bool Init(udword nb_objects);
45
46 void AddPair(udword id1, udword id2);
47 void RemovePair(udword id1, udword id2);
48
49 void DumpPairs(Pairs& pairs) const;
50 void DumpPairs(PairCallback callback, void* user_data) const;
51 private:
52 udword mNbElements; //!< Total number of elements in the pool
53 udword mNbUsedElements; //!< Number of used elements
54 SAP_Element* mElementPool; //!< Array of mNbElements elements
55 SAP_Element* mFirstFree; //!< First free element in the pool
56
57 udword mNbObjects; //!< Max number of objects we can handle
58 SAP_Element** mArray; //!< Pointers to pool
59 // Internal methods
60 SAP_Element* GetFreeElem(udword id, SAP_Element* next, udword* remap=null);
61 inline_ void FreeElem(SAP_Element* elem);
62 void Release();
63 };
64
65 class OPCODE_API SweepAndPrune
66 {
67 public:
68 SweepAndPrune();
69 ~SweepAndPrune();
70
71 bool Init(udword nb_objects, const AABB** boxes);
72 bool UpdateObject(udword i, const AABB& box);
73
74 void GetPairs(Pairs& pairs) const;
75 void GetPairs(PairCallback callback, void* user_data) const;
76 private:
77 SAP_PairData mPairs;
78
79 udword mNbObjects;
80 SAP_Box* mBoxes;
81 SAP_EndPoint* mList[3];
82 // Internal methods
83 bool CheckListsIntegrity();
84 };
85
86#endif //__OPC_SWEEPANDPRUNE_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_TreeBuilders.cpp b/libraries/ode-0.9/OPCODE/OPC_TreeBuilders.cpp
new file mode 100644
index 0000000..d2359a0
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_TreeBuilders.cpp
@@ -0,0 +1,255 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for tree builders.
12 * \file OPC_TreeBuilders.cpp
13 * \author Pierre Terdiman
14 * \date March, 20, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19/**
20 * A builder for AABB-trees of vertices.
21 *
22 * \class AABBTreeOfVerticesBuilder
23 * \author Pierre Terdiman
24 * \version 1.3
25 * \date March, 20, 2001
26*/
27///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
28
29///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
30/**
31 * A builder for AABB-trees of AABBs.
32 *
33 * \class AABBTreeOfAABBsBuilder
34 * \author Pierre Terdiman
35 * \version 1.3
36 * \date March, 20, 2001
37*/
38///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
39
40///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
41/**
42 * A builder for AABB-trees of triangles.
43 *
44 * \class AABBTreeOfTrianglesBuilder
45 * \author Pierre Terdiman
46 * \version 1.3
47 * \date March, 20, 2001
48*/
49///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
50
51///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
52// Precompiled Header
53#include "Stdafx.h"
54
55using namespace Opcode;
56
57///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
58/**
59 * Computes the AABB of a set of primitives.
60 * \param primitives [in] list of indices of primitives
61 * \param nb_prims [in] number of indices
62 * \param global_box [out] global AABB enclosing the set of input primitives
63 * \return true if success
64 */
65///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
66bool AABBTreeOfAABBsBuilder::ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const
67{
68 // Checkings
69 if(!primitives || !nb_prims) return false;
70
71 // Initialize global box
72 global_box = mAABBArray[primitives[0]];
73
74 // Loop through boxes
75 for(udword i=1;i<nb_prims;i++)
76 {
77 // Update global box
78 global_box.Add(mAABBArray[primitives[i]]);
79 }
80 return true;
81}
82
83///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
84/**
85 * Computes the splitting value along a given axis for a given primitive.
86 * \param index [in] index of the primitive to split
87 * \param axis [in] axis index (0,1,2)
88 * \return splitting value
89 */
90///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
91float AABBTreeOfAABBsBuilder::GetSplittingValue(udword index, udword axis) const
92{
93 // For an AABB, the splitting value is the middle of the given axis,
94 // i.e. the corresponding component of the center point
95 return mAABBArray[index].GetCenter(axis);
96}
97
98///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
99/**
100 * Computes the AABB of a set of primitives.
101 * \param primitives [in] list of indices of primitives
102 * \param nb_prims [in] number of indices
103 * \param global_box [out] global AABB enclosing the set of input primitives
104 * \return true if success
105 */
106///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
107bool AABBTreeOfTrianglesBuilder::ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const
108{
109 // Checkings
110 if(!primitives || !nb_prims) return false;
111
112 // Initialize global box
113 Point Min(MAX_FLOAT, MAX_FLOAT, MAX_FLOAT);
114 Point Max(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);
115
116 // Loop through triangles
117 VertexPointers VP;
118 while(nb_prims--)
119 {
120 // Get current triangle-vertices
121 mIMesh->GetTriangle(VP, *primitives++);
122 // Update global box
123 Min.Min(*VP.Vertex[0]).Min(*VP.Vertex[1]).Min(*VP.Vertex[2]);
124 Max.Max(*VP.Vertex[0]).Max(*VP.Vertex[1]).Max(*VP.Vertex[2]);
125 }
126 global_box.SetMinMax(Min, Max);
127 return true;
128}
129
130///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
131/**
132 * Computes the splitting value along a given axis for a given primitive.
133 * \param index [in] index of the primitive to split
134 * \param axis [in] axis index (0,1,2)
135 * \return splitting value
136 */
137///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
138float AABBTreeOfTrianglesBuilder::GetSplittingValue(udword index, udword axis) const
139{
140/* // Compute center of triangle
141 Point Center;
142 mTriList[index].Center(mVerts, Center);
143 // Return value
144 return Center[axis];*/
145
146 // Compute correct component from center of triangle
147// return (mVerts[mTriList[index].mVRef[0]][axis]
148// +mVerts[mTriList[index].mVRef[1]][axis]
149// +mVerts[mTriList[index].mVRef[2]][axis])*INV3;
150
151 VertexPointers VP;
152 mIMesh->GetTriangle(VP, index);
153
154 // Compute correct component from center of triangle
155 return ((*VP.Vertex[0])[axis]
156 +(*VP.Vertex[1])[axis]
157 +(*VP.Vertex[2])[axis])*INV3;
158}
159
160///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
161/**
162 * Computes the splitting value along a given axis for a given node.
163 * \param primitives [in] list of indices of primitives
164 * \param nb_prims [in] number of indices
165 * \param global_box [in] global AABB enclosing the set of input primitives
166 * \param axis [in] axis index (0,1,2)
167 * \return splitting value
168 */
169///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
170float AABBTreeOfTrianglesBuilder::GetSplittingValue(const udword* primitives, udword nb_prims, const AABB& global_box, udword axis) const
171{
172 if(mSettings.mRules&SPLIT_GEOM_CENTER)
173 {
174 // Loop through triangles
175 float SplitValue = 0.0f;
176 VertexPointers VP;
177 for(udword i=0;i<nb_prims;i++)
178 {
179 // Get current triangle-vertices
180 mIMesh->GetTriangle(VP, primitives[i]);
181 // Update split value
182 SplitValue += (*VP.Vertex[0])[axis];
183 SplitValue += (*VP.Vertex[1])[axis];
184 SplitValue += (*VP.Vertex[2])[axis];
185 }
186 return SplitValue / float(nb_prims*3);
187 }
188 else return AABBTreeBuilder::GetSplittingValue(primitives, nb_prims, global_box, axis);
189}
190
191///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
192/**
193 * Computes the AABB of a set of primitives.
194 * \param primitives [in] list of indices of primitives
195 * \param nb_prims [in] number of indices
196 * \param global_box [out] global AABB enclosing the set of input primitives
197 * \return true if success
198 */
199///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
200bool AABBTreeOfVerticesBuilder::ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const
201{
202 // Checkings
203 if(!primitives || !nb_prims) return false;
204
205 // Initialize global box
206 global_box.SetEmpty();
207
208 // Loop through vertices
209 for(udword i=0;i<nb_prims;i++)
210 {
211 // Update global box
212 global_box.Extend(mVertexArray[primitives[i]]);
213 }
214 return true;
215}
216
217///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
218/**
219 * Computes the splitting value along a given axis for a given primitive.
220 * \param index [in] index of the primitive to split
221 * \param axis [in] axis index (0,1,2)
222 * \return splitting value
223 */
224///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
225float AABBTreeOfVerticesBuilder::GetSplittingValue(udword index, udword axis) const
226{
227 // For a vertex, the splitting value is simply the vertex coordinate.
228 return mVertexArray[index][axis];
229}
230
231///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
232/**
233 * Computes the splitting value along a given axis for a given node.
234 * \param primitives [in] list of indices of primitives
235 * \param nb_prims [in] number of indices
236 * \param global_box [in] global AABB enclosing the set of input primitives
237 * \param axis [in] axis index (0,1,2)
238 * \return splitting value
239 */
240///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
241float AABBTreeOfVerticesBuilder::GetSplittingValue(const udword* primitives, udword nb_prims, const AABB& global_box, udword axis) const
242{
243 if(mSettings.mRules&SPLIT_GEOM_CENTER)
244 {
245 // Loop through vertices
246 float SplitValue = 0.0f;
247 for(udword i=0;i<nb_prims;i++)
248 {
249 // Update split value
250 SplitValue += mVertexArray[primitives[i]][axis];
251 }
252 return SplitValue / float(nb_prims);
253 }
254 else return AABBTreeBuilder::GetSplittingValue(primitives, nb_prims, global_box, axis);
255}
diff --git a/libraries/ode-0.9/OPCODE/OPC_TreeBuilders.h b/libraries/ode-0.9/OPCODE/OPC_TreeBuilders.h
new file mode 100644
index 0000000..b9a2a98
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_TreeBuilders.h
@@ -0,0 +1,173 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for tree builders.
12 * \file OPC_TreeBuilders.h
13 * \author Pierre Terdiman
14 * \date March, 20, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_TREEBUILDERS_H__
21#define __OPC_TREEBUILDERS_H__
22
23 //! Tree splitting rules
24 enum SplittingRules
25 {
26 // Primitive split
27 SPLIT_LARGEST_AXIS = (1<<0), //!< Split along the largest axis
28 SPLIT_SPLATTER_POINTS = (1<<1), //!< Splatter primitive centers (QuickCD-style)
29 SPLIT_BEST_AXIS = (1<<2), //!< Try largest axis, then second, then last
30 SPLIT_BALANCED = (1<<3), //!< Try to keep a well-balanced tree
31 SPLIT_FIFTY = (1<<4), //!< Arbitrary 50-50 split
32 // Node split
33 SPLIT_GEOM_CENTER = (1<<5), //!< Split at geometric center (else split in the middle)
34 //
35 SPLIT_FORCE_DWORD = 0x7fffffff
36 };
37
38 //! Simple wrapper around build-related settings [Opcode 1.3]
39 struct OPCODE_API BuildSettings
40 {
41 inline_ BuildSettings() : mLimit(1), mRules(SPLIT_FORCE_DWORD) {}
42
43 udword mLimit; //!< Limit number of primitives / node. If limit is 1, build a complete tree (2*N-1 nodes)
44 udword mRules; //!< Building/Splitting rules (a combination of SplittingRules flags)
45 };
46
47 class OPCODE_API AABBTreeBuilder
48 {
49 public:
50 //! Constructor
51 AABBTreeBuilder() :
52 mNbPrimitives(0),
53 mNodeBase(null),
54 mCount(0),
55 mNbInvalidSplits(0) {}
56 //! Destructor
57 virtual ~AABBTreeBuilder() {}
58
59 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
60 /**
61 * Computes the AABB of a set of primitives.
62 * \param primitives [in] list of indices of primitives
63 * \param nb_prims [in] number of indices
64 * \param global_box [out] global AABB enclosing the set of input primitives
65 * \return true if success
66 */
67 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
68 virtual bool ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const = 0;
69
70 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
71 /**
72 * Computes the splitting value along a given axis for a given primitive.
73 * \param index [in] index of the primitive to split
74 * \param axis [in] axis index (0,1,2)
75 * \return splitting value
76 */
77 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
78 virtual float GetSplittingValue(udword index, udword axis) const = 0;
79
80 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
81 /**
82 * Computes the splitting value along a given axis for a given node.
83 * \param primitives [in] list of indices of primitives
84 * \param nb_prims [in] number of indices
85 * \param global_box [in] global AABB enclosing the set of input primitives
86 * \param axis [in] axis index (0,1,2)
87 * \return splitting value
88 */
89 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
90 virtual float GetSplittingValue(const udword* primitives, udword nb_prims, const AABB& global_box, udword axis) const
91 {
92 // Default split value = middle of the axis (using only the box)
93 return global_box.GetCenter(axis);
94 }
95
96 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
97 /**
98 * Validates node subdivision. This is called each time a node is considered for subdivision, during tree building.
99 * \param primitives [in] list of indices of primitives
100 * \param nb_prims [in] number of indices
101 * \param global_box [in] global AABB enclosing the set of input primitives
102 * \return TRUE if the node should be subdivised
103 */
104 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
105 virtual BOOL ValidateSubdivision(const udword* primitives, udword nb_prims, const AABB& global_box)
106 {
107 // Check the user-defined limit
108 if(nb_prims<=mSettings.mLimit) return FALSE;
109
110 return TRUE;
111 }
112
113 BuildSettings mSettings; //!< Splitting rules & split limit [Opcode 1.3]
114 udword mNbPrimitives; //!< Total number of primitives.
115 void* mNodeBase; //!< Address of node pool [Opcode 1.3]
116 // Stats
117 inline_ void SetCount(udword nb) { mCount=nb; }
118 inline_ void IncreaseCount(udword nb) { mCount+=nb; }
119 inline_ udword GetCount() const { return mCount; }
120 inline_ void SetNbInvalidSplits(udword nb) { mNbInvalidSplits=nb; }
121 inline_ void IncreaseNbInvalidSplits() { mNbInvalidSplits++; }
122 inline_ udword GetNbInvalidSplits() const { return mNbInvalidSplits; }
123
124 private:
125 udword mCount; //!< Stats: number of nodes created
126 udword mNbInvalidSplits; //!< Stats: number of invalid splits
127 };
128
129 class OPCODE_API AABBTreeOfVerticesBuilder : public AABBTreeBuilder
130 {
131 public:
132 //! Constructor
133 AABBTreeOfVerticesBuilder() : mVertexArray(null) {}
134 //! Destructor
135 virtual ~AABBTreeOfVerticesBuilder() {}
136
137 override(AABBTreeBuilder) bool ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const;
138 override(AABBTreeBuilder) float GetSplittingValue(udword index, udword axis) const;
139 override(AABBTreeBuilder) float GetSplittingValue(const udword* primitives, udword nb_prims, const AABB& global_box, udword axis) const;
140
141 const Point* mVertexArray; //!< Shortcut to an app-controlled array of vertices.
142 };
143
144 class OPCODE_API AABBTreeOfAABBsBuilder : public AABBTreeBuilder
145 {
146 public:
147 //! Constructor
148 AABBTreeOfAABBsBuilder() : mAABBArray(null) {}
149 //! Destructor
150 virtual ~AABBTreeOfAABBsBuilder() {}
151
152 override(AABBTreeBuilder) bool ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const;
153 override(AABBTreeBuilder) float GetSplittingValue(udword index, udword axis) const;
154
155 const AABB* mAABBArray; //!< Shortcut to an app-controlled array of AABBs.
156 };
157
158 class OPCODE_API AABBTreeOfTrianglesBuilder : public AABBTreeBuilder
159 {
160 public:
161 //! Constructor
162 AABBTreeOfTrianglesBuilder() : mIMesh(null) {}
163 //! Destructor
164 virtual ~AABBTreeOfTrianglesBuilder() {}
165
166 override(AABBTreeBuilder) bool ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const;
167 override(AABBTreeBuilder) float GetSplittingValue(udword index, udword axis) const;
168 override(AABBTreeBuilder) float GetSplittingValue(const udword* primitives, udword nb_prims, const AABB& global_box, udword axis) const;
169
170 const MeshInterface* mIMesh; //!< Shortcut to an app-controlled mesh interface
171 };
172
173#endif // __OPC_TREEBUILDERS_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_TreeCollider.cpp b/libraries/ode-0.9/OPCODE/OPC_TreeCollider.cpp
new file mode 100644
index 0000000..f21b39b
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_TreeCollider.cpp
@@ -0,0 +1,943 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for a tree collider.
12 * \file OPC_TreeCollider.cpp
13 * \author Pierre Terdiman
14 * \date March, 20, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19/**
20 * Contains an AABB tree collider.
21 * This class performs a collision test between two AABB trees.
22 *
23 * \class AABBTreeCollider
24 * \author Pierre Terdiman
25 * \version 1.3
26 * \date March, 20, 2001
27*/
28///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
29
30///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
31// Precompiled Header
32#include "Stdafx.h"
33
34using namespace Opcode;
35
36#include "OPC_BoxBoxOverlap.h"
37#include "OPC_TriBoxOverlap.h"
38#include "OPC_TriTriOverlap.h"
39
40///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
41/**
42 * Constructor.
43 */
44///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
45AABBTreeCollider::AABBTreeCollider() :
46 mNbBVBVTests (0),
47 mNbPrimPrimTests (0),
48 mNbBVPrimTests (0),
49 mFullBoxBoxTest (true),
50 mFullPrimBoxTest (true),
51 mIMesh0 (null),
52 mIMesh1 (null)
53{
54}
55
56///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
57/**
58 * Destructor.
59 */
60///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
61AABBTreeCollider::~AABBTreeCollider()
62{
63}
64
65///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
66/**
67 * Validates current settings. You should call this method after all the settings and callbacks have been defined.
68 * \return null if everything is ok, else a string describing the problem
69 */
70///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
71const char* AABBTreeCollider::ValidateSettings()
72{
73 if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!";
74 return null;
75}
76
77///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
78/**
79 * Generic collision query for generic OPCODE models. After the call, access the results with:
80 * - GetContactStatus()
81 * - GetNbPairs()
82 * - GetPairs()
83 *
84 * \param cache [in] collision cache for model pointers and a colliding pair of primitives
85 * \param world0 [in] world matrix for first object
86 * \param world1 [in] world matrix for second object
87 * \return true if success
88 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
89 */
90///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
91bool AABBTreeCollider::Collide(BVTCache& cache, const Matrix4x4* world0, const Matrix4x4* world1)
92{
93 // Checkings
94 if(!cache.Model0 || !cache.Model1) return false;
95 if(cache.Model0->HasLeafNodes()!=cache.Model1->HasLeafNodes()) return false;
96 if(cache.Model0->IsQuantized()!=cache.Model1->IsQuantized()) return false;
97
98 /*
99
100 Rules:
101 - perform hull test
102 - when hulls collide, disable hull test
103 - if meshes overlap, reset countdown
104 - if countdown reaches 0, enable hull test
105
106 */
107
108#ifdef __MESHMERIZER_H__
109 // Handle hulls
110 if(cache.HullTest)
111 {
112 if(cache.Model0->GetHull() && cache.Model1->GetHull())
113 {
114 struct Local
115 {
116 static Point* SVCallback(const Point& sv, udword& previndex, udword user_data)
117 {
118 CollisionHull* Hull = (CollisionHull*)user_data;
119 previndex = Hull->ComputeSupportingVertex(sv, previndex);
120 return (Point*)&Hull->GetVerts()[previndex];
121 }
122 };
123
124 bool Collide;
125
126 if(0)
127 {
128 static GJKEngine GJK;
129 static bool GJKInitDone=false;
130 if(!GJKInitDone)
131 {
132 GJK.Enable(GJK_BACKUP_PROCEDURE);
133 GJK.Enable(GJK_DEGENERATE);
134 GJK.Enable(GJK_HILLCLIMBING);
135 GJKInitDone = true;
136 }
137 GJK.SetCallbackObj0(Local::SVCallback);
138 GJK.SetCallbackObj1(Local::SVCallback);
139 GJK.SetUserData0(udword(cache.Model0->GetHull()));
140 GJK.SetUserData1(udword(cache.Model1->GetHull()));
141 Collide = GJK.Collide(*world0, *world1, &cache.SepVector);
142 }
143 else
144 {
145 static SVEngine SVE;
146 SVE.SetCallbackObj0(Local::SVCallback);
147 SVE.SetCallbackObj1(Local::SVCallback);
148 SVE.SetUserData0(udword(cache.Model0->GetHull()));
149 SVE.SetUserData1(udword(cache.Model1->GetHull()));
150 Collide = SVE.Collide(*world0, *world1, &cache.SepVector);
151 }
152
153 if(!Collide)
154 {
155 // Reset stats & contact status
156 mFlags &= ~OPC_CONTACT;
157 mNbBVBVTests = 0;
158 mNbPrimPrimTests = 0;
159 mNbBVPrimTests = 0;
160 mPairs.Reset();
161 return true;
162 }
163 }
164 }
165
166 // Here, hulls collide
167 cache.HullTest = false;
168#endif // __MESHMERIZER_H__
169
170 // Checkings
171 if(!Setup(cache.Model0->GetMeshInterface(), cache.Model1->GetMeshInterface())) return false;
172
173 // Simple double-dispatch
174 bool Status;
175 if(!cache.Model0->HasLeafNodes())
176 {
177 if(cache.Model0->IsQuantized())
178 {
179 const AABBQuantizedNoLeafTree* T0 = (const AABBQuantizedNoLeafTree*)cache.Model0->GetTree();
180 const AABBQuantizedNoLeafTree* T1 = (const AABBQuantizedNoLeafTree*)cache.Model1->GetTree();
181 Status = Collide(T0, T1, world0, world1, &cache);
182 }
183 else
184 {
185 const AABBNoLeafTree* T0 = (const AABBNoLeafTree*)cache.Model0->GetTree();
186 const AABBNoLeafTree* T1 = (const AABBNoLeafTree*)cache.Model1->GetTree();
187 Status = Collide(T0, T1, world0, world1, &cache);
188 }
189 }
190 else
191 {
192 if(cache.Model0->IsQuantized())
193 {
194 const AABBQuantizedTree* T0 = (const AABBQuantizedTree*)cache.Model0->GetTree();
195 const AABBQuantizedTree* T1 = (const AABBQuantizedTree*)cache.Model1->GetTree();
196 Status = Collide(T0, T1, world0, world1, &cache);
197 }
198 else
199 {
200 const AABBCollisionTree* T0 = (const AABBCollisionTree*)cache.Model0->GetTree();
201 const AABBCollisionTree* T1 = (const AABBCollisionTree*)cache.Model1->GetTree();
202 Status = Collide(T0, T1, world0, world1, &cache);
203 }
204 }
205
206#ifdef __MESHMERIZER_H__
207 if(Status)
208 {
209 // Reset counter as long as overlap occurs
210 if(GetContactStatus()) cache.ResetCountDown();
211
212 // Enable hull test again when counter reaches zero
213 cache.CountDown--;
214 if(!cache.CountDown)
215 {
216 cache.ResetCountDown();
217 cache.HullTest = true;
218 }
219 }
220#endif
221 return Status;
222}
223
224///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
225/**
226 * Initializes a collision query :
227 * - reset stats & contact status
228 * - setup matrices
229 *
230 * \param world0 [in] world matrix for first object
231 * \param world1 [in] world matrix for second object
232 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
233 */
234///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
235void AABBTreeCollider::InitQuery(const Matrix4x4* world0, const Matrix4x4* world1)
236{
237 // Reset stats & contact status
238 Collider::InitQuery();
239 mNbBVBVTests = 0;
240 mNbPrimPrimTests = 0;
241 mNbBVPrimTests = 0;
242 mPairs.Reset();
243
244 // Setup matrices
245 Matrix4x4 InvWorld0, InvWorld1;
246 if(world0) InvertPRMatrix(InvWorld0, *world0);
247 else InvWorld0.Identity();
248
249 if(world1) InvertPRMatrix(InvWorld1, *world1);
250 else InvWorld1.Identity();
251
252 Matrix4x4 World0to1 = world0 ? (*world0 * InvWorld1) : InvWorld1;
253 Matrix4x4 World1to0 = world1 ? (*world1 * InvWorld0) : InvWorld0;
254
255 mR0to1 = World0to1; World0to1.GetTrans(mT0to1);
256 mR1to0 = World1to0; World1to0.GetTrans(mT1to0);
257
258 // Precompute absolute 1-to-0 rotation matrix
259 for(udword i=0;i<3;i++)
260 {
261 for(udword j=0;j<3;j++)
262 {
263 // Epsilon value prevents floating-point inaccuracies (strategy borrowed from RAPID)
264 mAR.m[i][j] = 1e-6f + fabsf(mR1to0.m[i][j]);
265 }
266 }
267}
268
269///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
270/**
271 * Takes advantage of temporal coherence.
272 * \param cache [in] cache for a pair of previously colliding primitives
273 * \return true if we can return immediately
274 * \warning only works for "First Contact" mode
275 */
276///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
277bool AABBTreeCollider::CheckTemporalCoherence(Pair* cache)
278{
279 // Checkings
280 if(!cache) return false;
281
282 // Test previously colliding primitives first
283 if(TemporalCoherenceEnabled() && FirstContactEnabled())
284 {
285 PrimTest(cache->id0, cache->id1);
286 if(GetContactStatus()) return true;
287 }
288 return false;
289}
290
291#define UPDATE_CACHE \
292 if(cache && GetContactStatus()) \
293 { \
294 cache->id0 = mPairs.GetEntry(0); \
295 cache->id1 = mPairs.GetEntry(1); \
296 }
297
298///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
299/**
300 * Collision query for normal AABB trees.
301 * \param tree0 [in] AABB tree from first object
302 * \param tree1 [in] AABB tree from second object
303 * \param world0 [in] world matrix for first object
304 * \param world1 [in] world matrix for second object
305 * \param cache [in/out] cache for a pair of previously colliding primitives
306 * \return true if success
307 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
308 */
309///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
310bool AABBTreeCollider::Collide(const AABBCollisionTree* tree0, const AABBCollisionTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache)
311{
312 // Init collision query
313 InitQuery(world0, world1);
314
315 // Check previous state
316 if(CheckTemporalCoherence(cache)) return true;
317
318 // Perform collision query
319 _Collide(tree0->GetNodes(), tree1->GetNodes());
320
321 UPDATE_CACHE
322
323 return true;
324}
325
326///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
327/**
328 * Collision query for no-leaf AABB trees.
329 * \param tree0 [in] AABB tree from first object
330 * \param tree1 [in] AABB tree from second object
331 * \param world0 [in] world matrix for first object
332 * \param world1 [in] world matrix for second object
333 * \param cache [in/out] cache for a pair of previously colliding primitives
334 * \return true if success
335 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
336 */
337///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
338bool AABBTreeCollider::Collide(const AABBNoLeafTree* tree0, const AABBNoLeafTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache)
339{
340 // Init collision query
341 InitQuery(world0, world1);
342
343 // Check previous state
344 if(CheckTemporalCoherence(cache)) return true;
345
346 // Perform collision query
347 _Collide(tree0->GetNodes(), tree1->GetNodes());
348
349 UPDATE_CACHE
350
351 return true;
352}
353
354///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
355/**
356 * Collision query for quantized AABB trees.
357 * \param tree0 [in] AABB tree from first object
358 * \param tree1 [in] AABB tree from second object
359 * \param world0 [in] world matrix for first object
360 * \param world1 [in] world matrix for second object
361 * \param cache [in/out] cache for a pair of previously colliding primitives
362 * \return true if success
363 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
364 */
365///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
366bool AABBTreeCollider::Collide(const AABBQuantizedTree* tree0, const AABBQuantizedTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache)
367{
368 // Init collision query
369 InitQuery(world0, world1);
370
371 // Check previous state
372 if(CheckTemporalCoherence(cache)) return true;
373
374 // Setup dequantization coeffs
375 mCenterCoeff0 = tree0->mCenterCoeff;
376 mExtentsCoeff0 = tree0->mExtentsCoeff;
377 mCenterCoeff1 = tree1->mCenterCoeff;
378 mExtentsCoeff1 = tree1->mExtentsCoeff;
379
380 // Dequantize box A
381 const AABBQuantizedNode* N0 = tree0->GetNodes();
382 const Point a(float(N0->mAABB.mExtents[0]) * mExtentsCoeff0.x, float(N0->mAABB.mExtents[1]) * mExtentsCoeff0.y, float(N0->mAABB.mExtents[2]) * mExtentsCoeff0.z);
383 const Point Pa(float(N0->mAABB.mCenter[0]) * mCenterCoeff0.x, float(N0->mAABB.mCenter[1]) * mCenterCoeff0.y, float(N0->mAABB.mCenter[2]) * mCenterCoeff0.z);
384 // Dequantize box B
385 const AABBQuantizedNode* N1 = tree1->GetNodes();
386 const Point b(float(N1->mAABB.mExtents[0]) * mExtentsCoeff1.x, float(N1->mAABB.mExtents[1]) * mExtentsCoeff1.y, float(N1->mAABB.mExtents[2]) * mExtentsCoeff1.z);
387 const Point Pb(float(N1->mAABB.mCenter[0]) * mCenterCoeff1.x, float(N1->mAABB.mCenter[1]) * mCenterCoeff1.y, float(N1->mAABB.mCenter[2]) * mCenterCoeff1.z);
388
389 // Perform collision query
390 _Collide(N0, N1, a, Pa, b, Pb);
391
392 UPDATE_CACHE
393
394 return true;
395}
396
397///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
398/**
399 * Collision query for quantized no-leaf AABB trees.
400 * \param tree0 [in] AABB tree from first object
401 * \param tree1 [in] AABB tree from second object
402 * \param world0 [in] world matrix for first object
403 * \param world1 [in] world matrix for second object
404 * \param cache [in/out] cache for a pair of previously colliding primitives
405 * \return true if success
406 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
407 */
408///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
409bool AABBTreeCollider::Collide(const AABBQuantizedNoLeafTree* tree0, const AABBQuantizedNoLeafTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache)
410{
411 // Init collision query
412 InitQuery(world0, world1);
413
414 // Check previous state
415 if(CheckTemporalCoherence(cache)) return true;
416
417 // Setup dequantization coeffs
418 mCenterCoeff0 = tree0->mCenterCoeff;
419 mExtentsCoeff0 = tree0->mExtentsCoeff;
420 mCenterCoeff1 = tree1->mCenterCoeff;
421 mExtentsCoeff1 = tree1->mExtentsCoeff;
422
423 // Perform collision query
424 _Collide(tree0->GetNodes(), tree1->GetNodes());
425
426 UPDATE_CACHE
427
428 return true;
429}
430
431///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
432// Standard trees
433///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
434
435// The normal AABB tree can use 2 different descent rules (with different performances)
436//#define ORIGINAL_CODE //!< UNC-like descent rules
437#define ALTERNATIVE_CODE //!< Alternative descent rules
438
439#ifdef ORIGINAL_CODE
440///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
441/**
442 * Recursive collision query for normal AABB trees.
443 * \param b0 [in] collision node from first tree
444 * \param b1 [in] collision node from second tree
445 */
446///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
447void AABBTreeCollider::_Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1)
448{
449 // Perform BV-BV overlap test
450 if(!BoxBoxOverlap(b0->mAABB.mExtents, b0->mAABB.mCenter, b1->mAABB.mExtents, b1->mAABB.mCenter)) return;
451
452 if(b0->IsLeaf() && b1->IsLeaf()) { PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); return; }
453
454 if(b1->IsLeaf() || (!b0->IsLeaf() && (b0->GetSize() > b1->GetSize())))
455 {
456 _Collide(b0->GetNeg(), b1);
457 if(ContactFound()) return;
458 _Collide(b0->GetPos(), b1);
459 }
460 else
461 {
462 _Collide(b0, b1->GetNeg());
463 if(ContactFound()) return;
464 _Collide(b0, b1->GetPos());
465 }
466}
467#endif
468
469#ifdef ALTERNATIVE_CODE
470///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
471/**
472 * Recursive collision query for normal AABB trees.
473 * \param b0 [in] collision node from first tree
474 * \param b1 [in] collision node from second tree
475 */
476///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
477void AABBTreeCollider::_Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1)
478{
479 // Perform BV-BV overlap test
480 if(!BoxBoxOverlap(b0->mAABB.mExtents, b0->mAABB.mCenter, b1->mAABB.mExtents, b1->mAABB.mCenter))
481 {
482 return;
483 }
484
485 if(b0->IsLeaf())
486 {
487 if(b1->IsLeaf())
488 {
489 PrimTest(b0->GetPrimitive(), b1->GetPrimitive());
490 }
491 else
492 {
493 _Collide(b0, b1->GetNeg());
494 if(ContactFound()) return;
495 _Collide(b0, b1->GetPos());
496 }
497 }
498 else if(b1->IsLeaf())
499 {
500 _Collide(b0->GetNeg(), b1);
501 if(ContactFound()) return;
502 _Collide(b0->GetPos(), b1);
503 }
504 else
505 {
506 _Collide(b0->GetNeg(), b1->GetNeg());
507 if(ContactFound()) return;
508 _Collide(b0->GetNeg(), b1->GetPos());
509 if(ContactFound()) return;
510 _Collide(b0->GetPos(), b1->GetNeg());
511 if(ContactFound()) return;
512 _Collide(b0->GetPos(), b1->GetPos());
513 }
514}
515#endif
516
517///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
518// No-leaf trees
519///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
520
521///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
522/**
523 * Leaf-leaf test for two primitive indices.
524 * \param id0 [in] index from first leaf-triangle
525 * \param id1 [in] index from second leaf-triangle
526 */
527///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
528void AABBTreeCollider::PrimTest(udword id0, udword id1)
529{
530 // Request vertices from the app
531 VertexPointers VP0;
532 VertexPointers VP1;
533 mIMesh0->GetTriangle(VP0, id0);
534 mIMesh1->GetTriangle(VP1, id1);
535
536 // Transform from space 1 to space 0
537 Point u0,u1,u2;
538 TransformPoint(u0, *VP1.Vertex[0], mR1to0, mT1to0);
539 TransformPoint(u1, *VP1.Vertex[1], mR1to0, mT1to0);
540 TransformPoint(u2, *VP1.Vertex[2], mR1to0, mT1to0);
541
542 // Perform triangle-triangle overlap test
543 if(TriTriOverlap(*VP0.Vertex[0], *VP0.Vertex[1], *VP0.Vertex[2], u0, u1, u2))
544 {
545 // Keep track of colliding pairs
546 mPairs.Add(id0).Add(id1);
547 // Set contact status
548 mFlags |= OPC_CONTACT;
549 }
550}
551
552///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
553/**
554 * Leaf-leaf test for a previously fetched triangle from tree A (in B's space) and a new leaf from B.
555 * \param id1 [in] leaf-triangle index from tree B
556 */
557///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
558inline_ void AABBTreeCollider::PrimTestTriIndex(udword id1)
559{
560 // Request vertices from the app
561 VertexPointers VP;
562 mIMesh1->GetTriangle(VP, id1);
563
564 // Perform triangle-triangle overlap test
565 if(TriTriOverlap(mLeafVerts[0], mLeafVerts[1], mLeafVerts[2], *VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2]))
566 {
567 // Keep track of colliding pairs
568 mPairs.Add(mLeafIndex).Add(id1);
569 // Set contact status
570 mFlags |= OPC_CONTACT;
571 }
572}
573
574///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
575/**
576 * Leaf-leaf test for a previously fetched triangle from tree B (in A's space) and a new leaf from A.
577 * \param id0 [in] leaf-triangle index from tree A
578 */
579///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
580inline_ void AABBTreeCollider::PrimTestIndexTri(udword id0)
581{
582 // Request vertices from the app
583 VertexPointers VP;
584 mIMesh0->GetTriangle(VP, id0);
585
586 // Perform triangle-triangle overlap test
587 if(TriTriOverlap(mLeafVerts[0], mLeafVerts[1], mLeafVerts[2], *VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2]))
588 {
589 // Keep track of colliding pairs
590 mPairs.Add(id0).Add(mLeafIndex);
591 // Set contact status
592 mFlags |= OPC_CONTACT;
593 }
594}
595
596///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
597/**
598 * Recursive collision of a leaf node from A and a branch from B.
599 * \param b [in] collision node from second tree
600 */
601///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
602void AABBTreeCollider::_CollideTriBox(const AABBNoLeafNode* b)
603{
604 // Perform triangle-box overlap test
605 if(!TriBoxOverlap(b->mAABB.mCenter, b->mAABB.mExtents)) return;
606
607 // Keep same triangle, deal with first child
608 if(b->HasPosLeaf()) PrimTestTriIndex(b->GetPosPrimitive());
609 else _CollideTriBox(b->GetPos());
610
611 if(ContactFound()) return;
612
613 // Keep same triangle, deal with second child
614 if(b->HasNegLeaf()) PrimTestTriIndex(b->GetNegPrimitive());
615 else _CollideTriBox(b->GetNeg());
616}
617
618///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
619/**
620 * Recursive collision of a leaf node from B and a branch from A.
621 * \param b [in] collision node from first tree
622 */
623///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
624void AABBTreeCollider::_CollideBoxTri(const AABBNoLeafNode* b)
625{
626 // Perform triangle-box overlap test
627 if(!TriBoxOverlap(b->mAABB.mCenter, b->mAABB.mExtents)) return;
628
629 // Keep same triangle, deal with first child
630 if(b->HasPosLeaf()) PrimTestIndexTri(b->GetPosPrimitive());
631 else _CollideBoxTri(b->GetPos());
632
633 if(ContactFound()) return;
634
635 // Keep same triangle, deal with second child
636 if(b->HasNegLeaf()) PrimTestIndexTri(b->GetNegPrimitive());
637 else _CollideBoxTri(b->GetNeg());
638}
639
640//! Request triangle vertices from the app and transform them
641#define FETCH_LEAF(prim_index, imesh, rot, trans) \
642 mLeafIndex = prim_index; \
643 /* Request vertices from the app */ \
644 VertexPointers VP; imesh->GetTriangle(VP, prim_index); \
645 /* Transform them in a common space */ \
646 TransformPoint(mLeafVerts[0], *VP.Vertex[0], rot, trans); \
647 TransformPoint(mLeafVerts[1], *VP.Vertex[1], rot, trans); \
648 TransformPoint(mLeafVerts[2], *VP.Vertex[2], rot, trans);
649
650///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
651/**
652 * Recursive collision query for no-leaf AABB trees.
653 * \param a [in] collision node from first tree
654 * \param b [in] collision node from second tree
655 */
656///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
657void AABBTreeCollider::_Collide(const AABBNoLeafNode* a, const AABBNoLeafNode* b)
658{
659 // Perform BV-BV overlap test
660 if(!BoxBoxOverlap(a->mAABB.mExtents, a->mAABB.mCenter, b->mAABB.mExtents, b->mAABB.mCenter)) return;
661
662 // Catch leaf status
663 BOOL BHasPosLeaf = b->HasPosLeaf();
664 BOOL BHasNegLeaf = b->HasNegLeaf();
665
666 if(a->HasPosLeaf())
667 {
668 FETCH_LEAF(a->GetPosPrimitive(), mIMesh0, mR0to1, mT0to1)
669
670 if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive());
671 else _CollideTriBox(b->GetPos());
672
673 if(ContactFound()) return;
674
675 if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive());
676 else _CollideTriBox(b->GetNeg());
677 }
678 else
679 {
680 if(BHasPosLeaf)
681 {
682 FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0)
683
684 _CollideBoxTri(a->GetPos());
685 }
686 else _Collide(a->GetPos(), b->GetPos());
687
688 if(ContactFound()) return;
689
690 if(BHasNegLeaf)
691 {
692 FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0)
693
694 _CollideBoxTri(a->GetPos());
695 }
696 else _Collide(a->GetPos(), b->GetNeg());
697 }
698
699 if(ContactFound()) return;
700
701 if(a->HasNegLeaf())
702 {
703 FETCH_LEAF(a->GetNegPrimitive(), mIMesh0, mR0to1, mT0to1)
704
705 if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive());
706 else _CollideTriBox(b->GetPos());
707
708 if(ContactFound()) return;
709
710 if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive());
711 else _CollideTriBox(b->GetNeg());
712 }
713 else
714 {
715 if(BHasPosLeaf)
716 {
717 // ### That leaf has possibly already been fetched
718 FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0)
719
720 _CollideBoxTri(a->GetNeg());
721 }
722 else _Collide(a->GetNeg(), b->GetPos());
723
724 if(ContactFound()) return;
725
726 if(BHasNegLeaf)
727 {
728 // ### That leaf has possibly already been fetched
729 FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0)
730
731 _CollideBoxTri(a->GetNeg());
732 }
733 else _Collide(a->GetNeg(), b->GetNeg());
734 }
735}
736
737///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
738// Quantized trees
739///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
740
741///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
742/**
743 * Recursive collision query for quantized AABB trees.
744 * \param b0 [in] collision node from first tree
745 * \param b1 [in] collision node from second tree
746 * \param a [in] extent from box A
747 * \param Pa [in] center from box A
748 * \param b [in] extent from box B
749 * \param Pb [in] center from box B
750 */
751///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
752void AABBTreeCollider::_Collide(const AABBQuantizedNode* b0, const AABBQuantizedNode* b1, const Point& a, const Point& Pa, const Point& b, const Point& Pb)
753{
754 // Perform BV-BV overlap test
755 if(!BoxBoxOverlap(a, Pa, b, Pb)) return;
756
757 if(b0->IsLeaf() && b1->IsLeaf()) { PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); return; }
758
759 if(b1->IsLeaf() || (!b0->IsLeaf() && (b0->GetSize() > b1->GetSize())))
760 {
761 // Dequantize box
762 const QuantizedAABB* Box = &b0->GetNeg()->mAABB;
763 const Point negPa(float(Box->mCenter[0]) * mCenterCoeff0.x, float(Box->mCenter[1]) * mCenterCoeff0.y, float(Box->mCenter[2]) * mCenterCoeff0.z);
764 const Point nega(float(Box->mExtents[0]) * mExtentsCoeff0.x, float(Box->mExtents[1]) * mExtentsCoeff0.y, float(Box->mExtents[2]) * mExtentsCoeff0.z);
765 _Collide(b0->GetNeg(), b1, nega, negPa, b, Pb);
766
767 if(ContactFound()) return;
768
769 // Dequantize box
770 Box = &b0->GetPos()->mAABB;
771 const Point posPa(float(Box->mCenter[0]) * mCenterCoeff0.x, float(Box->mCenter[1]) * mCenterCoeff0.y, float(Box->mCenter[2]) * mCenterCoeff0.z);
772 const Point posa(float(Box->mExtents[0]) * mExtentsCoeff0.x, float(Box->mExtents[1]) * mExtentsCoeff0.y, float(Box->mExtents[2]) * mExtentsCoeff0.z);
773 _Collide(b0->GetPos(), b1, posa, posPa, b, Pb);
774 }
775 else
776 {
777 // Dequantize box
778 const QuantizedAABB* Box = &b1->GetNeg()->mAABB;
779 const Point negPb(float(Box->mCenter[0]) * mCenterCoeff1.x, float(Box->mCenter[1]) * mCenterCoeff1.y, float(Box->mCenter[2]) * mCenterCoeff1.z);
780 const Point negb(float(Box->mExtents[0]) * mExtentsCoeff1.x, float(Box->mExtents[1]) * mExtentsCoeff1.y, float(Box->mExtents[2]) * mExtentsCoeff1.z);
781 _Collide(b0, b1->GetNeg(), a, Pa, negb, negPb);
782
783 if(ContactFound()) return;
784
785 // Dequantize box
786 Box = &b1->GetPos()->mAABB;
787 const Point posPb(float(Box->mCenter[0]) * mCenterCoeff1.x, float(Box->mCenter[1]) * mCenterCoeff1.y, float(Box->mCenter[2]) * mCenterCoeff1.z);
788 const Point posb(float(Box->mExtents[0]) * mExtentsCoeff1.x, float(Box->mExtents[1]) * mExtentsCoeff1.y, float(Box->mExtents[2]) * mExtentsCoeff1.z);
789 _Collide(b0, b1->GetPos(), a, Pa, posb, posPb);
790 }
791}
792
793///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
794// Quantized no-leaf trees
795///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
796
797///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
798/**
799 * Recursive collision of a leaf node from A and a quantized branch from B.
800 * \param leaf [in] leaf triangle from first tree
801 * \param b [in] collision node from second tree
802 */
803///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
804void AABBTreeCollider::_CollideTriBox(const AABBQuantizedNoLeafNode* b)
805{
806 // Dequantize box
807 const QuantizedAABB* bb = &b->mAABB;
808 const Point Pb(float(bb->mCenter[0]) * mCenterCoeff1.x, float(bb->mCenter[1]) * mCenterCoeff1.y, float(bb->mCenter[2]) * mCenterCoeff1.z);
809 const Point eb(float(bb->mExtents[0]) * mExtentsCoeff1.x, float(bb->mExtents[1]) * mExtentsCoeff1.y, float(bb->mExtents[2]) * mExtentsCoeff1.z);
810
811 // Perform triangle-box overlap test
812 if(!TriBoxOverlap(Pb, eb)) return;
813
814 if(b->HasPosLeaf()) PrimTestTriIndex(b->GetPosPrimitive());
815 else _CollideTriBox(b->GetPos());
816
817 if(ContactFound()) return;
818
819 if(b->HasNegLeaf()) PrimTestTriIndex(b->GetNegPrimitive());
820 else _CollideTriBox(b->GetNeg());
821}
822
823///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
824/**
825 * Recursive collision of a leaf node from B and a quantized branch from A.
826 * \param b [in] collision node from first tree
827 * \param leaf [in] leaf triangle from second tree
828 */
829///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
830void AABBTreeCollider::_CollideBoxTri(const AABBQuantizedNoLeafNode* b)
831{
832 // Dequantize box
833 const QuantizedAABB* bb = &b->mAABB;
834 const Point Pa(float(bb->mCenter[0]) * mCenterCoeff0.x, float(bb->mCenter[1]) * mCenterCoeff0.y, float(bb->mCenter[2]) * mCenterCoeff0.z);
835 const Point ea(float(bb->mExtents[0]) * mExtentsCoeff0.x, float(bb->mExtents[1]) * mExtentsCoeff0.y, float(bb->mExtents[2]) * mExtentsCoeff0.z);
836
837 // Perform triangle-box overlap test
838 if(!TriBoxOverlap(Pa, ea)) return;
839
840 if(b->HasPosLeaf()) PrimTestIndexTri(b->GetPosPrimitive());
841 else _CollideBoxTri(b->GetPos());
842
843 if(ContactFound()) return;
844
845 if(b->HasNegLeaf()) PrimTestIndexTri(b->GetNegPrimitive());
846 else _CollideBoxTri(b->GetNeg());
847}
848
849///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
850/**
851 * Recursive collision query for quantized no-leaf AABB trees.
852 * \param a [in] collision node from first tree
853 * \param b [in] collision node from second tree
854 */
855///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
856void AABBTreeCollider::_Collide(const AABBQuantizedNoLeafNode* a, const AABBQuantizedNoLeafNode* b)
857{
858 // Dequantize box A
859 const QuantizedAABB* ab = &a->mAABB;
860 const Point Pa(float(ab->mCenter[0]) * mCenterCoeff0.x, float(ab->mCenter[1]) * mCenterCoeff0.y, float(ab->mCenter[2]) * mCenterCoeff0.z);
861 const Point ea(float(ab->mExtents[0]) * mExtentsCoeff0.x, float(ab->mExtents[1]) * mExtentsCoeff0.y, float(ab->mExtents[2]) * mExtentsCoeff0.z);
862 // Dequantize box B
863 const QuantizedAABB* bb = &b->mAABB;
864 const Point Pb(float(bb->mCenter[0]) * mCenterCoeff1.x, float(bb->mCenter[1]) * mCenterCoeff1.y, float(bb->mCenter[2]) * mCenterCoeff1.z);
865 const Point eb(float(bb->mExtents[0]) * mExtentsCoeff1.x, float(bb->mExtents[1]) * mExtentsCoeff1.y, float(bb->mExtents[2]) * mExtentsCoeff1.z);
866
867 // Perform BV-BV overlap test
868 if(!BoxBoxOverlap(ea, Pa, eb, Pb)) return;
869
870 // Catch leaf status
871 BOOL BHasPosLeaf = b->HasPosLeaf();
872 BOOL BHasNegLeaf = b->HasNegLeaf();
873
874 if(a->HasPosLeaf())
875 {
876 FETCH_LEAF(a->GetPosPrimitive(), mIMesh0, mR0to1, mT0to1)
877
878 if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive());
879 else _CollideTriBox(b->GetPos());
880
881 if(ContactFound()) return;
882
883 if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive());
884 else _CollideTriBox(b->GetNeg());
885 }
886 else
887 {
888 if(BHasPosLeaf)
889 {
890 FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0)
891
892 _CollideBoxTri(a->GetPos());
893 }
894 else _Collide(a->GetPos(), b->GetPos());
895
896 if(ContactFound()) return;
897
898 if(BHasNegLeaf)
899 {
900 FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0)
901
902 _CollideBoxTri(a->GetPos());
903 }
904 else _Collide(a->GetPos(), b->GetNeg());
905 }
906
907 if(ContactFound()) return;
908
909 if(a->HasNegLeaf())
910 {
911 FETCH_LEAF(a->GetNegPrimitive(), mIMesh0, mR0to1, mT0to1)
912
913 if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive());
914 else _CollideTriBox(b->GetPos());
915
916 if(ContactFound()) return;
917
918 if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive());
919 else _CollideTriBox(b->GetNeg());
920 }
921 else
922 {
923 if(BHasPosLeaf)
924 {
925 // ### That leaf has possibly already been fetched
926 FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0)
927
928 _CollideBoxTri(a->GetNeg());
929 }
930 else _Collide(a->GetNeg(), b->GetPos());
931
932 if(ContactFound()) return;
933
934 if(BHasNegLeaf)
935 {
936 // ### That leaf has possibly already been fetched
937 FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0)
938
939 _CollideBoxTri(a->GetNeg());
940 }
941 else _Collide(a->GetNeg(), b->GetNeg());
942 }
943}
diff --git a/libraries/ode-0.9/OPCODE/OPC_TreeCollider.h b/libraries/ode-0.9/OPCODE/OPC_TreeCollider.h
new file mode 100644
index 0000000..1e943a4
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_TreeCollider.h
@@ -0,0 +1,246 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains code for a tree collider.
12 * \file OPC_TreeCollider.h
13 * \author Pierre Terdiman
14 * \date March, 20, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_TREECOLLIDER_H__
21#define __OPC_TREECOLLIDER_H__
22
23 //! This structure holds cached information used by the algorithm.
24 //! Two model pointers and two colliding primitives are cached. Model pointers are assigned
25 //! to their respective meshes, and the pair of colliding primitives is used for temporal
26 //! coherence. That is, in case temporal coherence is enabled, those two primitives are
27 //! tested for overlap before everything else. If they still collide, we're done before
28 //! even entering the recursive collision code.
29 struct OPCODE_API BVTCache : Pair
30 {
31 //! Constructor
32 inline_ BVTCache()
33 {
34 ResetCache();
35 ResetCountDown();
36 }
37
38 void ResetCache()
39 {
40 Model0 = null;
41 Model1 = null;
42 id0 = 0;
43 id1 = 1;
44#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE !
45 HullTest = true;
46 SepVector.pid = 0;
47 SepVector.qid = 0;
48 SepVector.SV = Point(1.0f, 0.0f, 0.0f);
49#endif // __MESHMERIZER_H__
50 }
51
52#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE !
53 inline_ void ResetCountDown()
54 {
55 CountDown = 50;
56 }
57#else
58 void ResetCountDown(){};
59#endif // __MESHMERIZER_H__
60
61 const Model* Model0; //!< Model for first object
62 const Model* Model1; //!< Model for second object
63
64#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE !
65 SVCache SepVector;
66 udword CountDown;
67 bool HullTest;
68#endif // __MESHMERIZER_H__
69 };
70
71 class OPCODE_API AABBTreeCollider : public Collider
72 {
73 public:
74 // Constructor / Destructor
75 AABBTreeCollider();
76 virtual ~AABBTreeCollider();
77 // Generic collision query
78
79 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
80 /**
81 * Generic collision query for generic OPCODE models. After the call, access the results with:
82 * - GetContactStatus()
83 * - GetNbPairs()
84 * - GetPairs()
85 *
86 * \param cache [in] collision cache for model pointers and a colliding pair of primitives
87 * \param world0 [in] world matrix for first object, or null
88 * \param world1 [in] world matrix for second object, or null
89 * \return true if success
90 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
91 */
92 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
93 bool Collide(BVTCache& cache, const Matrix4x4* world0=null, const Matrix4x4* world1=null);
94
95 // Collision queries
96 bool Collide(const AABBCollisionTree* tree0, const AABBCollisionTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null);
97 bool Collide(const AABBNoLeafTree* tree0, const AABBNoLeafTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null);
98 bool Collide(const AABBQuantizedTree* tree0, const AABBQuantizedTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null);
99 bool Collide(const AABBQuantizedNoLeafTree* tree0, const AABBQuantizedNoLeafTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null);
100 // Settings
101
102 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
103 /**
104 * Settings: selects between full box-box tests or "SAT-lite" tests (where Class III axes are discarded)
105 * \param flag [in] true for full tests, false for coarse tests
106 * \see SetFullPrimBoxTest(bool flag)
107 */
108 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
109 inline_ void SetFullBoxBoxTest(bool flag) { mFullBoxBoxTest = flag; }
110
111 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
112 /**
113 * Settings: selects between full triangle-box tests or "SAT-lite" tests (where Class III axes are discarded)
114 * \param flag [in] true for full tests, false for coarse tests
115 * \see SetFullBoxBoxTest(bool flag)
116 */
117 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
118 inline_ void SetFullPrimBoxTest(bool flag) { mFullPrimBoxTest = flag; }
119
120 // Stats
121
122 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
123 /**
124 * Stats: gets the number of BV-BV overlap tests after a collision query.
125 * \see GetNbPrimPrimTests()
126 * \see GetNbBVPrimTests()
127 * \return the number of BV-BV tests performed during last query
128 */
129 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
130 inline_ udword GetNbBVBVTests() const { return mNbBVBVTests; }
131
132 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
133 /**
134 * Stats: gets the number of Triangle-Triangle overlap tests after a collision query.
135 * \see GetNbBVBVTests()
136 * \see GetNbBVPrimTests()
137 * \return the number of Triangle-Triangle tests performed during last query
138 */
139 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
140 inline_ udword GetNbPrimPrimTests() const { return mNbPrimPrimTests; }
141
142 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
143 /**
144 * Stats: gets the number of BV-Triangle overlap tests after a collision query.
145 * \see GetNbBVBVTests()
146 * \see GetNbPrimPrimTests()
147 * \return the number of BV-Triangle tests performed during last query
148 */
149 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
150 inline_ udword GetNbBVPrimTests() const { return mNbBVPrimTests; }
151
152 // Data access
153
154 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
155 /**
156 * Gets the number of contacts after a collision query.
157 * \see GetContactStatus()
158 * \see GetPairs()
159 * \return the number of contacts / colliding pairs.
160 */
161 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
162 inline_ udword GetNbPairs() const { return mPairs.GetNbEntries()>>1; }
163
164 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
165 /**
166 * Gets the pairs of colliding triangles after a collision query.
167 * \see GetContactStatus()
168 * \see GetNbPairs()
169 * \return the list of colliding pairs (triangle indices)
170 */
171 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
172 inline_ const Pair* GetPairs() const { return (const Pair*)mPairs.GetEntries(); }
173
174 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
175 /**
176 * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider.
177 * \return null if everything is ok, else a string describing the problem
178 */
179 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
180 override(Collider) const char* ValidateSettings();
181
182 protected:
183 // Colliding pairs
184 Container mPairs; //!< Pairs of colliding primitives
185 // User mesh interfaces
186 const MeshInterface* mIMesh0; //!< User-defined mesh interface for object0
187 const MeshInterface* mIMesh1; //!< User-defined mesh interface for object1
188 // Stats
189 udword mNbBVBVTests; //!< Number of BV-BV tests
190 udword mNbPrimPrimTests; //!< Number of Primitive-Primitive tests
191 udword mNbBVPrimTests; //!< Number of BV-Primitive tests
192 // Precomputed data
193 Matrix3x3 mAR; //!< Absolute rotation matrix
194 Matrix3x3 mR0to1; //!< Rotation from object0 to object1
195 Matrix3x3 mR1to0; //!< Rotation from object1 to object0
196 Point mT0to1; //!< Translation from object0 to object1
197 Point mT1to0; //!< Translation from object1 to object0
198 // Dequantization coeffs
199 Point mCenterCoeff0;
200 Point mExtentsCoeff0;
201 Point mCenterCoeff1;
202 Point mExtentsCoeff1;
203 // Leaf description
204 Point mLeafVerts[3]; //!< Triangle vertices
205 udword mLeafIndex; //!< Triangle index
206 // Settings
207 bool mFullBoxBoxTest; //!< Perform full BV-BV tests (true) or SAT-lite tests (false)
208 bool mFullPrimBoxTest; //!< Perform full Primitive-BV tests (true) or SAT-lite tests (false)
209 // Internal methods
210
211 // Standard AABB trees
212 void _Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1);
213 // Quantized AABB trees
214 void _Collide(const AABBQuantizedNode* b0, const AABBQuantizedNode* b1, const Point& a, const Point& Pa, const Point& b, const Point& Pb);
215 // No-leaf AABB trees
216 void _CollideTriBox(const AABBNoLeafNode* b);
217 void _CollideBoxTri(const AABBNoLeafNode* b);
218 void _Collide(const AABBNoLeafNode* a, const AABBNoLeafNode* b);
219 // Quantized no-leaf AABB trees
220 void _CollideTriBox(const AABBQuantizedNoLeafNode* b);
221 void _CollideBoxTri(const AABBQuantizedNoLeafNode* b);
222 void _Collide(const AABBQuantizedNoLeafNode* a, const AABBQuantizedNoLeafNode* b);
223 // Overlap tests
224 void PrimTest(udword id0, udword id1);
225 inline_ void PrimTestTriIndex(udword id1);
226 inline_ void PrimTestIndexTri(udword id0);
227
228 inline_ BOOL BoxBoxOverlap(const Point& ea, const Point& ca, const Point& eb, const Point& cb);
229 inline_ BOOL TriBoxOverlap(const Point& center, const Point& extents);
230 inline_ BOOL TriTriOverlap(const Point& V0, const Point& V1, const Point& V2, const Point& U0, const Point& U1, const Point& U2);
231 // Init methods
232 void InitQuery(const Matrix4x4* world0=null, const Matrix4x4* world1=null);
233 bool CheckTemporalCoherence(Pair* cache);
234
235 inline_ BOOL Setup(const MeshInterface* mi0, const MeshInterface* mi1)
236 {
237 mIMesh0 = mi0;
238 mIMesh1 = mi1;
239
240 if(!mIMesh0 || !mIMesh1) return FALSE;
241
242 return TRUE;
243 }
244 };
245
246#endif // __OPC_TREECOLLIDER_H__
diff --git a/libraries/ode-0.9/OPCODE/OPC_TriBoxOverlap.h b/libraries/ode-0.9/OPCODE/OPC_TriBoxOverlap.h
new file mode 100644
index 0000000..b3a9bde
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_TriBoxOverlap.h
@@ -0,0 +1,339 @@
1
2//! This macro quickly finds the min & max values among 3 variables
3#define FINDMINMAX(x0, x1, x2, min, max) \
4 min = max = x0; \
5 if(x1<min) min=x1; \
6 if(x1>max) max=x1; \
7 if(x2<min) min=x2; \
8 if(x2>max) max=x2;
9
10//! TO BE DOCUMENTED
11inline_ BOOL planeBoxOverlap(const Point& normal, const float d, const Point& maxbox)
12{
13 Point vmin, vmax;
14 for(udword q=0;q<=2;q++)
15 {
16 if(normal[q]>0.0f) { vmin[q]=-maxbox[q]; vmax[q]=maxbox[q]; }
17 else { vmin[q]=maxbox[q]; vmax[q]=-maxbox[q]; }
18 }
19 if((normal|vmin)+d>0.0f) return FALSE;
20 if((normal|vmax)+d>=0.0f) return TRUE;
21
22 return FALSE;
23}
24
25//! TO BE DOCUMENTED
26#define AXISTEST_X01(a, b, fa, fb) \
27 min = a*v0.y - b*v0.z; \
28 max = a*v2.y - b*v2.z; \
29 if(min>max) {const float tmp=max; max=min; min=tmp; } \
30 rad = fa * extents.y + fb * extents.z; \
31 if(min>rad || max<-rad) return FALSE;
32
33//! TO BE DOCUMENTED
34#define AXISTEST_X2(a, b, fa, fb) \
35 min = a*v0.y - b*v0.z; \
36 max = a*v1.y - b*v1.z; \
37 if(min>max) {const float tmp=max; max=min; min=tmp; } \
38 rad = fa * extents.y + fb * extents.z; \
39 if(min>rad || max<-rad) return FALSE;
40
41//! TO BE DOCUMENTED
42#define AXISTEST_Y02(a, b, fa, fb) \
43 min = b*v0.z - a*v0.x; \
44 max = b*v2.z - a*v2.x; \
45 if(min>max) {const float tmp=max; max=min; min=tmp; } \
46 rad = fa * extents.x + fb * extents.z; \
47 if(min>rad || max<-rad) return FALSE;
48
49//! TO BE DOCUMENTED
50#define AXISTEST_Y1(a, b, fa, fb) \
51 min = b*v0.z - a*v0.x; \
52 max = b*v1.z - a*v1.x; \
53 if(min>max) {const float tmp=max; max=min; min=tmp; } \
54 rad = fa * extents.x + fb * extents.z; \
55 if(min>rad || max<-rad) return FALSE;
56
57//! TO BE DOCUMENTED
58#define AXISTEST_Z12(a, b, fa, fb) \
59 min = a*v1.x - b*v1.y; \
60 max = a*v2.x - b*v2.y; \
61 if(min>max) {const float tmp=max; max=min; min=tmp; } \
62 rad = fa * extents.x + fb * extents.y; \
63 if(min>rad || max<-rad) return FALSE;
64
65//! TO BE DOCUMENTED
66#define AXISTEST_Z0(a, b, fa, fb) \
67 min = a*v0.x - b*v0.y; \
68 max = a*v1.x - b*v1.y; \
69 if(min>max) {const float tmp=max; max=min; min=tmp; } \
70 rad = fa * extents.x + fb * extents.y; \
71 if(min>rad || max<-rad) return FALSE;
72
73// compute triangle edges
74// - edges lazy evaluated to take advantage of early exits
75// - fabs precomputed (half less work, possible since extents are always >0)
76// - customized macros to take advantage of the null component
77// - axis vector discarded, possibly saves useless movs
78#define IMPLEMENT_CLASS3_TESTS \
79 float rad; \
80 float min, max; \
81 \
82 const float fey0 = fabsf(e0.y); \
83 const float fez0 = fabsf(e0.z); \
84 AXISTEST_X01(e0.z, e0.y, fez0, fey0); \
85 const float fex0 = fabsf(e0.x); \
86 AXISTEST_Y02(e0.z, e0.x, fez0, fex0); \
87 AXISTEST_Z12(e0.y, e0.x, fey0, fex0); \
88 \
89 const float fey1 = fabsf(e1.y); \
90 const float fez1 = fabsf(e1.z); \
91 AXISTEST_X01(e1.z, e1.y, fez1, fey1); \
92 const float fex1 = fabsf(e1.x); \
93 AXISTEST_Y02(e1.z, e1.x, fez1, fex1); \
94 AXISTEST_Z0(e1.y, e1.x, fey1, fex1); \
95 \
96 const Point e2 = mLeafVerts[0] - mLeafVerts[2]; \
97 const float fey2 = fabsf(e2.y); \
98 const float fez2 = fabsf(e2.z); \
99 AXISTEST_X2(e2.z, e2.y, fez2, fey2); \
100 const float fex2 = fabsf(e2.x); \
101 AXISTEST_Y1(e2.z, e2.x, fez2, fex2); \
102 AXISTEST_Z12(e2.y, e2.x, fey2, fex2);
103
104///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
105/**
106 * Triangle-Box overlap test using the separating axis theorem.
107 * This is the code from Tomas Möller, a bit optimized:
108 * - with some more lazy evaluation (faster path on PC)
109 * - with a tiny bit of assembly
110 * - with "SAT-lite" applied if needed
111 * - and perhaps with some more minor modifs...
112 *
113 * \param center [in] box center
114 * \param extents [in] box extents
115 * \return true if triangle & box overlap
116 */
117///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
118inline_ BOOL AABBTreeCollider::TriBoxOverlap(const Point& center, const Point& extents)
119{
120 // Stats
121 mNbBVPrimTests++;
122
123 // use separating axis theorem to test overlap between triangle and box
124 // need to test for overlap in these directions:
125 // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle
126 // we do not even need to test these)
127 // 2) normal of the triangle
128 // 3) crossproduct(edge from tri, {x,y,z}-directin)
129 // this gives 3x3=9 more tests
130
131 // move everything so that the boxcenter is in (0,0,0)
132 Point v0, v1, v2;
133 v0.x = mLeafVerts[0].x - center.x;
134 v1.x = mLeafVerts[1].x - center.x;
135 v2.x = mLeafVerts[2].x - center.x;
136
137 // First, test overlap in the {x,y,z}-directions
138#ifdef OPC_USE_FCOMI
139 // find min, max of the triangle in x-direction, and test for overlap in X
140 if(FCMin3(v0.x, v1.x, v2.x)>extents.x) return FALSE;
141 if(FCMax3(v0.x, v1.x, v2.x)<-extents.x) return FALSE;
142
143 // same for Y
144 v0.y = mLeafVerts[0].y - center.y;
145 v1.y = mLeafVerts[1].y - center.y;
146 v2.y = mLeafVerts[2].y - center.y;
147
148 if(FCMin3(v0.y, v1.y, v2.y)>extents.y) return FALSE;
149 if(FCMax3(v0.y, v1.y, v2.y)<-extents.y) return FALSE;
150
151 // same for Z
152 v0.z = mLeafVerts[0].z - center.z;
153 v1.z = mLeafVerts[1].z - center.z;
154 v2.z = mLeafVerts[2].z - center.z;
155
156 if(FCMin3(v0.z, v1.z, v2.z)>extents.z) return FALSE;
157 if(FCMax3(v0.z, v1.z, v2.z)<-extents.z) return FALSE;
158#else
159 float min,max;
160 // Find min, max of the triangle in x-direction, and test for overlap in X
161 FINDMINMAX(v0.x, v1.x, v2.x, min, max);
162 if(min>extents.x || max<-extents.x) return FALSE;
163
164 // Same for Y
165 v0.y = mLeafVerts[0].y - center.y;
166 v1.y = mLeafVerts[1].y - center.y;
167 v2.y = mLeafVerts[2].y - center.y;
168
169 FINDMINMAX(v0.y, v1.y, v2.y, min, max);
170 if(min>extents.y || max<-extents.y) return FALSE;
171
172 // Same for Z
173 v0.z = mLeafVerts[0].z - center.z;
174 v1.z = mLeafVerts[1].z - center.z;
175 v2.z = mLeafVerts[2].z - center.z;
176
177 FINDMINMAX(v0.z, v1.z, v2.z, min, max);
178 if(min>extents.z || max<-extents.z) return FALSE;
179#endif
180 // 2) Test if the box intersects the plane of the triangle
181 // compute plane equation of triangle: normal*x+d=0
182 // ### could be precomputed since we use the same leaf triangle several times
183 const Point e0 = v1 - v0;
184 const Point e1 = v2 - v1;
185 const Point normal = e0 ^ e1;
186 const float d = -normal|v0;
187 if(!planeBoxOverlap(normal, d, extents)) return FALSE;
188
189 // 3) "Class III" tests
190 if(mFullPrimBoxTest)
191 {
192 IMPLEMENT_CLASS3_TESTS
193 }
194 return TRUE;
195}
196
197//! A dedicated version where the box is constant
198inline_ BOOL OBBCollider::TriBoxOverlap()
199{
200 // Stats
201 mNbVolumePrimTests++;
202
203 // Hook
204 const Point& extents = mBoxExtents;
205 const Point& v0 = mLeafVerts[0];
206 const Point& v1 = mLeafVerts[1];
207 const Point& v2 = mLeafVerts[2];
208
209 // use separating axis theorem to test overlap between triangle and box
210 // need to test for overlap in these directions:
211 // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle
212 // we do not even need to test these)
213 // 2) normal of the triangle
214 // 3) crossproduct(edge from tri, {x,y,z}-directin)
215 // this gives 3x3=9 more tests
216
217 // Box center is already in (0,0,0)
218
219 // First, test overlap in the {x,y,z}-directions
220#ifdef OPC_USE_FCOMI
221 // find min, max of the triangle in x-direction, and test for overlap in X
222 if(FCMin3(v0.x, v1.x, v2.x)>mBoxExtents.x) return FALSE;
223 if(FCMax3(v0.x, v1.x, v2.x)<-mBoxExtents.x) return FALSE;
224
225 if(FCMin3(v0.y, v1.y, v2.y)>mBoxExtents.y) return FALSE;
226 if(FCMax3(v0.y, v1.y, v2.y)<-mBoxExtents.y) return FALSE;
227
228 if(FCMin3(v0.z, v1.z, v2.z)>mBoxExtents.z) return FALSE;
229 if(FCMax3(v0.z, v1.z, v2.z)<-mBoxExtents.z) return FALSE;
230#else
231 float min,max;
232 // Find min, max of the triangle in x-direction, and test for overlap in X
233 FINDMINMAX(v0.x, v1.x, v2.x, min, max);
234 if(min>mBoxExtents.x || max<-mBoxExtents.x) return FALSE;
235
236 FINDMINMAX(v0.y, v1.y, v2.y, min, max);
237 if(min>mBoxExtents.y || max<-mBoxExtents.y) return FALSE;
238
239 FINDMINMAX(v0.z, v1.z, v2.z, min, max);
240 if(min>mBoxExtents.z || max<-mBoxExtents.z) return FALSE;
241#endif
242 // 2) Test if the box intersects the plane of the triangle
243 // compute plane equation of triangle: normal*x+d=0
244 // ### could be precomputed since we use the same leaf triangle several times
245 const Point e0 = v1 - v0;
246 const Point e1 = v2 - v1;
247 const Point normal = e0 ^ e1;
248 const float d = -normal|v0;
249 if(!planeBoxOverlap(normal, d, mBoxExtents)) return FALSE;
250
251 // 3) "Class III" tests - here we always do full tests since the box is a primitive (not a BV)
252 {
253 IMPLEMENT_CLASS3_TESTS
254 }
255 return TRUE;
256}
257
258//! ...and another one, jeez
259inline_ BOOL AABBCollider::TriBoxOverlap()
260{
261 // Stats
262 mNbVolumePrimTests++;
263
264 // Hook
265 const Point& center = mBox.mCenter;
266 const Point& extents = mBox.mExtents;
267
268 // use separating axis theorem to test overlap between triangle and box
269 // need to test for overlap in these directions:
270 // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle
271 // we do not even need to test these)
272 // 2) normal of the triangle
273 // 3) crossproduct(edge from tri, {x,y,z}-directin)
274 // this gives 3x3=9 more tests
275
276 // move everything so that the boxcenter is in (0,0,0)
277 Point v0, v1, v2;
278 v0.x = mLeafVerts[0].x - center.x;
279 v1.x = mLeafVerts[1].x - center.x;
280 v2.x = mLeafVerts[2].x - center.x;
281
282 // First, test overlap in the {x,y,z}-directions
283#ifdef OPC_USE_FCOMI
284 // find min, max of the triangle in x-direction, and test for overlap in X
285 if(FCMin3(v0.x, v1.x, v2.x)>extents.x) return FALSE;
286 if(FCMax3(v0.x, v1.x, v2.x)<-extents.x) return FALSE;
287
288 // same for Y
289 v0.y = mLeafVerts[0].y - center.y;
290 v1.y = mLeafVerts[1].y - center.y;
291 v2.y = mLeafVerts[2].y - center.y;
292
293 if(FCMin3(v0.y, v1.y, v2.y)>extents.y) return FALSE;
294 if(FCMax3(v0.y, v1.y, v2.y)<-extents.y) return FALSE;
295
296 // same for Z
297 v0.z = mLeafVerts[0].z - center.z;
298 v1.z = mLeafVerts[1].z - center.z;
299 v2.z = mLeafVerts[2].z - center.z;
300
301 if(FCMin3(v0.z, v1.z, v2.z)>extents.z) return FALSE;
302 if(FCMax3(v0.z, v1.z, v2.z)<-extents.z) return FALSE;
303#else
304 float min,max;
305 // Find min, max of the triangle in x-direction, and test for overlap in X
306 FINDMINMAX(v0.x, v1.x, v2.x, min, max);
307 if(min>extents.x || max<-extents.x) return FALSE;
308
309 // Same for Y
310 v0.y = mLeafVerts[0].y - center.y;
311 v1.y = mLeafVerts[1].y - center.y;
312 v2.y = mLeafVerts[2].y - center.y;
313
314 FINDMINMAX(v0.y, v1.y, v2.y, min, max);
315 if(min>extents.y || max<-extents.y) return FALSE;
316
317 // Same for Z
318 v0.z = mLeafVerts[0].z - center.z;
319 v1.z = mLeafVerts[1].z - center.z;
320 v2.z = mLeafVerts[2].z - center.z;
321
322 FINDMINMAX(v0.z, v1.z, v2.z, min, max);
323 if(min>extents.z || max<-extents.z) return FALSE;
324#endif
325 // 2) Test if the box intersects the plane of the triangle
326 // compute plane equation of triangle: normal*x+d=0
327 // ### could be precomputed since we use the same leaf triangle several times
328 const Point e0 = v1 - v0;
329 const Point e1 = v2 - v1;
330 const Point normal = e0 ^ e1;
331 const float d = -normal|v0;
332 if(!planeBoxOverlap(normal, d, extents)) return FALSE;
333
334 // 3) "Class III" tests - here we always do full tests since the box is a primitive (not a BV)
335 {
336 IMPLEMENT_CLASS3_TESTS
337 }
338 return TRUE;
339}
diff --git a/libraries/ode-0.9/OPCODE/OPC_TriTriOverlap.h b/libraries/ode-0.9/OPCODE/OPC_TriTriOverlap.h
new file mode 100644
index 0000000..1e71c6a
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_TriTriOverlap.h
@@ -0,0 +1,279 @@
1
2//! if OPC_TRITRI_EPSILON_TEST is true then we do a check (if |dv|<EPSILON then dv=0.0;) else no check is done (which is less robust, but faster)
3#define LOCAL_EPSILON 0.000001f
4
5//! sort so that a<=b
6#define SORT(a,b) \
7 if(a>b) \
8 { \
9 const float c=a; \
10 a=b; \
11 b=c; \
12 }
13
14//! Edge to edge test based on Franlin Antonio's gem: "Faster Line Segment Intersection", in Graphics Gems III, pp. 199-202
15#define EDGE_EDGE_TEST(V0, U0, U1) \
16 Bx = U0[i0] - U1[i0]; \
17 By = U0[i1] - U1[i1]; \
18 Cx = V0[i0] - U0[i0]; \
19 Cy = V0[i1] - U0[i1]; \
20 f = Ay*Bx - Ax*By; \
21 d = By*Cx - Bx*Cy; \
22 if((f>0.0f && d>=0.0f && d<=f) || (f<0.0f && d<=0.0f && d>=f)) \
23 { \
24 const float e=Ax*Cy - Ay*Cx; \
25 if(f>0.0f) \
26 { \
27 if(e>=0.0f && e<=f) return TRUE; \
28 } \
29 else \
30 { \
31 if(e<=0.0f && e>=f) return TRUE; \
32 } \
33 }
34
35//! TO BE DOCUMENTED
36#define EDGE_AGAINST_TRI_EDGES(V0, V1, U0, U1, U2) \
37{ \
38 float Bx,By,Cx,Cy,d,f; \
39 const float Ax = V1[i0] - V0[i0]; \
40 const float Ay = V1[i1] - V0[i1]; \
41 /* test edge U0,U1 against V0,V1 */ \
42 EDGE_EDGE_TEST(V0, U0, U1); \
43 /* test edge U1,U2 against V0,V1 */ \
44 EDGE_EDGE_TEST(V0, U1, U2); \
45 /* test edge U2,U1 against V0,V1 */ \
46 EDGE_EDGE_TEST(V0, U2, U0); \
47}
48
49//! TO BE DOCUMENTED
50#define POINT_IN_TRI(V0, U0, U1, U2) \
51{ \
52 /* is T1 completly inside T2? */ \
53 /* check if V0 is inside tri(U0,U1,U2) */ \
54 float a = U1[i1] - U0[i1]; \
55 float b = -(U1[i0] - U0[i0]); \
56 float c = -a*U0[i0] - b*U0[i1]; \
57 float d0 = a*V0[i0] + b*V0[i1] + c; \
58 \
59 a = U2[i1] - U1[i1]; \
60 b = -(U2[i0] - U1[i0]); \
61 c = -a*U1[i0] - b*U1[i1]; \
62 const float d1 = a*V0[i0] + b*V0[i1] + c; \
63 \
64 a = U0[i1] - U2[i1]; \
65 b = -(U0[i0] - U2[i0]); \
66 c = -a*U2[i0] - b*U2[i1]; \
67 const float d2 = a*V0[i0] + b*V0[i1] + c; \
68 if(d0*d1>0.0f) \
69 { \
70 if(d0*d2>0.0f) return TRUE; \
71 } \
72}
73
74//! TO BE DOCUMENTED
75BOOL CoplanarTriTri(const Point& n, const Point& v0, const Point& v1, const Point& v2, const Point& u0, const Point& u1, const Point& u2)
76{
77 float A[3];
78 short i0,i1;
79 /* first project onto an axis-aligned plane, that maximizes the area */
80 /* of the triangles, compute indices: i0,i1. */
81 A[0] = fabsf(n[0]);
82 A[1] = fabsf(n[1]);
83 A[2] = fabsf(n[2]);
84 if(A[0]>A[1])
85 {
86 if(A[0]>A[2])
87 {
88 i0=1; /* A[0] is greatest */
89 i1=2;
90 }
91 else
92 {
93 i0=0; /* A[2] is greatest */
94 i1=1;
95 }
96 }
97 else /* A[0]<=A[1] */
98 {
99 if(A[2]>A[1])
100 {
101 i0=0; /* A[2] is greatest */
102 i1=1;
103 }
104 else
105 {
106 i0=0; /* A[1] is greatest */
107 i1=2;
108 }
109 }
110
111 /* test all edges of triangle 1 against the edges of triangle 2 */
112 EDGE_AGAINST_TRI_EDGES(v0, v1, u0, u1, u2);
113 EDGE_AGAINST_TRI_EDGES(v1, v2, u0, u1, u2);
114 EDGE_AGAINST_TRI_EDGES(v2, v0, u0, u1, u2);
115
116 /* finally, test if tri1 is totally contained in tri2 or vice versa */
117 POINT_IN_TRI(v0, u0, u1, u2);
118 POINT_IN_TRI(u0, v0, v1, v2);
119
120 return FALSE;
121}
122
123//! TO BE DOCUMENTED
124#define NEWCOMPUTE_INTERVALS(VV0, VV1, VV2, D0, D1, D2, D0D1, D0D2, A, B, C, X0, X1) \
125{ \
126 if(D0D1>0.0f) \
127 { \
128 /* here we know that D0D2<=0.0 */ \
129 /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \
130 A=VV2; B=(VV0 - VV2)*D2; C=(VV1 - VV2)*D2; X0=D2 - D0; X1=D2 - D1; \
131 } \
132 else if(D0D2>0.0f) \
133 { \
134 /* here we know that d0d1<=0.0 */ \
135 A=VV1; B=(VV0 - VV1)*D1; C=(VV2 - VV1)*D1; X0=D1 - D0; X1=D1 - D2; \
136 } \
137 else if(D1*D2>0.0f || D0!=0.0f) \
138 { \
139 /* here we know that d0d1<=0.0 or that D0!=0.0 */ \
140 A=VV0; B=(VV1 - VV0)*D0; C=(VV2 - VV0)*D0; X0=D0 - D1; X1=D0 - D2; \
141 } \
142 else if(D1!=0.0f) \
143 { \
144 A=VV1; B=(VV0 - VV1)*D1; C=(VV2 - VV1)*D1; X0=D1 - D0; X1=D1 - D2; \
145 } \
146 else if(D2!=0.0f) \
147 { \
148 A=VV2; B=(VV0 - VV2)*D2; C=(VV1 - VV2)*D2; X0=D2 - D0; X1=D2 - D1; \
149 } \
150 else \
151 { \
152 /* triangles are coplanar */ \
153 return CoplanarTriTri(N1, V0, V1, V2, U0, U1, U2); \
154 } \
155}
156
157///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
158/**
159 * Triangle/triangle intersection test routine,
160 * by Tomas Moller, 1997.
161 * See article "A Fast Triangle-Triangle Intersection Test",
162 * Journal of Graphics Tools, 2(2), 1997
163 *
164 * Updated June 1999: removed the divisions -- a little faster now!
165 * Updated October 1999: added {} to CROSS and SUB macros
166 *
167 * int NoDivTriTriIsect(float V0[3],float V1[3],float V2[3],
168 * float U0[3],float U1[3],float U2[3])
169 *
170 * \param V0 [in] triangle 0, vertex 0
171 * \param V1 [in] triangle 0, vertex 1
172 * \param V2 [in] triangle 0, vertex 2
173 * \param U0 [in] triangle 1, vertex 0
174 * \param U1 [in] triangle 1, vertex 1
175 * \param U2 [in] triangle 1, vertex 2
176 * \return true if triangles overlap
177 */
178///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
179inline_ BOOL AABBTreeCollider::TriTriOverlap(const Point& V0, const Point& V1, const Point& V2, const Point& U0, const Point& U1, const Point& U2)
180{
181 // Stats
182 mNbPrimPrimTests++;
183
184 // Compute plane equation of triangle(V0,V1,V2)
185 Point E1 = V1 - V0;
186 Point E2 = V2 - V0;
187 const Point N1 = E1 ^ E2;
188 const float d1 =-N1 | V0;
189 // Plane equation 1: N1.X+d1=0
190
191 // Put U0,U1,U2 into plane equation 1 to compute signed distances to the plane
192 float du0 = (N1|U0) + d1;
193 float du1 = (N1|U1) + d1;
194 float du2 = (N1|U2) + d1;
195
196 // Coplanarity robustness check
197#ifdef OPC_TRITRI_EPSILON_TEST
198 if(fabsf(du0)<LOCAL_EPSILON) du0 = 0.0f;
199 if(fabsf(du1)<LOCAL_EPSILON) du1 = 0.0f;
200 if(fabsf(du2)<LOCAL_EPSILON) du2 = 0.0f;
201#endif
202 const float du0du1 = du0 * du1;
203 const float du0du2 = du0 * du2;
204
205 if(du0du1>0.0f && du0du2>0.0f) // same sign on all of them + not equal 0 ?
206 return FALSE; // no intersection occurs
207
208 // Compute plane of triangle (U0,U1,U2)
209 E1 = U1 - U0;
210 E2 = U2 - U0;
211 const Point N2 = E1 ^ E2;
212 const float d2=-N2 | U0;
213 // plane equation 2: N2.X+d2=0
214
215 // put V0,V1,V2 into plane equation 2
216 float dv0 = (N2|V0) + d2;
217 float dv1 = (N2|V1) + d2;
218 float dv2 = (N2|V2) + d2;
219
220#ifdef OPC_TRITRI_EPSILON_TEST
221 if(fabsf(dv0)<LOCAL_EPSILON) dv0 = 0.0f;
222 if(fabsf(dv1)<LOCAL_EPSILON) dv1 = 0.0f;
223 if(fabsf(dv2)<LOCAL_EPSILON) dv2 = 0.0f;
224#endif
225
226 const float dv0dv1 = dv0 * dv1;
227 const float dv0dv2 = dv0 * dv2;
228
229 if(dv0dv1>0.0f && dv0dv2>0.0f) // same sign on all of them + not equal 0 ?
230 return FALSE; // no intersection occurs
231
232 // Compute direction of intersection line
233 const Point D = N1^N2;
234
235 // Compute and index to the largest component of D
236 float max=fabsf(D[0]);
237 short index=0;
238 float bb=fabsf(D[1]);
239 float cc=fabsf(D[2]);
240 if(bb>max) max=bb,index=1;
241 if(cc>max) max=cc,index=2;
242
243 // This is the simplified projection onto L
244 const float vp0 = V0[index];
245 const float vp1 = V1[index];
246 const float vp2 = V2[index];
247
248 const float up0 = U0[index];
249 const float up1 = U1[index];
250 const float up2 = U2[index];
251
252 // Compute interval for triangle 1
253 float a,b,c,x0,x1;
254 NEWCOMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,a,b,c,x0,x1);
255
256 // Compute interval for triangle 2
257 float d,e,f,y0,y1;
258 NEWCOMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,d,e,f,y0,y1);
259
260 const float xx=x0*x1;
261 const float yy=y0*y1;
262 const float xxyy=xx*yy;
263
264 float isect1[2], isect2[2];
265
266 float tmp=a*xxyy;
267 isect1[0]=tmp+b*x1*yy;
268 isect1[1]=tmp+c*x0*yy;
269
270 tmp=d*xxyy;
271 isect2[0]=tmp+e*xx*y1;
272 isect2[1]=tmp+f*xx*y0;
273
274 SORT(isect1[0],isect1[1]);
275 SORT(isect2[0],isect2[1]);
276
277 if(isect1[1]<isect2[0] || isect2[1]<isect1[0]) return FALSE;
278 return TRUE;
279}
diff --git a/libraries/ode-0.9/OPCODE/OPC_VolumeCollider.cpp b/libraries/ode-0.9/OPCODE/OPC_VolumeCollider.cpp
new file mode 100644
index 0000000..f374209
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_VolumeCollider.cpp
@@ -0,0 +1,103 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains base volume collider class.
12 * \file OPC_VolumeCollider.cpp
13 * \author Pierre Terdiman
14 * \date June, 2, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19/**
20 * Contains the abstract class for volume colliders.
21 *
22 * \class VolumeCollider
23 * \author Pierre Terdiman
24 * \version 1.3
25 * \date June, 2, 2001
26*/
27///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
28
29///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
30// Precompiled Header
31#include "Stdafx.h"
32
33using namespace Opcode;
34
35///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
36/**
37 * Constructor.
38 */
39///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
40VolumeCollider::VolumeCollider() :
41 mTouchedPrimitives (null),
42 mNbVolumeBVTests (0),
43 mNbVolumePrimTests (0)
44{
45}
46
47///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
48/**
49 * Destructor.
50 */
51///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
52VolumeCollider::~VolumeCollider()
53{
54 mTouchedPrimitives = null;
55}
56
57///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
58/**
59 * Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider.
60 * \return null if everything is ok, else a string describing the problem
61 */
62///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
63const char* VolumeCollider::ValidateSettings()
64{
65 return null;
66}
67
68// Pretty dumb way to dump - to do better - one day...
69
70#define IMPLEMENT_NOLEAFDUMP(type) \
71void VolumeCollider::_Dump(const type* node) \
72{ \
73 if(node->HasPosLeaf()) mTouchedPrimitives->Add(udword(node->GetPosPrimitive())); \
74 else _Dump(node->GetPos()); \
75 \
76 if(ContactFound()) return; \
77 \
78 if(node->HasNegLeaf()) mTouchedPrimitives->Add(udword(node->GetNegPrimitive())); \
79 else _Dump(node->GetNeg()); \
80}
81
82#define IMPLEMENT_LEAFDUMP(type) \
83void VolumeCollider::_Dump(const type* node) \
84{ \
85 if(node->IsLeaf()) \
86 { \
87 mTouchedPrimitives->Add(udword(node->GetPrimitive())); \
88 } \
89 else \
90 { \
91 _Dump(node->GetPos()); \
92 \
93 if(ContactFound()) return; \
94 \
95 _Dump(node->GetNeg()); \
96 } \
97}
98
99IMPLEMENT_NOLEAFDUMP(AABBNoLeafNode)
100IMPLEMENT_NOLEAFDUMP(AABBQuantizedNoLeafNode)
101
102IMPLEMENT_LEAFDUMP(AABBCollisionNode)
103IMPLEMENT_LEAFDUMP(AABBQuantizedNode)
diff --git a/libraries/ode-0.9/OPCODE/OPC_VolumeCollider.h b/libraries/ode-0.9/OPCODE/OPC_VolumeCollider.h
new file mode 100644
index 0000000..c0b812e
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/OPC_VolumeCollider.h
@@ -0,0 +1,138 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Contains base volume collider class.
12 * \file OPC_VolumeCollider.h
13 * \author Pierre Terdiman
14 * \date June, 2, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPC_VOLUMECOLLIDER_H__
21#define __OPC_VOLUMECOLLIDER_H__
22
23 struct OPCODE_API VolumeCache
24 {
25 VolumeCache() : Model(null) {}
26 ~VolumeCache() {}
27
28 Container TouchedPrimitives; //!< Indices of touched primitives
29 const BaseModel* Model; //!< Owner
30 };
31
32 class OPCODE_API VolumeCollider : public Collider
33 {
34 public:
35 // Constructor / Destructor
36 VolumeCollider();
37 virtual ~VolumeCollider() = 0;
38
39 // Collision report
40
41 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
42 /**
43 * Gets the number of touched primitives after a collision query.
44 * \see GetContactStatus()
45 * \see GetTouchedPrimitives()
46 * \return the number of touched primitives
47 */
48 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
49 inline_ udword GetNbTouchedPrimitives() const { return mTouchedPrimitives ? mTouchedPrimitives->GetNbEntries() : 0; }
50
51 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
52 /**
53 * Gets the list of touched primitives after a collision query.
54 * \see GetContactStatus()
55 * \see GetNbTouchedPrimitives()
56 * \return the list of touched primitives (primitive indices)
57 */
58 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
59 inline_ const udword* GetTouchedPrimitives() const { return mTouchedPrimitives ? mTouchedPrimitives->GetEntries() : null; }
60
61 // Stats
62
63 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
64 /**
65 * Stats: gets the number of Volume-BV overlap tests after a collision query.
66 * \see GetNbVolumePrimTests()
67 * \return the number of Volume-BV tests performed during last query
68 */
69 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
70 inline_ udword GetNbVolumeBVTests() const { return mNbVolumeBVTests; }
71
72 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
73 /**
74 * Stats: gets the number of Volume-Triangle overlap tests after a collision query.
75 * \see GetNbVolumeBVTests()
76 * \return the number of Volume-Triangle tests performed during last query
77 */
78 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
79 inline_ udword GetNbVolumePrimTests() const { return mNbVolumePrimTests; }
80
81 // Settings
82
83 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
84 /**
85 * Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider.
86 * \return null if everything is ok, else a string describing the problem
87 */
88 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
89 override(Collider) const char* ValidateSettings();
90
91 protected:
92 // Touched primitives
93 Container* mTouchedPrimitives; //!< List of touched primitives
94
95 // Dequantization coeffs
96 Point mCenterCoeff;
97 Point mExtentsCoeff;
98 // Stats
99 udword mNbVolumeBVTests; //!< Number of Volume-BV tests
100 udword mNbVolumePrimTests; //!< Number of Volume-Primitive tests
101 // Internal methods
102 void _Dump(const AABBCollisionNode* node);
103 void _Dump(const AABBNoLeafNode* node);
104 void _Dump(const AABBQuantizedNode* node);
105 void _Dump(const AABBQuantizedNoLeafNode* node);
106
107 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
108 /**
109 * Initializes a query
110 */
111 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
112 override(Collider) inline_ void InitQuery()
113 {
114 // Reset stats & contact status
115 mNbVolumeBVTests = 0;
116 mNbVolumePrimTests = 0;
117 Collider::InitQuery();
118 }
119
120 inline_ BOOL IsCacheValid(VolumeCache& cache)
121 {
122 // We're going to do a volume-vs-model query.
123 if(cache.Model!=mCurrentModel)
124 {
125 // Cached list was for another model so we can't keep it
126 // Keep track of new owner and reset cache
127 cache.Model = mCurrentModel;
128 return FALSE;
129 }
130 else
131 {
132 // Same models, no problem
133 return TRUE;
134 }
135 }
136 };
137
138#endif // __OPC_VOLUMECOLLIDER_H__
diff --git a/libraries/ode-0.9/OPCODE/Opcode.cpp b/libraries/ode-0.9/OPCODE/Opcode.cpp
new file mode 100644
index 0000000..c9fa104
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Opcode.cpp
@@ -0,0 +1,65 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Main file for Opcode.dll.
12 * \file Opcode.cpp
13 * \author Pierre Terdiman
14 * \date March, 20, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18/*
19 Finding a good name is difficult!
20 Here's the draft for this lib.... Spooky, uh?
21
22 VOID? Very Optimized Interference Detection
23 ZOID? Zappy's Optimized Interference Detection
24 CID? Custom/Clever Interference Detection
25 AID / ACID! Accurate Interference Detection
26 QUID? Quick Interference Detection
27 RIDE? Realtime Interference DEtection
28 WIDE? Wicked Interference DEtection (....)
29 GUID!
30 KID ! k-dop interference detection :)
31 OPCODE! OPtimized COllision DEtection
32*/
33
34///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
35// Precompiled Header
36#include "Stdafx.h"
37
38bool Opcode::InitOpcode()
39{
40 Log("// Initializing OPCODE\n\n");
41// LogAPIInfo();
42 return true;
43}
44
45void ReleasePruningSorters();
46bool Opcode::CloseOpcode()
47{
48 Log("// Closing OPCODE\n\n");
49
50 ReleasePruningSorters();
51
52 return true;
53}
54
55#ifdef ICE_MAIN
56
57void ModuleAttach(HINSTANCE hinstance)
58{
59}
60
61void ModuleDetach()
62{
63}
64
65#endif
diff --git a/libraries/ode-0.9/OPCODE/Opcode.dsp b/libraries/ode-0.9/OPCODE/Opcode.dsp
new file mode 100644
index 0000000..560cf56
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Opcode.dsp
@@ -0,0 +1,470 @@
1# Microsoft Developer Studio Project File - Name="OPCODE" - Package Owner=<4>
2# Microsoft Developer Studio Generated Build File, Format Version 6.00
3# ** DO NOT EDIT **
4
5# TARGTYPE "Win32 (x86) Static Library" 0x0104
6
7CFG=OPCODE - Win32 Debug
8!MESSAGE This is not a valid makefile. To build this project using NMAKE,
9!MESSAGE use the Export Makefile command and run
10!MESSAGE
11!MESSAGE NMAKE /f "Opcode.mak".
12!MESSAGE
13!MESSAGE You can specify a configuration when running NMAKE
14!MESSAGE by defining the macro CFG on the command line. For example:
15!MESSAGE
16!MESSAGE NMAKE /f "Opcode.mak" CFG="OPCODE - Win32 Debug"
17!MESSAGE
18!MESSAGE Possible choices for configuration are:
19!MESSAGE
20!MESSAGE "OPCODE - Win32 Release" (based on "Win32 (x86) Static Library")
21!MESSAGE "OPCODE - Win32 Debug" (based on "Win32 (x86) Static Library")
22!MESSAGE
23
24# Begin Project
25# PROP AllowPerConfigDependencies 0
26# PROP Scc_ProjName ""$/TR4/ODE/VC6", WNKAAAAA"
27# PROP Scc_LocalPath "..\vc6"
28CPP=cl.exe
29RSC=rc.exe
30
31!IF "$(CFG)" == "OPCODE - Win32 Release"
32
33# PROP BASE Use_MFC 0
34# PROP BASE Use_Debug_Libraries 0
35# PROP BASE Output_Dir "Release"
36# PROP BASE Intermediate_Dir "Release"
37# PROP BASE Target_Dir ""
38# PROP Use_MFC 0
39# PROP Use_Debug_Libraries 0
40# PROP Output_Dir "Release"
41# PROP Intermediate_Dir "Release"
42# PROP Target_Dir ""
43# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
44# ADD CPP /nologo /G6 /Zp4 /MD /O2 /Ob0 /I ".\\" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "ICE_NO_DLL" /FD /c
45# SUBTRACT CPP /Fr /YX
46# ADD BASE RSC /l 0x409 /d "NDEBUG"
47# ADD RSC /l 0x409 /d "NDEBUG"
48BSC32=bscmake.exe
49# ADD BASE BSC32 /nologo
50# ADD BSC32 /nologo
51LIB32=link.exe -lib
52# ADD BASE LIB32 /nologo
53# ADD LIB32 /nologo /out:"..\lib\OPCODE.lib"
54
55!ELSEIF "$(CFG)" == "OPCODE - Win32 Debug"
56
57# PROP BASE Use_MFC 0
58# PROP BASE Use_Debug_Libraries 1
59# PROP BASE Output_Dir "Debug"
60# PROP BASE Intermediate_Dir "Debug"
61# PROP BASE Target_Dir ""
62# PROP Use_MFC 0
63# PROP Use_Debug_Libraries 1
64# PROP Output_Dir "Debug"
65# PROP Intermediate_Dir "Debug"
66# PROP Target_Dir ""
67# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
68# ADD CPP /nologo /G6 /Zp4 /MDd /Gm /ZI /Od /I ".\\" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "ICE_NO_DLL" /FR /FD /GZ /c
69# SUBTRACT CPP /YX
70# ADD BASE RSC /l 0x409 /d "_DEBUG"
71# ADD RSC /l 0x409 /d "_DEBUG"
72BSC32=bscmake.exe
73# ADD BASE BSC32 /nologo
74# ADD BSC32 /nologo
75LIB32=link.exe -lib
76# ADD BASE LIB32 /nologo
77# ADD LIB32 /nologo /out:"..\lib\OPCODE_D.lib"
78
79!ENDIF
80
81# Begin Target
82
83# Name "OPCODE - Win32 Release"
84# Name "OPCODE - Win32 Debug"
85# Begin Source File
86
87SOURCE=.\Ice\IceAABB.cpp
88# End Source File
89# Begin Source File
90
91SOURCE=.\Ice\IceAABB.h
92# End Source File
93# Begin Source File
94
95SOURCE=.\Ice\IceAxes.h
96# End Source File
97# Begin Source File
98
99SOURCE=.\Ice\IceBoundingSphere.h
100# End Source File
101# Begin Source File
102
103SOURCE=.\Ice\IceContainer.cpp
104# End Source File
105# Begin Source File
106
107SOURCE=.\Ice\IceContainer.h
108# End Source File
109# Begin Source File
110
111SOURCE=.\Ice\IceFPU.h
112# End Source File
113# Begin Source File
114
115SOURCE=.\Ice\IceHPoint.cpp
116# End Source File
117# Begin Source File
118
119SOURCE=.\Ice\IceHPoint.h
120# End Source File
121# Begin Source File
122
123SOURCE=.\Ice\IceIndexedTriangle.cpp
124# End Source File
125# Begin Source File
126
127SOURCE=.\Ice\IceIndexedTriangle.h
128# End Source File
129# Begin Source File
130
131SOURCE=.\Ice\IceLSS.h
132# End Source File
133# Begin Source File
134
135SOURCE=.\Ice\IceMatrix3x3.cpp
136# End Source File
137# Begin Source File
138
139SOURCE=.\Ice\IceMatrix3x3.h
140# End Source File
141# Begin Source File
142
143SOURCE=.\Ice\IceMatrix4x4.cpp
144# End Source File
145# Begin Source File
146
147SOURCE=.\Ice\IceMatrix4x4.h
148# End Source File
149# Begin Source File
150
151SOURCE=.\Ice\IceMemoryMacros.h
152# End Source File
153# Begin Source File
154
155SOURCE=.\Ice\IceOBB.cpp
156# End Source File
157# Begin Source File
158
159SOURCE=.\Ice\IceOBB.h
160# End Source File
161# Begin Source File
162
163SOURCE=.\Ice\IcePairs.h
164# End Source File
165# Begin Source File
166
167SOURCE=.\Ice\IcePlane.cpp
168# End Source File
169# Begin Source File
170
171SOURCE=.\Ice\IcePlane.h
172# End Source File
173# Begin Source File
174
175SOURCE=.\Ice\IcePoint.cpp
176# End Source File
177# Begin Source File
178
179SOURCE=.\Ice\IcePoint.h
180# End Source File
181# Begin Source File
182
183SOURCE=.\Ice\IcePreprocessor.h
184# End Source File
185# Begin Source File
186
187SOURCE=.\Ice\IceRandom.cpp
188# End Source File
189# Begin Source File
190
191SOURCE=.\Ice\IceRandom.h
192# End Source File
193# Begin Source File
194
195SOURCE=.\Ice\IceRay.cpp
196# End Source File
197# Begin Source File
198
199SOURCE=.\Ice\IceRay.h
200# End Source File
201# Begin Source File
202
203SOURCE=.\Ice\IceRevisitedRadix.cpp
204# End Source File
205# Begin Source File
206
207SOURCE=.\Ice\IceRevisitedRadix.h
208# End Source File
209# Begin Source File
210
211SOURCE=.\Ice\IceSegment.cpp
212# End Source File
213# Begin Source File
214
215SOURCE=.\Ice\IceSegment.h
216# End Source File
217# Begin Source File
218
219SOURCE=.\Ice\IceTriangle.cpp
220# End Source File
221# Begin Source File
222
223SOURCE=.\Ice\IceTriangle.h
224# End Source File
225# Begin Source File
226
227SOURCE=.\Ice\IceTrilist.h
228# End Source File
229# Begin Source File
230
231SOURCE=.\Ice\IceTypes.h
232# End Source File
233# Begin Source File
234
235SOURCE=.\Ice\IceUtils.cpp
236# End Source File
237# Begin Source File
238
239SOURCE=.\Ice\IceUtils.h
240# End Source File
241# Begin Source File
242
243SOURCE=.\OPC_AABBCollider.cpp
244# End Source File
245# Begin Source File
246
247SOURCE=.\OPC_AABBCollider.h
248# End Source File
249# Begin Source File
250
251SOURCE=.\OPC_AABBTree.cpp
252# End Source File
253# Begin Source File
254
255SOURCE=.\OPC_AABBTree.h
256# End Source File
257# Begin Source File
258
259SOURCE=.\OPC_BaseModel.cpp
260# End Source File
261# Begin Source File
262
263SOURCE=.\OPC_BaseModel.h
264# End Source File
265# Begin Source File
266
267SOURCE=.\OPC_BoxBoxOverlap.h
268# End Source File
269# Begin Source File
270
271SOURCE=.\OPC_BoxPruning.cpp
272# End Source File
273# Begin Source File
274
275SOURCE=.\OPC_BoxPruning.h
276# End Source File
277# Begin Source File
278
279SOURCE=.\OPC_Collider.cpp
280# End Source File
281# Begin Source File
282
283SOURCE=.\OPC_Collider.h
284# End Source File
285# Begin Source File
286
287SOURCE=.\OPC_Common.cpp
288# End Source File
289# Begin Source File
290
291SOURCE=.\OPC_Common.h
292# End Source File
293# Begin Source File
294
295SOURCE=.\OPC_HybridModel.cpp
296# End Source File
297# Begin Source File
298
299SOURCE=.\OPC_HybridModel.h
300# End Source File
301# Begin Source File
302
303SOURCE=.\OPC_IceHook.h
304# End Source File
305# Begin Source File
306
307SOURCE=.\OPC_LSSAABBOverlap.h
308# End Source File
309# Begin Source File
310
311SOURCE=.\OPC_LSSCollider.cpp
312# End Source File
313# Begin Source File
314
315SOURCE=.\OPC_LSSCollider.h
316# End Source File
317# Begin Source File
318
319SOURCE=.\OPC_LSSTriOverlap.h
320# End Source File
321# Begin Source File
322
323SOURCE=.\OPC_MeshInterface.cpp
324# End Source File
325# Begin Source File
326
327SOURCE=.\OPC_MeshInterface.h
328# End Source File
329# Begin Source File
330
331SOURCE=.\OPC_Model.cpp
332# End Source File
333# Begin Source File
334
335SOURCE=.\OPC_Model.h
336# End Source File
337# Begin Source File
338
339SOURCE=.\OPC_OBBCollider.cpp
340# End Source File
341# Begin Source File
342
343SOURCE=.\OPC_OBBCollider.h
344# End Source File
345# Begin Source File
346
347SOURCE=.\OPC_OptimizedTree.cpp
348# End Source File
349# Begin Source File
350
351SOURCE=.\OPC_OptimizedTree.h
352# End Source File
353# Begin Source File
354
355SOURCE=.\OPC_Picking.cpp
356# End Source File
357# Begin Source File
358
359SOURCE=.\OPC_Picking.h
360# End Source File
361# Begin Source File
362
363SOURCE=.\OPC_PlanesAABBOverlap.h
364# End Source File
365# Begin Source File
366
367SOURCE=.\OPC_PlanesCollider.cpp
368# End Source File
369# Begin Source File
370
371SOURCE=.\OPC_PlanesCollider.h
372# End Source File
373# Begin Source File
374
375SOURCE=.\OPC_PlanesTriOverlap.h
376# End Source File
377# Begin Source File
378
379SOURCE=.\OPC_RayAABBOverlap.h
380# End Source File
381# Begin Source File
382
383SOURCE=.\OPC_RayCollider.cpp
384# End Source File
385# Begin Source File
386
387SOURCE=.\OPC_RayCollider.h
388# End Source File
389# Begin Source File
390
391SOURCE=.\OPC_RayTriOverlap.h
392# End Source File
393# Begin Source File
394
395SOURCE=.\OPC_Settings.h
396# End Source File
397# Begin Source File
398
399SOURCE=.\OPC_SphereAABBOverlap.h
400# End Source File
401# Begin Source File
402
403SOURCE=.\OPC_SphereCollider.cpp
404# End Source File
405# Begin Source File
406
407SOURCE=.\OPC_SphereCollider.h
408# End Source File
409# Begin Source File
410
411SOURCE=.\OPC_SphereTriOverlap.h
412# End Source File
413# Begin Source File
414
415SOURCE=.\OPC_SweepAndPrune.cpp
416# End Source File
417# Begin Source File
418
419SOURCE=.\OPC_SweepAndPrune.h
420# End Source File
421# Begin Source File
422
423SOURCE=.\OPC_TreeBuilders.cpp
424# End Source File
425# Begin Source File
426
427SOURCE=.\OPC_TreeBuilders.h
428# End Source File
429# Begin Source File
430
431SOURCE=.\OPC_TreeCollider.cpp
432# End Source File
433# Begin Source File
434
435SOURCE=.\OPC_TreeCollider.h
436# End Source File
437# Begin Source File
438
439SOURCE=.\OPC_TriBoxOverlap.h
440# End Source File
441# Begin Source File
442
443SOURCE=.\OPC_TriTriOverlap.h
444# End Source File
445# Begin Source File
446
447SOURCE=.\OPC_VolumeCollider.cpp
448# End Source File
449# Begin Source File
450
451SOURCE=.\OPC_VolumeCollider.h
452# End Source File
453# Begin Source File
454
455SOURCE=.\Opcode.cpp
456# End Source File
457# Begin Source File
458
459SOURCE=.\Opcode.h
460# End Source File
461# Begin Source File
462
463SOURCE=.\StdAfx.cpp
464# End Source File
465# Begin Source File
466
467SOURCE=.\StdAfx.h
468# End Source File
469# End Target
470# End Project
diff --git a/libraries/ode-0.9/OPCODE/Opcode.dsw b/libraries/ode-0.9/OPCODE/Opcode.dsw
new file mode 100644
index 0000000..27f5c28
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Opcode.dsw
@@ -0,0 +1,29 @@
1Microsoft Developer Studio Workspace File, Format Version 6.00
2# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
3
4###############################################################################
5
6Project: "OPCODE"=.\Opcode.dsp - Package Owner=<4>
7
8Package=<5>
9{{{
10}}}
11
12Package=<4>
13{{{
14}}}
15
16###############################################################################
17
18Global:
19
20Package=<5>
21{{{
22}}}
23
24Package=<3>
25{{{
26}}}
27
28###############################################################################
29
diff --git a/libraries/ode-0.9/OPCODE/Opcode.h b/libraries/ode-0.9/OPCODE/Opcode.h
new file mode 100644
index 0000000..2a7a6c5
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Opcode.h
@@ -0,0 +1,113 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 * Main file for Opcode.dll.
12 * \file Opcode.h
13 * \author Pierre Terdiman
14 * \date March, 20, 2001
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19// Include Guard
20#ifndef __OPCODE_H__
21#define __OPCODE_H__
22
23///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
24// Things to help us compile on non-windows platforms
25
26#if defined(__APPLE__) || defined(__MACOSX__)
27#if __APPLE_CC__ < 1495
28#define sqrtf sqrt
29#define sinf sin
30#define cosf cos
31#define acosf acos
32#define asinf asin
33#endif
34#endif
35
36#ifndef _MSC_VER
37#ifndef __int64
38#define __int64 long long int
39#endif
40#ifndef __stdcall /* this is defined in MinGW and CygWin, so avoid the warning */
41#define __stdcall /* */
42#endif
43#endif
44
45///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
46// Compilation messages
47#ifdef _MSC_VER
48 #if defined(OPCODE_EXPORTS)
49 // #pragma message("Compiling OPCODE")
50 #elif !defined(OPCODE_EXPORTS)
51 // #pragma message("Using OPCODE")
52 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
53 // Automatic linking
54 #ifndef BAN_OPCODE_AUTOLINK
55 #ifdef _DEBUG
56 //#pragma comment(lib, "Opcode_D.lib")
57 #else
58 //#pragma comment(lib, "Opcode.lib")
59 #endif
60 #endif
61 #endif
62#endif
63
64///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
65// Preprocessor
66#ifndef ICE_NO_DLL
67 #ifdef OPCODE_EXPORTS
68 #define OPCODE_API// __declspec(dllexport)
69 #else
70 #define OPCODE_API// __declspec(dllimport)
71 #endif
72#else
73 #define OPCODE_API
74#endif
75
76 #include "OPC_IceHook.h"
77
78 namespace Opcode
79 {
80 // Bulk-of-the-work
81 #include "OPC_Settings.h"
82 #include "OPC_Common.h"
83 #include "OPC_MeshInterface.h"
84 // Builders
85 #include "OPC_TreeBuilders.h"
86 // Trees
87 #include "OPC_AABBTree.h"
88 #include "OPC_OptimizedTree.h"
89 // Models
90 #include "OPC_BaseModel.h"
91 #include "OPC_Model.h"
92 #include "OPC_HybridModel.h"
93 // Colliders
94 #include "OPC_Collider.h"
95 #include "OPC_VolumeCollider.h"
96 #include "OPC_TreeCollider.h"
97 #include "OPC_RayCollider.h"
98 #include "OPC_SphereCollider.h"
99 #include "OPC_OBBCollider.h"
100 #include "OPC_AABBCollider.h"
101 #include "OPC_LSSCollider.h"
102 #include "OPC_PlanesCollider.h"
103 // Usages
104 #include "OPC_Picking.h"
105 // Sweep-and-prune
106 #include "OPC_BoxPruning.h"
107 #include "OPC_SweepAndPrune.h"
108
109 FUNCTION OPCODE_API bool InitOpcode();
110 FUNCTION OPCODE_API bool CloseOpcode();
111 }
112
113#endif // __OPCODE_H__
diff --git a/libraries/ode-0.9/OPCODE/README-ODE.txt b/libraries/ode-0.9/OPCODE/README-ODE.txt
new file mode 100644
index 0000000..c5d5800
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/README-ODE.txt
@@ -0,0 +1,13 @@
1
2This is a copy of the OPCODE collision detection library by Pierre Terdiman.
3See http://www.codercorner.com/Opcode.htm for more information, and read
4the ReadMe.txt in this directory.
5
6If you want to use the TriList (triangle mesh) geometry class in ODE, the
7OPCODE library must be compiled. If you are using the autotools support to
8compile ODE, you just have to specify --with-trimesh=opcode when calling ./configure.
9
10This code was originally written for and compiled on windows, but it has been
11ported so that it should compile under unix/gcc too. Your mileage may vary.
12
13Russ Smith, April 12 2005.
diff --git a/libraries/ode-0.9/OPCODE/ReadMe.txt b/libraries/ode-0.9/OPCODE/ReadMe.txt
new file mode 100644
index 0000000..8a39eff
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/ReadMe.txt
@@ -0,0 +1,171 @@
1
2 OPCODE distribution 1.3 (june 2003)
3 -----------------------
4
5 New in Opcode 1.3:
6 - fixed the divide by 0 bug that was happening when all centers where located on a coordinate axis (thanks to Jorrit T)
7 - linearized "complete" vanilla AABB trees
8 - ANSI-compliant "for" loops (for the ones porting it to Linux...)
9 - callbacks & pointers moved to mesh interface
10 - support for triangle & vertex strides
11 - optimized the sphere-triangle overlap code a bit
12 - dynamic trees (refit)
13 - more builders
14 - ValidateSubdivision in builders
15 - LSS collider
16 - primitive-bv tests can now be skipped in most volume queries
17 - temporal coherence now also works for airborne objects
18 - temporal coherence completed for boxes / all contacts, LSS, etc
19 - ray-collider now uses a callback
20 - some common "usages" have been introduced (only picking for now)
21 - SPLIT_COMPLETE removed (now implicitely using mLimit = 1)
22 - hybrid collision models
23 - sweep-and-prune code added, moved from my old Z-Collide lib
24 - it now works with meshes made of only 1 triangle (except in mesh-mesh case!)
25
26 Disclaimer:
27
28 - I forced myself to actually *do* the release today no matter what. Else it would never have been done. That's
29 why the code may not be very polished. I also removed a *lot* of things (more usages, distance queries, etc...)
30 that weren't ready for prime-time (or that were linked to too many of my supporting libs)
31
32 - Some comments may also be obsolete here and there. The old User Manual for Opcode 1.2 may not fit version 1.3
33 either, since there's a new "mesh interface" to support strides, etc.
34
35 - Everything in the "Ice" directory has been hacked out of my engine and edited until everything compiled. Don't
36 expect anything out there to be cute or something. In particular, some CPP files are not even included when not
37 needed, so you can expect some linker errors if you try messing around with them...
38
39 Otherwise, it should be just like previous version, only better. In particular, hybrid models can be very
40 memory-friendly (sometimes using like 10 times less ram than the best trees from version 1.2). The possible
41 speed hit is often invisible (if it even exists), especially using temporal coherence in "all contacts" mode.
42 (Admittedly, this depends on your particular usage pattern / what you do on collided triangles).
43
44 The sweep-and-prune code is similar to the "vanilla" version found in V-Collide (but that one's better IMHO...)
45 The simple "radix" version is often just as good, see for yourself.
46
47 OPCODE distribution 1.2 (august 2002)
48 -----------------------
49
50 New in Opcode 1.2:
51 - new VolumeCollider base class
52 - simplified callback setup
53 - you can now use callbacks or pointers (setup at compile time)
54 - destination array not needed anymore in the RayCollider (faster in-out tests)
55 - renamed classes: AABBRayCollider => RayCollider, AABBSphereCollider => SphereCollider
56 - the sphere query now only returns a list of faces (extra info discarded). On the other hand it's a lot faster.
57 - OBB, AABB and planes queries. Original OBB and AABB queries contributed by Erwin de Vries.
58 - cosmetic changes in OPC_BoxBoxOverlap.h contributed by Gottfried Chen
59 - some inlining problems fixed
60 - faster ray-mesh tests using the separating axis theorem
61 - new split value in AABB tree construction (contributed by Igor Kravtchenko). Provides faster queries most of the time.
62 - improved temporal coherence for sphere & AABB queries (works in "All contacts" mode)
63
64 Notes:
65
66 - Everything in the "Ice code" directory (in VC++) is basically copy-pasted from my engine, with a lot
67 of code removed until there was no link error anymore. Don't expect those files to be cute or anything,
68 they've never been meant to be released and they're often updated/modified/messy.
69 - Some experimental features have been removed as well. Else I would never have released the 1.2...
70 - Not as polished/optimal as I would like it to be, but that's life. I promised myself to release it
71 before october 2002 (one YEAR later ?!).... That's the only reason why it's there.
72 - Some people reported ColDet was faster. Uh, come on. They were using Opcode in
73 "All contacts" mode whereas ColDet was doing "first contact"...
74
75 OPCODE distribution 1.1 (october 2001)
76 -----------------------
77
78 New in Opcode 1.1:
79 - stabbing queries
80 - sphere queries
81 - abtract base class for colliders
82 - settings validation methods
83 - compilation flags now grouped in OPC_Settings.h
84 - smaller files, new VC++ virtual dirs (cleaner)
85
86 Notes:
87
88 - "override(baseclass)" is a personal cosmetic thing. It's the same as "virtual", but provides more info.
89 - I code in 1600*1200, so some lines may look a bit long..
90 - This version is not as polished as the previous one due to lack of time. The stabbing & sphere queries
91 can still be optimized: for example by trying other atomic overlap tests. I'm using my first ray-AABB
92 code, but the newer one seems better. Tim Schröder's one is good as well. See: www.codercorner.com/RayAABB.cpp
93 - The trees can easily be compressed even more, I save this for later (lack of time, lack of time!)
94 - I removed various tests before releasing this one:
95 - a separation line, a.k.a. "front" in QuickCD, because gains were unclear
96 - distance queries in a PQP style, because it was way too slow
97 - support for deformable models, too slow as well
98 - You can easily use Opcode to do your player-vs-world collision detection, in a Nettle/Telemachos way.
99 If someone out there wants to donate some art / level for the cause, I'd be glad to release a demo. (current
100 demo uses copyrighted art I'm not allowed to spread)
101 - Sorry for the lack of real docs and/or solid examples. I just don't have enough time.
102
103 OPCODE distribution 1.0 (march 2001)
104 -----------------------
105
106 - First release
107
108 ===============================================================================
109
110 WHAT ?
111
112 OPCODE means OPtimized COllision DEtection.
113 So this is a collision detection package similar to RAPID. Here's a
114 quick list of features:
115
116 - C++ interface, developed for Windows systems using VC++ 6.0
117 - Works on arbitrary meshes (convex or non-convex), even polygon soups
118 - Current implementation uses AABB-trees
119 - Introduces Primitive-BV overlap tests during recursive collision queries (whereas
120 standard libraries only rely on Primitive-Primitive and BV-BV tests)
121 - Introduces no-leaf trees, i.e. collision trees whose leaf nodes have been removed
122 - Supports collision queries on quantized trees (decompressed on-the-fly)
123 - Supports "first contact" or "all contacts" modes (ā la RAPID)
124 - Uses temporal coherence for "first contact" mode (~10 to 20 times faster, useful
125 in rigid body simulation during bisection)
126 - Memory footprint is 7.2 times smaller than RAPID's one, which is ideal for console
127 games with limited ram (actually, if you use the unmodified RAPID code using double
128 precision, it's more like 13 times smaller...)
129 - And yet it often runs faster than RAPID (according to RDTSC, sometimes more than 5
130 times faster when objects are deeply overlapping)
131 - Performance is usually close to RAPID's one in close-proximity situations
132 - Stabbing, planes & volume queries (sphere, AABB, OBB, LSS)
133 - Sweep-and-prune
134 - Now works with deformable meshes
135 - Hybrid trees
136
137
138 What it can be used for:
139 - standard mesh-mesh collision detection (similar to RAPID, SOLID, QuickCD, PQP, ColDet...)
140 - N-body collisions (similar to V-Collide)
141 - camera-vs-world collisions (similar to Telemachos/Paul Nettle/Stan Melax articles)
142 - shadow feelers to speed up lightmap computations
143 - in-out tests to speed up voxelization processes
144 - picking
145 - rigid body simulation
146 - view frustum culling
147 - etc
148
149 WHY ?
150
151 - Because RAPID uses too many bytes.
152 - Because the idea was nice...
153
154 WHEN ?
155
156 It's been coded in march 2001 following a thread on the GD-Algorithms list.
157
158 GDAlgorithms-list mailing list
159 GDAlgorithms-list@lists.sourceforge.net
160 http://lists.sourceforge.net/lists/listinfo/gdalgorithms-list
161
162 WHO ?
163
164 Pierre Terdiman
165 June, 1, 2003
166
167 p.terdiman@wanadoo.fr
168 p.terdiman@codercorner.com
169
170 http://www.codercorner.com
171 http://www.codercorner.com/Opcode.htm
diff --git a/libraries/ode-0.9/OPCODE/StdAfx.cpp b/libraries/ode-0.9/OPCODE/StdAfx.cpp
new file mode 100644
index 0000000..9c381f6
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/StdAfx.cpp
@@ -0,0 +1,10 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9//#define ICE_MAIN
10#include "Stdafx.h"
diff --git a/libraries/ode-0.9/OPCODE/Stdafx.h b/libraries/ode-0.9/OPCODE/Stdafx.h
new file mode 100644
index 0000000..0223a6c
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/Stdafx.h
@@ -0,0 +1,24 @@
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9#if !defined(AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_)
10#define AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_
11
12#if _MSC_VER > 1000
13#pragma once
14#endif // _MSC_VER > 1000
15
16// Insert your headers here
17#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
18
19#include "Opcode.h"
20
21//{{AFX_INSERT_LOCATION}}
22// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
23
24#endif // !defined(AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_)
diff --git a/libraries/ode-0.9/OPCODE/TemporalCoherence.txt b/libraries/ode-0.9/OPCODE/TemporalCoherence.txt
new file mode 100644
index 0000000..fb85931
--- /dev/null
+++ b/libraries/ode-0.9/OPCODE/TemporalCoherence.txt
@@ -0,0 +1,32 @@
1
2> Hi John,
3>
4> I know I'll forget to tell you this if I don't write it right now....
5>
6> >(2) How is the receiving geometry for the shadow decided?
7>
8> I wrote about an LSS-test but actually performing a new VFC test (from the
9> light's view) is the same. In both cases, here's a trick to take advantage
10> of temporal coherence : test the world against a slightly larger than
11> necessary LSS or frustum. Keep the list of touched surfaces. Then next
12> frame, if the new volume is still contained within the previous one used
13for
14> the query, you can reuse the same list immediately. Actually it's a bit
15> similar to what you did in your sphere-tree, I think. Anyway, now the
16O(log
17> N) VFC is O(1) for some frames. It's not worth it for the "real" VFC, but
18> when you have N virtual frustum to test to drop N shadows, that's another
19> story.
20>
21> Two downsides:
22> - You need more ram to keep track of one list of meshes / shadow, but
23> usually it's not a lot.
24> - By using a larger volume for the query you possibly touch more
25> faces/surfaces, which will be rendered in the shadow pass. Usually it's
26not
27> a problem either since rendering is simply faster than geometric queries
28> those days. But of course, "your mileage may vary".
29>
30> Happy new year !
31>
32> Pierre