diff options
Diffstat (limited to 'libraries/ode-0.9/OPCODE/Ice')
39 files changed, 7561 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 | |||
23 | using 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
32 | AABB& 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
55 | float 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
71 | void 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
85 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
103 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
146 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
184 | const 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
206 | const 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
223 | const 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 | |||
286 | static 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 | |||
354 | const 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) | ||
382 | float 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 | |||
27 | using namespace IceCore; | ||
28 | |||
29 | // Static members | ||
30 | #ifdef CONTAINER_STATS | ||
31 | udword Container::mNbContainers = 0; | ||
32 | udword Container::mUsedRam = 0; | ||
33 | #endif | ||
34 | |||
35 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
36 | /** | ||
37 | * Constructor. No entries allocated there. | ||
38 | */ | ||
39 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
40 | Container::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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
53 | Container::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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
67 | Container::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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
81 | Container::~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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
97 | Container& 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
114 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
153 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
181 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
224 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
246 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
269 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
297 | Container& 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
317 | Container& 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
335 | udword 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 | |||
31 | using namespace IceMaths; | ||
32 | |||
33 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
34 | // Point Mul = HPoint * Matrix3x3; | ||
35 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
36 | Point 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
47 | HPoint 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
59 | HPoint& 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 | |||
14 | using 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
32 | void 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
44 | float 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
60 | float 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
78 | float 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
93 | void 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
110 | void 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
127 | void 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
144 | void 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
162 | void 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
189 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
217 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
249 | float 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
273 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
287 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
302 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
318 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
334 | ubyte 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
353 | udword 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
377 | void 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
406 | float 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
427 | float 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
450 | void 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
516 | float 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
542 | bool 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 | |||
38 | using namespace IceMaths; | ||
39 | |||
40 | // Cast operator | ||
41 | Matrix3x3::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 | |||
343 | void FromQuat(const Quat &q); | ||
344 | void 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 | |||
41 | using 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
54 | ICEMATHS_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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
80 | float 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
93 | float 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
104 | Matrix4x4& 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 | |||
23 | using 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
32 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
60 | void 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
82 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
125 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
166 | bool 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
197 | const 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
214 | const 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
243 | void 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
255 | void 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
288 | BOOL 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 | |||
23 | using 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
34 | Plane& 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 | |||
51 | using namespace IceMaths; | ||
52 | |||
53 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
54 | /** | ||
55 | * Creates a positive unit random vector. | ||
56 | * \return Self-reference | ||
57 | */ | ||
58 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
59 | Point& 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
74 | Point& 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 | ||
85 | Point::operator HPoint() const { return HPoint(x, y, z, 0.0f); } | ||
86 | |||
87 | Point& 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 | |||
109 | Point& Point::ProjectToPlane(const Plane& p) | ||
110 | { | ||
111 | *this-= (p.d + (*this|p.n))*p.n; | ||
112 | return *this; | ||
113 | } | ||
114 | |||
115 | void 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 | |||
128 | void 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 | |||
136 | BOOL 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 | |||
144 | Point& 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 | |||
152 | Point& 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 | |||
160 | Point& 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 | |||
168 | Point& 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 | |||
176 | Point& 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 | |||
184 | Point& 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 | |||
14 | using namespace IceCore; | ||
15 | |||
16 | void IceCore:: SRand(udword seed) | ||
17 | { | ||
18 | srand(seed); | ||
19 | } | ||
20 | |||
21 | udword IceCore::Rand() | ||
22 | { | ||
23 | return rand(); | ||
24 | } | ||
25 | |||
26 | |||
27 | static BasicRandom gRandomGenerator(42); | ||
28 | |||
29 | udword 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 | |||
64 | using namespace IceMaths; | ||
65 | |||
66 | float 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 | /* | ||
42 | To 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 | |||
54 | using 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
170 | RadixSort::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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
186 | RadixSort::~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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
204 | bool 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 | |||
217 | inline_ 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
238 | RadixSort& 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
350 | RadixSort& 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
511 | udword 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 | |||
27 | using namespace IceMaths; | ||
28 | |||
29 | float 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 | |||
14 | using 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 | |||
27 | static 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
43 | void 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
56 | float 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
70 | float 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
86 | float 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
99 | void 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
113 | void 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
127 | void 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 | |||
135 | PartVal 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 | /* | ||
165 | void 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
213 | float 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
231 | float 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
251 | void 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 | |||
269 | void 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 | |||
14 | using 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 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
24 | udword 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__ | ||