diff options
author | dan miller | 2007-10-19 05:20:48 +0000 |
---|---|---|
committer | dan miller | 2007-10-19 05:20:48 +0000 |
commit | d48ea5bb797037069d641da41da0f195f0124491 (patch) | |
tree | 40ff433d94859d629aac933d5ec73b382f62ba1a /libraries/ode-0.9/contrib | |
parent | dont ask (diff) | |
download | opensim-SC_OLD-d48ea5bb797037069d641da41da0f195f0124491.zip opensim-SC_OLD-d48ea5bb797037069d641da41da0f195f0124491.tar.gz opensim-SC_OLD-d48ea5bb797037069d641da41da0f195f0124491.tar.bz2 opensim-SC_OLD-d48ea5bb797037069d641da41da0f195f0124491.tar.xz |
one more for the gipper
Diffstat (limited to '')
105 files changed, 23566 insertions, 0 deletions
diff --git a/libraries/ode-0.9/contrib/BreakableJoints/README.txt b/libraries/ode-0.9/contrib/BreakableJoints/README.txt new file mode 100644 index 0000000..e996816 --- /dev/null +++ b/libraries/ode-0.9/contrib/BreakableJoints/README.txt | |||
@@ -0,0 +1,110 @@ | |||
1 | Breakable Joints | ||
2 | |||
3 | ================================================================================ | ||
4 | |||
5 | Description: | ||
6 | This is a small addition to ODE that makes joints breakable. Breakable means | ||
7 | that if a force on a joint is to high it wil break. I have included a modified | ||
8 | version of test_buggy.cpp (test_breakable.cpp) so you can see it for your self. | ||
9 | Just drive your buggy into an obstacle and enjoy! | ||
10 | |||
11 | ================================================================================ | ||
12 | |||
13 | Installation instructions: | ||
14 | - copy joint.h, joint.cpp, ode.cpp and step.cpp to the ode/src/ directory | ||
15 | - copy common.h and object.h to the include/ directory | ||
16 | - copy test_breakable.cpp to the ode/test/ directory | ||
17 | - add test_breakable.cpp to the ODE_TEST_SRC_CPP object in the makefile. | ||
18 | - make ode-lib | ||
19 | - make ode-test | ||
20 | You can also use the diffs. The above files will quickly go out of sync with the | ||
21 | rest of ODE but the diffs wil remain valid longer. | ||
22 | |||
23 | ================================================================================ | ||
24 | |||
25 | Functions: | ||
26 | dJointSetBreakable (dJointID joint, int b) | ||
27 | If b is 1 the joint is made breakable. If b is 0 the joint is made | ||
28 | unbreakable. | ||
29 | |||
30 | void dJointSetBreakCallback (dJointID joint, dJointBreakCallback *callbackFunc) | ||
31 | Sets the callback function for this joint. If a funtion is set it will be | ||
32 | called if the joint is broken but before it is actually detached or deleted. | ||
33 | |||
34 | void dJointSetBreakMode (dJointID joint, int mode) | ||
35 | Use this functions to set some flags. These flags can be ORred ( | ) | ||
36 | together; ie. dJointSetBreakMode (someJoint, | ||
37 | dJOINT_BREAK_AT_B1_FORCE|dJOINT_DELETE_ON_BREAK) | ||
38 | dJOINT_DELETE_ON_BREAK - If the joint breaks it wil be deleted. | ||
39 | dJOINT_BREAK_AT_B1_FORCE - If the force on body 1 is to high the joint will | ||
40 | break | ||
41 | dJOINT_BREAK_AT_B1_TORQUE - If the torque on body 1 is to high the joint will | ||
42 | break | ||
43 | dJOINT_BREAK_AT_B2_FORCE - If the force on body 2 is to high the joint will | ||
44 | break | ||
45 | dJOINT_BREAK_AT_B2_TORQUE - If the torque on body 2 is to high the joint will | ||
46 | break | ||
47 | |||
48 | void dJointSetBreakForce (dJointID joint, int body, dReal x, dReal y, dReal z) | ||
49 | With this function you can set the maximum force for a body connected to this | ||
50 | joint. A value of 0 for body means body 1, 1 means body 2. The force is | ||
51 | relative to the bodies rotation. | ||
52 | |||
53 | void dJointSetBreakTorque (dJointID joint, int body, dReal x, dReal y, dReal z) | ||
54 | With this function you can set the maximum torque for a body connected to this | ||
55 | joint. A value of 0 for body means body 1, 1 means body 2. The torque is | ||
56 | relative to the bodies rotation. | ||
57 | |||
58 | int dJointIsBreakable (dJointID joint) | ||
59 | Returns 1 if this joint is breakable, 0 otherwise. | ||
60 | |||
61 | int dJointGetBreakMode (dJointID joint) | ||
62 | Returns the breakmode flag. | ||
63 | |||
64 | void dJointGetBreakForce (dJointID joint, int body, dReal *force) | ||
65 | Returns the force at what this joint will break. A value of 0 for body means | ||
66 | body 1, 1 means body 2. force must have enough space for 3 dReal values. | ||
67 | |||
68 | void dJointGetBreakTorque (dJointID joint, int body, dReal *torque) | ||
69 | Returns the torque at what this joint will break. A value of 0 for body | ||
70 | means body 1, 1 means body 2. force must have enough space for 3 dReal | ||
71 | values. | ||
72 | |||
73 | ================================================================================ | ||
74 | |||
75 | The callback function is defined like this (in common.h): | ||
76 | void dJointBreakCallback (dJointID); | ||
77 | |||
78 | ================================================================================ | ||
79 | |||
80 | Problems, known bugs & other issues: | ||
81 | - If the timestep is very small then joints get a lot weaker. They can even fall | ||
82 | apart! | ||
83 | - I have tested all this with the latest checkout from CVS (at the time of | ||
84 | writing ofcourse). I haven't tested it with earlier versions of ODE. | ||
85 | - I have modified the code that fills the jointfeedback struct. I haven't tested | ||
86 | if it still works. | ||
87 | - I'm not sure if the forces are really relative to the connected bodies. | ||
88 | - There are some memory leaks in the test_breakable.cpp example. | ||
89 | |||
90 | ================================================================================ | ||
91 | |||
92 | Bugfixes and changes: | ||
93 | 09/08/2003 | ||
94 | - I fixed a bug when there where 0 joints in the simulation | ||
95 | |||
96 | 06/12/2003 | ||
97 | - dJointGetBreakMode() added, by vadim_mcagon@hotmail.com | ||
98 | |||
99 | 11/03/2004 | ||
100 | - Updated files to work with latest CVS checkout. | ||
101 | - Added support for dWorldStepFast1() | ||
102 | - Added separate test_breakable.cpp example. | ||
103 | - Updated the code that breaks and destroys a joint. | ||
104 | |||
105 | ================================================================================ | ||
106 | |||
107 | Send me an e-mail if you have any suggestions, ideas, bugs, bug-fixes, anything! | ||
108 | e-mail: roelvandijk@home.nl | ||
109 | |||
110 | Roel van Dijk - 11/03/2004 | ||
diff --git a/libraries/ode-0.9/contrib/BreakableJoints/common.h b/libraries/ode-0.9/contrib/BreakableJoints/common.h new file mode 100644 index 0000000..bc4272d --- /dev/null +++ b/libraries/ode-0.9/contrib/BreakableJoints/common.h | |||
@@ -0,0 +1,337 @@ | |||
1 | /************************************************************************* | ||
2 | * * | ||
3 | * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * | ||
4 | * All rights reserved. Email: russ@q12.org Web: www.q12.org * | ||
5 | * * | ||
6 | * This library is free software; you can redistribute it and/or * | ||
7 | * modify it under the terms of EITHER: * | ||
8 | * (1) The GNU Lesser General Public License as published by the Free * | ||
9 | * Software Foundation; either version 2.1 of the License, or (at * | ||
10 | * your option) any later version. The text of the GNU Lesser * | ||
11 | * General Public License is included with this library in the * | ||
12 | * file LICENSE.TXT. * | ||
13 | * (2) The BSD-style license that is included with this library in * | ||
14 | * the file LICENSE-BSD.TXT. * | ||
15 | * * | ||
16 | * This library is distributed in the hope that it will be useful, * | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * | ||
19 | * LICENSE.TXT and LICENSE-BSD.TXT for more details. * | ||
20 | * * | ||
21 | *************************************************************************/ | ||
22 | |||
23 | #ifndef _ODE_COMMON_H_ | ||
24 | #define _ODE_COMMON_H_ | ||
25 | |||
26 | #include <ode/config.h> | ||
27 | #include <ode/error.h> | ||
28 | |||
29 | #ifdef __cplusplus | ||
30 | extern "C" { | ||
31 | #endif | ||
32 | |||
33 | |||
34 | /* configuration stuff */ | ||
35 | |||
36 | /* the efficient alignment. most platforms align data structures to some | ||
37 | * number of bytes, but this is not always the most efficient alignment. | ||
38 | * for example, many x86 compilers align to 4 bytes, but on a pentium it | ||
39 | * is important to align doubles to 8 byte boundaries (for speed), and | ||
40 | * the 4 floats in a SIMD register to 16 byte boundaries. many other | ||
41 | * platforms have similar behavior. setting a larger alignment can waste | ||
42 | * a (very) small amount of memory. NOTE: this number must be a power of | ||
43 | * two. this is set to 16 by default. | ||
44 | */ | ||
45 | #define EFFICIENT_ALIGNMENT 16 | ||
46 | |||
47 | |||
48 | /* constants */ | ||
49 | |||
50 | /* pi and 1/sqrt(2) are defined here if necessary because they don't get | ||
51 | * defined in <math.h> on some platforms (like MS-Windows) | ||
52 | */ | ||
53 | |||
54 | #ifndef M_PI | ||
55 | #define M_PI REAL(3.1415926535897932384626433832795029) | ||
56 | #endif | ||
57 | #ifndef M_SQRT1_2 | ||
58 | #define M_SQRT1_2 REAL(0.7071067811865475244008443621048490) | ||
59 | #endif | ||
60 | |||
61 | |||
62 | /* debugging: | ||
63 | * IASSERT is an internal assertion, i.e. a consistency check. if it fails | ||
64 | * we want to know where. | ||
65 | * UASSERT is a user assertion, i.e. if it fails a nice error message | ||
66 | * should be printed for the user. | ||
67 | * AASSERT is an arguments assertion, i.e. if it fails "bad argument(s)" | ||
68 | * is printed. | ||
69 | * DEBUGMSG just prints out a message | ||
70 | */ | ||
71 | |||
72 | #ifndef dNODEBUG | ||
73 | #ifdef __GNUC__ | ||
74 | #define dIASSERT(a) if (!(a)) dDebug (d_ERR_IASSERT, \ | ||
75 | "assertion \"" #a "\" failed in %s() [%s]",__FUNCTION__,__FILE__); | ||
76 | #define dUASSERT(a,msg) if (!(a)) dDebug (d_ERR_UASSERT, \ | ||
77 | msg " in %s()", __FUNCTION__); | ||
78 | #define dDEBUGMSG(msg) dMessage (d_ERR_UASSERT, \ | ||
79 | msg " in %s()", __FUNCTION__); | ||
80 | #else | ||
81 | #define dIASSERT(a) if (!(a)) dDebug (d_ERR_IASSERT, \ | ||
82 | "assertion \"" #a "\" failed in %s:%d",__FILE__,__LINE__); | ||
83 | #define dUASSERT(a,msg) if (!(a)) dDebug (d_ERR_UASSERT, \ | ||
84 | msg " (%s:%d)", __FILE__,__LINE__); | ||
85 | #define dDEBUGMSG(msg) dMessage (d_ERR_UASSERT, \ | ||
86 | msg " (%s:%d)", __FILE__,__LINE__); | ||
87 | #endif | ||
88 | #else | ||
89 | #define dIASSERT(a) ; | ||
90 | #define dUASSERT(a,msg) ; | ||
91 | #define dDEBUGMSG(msg) ; | ||
92 | #endif | ||
93 | #define dAASSERT(a) dUASSERT(a,"Bad argument(s)") | ||
94 | |||
95 | /* floating point data type, vector, matrix and quaternion types */ | ||
96 | |||
97 | #if defined(dSINGLE) | ||
98 | typedef float dReal; | ||
99 | #elif defined(dDOUBLE) | ||
100 | typedef double dReal; | ||
101 | #else | ||
102 | #error You must #define dSINGLE or dDOUBLE | ||
103 | #endif | ||
104 | |||
105 | |||
106 | /* round an integer up to a multiple of 4, except that 0 and 1 are unmodified | ||
107 | * (used to compute matrix leading dimensions) | ||
108 | */ | ||
109 | #define dPAD(a) (((a) > 1) ? ((((a)-1)|3)+1) : (a)) | ||
110 | |||
111 | /* these types are mainly just used in headers */ | ||
112 | typedef dReal dVector3[4]; | ||
113 | typedef dReal dVector4[4]; | ||
114 | typedef dReal dMatrix3[4*3]; | ||
115 | typedef dReal dMatrix4[4*4]; | ||
116 | typedef dReal dMatrix6[8*6]; | ||
117 | typedef dReal dQuaternion[4]; | ||
118 | |||
119 | |||
120 | /* precision dependent scalar math functions */ | ||
121 | |||
122 | #if defined(dSINGLE) | ||
123 | |||
124 | #define REAL(x) (x ## f) /* form a constant */ | ||
125 | #define dRecip(x) ((float)(1.0f/(x))) /* reciprocal */ | ||
126 | #define dSqrt(x) ((float)sqrt(x)) /* square root */ | ||
127 | #define dRecipSqrt(x) ((float)(1.0f/sqrt(x))) /* reciprocal square root */ | ||
128 | #define dSin(x) ((float)sin(x)) /* sine */ | ||
129 | #define dCos(x) ((float)cos(x)) /* cosine */ | ||
130 | #define dFabs(x) ((float)fabs(x)) /* absolute value */ | ||
131 | #define dAtan2(y,x) ((float)atan2((y),(x))) /* arc tangent with 2 args */ | ||
132 | |||
133 | #elif defined(dDOUBLE) | ||
134 | |||
135 | #define REAL(x) (x) | ||
136 | #define dRecip(x) (1.0/(x)) | ||
137 | #define dSqrt(x) sqrt(x) | ||
138 | #define dRecipSqrt(x) (1.0/sqrt(x)) | ||
139 | #define dSin(x) sin(x) | ||
140 | #define dCos(x) cos(x) | ||
141 | #define dFabs(x) fabs(x) | ||
142 | #define dAtan2(y,x) atan2((y),(x)) | ||
143 | |||
144 | #else | ||
145 | #error You must #define dSINGLE or dDOUBLE | ||
146 | #endif | ||
147 | |||
148 | |||
149 | /* utility */ | ||
150 | |||
151 | |||
152 | /* round something up to be a multiple of the EFFICIENT_ALIGNMENT */ | ||
153 | |||
154 | #define dEFFICIENT_SIZE(x) ((((x)-1)|(EFFICIENT_ALIGNMENT-1))+1) | ||
155 | |||
156 | |||
157 | /* alloca aligned to the EFFICIENT_ALIGNMENT. note that this can waste | ||
158 | * up to 15 bytes per allocation, depending on what alloca() returns. | ||
159 | */ | ||
160 | |||
161 | #define dALLOCA16(n) \ | ||
162 | ((char*)dEFFICIENT_SIZE(((int)(alloca((n)+(EFFICIENT_ALIGNMENT-1)))))) | ||
163 | |||
164 | |||
165 | /* internal object types (all prefixed with `dx') */ | ||
166 | |||
167 | struct dxWorld; /* dynamics world */ | ||
168 | struct dxSpace; /* collision space */ | ||
169 | struct dxBody; /* rigid body (dynamics object) */ | ||
170 | struct dxGeom; /* geometry (collision object) */ | ||
171 | struct dxJoint; | ||
172 | struct dxJointNode; | ||
173 | struct dxJointGroup; | ||
174 | |||
175 | typedef struct dxWorld *dWorldID; | ||
176 | typedef struct dxSpace *dSpaceID; | ||
177 | typedef struct dxBody *dBodyID; | ||
178 | typedef struct dxGeom *dGeomID; | ||
179 | typedef struct dxJoint *dJointID; | ||
180 | typedef struct dxJointGroup *dJointGroupID; | ||
181 | |||
182 | |||
183 | /* error numbers */ | ||
184 | |||
185 | enum { | ||
186 | d_ERR_UNKNOWN = 0, /* unknown error */ | ||
187 | d_ERR_IASSERT, /* internal assertion failed */ | ||
188 | d_ERR_UASSERT, /* user assertion failed */ | ||
189 | d_ERR_LCP /* user assertion failed */ | ||
190 | }; | ||
191 | |||
192 | |||
193 | /* joint type numbers */ | ||
194 | |||
195 | enum { | ||
196 | dJointTypeNone = 0, /* or "unknown" */ | ||
197 | dJointTypeBall, | ||
198 | dJointTypeHinge, | ||
199 | dJointTypeSlider, | ||
200 | dJointTypeContact, | ||
201 | dJointTypeUniversal, | ||
202 | dJointTypeHinge2, | ||
203 | dJointTypeFixed, | ||
204 | dJointTypeNull, | ||
205 | dJointTypeAMotor | ||
206 | }; | ||
207 | |||
208 | /******************** breakable joint contribution ***********************/ | ||
209 | /* joint break callback function */ | ||
210 | typedef void dJointBreakCallback (dJointID joint); | ||
211 | |||
212 | /* joint break modes */ | ||
213 | enum { | ||
214 | // if this flag is set, the joint wil break | ||
215 | dJOINT_BROKEN = 0x0001, | ||
216 | // if this flag is set, the joint wil be deleted when it breaks | ||
217 | dJOINT_DELETE_ON_BREAK = 0x0002, | ||
218 | // if this flag is set, the joint can break at a certain force on body 1 | ||
219 | dJOINT_BREAK_AT_B1_FORCE = 0x0004, | ||
220 | // if this flag is set, the joint can break at a certain torque on body 1 | ||
221 | dJOINT_BREAK_AT_B1_TORQUE = 0x0008, | ||
222 | // if this flag is set, the joint can break at a certain force on body 2 | ||
223 | dJOINT_BREAK_AT_B2_FORCE = 0x0010, | ||
224 | // if this flag is set, the joint can break at a certain torque on body 2 | ||
225 | dJOINT_BREAK_AT_B2_TORQUE = 0x0020 | ||
226 | }; | ||
227 | /*************************************************************************/ | ||
228 | |||
229 | /* an alternative way of setting joint parameters, using joint parameter | ||
230 | * structures and member constants. we don't actually do this yet. | ||
231 | */ | ||
232 | |||
233 | /* | ||
234 | typedef struct dLimot { | ||
235 | int mode; | ||
236 | dReal lostop, histop; | ||
237 | dReal vel, fmax; | ||
238 | dReal fudge_factor; | ||
239 | dReal bounce, soft; | ||
240 | dReal suspension_erp, suspension_cfm; | ||
241 | } dLimot; | ||
242 | |||
243 | enum { | ||
244 | dLimotLoStop = 0x0001, | ||
245 | dLimotHiStop = 0x0002, | ||
246 | dLimotVel = 0x0004, | ||
247 | dLimotFMax = 0x0008, | ||
248 | dLimotFudgeFactor = 0x0010, | ||
249 | dLimotBounce = 0x0020, | ||
250 | dLimotSoft = 0x0040 | ||
251 | }; | ||
252 | */ | ||
253 | |||
254 | |||
255 | /* standard joint parameter names. why are these here? - because we don't want | ||
256 | * to include all the joint function definitions in joint.cpp. hmmmm. | ||
257 | * MSVC complains if we call D_ALL_PARAM_NAMES_X with a blank second argument, | ||
258 | * which is why we have the D_ALL_PARAM_NAMES macro as well. please copy and | ||
259 | * paste between these two. | ||
260 | */ | ||
261 | |||
262 | #define D_ALL_PARAM_NAMES(start) \ | ||
263 | /* parameters for limits and motors */ \ | ||
264 | dParamLoStop = start, \ | ||
265 | dParamHiStop, \ | ||
266 | dParamVel, \ | ||
267 | dParamFMax, \ | ||
268 | dParamFudgeFactor, \ | ||
269 | dParamBounce, \ | ||
270 | dParamCFM, \ | ||
271 | dParamStopERP, \ | ||
272 | dParamStopCFM, \ | ||
273 | /* parameters for suspension */ \ | ||
274 | dParamSuspensionERP, \ | ||
275 | dParamSuspensionCFM, | ||
276 | |||
277 | #define D_ALL_PARAM_NAMES_X(start,x) \ | ||
278 | /* parameters for limits and motors */ \ | ||
279 | dParamLoStop ## x = start, \ | ||
280 | dParamHiStop ## x, \ | ||
281 | dParamVel ## x, \ | ||
282 | dParamFMax ## x, \ | ||
283 | dParamFudgeFactor ## x, \ | ||
284 | dParamBounce ## x, \ | ||
285 | dParamCFM ## x, \ | ||
286 | dParamStopERP ## x, \ | ||
287 | dParamStopCFM ## x, \ | ||
288 | /* parameters for suspension */ \ | ||
289 | dParamSuspensionERP ## x, \ | ||
290 | dParamSuspensionCFM ## x, | ||
291 | |||
292 | enum { | ||
293 | D_ALL_PARAM_NAMES(0) | ||
294 | D_ALL_PARAM_NAMES_X(0x100,2) | ||
295 | D_ALL_PARAM_NAMES_X(0x200,3) | ||
296 | |||
297 | /* add a multiple of this constant to the basic parameter numbers to get | ||
298 | * the parameters for the second, third etc axes. | ||
299 | */ | ||
300 | dParamGroup=0x100 | ||
301 | }; | ||
302 | |||
303 | |||
304 | /* angular motor mode numbers */ | ||
305 | |||
306 | enum{ | ||
307 | dAMotorUser = 0, | ||
308 | dAMotorEuler = 1 | ||
309 | }; | ||
310 | |||
311 | |||
312 | /* joint force feedback information */ | ||
313 | |||
314 | typedef struct dJointFeedback { | ||
315 | dVector3 f1; /* force applied to body 1 */ | ||
316 | dVector3 t1; /* torque applied to body 1 */ | ||
317 | dVector3 f2; /* force applied to body 2 */ | ||
318 | dVector3 t2; /* torque applied to body 2 */ | ||
319 | } dJointFeedback; | ||
320 | |||
321 | |||
322 | /* private functions that must be implemented by the collision library: | ||
323 | * (1) indicate that a geom has moved, (2) get the next geom in a body list. | ||
324 | * these functions are called whenever the position of geoms connected to a | ||
325 | * body have changed, e.g. with dBodySetPosition(), dBodySetRotation(), or | ||
326 | * when the ODE step function updates the body state. | ||
327 | */ | ||
328 | |||
329 | void dGeomMoved (dGeomID); | ||
330 | dGeomID dGeomGetBodyNext (dGeomID); | ||
331 | |||
332 | |||
333 | #ifdef __cplusplus | ||
334 | } | ||
335 | #endif | ||
336 | |||
337 | #endif | ||
diff --git a/libraries/ode-0.9/contrib/BreakableJoints/diff/common.h.diff b/libraries/ode-0.9/contrib/BreakableJoints/diff/common.h.diff new file mode 100644 index 0000000..24415a1 --- /dev/null +++ b/libraries/ode-0.9/contrib/BreakableJoints/diff/common.h.diff | |||
@@ -0,0 +1,21 @@ | |||
1 | 208,227d207 | ||
2 | < /******************** breakable joint contribution ***********************/ | ||
3 | < /* joint break callback function */ | ||
4 | < typedef void dJointBreakCallback (dJointID joint); | ||
5 | < | ||
6 | < /* joint break modes */ | ||
7 | < enum { | ||
8 | < // if this flag is set, the joint wil break | ||
9 | < dJOINT_BROKEN = 0x0001, | ||
10 | < // if this flag is set, the joint wil be deleted when it breaks | ||
11 | < dJOINT_DELETE_ON_BREAK = 0x0002, | ||
12 | < // if this flag is set, the joint can break at a certain force on body 1 | ||
13 | < dJOINT_BREAK_AT_B1_FORCE = 0x0004, | ||
14 | < // if this flag is set, the joint can break at a certain torque on body 1 | ||
15 | < dJOINT_BREAK_AT_B1_TORQUE = 0x0008, | ||
16 | < // if this flag is set, the joint can break at a certain force on body 2 | ||
17 | < dJOINT_BREAK_AT_B2_FORCE = 0x0010, | ||
18 | < // if this flag is set, the joint can break at a certain torque on body 2 | ||
19 | < dJOINT_BREAK_AT_B2_TORQUE = 0x0020 | ||
20 | < }; | ||
21 | < /*************************************************************************/ | ||
diff --git a/libraries/ode-0.9/contrib/BreakableJoints/diff/joint.cpp.diff b/libraries/ode-0.9/contrib/BreakableJoints/diff/joint.cpp.diff new file mode 100644 index 0000000..80397f0 --- /dev/null +++ b/libraries/ode-0.9/contrib/BreakableJoints/diff/joint.cpp.diff | |||
@@ -0,0 +1,148 @@ | |||
1 | 2659,2804d2658 | ||
2 | < | ||
3 | < /******************** breakable joint contribution ***********************/ | ||
4 | < extern "C" void dJointSetBreakable (dxJoint *joint, int b) { | ||
5 | < dAASSERT(joint); | ||
6 | < if (b) { | ||
7 | < // we want this joint to be breakable but we must first check if it | ||
8 | < // was already breakable | ||
9 | < if (!joint->breakInfo) { | ||
10 | < // allocate a dxJointBreakInfo struct | ||
11 | < joint->breakInfo = new dxJointBreakInfo; | ||
12 | < joint->breakInfo->flags = 0; | ||
13 | < for (int i = 0; i < 3; i++) { | ||
14 | < joint->breakInfo->b1MaxF[0] = 0; | ||
15 | < joint->breakInfo->b1MaxT[0] = 0; | ||
16 | < joint->breakInfo->b2MaxF[0] = 0; | ||
17 | < joint->breakInfo->b2MaxT[0] = 0; | ||
18 | < } | ||
19 | < joint->breakInfo->callback = 0; | ||
20 | < } | ||
21 | < else { | ||
22 | < // the joint was already breakable | ||
23 | < return; | ||
24 | < } | ||
25 | < } | ||
26 | < else { | ||
27 | < // we want this joint to be unbreakable mut we must first check if | ||
28 | < // it is alreay unbreakable | ||
29 | < if (joint->breakInfo) { | ||
30 | < // deallocate the dxJointBreakInfo struct | ||
31 | < delete joint->breakInfo; | ||
32 | < joint->breakInfo = 0; | ||
33 | < } | ||
34 | < else { | ||
35 | < // the joint was already unbreakable | ||
36 | < return; | ||
37 | < } | ||
38 | < } | ||
39 | < } | ||
40 | < | ||
41 | < extern "C" void dJointSetBreakCallback (dxJoint *joint, dJointBreakCallback *callbackFunc) { | ||
42 | < dAASSERT(joint); | ||
43 | < # ifndef dNODEBUG | ||
44 | < // only works for a breakable joint | ||
45 | < if (!joint->breakInfo) { | ||
46 | < dDebug (0, "dJointSetBreakCallback called on unbreakable joint"); | ||
47 | < } | ||
48 | < # endif | ||
49 | < joint->breakInfo->callback = callbackFunc; | ||
50 | < } | ||
51 | < | ||
52 | < extern "C" void dJointSetBreakMode (dxJoint *joint, int mode) { | ||
53 | < dAASSERT(joint); | ||
54 | < # ifndef dNODEBUG | ||
55 | < // only works for a breakable joint | ||
56 | < if (!joint->breakInfo) { | ||
57 | < dDebug (0, "dJointSetBreakMode called on unbreakable joint"); | ||
58 | < } | ||
59 | < # endif | ||
60 | < joint->breakInfo->flags = mode; | ||
61 | < } | ||
62 | < | ||
63 | < extern "C" int dJointGetBreakMode (dxJoint *joint) { | ||
64 | < dAASSERT(joint); | ||
65 | < # ifndef dNODEBUG | ||
66 | < // only works for a breakable joint | ||
67 | < if (!joint->breakInfo) { | ||
68 | < dDebug (0, "dJointGetBreakMode called on unbreakable joint"); | ||
69 | < } | ||
70 | < # endif | ||
71 | < return joint->breakInfo->flags; | ||
72 | < } | ||
73 | < | ||
74 | < extern "C" void dJointSetBreakForce (dxJoint *joint, int body, dReal x, dReal y, dReal z) { | ||
75 | < dAASSERT(joint); | ||
76 | < # ifndef dNODEBUG | ||
77 | < // only works for a breakable joint | ||
78 | < if (!joint->breakInfo) { | ||
79 | < dDebug (0, "dJointSetBreakForce called on unbreakable joint"); | ||
80 | < } | ||
81 | < # endif | ||
82 | < if (body) { | ||
83 | < joint->breakInfo->b2MaxF[0] = x; | ||
84 | < joint->breakInfo->b2MaxF[1] = y; | ||
85 | < joint->breakInfo->b2MaxF[2] = z; | ||
86 | < } | ||
87 | < else { | ||
88 | < joint->breakInfo->b1MaxF[0] = x; | ||
89 | < joint->breakInfo->b1MaxF[1] = y; | ||
90 | < joint->breakInfo->b1MaxF[2] = z; | ||
91 | < } | ||
92 | < } | ||
93 | < | ||
94 | < extern "C" void dJointSetBreakTorque (dxJoint *joint, int body, dReal x, dReal y, dReal z) { | ||
95 | < dAASSERT(joint); | ||
96 | < # ifndef dNODEBUG | ||
97 | < // only works for a breakable joint | ||
98 | < if (!joint->breakInfo) { | ||
99 | < dDebug (0, "dJointSetBreakTorque called on unbreakable joint"); | ||
100 | < } | ||
101 | < # endif | ||
102 | < if (body) { | ||
103 | < joint->breakInfo->b2MaxT[0] = x; | ||
104 | < joint->breakInfo->b2MaxT[1] = y; | ||
105 | < joint->breakInfo->b2MaxT[2] = z; | ||
106 | < } | ||
107 | < else { | ||
108 | < joint->breakInfo->b1MaxT[0] = x; | ||
109 | < joint->breakInfo->b1MaxT[1] = y; | ||
110 | < joint->breakInfo->b1MaxT[2] = z; | ||
111 | < } | ||
112 | < } | ||
113 | < | ||
114 | < extern "C" int dJointIsBreakable (dxJoint *joint) { | ||
115 | < dAASSERT(joint); | ||
116 | < return joint->breakInfo != 0; | ||
117 | < } | ||
118 | < | ||
119 | < extern "C" void dJointGetBreakForce (dxJoint *joint, int body, dReal *force) { | ||
120 | < dAASSERT(joint); | ||
121 | < # ifndef dNODEBUG | ||
122 | < // only works for a breakable joint | ||
123 | < if (!joint->breakInfo) { | ||
124 | < dDebug (0, "dJointGetBreakForce called on unbreakable joint"); | ||
125 | < } | ||
126 | < # endif | ||
127 | < if (body) | ||
128 | < for (int i=0; i<3; i++) force[i]=joint->breakInfo->b2MaxF[i]; | ||
129 | < else | ||
130 | < for (int i=0; i<3; i++) force[i]=joint->breakInfo->b1MaxF[i]; | ||
131 | < } | ||
132 | < | ||
133 | < extern "C" void dJointGetBreakTorque (dxJoint *joint, int body, dReal *torque) { | ||
134 | < dAASSERT(joint); | ||
135 | < # ifndef dNODEBUG | ||
136 | < // only works for a breakable joint | ||
137 | < if (!joint->breakInfo) { | ||
138 | < dDebug (0, "dJointGetBreakTorque called on unbreakable joint"); | ||
139 | < } | ||
140 | < # endif | ||
141 | < if (body) | ||
142 | < for (int i=0; i<3; i++) torque[i]=joint->breakInfo->b2MaxT[i]; | ||
143 | < else | ||
144 | < for (int i=0; i<3; i++) torque[i]=joint->breakInfo->b1MaxT[i]; | ||
145 | < } | ||
146 | < /*************************************************************************/ | ||
147 | < | ||
148 | \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/BreakableJoints/diff/joint.h.diff b/libraries/ode-0.9/contrib/BreakableJoints/diff/joint.h.diff new file mode 100644 index 0000000..eed3c24 --- /dev/null +++ b/libraries/ode-0.9/contrib/BreakableJoints/diff/joint.h.diff | |||
@@ -0,0 +1,18 @@ | |||
1 | 61,70d60 | ||
2 | < /******************** breakable joint contribution ***********************/ | ||
3 | < struct dxJointBreakInfo : public dBase { | ||
4 | < int flags; | ||
5 | < dReal b1MaxF[3]; // maximum force on body 1 | ||
6 | < dReal b1MaxT[3]; // maximum torque on body 1 | ||
7 | < dReal b2MaxF[3]; // maximum force on body 2 | ||
8 | < dReal b2MaxT[3]; // maximum torque on body 2 | ||
9 | < dJointBreakCallback *callback; // function that is called when this joint breaks | ||
10 | < }; | ||
11 | < /*************************************************************************/ | ||
12 | 135,140d124 | ||
13 | < | ||
14 | < /******************** breakable joint contribution ***********************/ | ||
15 | < // optional break info structure. if this is not NULL the the joint is | ||
16 | < // breakable. | ||
17 | < dxJointBreakInfo *breakInfo; | ||
18 | < /*************************************************************************/ | ||
diff --git a/libraries/ode-0.9/contrib/BreakableJoints/diff/objects.h.diff b/libraries/ode-0.9/contrib/BreakableJoints/diff/objects.h.diff new file mode 100644 index 0000000..fd2129e --- /dev/null +++ b/libraries/ode-0.9/contrib/BreakableJoints/diff/objects.h.diff | |||
@@ -0,0 +1,13 @@ | |||
1 | 168,179d167 | ||
2 | < /******************** breakable joint contribution ***********************/ | ||
3 | < void dJointSetBreakable (dJointID, int b); | ||
4 | < void dJointSetBreakCallback (dJointID, dJointBreakCallback *callbackFunc); | ||
5 | < void dJointSetBreakMode (dJointID, int mode); | ||
6 | < int dJointGetBreakMode (dJointID); | ||
7 | < void dJointSetBreakForce (dJointID, int body, dReal x, dReal y, dReal z); | ||
8 | < void dJointSetBreakTorque (dJointID, int body, dReal x, dReal y, dReal z); | ||
9 | < int dJointIsBreakable (dJointID); | ||
10 | < void dJointGetBreakForce (dJointID, int body, dReal *force); | ||
11 | < void dJointGetBreakTorque (dJointID, int body, dReal *torque); | ||
12 | < /*************************************************************************/ | ||
13 | < | ||
diff --git a/libraries/ode-0.9/contrib/BreakableJoints/diff/ode.cpp.diff b/libraries/ode-0.9/contrib/BreakableJoints/diff/ode.cpp.diff new file mode 100644 index 0000000..761b7be --- /dev/null +++ b/libraries/ode-0.9/contrib/BreakableJoints/diff/ode.cpp.diff | |||
@@ -0,0 +1,28 @@ | |||
1 | 212,230d211 | ||
2 | < /******************** breakable joint contribution ***********************/ | ||
3 | < dxJoint* nextJ; | ||
4 | < if (!world->firstjoint) | ||
5 | < nextJ = 0; | ||
6 | < else | ||
7 | < nextJ = (dxJoint*)world->firstjoint->next; | ||
8 | < for (j=world->firstjoint; j; j=nextJ) { | ||
9 | < nextJ = (dxJoint*)j->next; | ||
10 | < // check if joint is breakable and broken | ||
11 | < if (j->breakInfo && j->breakInfo->flags & dJOINT_BROKEN) { | ||
12 | < // detach (break) the joint | ||
13 | < dJointAttach (j, 0, 0); | ||
14 | < // call the callback function if it is set | ||
15 | < if (j->breakInfo->callback) j->breakInfo->callback (j); | ||
16 | < // finally destroy the joint if the dJOINT_DELETE_ON_BREAK is set | ||
17 | < if (j->breakInfo->flags & dJOINT_DELETE_ON_BREAK) dJointDestroy (j); | ||
18 | < } | ||
19 | < } | ||
20 | < /*************************************************************************/ | ||
21 | 931,933d911 | ||
22 | < /******************** breakable joint contribution ***********************/ | ||
23 | < j->breakInfo = 0; | ||
24 | < /*************************************************************************/ | ||
25 | 1011,1013d988 | ||
26 | < /******************** breakable joint contribution ***********************/ | ||
27 | < if (j->breakInfo) delete j->breakInfo; | ||
28 | < /*************************************************************************/ | ||
diff --git a/libraries/ode-0.9/contrib/BreakableJoints/diff/step.cpp.diff b/libraries/ode-0.9/contrib/BreakableJoints/diff/step.cpp.diff new file mode 100644 index 0000000..dfc8c2f --- /dev/null +++ b/libraries/ode-0.9/contrib/BreakableJoints/diff/step.cpp.diff | |||
@@ -0,0 +1,130 @@ | |||
1 | 966,1066c966,989 | ||
2 | < /******************** breakable joint contribution ***********************/ | ||
3 | < // this saves us a few dereferences | ||
4 | < dxJointBreakInfo *jBI = joint[i]->breakInfo; | ||
5 | < // we need joint feedback if the joint is breakable or if the user | ||
6 | < // requested feedback. | ||
7 | < if (jBI||fb) { | ||
8 | < // we need feedback on the amount of force that this joint is | ||
9 | < // applying to the bodies. we use a slightly slower computation | ||
10 | < // that splits out the force components and puts them in the | ||
11 | < // feedback structure. | ||
12 | < dJointFeedback temp_fb; // temporary storage for joint feedback | ||
13 | < dReal data1[8],data2[8]; | ||
14 | < Multiply1_8q1 (data1, JJ, lambda+ofs[i], info[i].m); | ||
15 | < dReal *cf1 = cforce + 8*b1->tag; | ||
16 | < cf1[0] += (temp_fb.f1[0] = data1[0]); | ||
17 | < cf1[1] += (temp_fb.f1[1] = data1[1]); | ||
18 | < cf1[2] += (temp_fb.f1[2] = data1[2]); | ||
19 | < cf1[4] += (temp_fb.t1[0] = data1[4]); | ||
20 | < cf1[5] += (temp_fb.t1[1] = data1[5]); | ||
21 | < cf1[6] += (temp_fb.t1[2] = data1[6]); | ||
22 | < if (b2) { | ||
23 | < Multiply1_8q1 (data2, JJ + 8*info[i].m, lambda+ofs[i], info[i].m); | ||
24 | < dReal *cf2 = cforce + 8*b2->tag; | ||
25 | < cf2[0] += (temp_fb.f2[0] = data2[0]); | ||
26 | < cf2[1] += (temp_fb.f2[1] = data2[1]); | ||
27 | < cf2[2] += (temp_fb.f2[2] = data2[2]); | ||
28 | < cf2[4] += (temp_fb.t2[0] = data2[4]); | ||
29 | < cf2[5] += (temp_fb.t2[1] = data2[5]); | ||
30 | < cf2[6] += (temp_fb.t2[2] = data2[6]); | ||
31 | < } | ||
32 | < // if the user requested so we must copy the feedback information to | ||
33 | < // the feedback struct that the user suplied. | ||
34 | < if (fb) { | ||
35 | < // copy temp_fb to fb | ||
36 | < fb->f1[0] = temp_fb.f1[0]; | ||
37 | < fb->f1[1] = temp_fb.f1[1]; | ||
38 | < fb->f1[2] = temp_fb.f1[2]; | ||
39 | < fb->t1[0] = temp_fb.t1[0]; | ||
40 | < fb->t1[1] = temp_fb.t1[1]; | ||
41 | < fb->t1[2] = temp_fb.t1[2]; | ||
42 | < if (b2) { | ||
43 | < fb->f2[0] = temp_fb.f2[0]; | ||
44 | < fb->f2[1] = temp_fb.f2[1]; | ||
45 | < fb->f2[2] = temp_fb.f2[2]; | ||
46 | < fb->t2[0] = temp_fb.t2[0]; | ||
47 | < fb->t2[1] = temp_fb.t2[1]; | ||
48 | < fb->t2[2] = temp_fb.t2[2]; | ||
49 | < } | ||
50 | < } | ||
51 | < // if the joint is breakable we need to check the breaking conditions | ||
52 | < if (jBI) { | ||
53 | < dReal relCF1[3]; | ||
54 | < dReal relCT1[3]; | ||
55 | < // multiply the force and torque vectors by the rotation matrix of body 1 | ||
56 | < dMULTIPLY1_331 (&relCF1[0],b1->R,&temp_fb.f1[0]); | ||
57 | < dMULTIPLY1_331 (&relCT1[0],b1->R,&temp_fb.t1[0]); | ||
58 | < if (jBI->flags & dJOINT_BREAK_AT_B1_FORCE) { | ||
59 | < // check if the force is to high | ||
60 | < for (int i = 0; i < 3; i++) { | ||
61 | < if (relCF1[i] > jBI->b1MaxF[i]) { | ||
62 | < jBI->flags |= dJOINT_BROKEN; | ||
63 | < goto doneCheckingBreaks; | ||
64 | < } | ||
65 | < } | ||
66 | < } | ||
67 | < if (jBI->flags & dJOINT_BREAK_AT_B1_TORQUE) { | ||
68 | < // check if the torque is to high | ||
69 | < for (int i = 0; i < 3; i++) { | ||
70 | < if (relCT1[i] > jBI->b1MaxT[i]) { | ||
71 | < jBI->flags |= dJOINT_BROKEN; | ||
72 | < goto doneCheckingBreaks; | ||
73 | < } | ||
74 | < } | ||
75 | < } | ||
76 | < if (b2) { | ||
77 | < dReal relCF2[3]; | ||
78 | < dReal relCT2[3]; | ||
79 | < // multiply the force and torque vectors by the rotation matrix of body 2 | ||
80 | < dMULTIPLY1_331 (&relCF2[0],b2->R,&temp_fb.f2[0]); | ||
81 | < dMULTIPLY1_331 (&relCT2[0],b2->R,&temp_fb.t2[0]); | ||
82 | < if (jBI->flags & dJOINT_BREAK_AT_B2_FORCE) { | ||
83 | < // check if the force is to high | ||
84 | < for (int i = 0; i < 3; i++) { | ||
85 | < if (relCF2[i] > jBI->b2MaxF[i]) { | ||
86 | < jBI->flags |= dJOINT_BROKEN; | ||
87 | < goto doneCheckingBreaks; | ||
88 | < } | ||
89 | < } | ||
90 | < } | ||
91 | < if (jBI->flags & dJOINT_BREAK_AT_B2_TORQUE) { | ||
92 | < // check if the torque is to high | ||
93 | < for (int i = 0; i < 3; i++) { | ||
94 | < if (relCT2[i] > jBI->b2MaxT[i]) { | ||
95 | < jBI->flags |= dJOINT_BROKEN; | ||
96 | < goto doneCheckingBreaks; | ||
97 | < } | ||
98 | < } | ||
99 | < } | ||
100 | < } | ||
101 | < doneCheckingBreaks: | ||
102 | < ; | ||
103 | --- | ||
104 | > if (fb) { | ||
105 | > // the user has requested feedback on the amount of force that this | ||
106 | > // joint is applying to the bodies. we use a slightly slower | ||
107 | > // computation that splits out the force components and puts them | ||
108 | > // in the feedback structure. | ||
109 | > dReal data1[8],data2[8]; | ||
110 | > Multiply1_8q1 (data1, JJ, lambda+ofs[i], info[i].m); | ||
111 | > dReal *cf1 = cforce + 8*b1->tag; | ||
112 | > cf1[0] += (fb->f1[0] = data1[0]); | ||
113 | > cf1[1] += (fb->f1[1] = data1[1]); | ||
114 | > cf1[2] += (fb->f1[2] = data1[2]); | ||
115 | > cf1[4] += (fb->t1[0] = data1[4]); | ||
116 | > cf1[5] += (fb->t1[1] = data1[5]); | ||
117 | > cf1[6] += (fb->t1[2] = data1[6]); | ||
118 | > if (b2){ | ||
119 | > Multiply1_8q1 (data2, JJ + 8*info[i].m, lambda+ofs[i], info[i].m); | ||
120 | > dReal *cf2 = cforce + 8*b2->tag; | ||
121 | > cf2[0] += (fb->f2[0] = data2[0]); | ||
122 | > cf2[1] += (fb->f2[1] = data2[1]); | ||
123 | > cf2[2] += (fb->f2[2] = data2[2]); | ||
124 | > cf2[4] += (fb->t2[0] = data2[4]); | ||
125 | > cf2[5] += (fb->t2[1] = data2[5]); | ||
126 | > cf2[6] += (fb->t2[2] = data2[6]); | ||
127 | > } | ||
128 | 1068,1069d990 | ||
129 | < } | ||
130 | < /*************************************************************************/ | ||
diff --git a/libraries/ode-0.9/contrib/BreakableJoints/diff/stepfast.cpp.diff b/libraries/ode-0.9/contrib/BreakableJoints/diff/stepfast.cpp.diff new file mode 100644 index 0000000..ed64cba --- /dev/null +++ b/libraries/ode-0.9/contrib/BreakableJoints/diff/stepfast.cpp.diff | |||
@@ -0,0 +1,143 @@ | |||
1 | 587,598c587,593 | ||
2 | < /******************** breakable joint contribution ***********************/ | ||
3 | < // this saves us a few dereferences | ||
4 | < dxJointBreakInfo *jBI = joint->breakInfo; | ||
5 | < // we need joint feedback if the joint is breakable or if the user | ||
6 | < // requested feedback. | ||
7 | < if (jBI||fb) { | ||
8 | < // we need feedback on the amount of force that this joint is | ||
9 | < // applying to the bodies. we use a slightly slower computation | ||
10 | < // that splits out the force components and puts them in the | ||
11 | < // feedback structure. | ||
12 | < dJointFeedback temp_fb; // temporary storage for joint feedback | ||
13 | < dReal data1[8],data2[8]; | ||
14 | --- | ||
15 | > if (fb) | ||
16 | > { | ||
17 | > // the user has requested feedback on the amount of force that this | ||
18 | > // joint is applying to the bodies. we use a slightly slower | ||
19 | > // computation that splits out the force components and puts them | ||
20 | > // in the feedback structure. | ||
21 | > dReal data1[8], data2[8]; | ||
22 | 603,608c598,603 | ||
23 | < cf1[0] = (temp_fb.f1[0] = data1[0]); | ||
24 | < cf1[1] = (temp_fb.f1[1] = data1[1]); | ||
25 | < cf1[2] = (temp_fb.f1[2] = data1[2]); | ||
26 | < cf1[4] = (temp_fb.t1[0] = data1[4]); | ||
27 | < cf1[5] = (temp_fb.t1[1] = data1[5]); | ||
28 | < cf1[6] = (temp_fb.t1[2] = data1[6]); | ||
29 | --- | ||
30 | > cf1[0] = (fb->f1[0] = data1[0]); | ||
31 | > cf1[1] = (fb->f1[1] = data1[1]); | ||
32 | > cf1[2] = (fb->f1[2] = data1[2]); | ||
33 | > cf1[4] = (fb->t1[0] = data1[4]); | ||
34 | > cf1[5] = (fb->t1[1] = data1[5]); | ||
35 | > cf1[6] = (fb->t1[2] = data1[6]); | ||
36 | 614,691c609,614 | ||
37 | < cf2[0] = (temp_fb.f2[0] = data2[0]); | ||
38 | < cf2[1] = (temp_fb.f2[1] = data2[1]); | ||
39 | < cf2[2] = (temp_fb.f2[2] = data2[2]); | ||
40 | < cf2[4] = (temp_fb.t2[0] = data2[4]); | ||
41 | < cf2[5] = (temp_fb.t2[1] = data2[5]); | ||
42 | < cf2[6] = (temp_fb.t2[2] = data2[6]); | ||
43 | < } | ||
44 | < // if the user requested so we must copy the feedback information to | ||
45 | < // the feedback struct that the user suplied. | ||
46 | < if (fb) { | ||
47 | < // copy temp_fb to fb | ||
48 | < fb->f1[0] = temp_fb.f1[0]; | ||
49 | < fb->f1[1] = temp_fb.f1[1]; | ||
50 | < fb->f1[2] = temp_fb.f1[2]; | ||
51 | < fb->t1[0] = temp_fb.t1[0]; | ||
52 | < fb->t1[1] = temp_fb.t1[1]; | ||
53 | < fb->t1[2] = temp_fb.t1[2]; | ||
54 | < if (body[1]) { | ||
55 | < fb->f2[0] = temp_fb.f2[0]; | ||
56 | < fb->f2[1] = temp_fb.f2[1]; | ||
57 | < fb->f2[2] = temp_fb.f2[2]; | ||
58 | < fb->t2[0] = temp_fb.t2[0]; | ||
59 | < fb->t2[1] = temp_fb.t2[1]; | ||
60 | < fb->t2[2] = temp_fb.t2[2]; | ||
61 | < } | ||
62 | < } | ||
63 | < // if the joint is breakable we need to check the breaking conditions | ||
64 | < if (jBI) { | ||
65 | < dReal relCF1[3]; | ||
66 | < dReal relCT1[3]; | ||
67 | < // multiply the force and torque vectors by the rotation matrix of body 1 | ||
68 | < dMULTIPLY1_331 (&relCF1[0],body[0]->R,&temp_fb.f1[0]); | ||
69 | < dMULTIPLY1_331 (&relCT1[0],body[0]->R,&temp_fb.t1[0]); | ||
70 | < if (jBI->flags & dJOINT_BREAK_AT_B1_FORCE) { | ||
71 | < // check if the force is to high | ||
72 | < for (int i = 0; i < 3; i++) { | ||
73 | < if (relCF1[i] > jBI->b1MaxF[i]) { | ||
74 | < jBI->flags |= dJOINT_BROKEN; | ||
75 | < goto doneCheckingBreaks; | ||
76 | < } | ||
77 | < } | ||
78 | < } | ||
79 | < if (jBI->flags & dJOINT_BREAK_AT_B1_TORQUE) { | ||
80 | < // check if the torque is to high | ||
81 | < for (int i = 0; i < 3; i++) { | ||
82 | < if (relCT1[i] > jBI->b1MaxT[i]) { | ||
83 | < jBI->flags |= dJOINT_BROKEN; | ||
84 | < goto doneCheckingBreaks; | ||
85 | < } | ||
86 | < } | ||
87 | < } | ||
88 | < if (body[1]) { | ||
89 | < dReal relCF2[3]; | ||
90 | < dReal relCT2[3]; | ||
91 | < // multiply the force and torque vectors by the rotation matrix of body 2 | ||
92 | < dMULTIPLY1_331 (&relCF2[0],body[1]->R,&temp_fb.f2[0]); | ||
93 | < dMULTIPLY1_331 (&relCT2[0],body[1]->R,&temp_fb.t2[0]); | ||
94 | < if (jBI->flags & dJOINT_BREAK_AT_B2_FORCE) { | ||
95 | < // check if the force is to high | ||
96 | < for (int i = 0; i < 3; i++) { | ||
97 | < if (relCF2[i] > jBI->b2MaxF[i]) { | ||
98 | < jBI->flags |= dJOINT_BROKEN; | ||
99 | < goto doneCheckingBreaks; | ||
100 | < } | ||
101 | < } | ||
102 | < } | ||
103 | < if (jBI->flags & dJOINT_BREAK_AT_B2_TORQUE) { | ||
104 | < // check if the torque is to high | ||
105 | < for (int i = 0; i < 3; i++) { | ||
106 | < if (relCT2[i] > jBI->b2MaxT[i]) { | ||
107 | < jBI->flags |= dJOINT_BROKEN; | ||
108 | < goto doneCheckingBreaks; | ||
109 | < } | ||
110 | < } | ||
111 | < } | ||
112 | < } | ||
113 | < doneCheckingBreaks: | ||
114 | < ; | ||
115 | --- | ||
116 | > cf2[0] = (fb->f2[0] = data2[0]); | ||
117 | > cf2[1] = (fb->f2[1] = data2[1]); | ||
118 | > cf2[2] = (fb->f2[2] = data2[2]); | ||
119 | > cf2[4] = (fb->t2[0] = data2[4]); | ||
120 | > cf2[5] = (fb->t2[1] = data2[5]); | ||
121 | > cf2[6] = (fb->t2[2] = data2[6]); | ||
122 | 694d616 | ||
123 | < /*************************************************************************/ | ||
124 | 1178,1196d1099 | ||
125 | < /******************** breakable joint contribution ***********************/ | ||
126 | < dxJoint* nextJ; | ||
127 | < if (!world->firstjoint) | ||
128 | < nextJ = 0; | ||
129 | < else | ||
130 | < nextJ = (dxJoint*)world->firstjoint->next; | ||
131 | < for (j=world->firstjoint; j; j=nextJ) { | ||
132 | < nextJ = (dxJoint*)j->next; | ||
133 | < // check if joint is breakable and broken | ||
134 | < if (j->breakInfo && j->breakInfo->flags & dJOINT_BROKEN) { | ||
135 | < // detach (break) the joint | ||
136 | < dJointAttach (j, 0, 0); | ||
137 | < // call the callback function if it is set | ||
138 | < if (j->breakInfo->callback) j->breakInfo->callback (j); | ||
139 | < // finally destroy the joint if the dJOINT_DELETE_ON_BREAK is set | ||
140 | < if (j->breakInfo->flags & dJOINT_DELETE_ON_BREAK) dJointDestroy (j); | ||
141 | < } | ||
142 | < } | ||
143 | < /*************************************************************************/ | ||
diff --git a/libraries/ode-0.9/contrib/BreakableJoints/diff/test_buggy.cpp.diff b/libraries/ode-0.9/contrib/BreakableJoints/diff/test_buggy.cpp.diff new file mode 100644 index 0000000..65770da --- /dev/null +++ b/libraries/ode-0.9/contrib/BreakableJoints/diff/test_buggy.cpp.diff | |||
@@ -0,0 +1,16 @@ | |||
1 | 266,270d265 | ||
2 | < | ||
3 | < // breakable joints contribution | ||
4 | < dJointSetBreakable (joint[i], 1); | ||
5 | < dJointSetBreakMode (joint[i], dJOINT_BREAK_AT_FORCE); | ||
6 | < dJointSetBreakForce (joint[i], 0.5); | ||
7 | 298c293 | ||
8 | < ground_box = dCreateBox (space,2,1.5,5); | ||
9 | --- | ||
10 | > ground_box = dCreateBox (space,2,1.5,1); | ||
11 | 300,301c295,296 | ||
12 | < dRFromAxisAndAngle (R,0,1,0,-0.85); | ||
13 | < dGeomSetPosition (ground_box,5,0,-1); | ||
14 | --- | ||
15 | > dRFromAxisAndAngle (R,0,1,0,-0.15); | ||
16 | > dGeomSetPosition (ground_box,2,0,-0.34); | ||
diff --git a/libraries/ode-0.9/contrib/BreakableJoints/joint.cpp b/libraries/ode-0.9/contrib/BreakableJoints/joint.cpp new file mode 100644 index 0000000..2c724f8 --- /dev/null +++ b/libraries/ode-0.9/contrib/BreakableJoints/joint.cpp | |||
@@ -0,0 +1,2803 @@ | |||
1 | /************************************************************************* | ||
2 | * * | ||
3 | * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * | ||
4 | * All rights reserved. Email: russ@q12.org Web: www.q12.org * | ||
5 | * * | ||
6 | * This library is free software; you can redistribute it and/or * | ||
7 | * modify it under the terms of EITHER: * | ||
8 | * (1) The GNU Lesser General Public License as published by the Free * | ||
9 | * Software Foundation; either version 2.1 of the License, or (at * | ||
10 | * your option) any later version. The text of the GNU Lesser * | ||
11 | * General Public License is included with this library in the * | ||
12 | * file LICENSE.TXT. * | ||
13 | * (2) The BSD-style license that is included with this library in * | ||
14 | * the file LICENSE-BSD.TXT. * | ||
15 | * * | ||
16 | * This library is distributed in the hope that it will be useful, * | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * | ||
19 | * LICENSE.TXT and LICENSE-BSD.TXT for more details. * | ||
20 | * * | ||
21 | *************************************************************************/ | ||
22 | |||
23 | /* | ||
24 | |||
25 | design note: the general principle for giving a joint the option of connecting | ||
26 | to the static environment (i.e. the absolute frame) is to check the second | ||
27 | body (joint->node[1].body), and if it is zero then behave as if its body | ||
28 | transform is the identity. | ||
29 | |||
30 | */ | ||
31 | |||
32 | #include <ode/odemath.h> | ||
33 | #include <ode/rotation.h> | ||
34 | #include <ode/matrix.h> | ||
35 | #include "joint.h" | ||
36 | |||
37 | //**************************************************************************** | ||
38 | // externs | ||
39 | |||
40 | extern "C" void dBodyAddTorque (dBodyID, dReal fx, dReal fy, dReal fz); | ||
41 | extern "C" void dBodyAddForce (dBodyID, dReal fx, dReal fy, dReal fz); | ||
42 | |||
43 | //**************************************************************************** | ||
44 | // utility | ||
45 | |||
46 | // set three "ball-and-socket" rows in the constraint equation, and the | ||
47 | // corresponding right hand side. | ||
48 | |||
49 | static inline void setBall (dxJoint *joint, dxJoint::Info2 *info, | ||
50 | dVector3 anchor1, dVector3 anchor2) | ||
51 | { | ||
52 | // anchor points in global coordinates with respect to body PORs. | ||
53 | dVector3 a1,a2; | ||
54 | |||
55 | int s = info->rowskip; | ||
56 | |||
57 | // set jacobian | ||
58 | info->J1l[0] = 1; | ||
59 | info->J1l[s+1] = 1; | ||
60 | info->J1l[2*s+2] = 1; | ||
61 | dMULTIPLY0_331 (a1,joint->node[0].body->R,anchor1); | ||
62 | dCROSSMAT (info->J1a,a1,s,-,+); | ||
63 | if (joint->node[1].body) { | ||
64 | info->J2l[0] = -1; | ||
65 | info->J2l[s+1] = -1; | ||
66 | info->J2l[2*s+2] = -1; | ||
67 | dMULTIPLY0_331 (a2,joint->node[1].body->R,anchor2); | ||
68 | dCROSSMAT (info->J2a,a2,s,+,-); | ||
69 | } | ||
70 | |||
71 | // set right hand side | ||
72 | dReal k = info->fps * info->erp; | ||
73 | if (joint->node[1].body) { | ||
74 | for (int j=0; j<3; j++) { | ||
75 | info->c[j] = k * (a2[j] + joint->node[1].body->pos[j] - | ||
76 | a1[j] - joint->node[0].body->pos[j]); | ||
77 | } | ||
78 | } | ||
79 | else { | ||
80 | for (int j=0; j<3; j++) { | ||
81 | info->c[j] = k * (anchor2[j] - a1[j] - | ||
82 | joint->node[0].body->pos[j]); | ||
83 | } | ||
84 | } | ||
85 | } | ||
86 | |||
87 | |||
88 | // this is like setBall(), except that `axis' is a unit length vector | ||
89 | // (in global coordinates) that should be used for the first jacobian | ||
90 | // position row (the other two row vectors will be derived from this). | ||
91 | // `erp1' is the erp value to use along the axis. | ||
92 | |||
93 | static inline void setBall2 (dxJoint *joint, dxJoint::Info2 *info, | ||
94 | dVector3 anchor1, dVector3 anchor2, | ||
95 | dVector3 axis, dReal erp1) | ||
96 | { | ||
97 | // anchor points in global coordinates with respect to body PORs. | ||
98 | dVector3 a1,a2; | ||
99 | |||
100 | int i,s = info->rowskip; | ||
101 | |||
102 | // get vectors normal to the axis. in setBall() axis,q1,q2 is [1 0 0], | ||
103 | // [0 1 0] and [0 0 1], which makes everything much easier. | ||
104 | dVector3 q1,q2; | ||
105 | dPlaneSpace (axis,q1,q2); | ||
106 | |||
107 | // set jacobian | ||
108 | for (i=0; i<3; i++) info->J1l[i] = axis[i]; | ||
109 | for (i=0; i<3; i++) info->J1l[s+i] = q1[i]; | ||
110 | for (i=0; i<3; i++) info->J1l[2*s+i] = q2[i]; | ||
111 | dMULTIPLY0_331 (a1,joint->node[0].body->R,anchor1); | ||
112 | dCROSS (info->J1a,=,a1,axis); | ||
113 | dCROSS (info->J1a+s,=,a1,q1); | ||
114 | dCROSS (info->J1a+2*s,=,a1,q2); | ||
115 | if (joint->node[1].body) { | ||
116 | for (i=0; i<3; i++) info->J2l[i] = -axis[i]; | ||
117 | for (i=0; i<3; i++) info->J2l[s+i] = -q1[i]; | ||
118 | for (i=0; i<3; i++) info->J2l[2*s+i] = -q2[i]; | ||
119 | dMULTIPLY0_331 (a2,joint->node[1].body->R,anchor2); | ||
120 | dCROSS (info->J2a,= -,a2,axis); | ||
121 | dCROSS (info->J2a+s,= -,a2,q1); | ||
122 | dCROSS (info->J2a+2*s,= -,a2,q2); | ||
123 | } | ||
124 | |||
125 | // set right hand side - measure error along (axis,q1,q2) | ||
126 | dReal k1 = info->fps * erp1; | ||
127 | dReal k = info->fps * info->erp; | ||
128 | |||
129 | for (i=0; i<3; i++) a1[i] += joint->node[0].body->pos[i]; | ||
130 | if (joint->node[1].body) { | ||
131 | for (i=0; i<3; i++) a2[i] += joint->node[1].body->pos[i]; | ||
132 | info->c[0] = k1 * (dDOT(axis,a2) - dDOT(axis,a1)); | ||
133 | info->c[1] = k * (dDOT(q1,a2) - dDOT(q1,a1)); | ||
134 | info->c[2] = k * (dDOT(q2,a2) - dDOT(q2,a1)); | ||
135 | } | ||
136 | else { | ||
137 | info->c[0] = k1 * (dDOT(axis,anchor2) - dDOT(axis,a1)); | ||
138 | info->c[1] = k * (dDOT(q1,anchor2) - dDOT(q1,a1)); | ||
139 | info->c[2] = k * (dDOT(q2,anchor2) - dDOT(q2,a1)); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | |||
144 | // set three orientation rows in the constraint equation, and the | ||
145 | // corresponding right hand side. | ||
146 | |||
147 | static void setFixedOrientation(dxJoint *joint, dxJoint::Info2 *info, dQuaternion qrel, int start_row) | ||
148 | { | ||
149 | int s = info->rowskip; | ||
150 | int start_index = start_row * s; | ||
151 | |||
152 | // 3 rows to make body rotations equal | ||
153 | info->J1a[start_index] = 1; | ||
154 | info->J1a[start_index + s + 1] = 1; | ||
155 | info->J1a[start_index + s*2+2] = 1; | ||
156 | if (joint->node[1].body) { | ||
157 | info->J2a[start_index] = -1; | ||
158 | info->J2a[start_index + s+1] = -1; | ||
159 | info->J2a[start_index + s*2+2] = -1; | ||
160 | } | ||
161 | |||
162 | // compute the right hand side. the first three elements will result in | ||
163 | // relative angular velocity of the two bodies - this is set to bring them | ||
164 | // back into alignment. the correcting angular velocity is | ||
165 | // |angular_velocity| = angle/time = erp*theta / stepsize | ||
166 | // = (erp*fps) * theta | ||
167 | // angular_velocity = |angular_velocity| * u | ||
168 | // = (erp*fps) * theta * u | ||
169 | // where rotation along unit length axis u by theta brings body 2's frame | ||
170 | // to qrel with respect to body 1's frame. using a small angle approximation | ||
171 | // for sin(), this gives | ||
172 | // angular_velocity = (erp*fps) * 2 * v | ||
173 | // where the quaternion of the relative rotation between the two bodies is | ||
174 | // q = [cos(theta/2) sin(theta/2)*u] = [s v] | ||
175 | |||
176 | // get qerr = relative rotation (rotation error) between two bodies | ||
177 | dQuaternion qerr,e; | ||
178 | if (joint->node[1].body) { | ||
179 | dQuaternion qq; | ||
180 | dQMultiply1 (qq,joint->node[0].body->q,joint->node[1].body->q); | ||
181 | dQMultiply2 (qerr,qq,qrel); | ||
182 | } | ||
183 | else { | ||
184 | dQMultiply3 (qerr,joint->node[0].body->q,qrel); | ||
185 | } | ||
186 | if (qerr[0] < 0) { | ||
187 | qerr[1] = -qerr[1]; // adjust sign of qerr to make theta small | ||
188 | qerr[2] = -qerr[2]; | ||
189 | qerr[3] = -qerr[3]; | ||
190 | } | ||
191 | dMULTIPLY0_331 (e,joint->node[0].body->R,qerr+1); // @@@ bad SIMD padding! | ||
192 | dReal k = info->fps * info->erp; | ||
193 | info->c[start_row] = 2*k * e[0]; | ||
194 | info->c[start_row+1] = 2*k * e[1]; | ||
195 | info->c[start_row+2] = 2*k * e[2]; | ||
196 | } | ||
197 | |||
198 | |||
199 | // compute anchor points relative to bodies | ||
200 | |||
201 | static void setAnchors (dxJoint *j, dReal x, dReal y, dReal z, | ||
202 | dVector3 anchor1, dVector3 anchor2) | ||
203 | { | ||
204 | if (j->node[0].body) { | ||
205 | dReal q[4]; | ||
206 | q[0] = x - j->node[0].body->pos[0]; | ||
207 | q[1] = y - j->node[0].body->pos[1]; | ||
208 | q[2] = z - j->node[0].body->pos[2]; | ||
209 | q[3] = 0; | ||
210 | dMULTIPLY1_331 (anchor1,j->node[0].body->R,q); | ||
211 | if (j->node[1].body) { | ||
212 | q[0] = x - j->node[1].body->pos[0]; | ||
213 | q[1] = y - j->node[1].body->pos[1]; | ||
214 | q[2] = z - j->node[1].body->pos[2]; | ||
215 | q[3] = 0; | ||
216 | dMULTIPLY1_331 (anchor2,j->node[1].body->R,q); | ||
217 | } | ||
218 | else { | ||
219 | anchor2[0] = x; | ||
220 | anchor2[1] = y; | ||
221 | anchor2[2] = z; | ||
222 | } | ||
223 | } | ||
224 | anchor1[3] = 0; | ||
225 | anchor2[3] = 0; | ||
226 | } | ||
227 | |||
228 | |||
229 | // compute axes relative to bodies. either axis1 or axis2 can be 0. | ||
230 | |||
231 | static void setAxes (dxJoint *j, dReal x, dReal y, dReal z, | ||
232 | dVector3 axis1, dVector3 axis2) | ||
233 | { | ||
234 | if (j->node[0].body) { | ||
235 | dReal q[4]; | ||
236 | q[0] = x; | ||
237 | q[1] = y; | ||
238 | q[2] = z; | ||
239 | q[3] = 0; | ||
240 | dNormalize3 (q); | ||
241 | if (axis1) { | ||
242 | dMULTIPLY1_331 (axis1,j->node[0].body->R,q); | ||
243 | axis1[3] = 0; | ||
244 | } | ||
245 | if (axis2) { | ||
246 | if (j->node[1].body) { | ||
247 | dMULTIPLY1_331 (axis2,j->node[1].body->R,q); | ||
248 | } | ||
249 | else { | ||
250 | axis2[0] = x; | ||
251 | axis2[1] = y; | ||
252 | axis2[2] = z; | ||
253 | } | ||
254 | axis2[3] = 0; | ||
255 | } | ||
256 | } | ||
257 | } | ||
258 | |||
259 | |||
260 | static void getAnchor (dxJoint *j, dVector3 result, dVector3 anchor1) | ||
261 | { | ||
262 | if (j->node[0].body) { | ||
263 | dMULTIPLY0_331 (result,j->node[0].body->R,anchor1); | ||
264 | result[0] += j->node[0].body->pos[0]; | ||
265 | result[1] += j->node[0].body->pos[1]; | ||
266 | result[2] += j->node[0].body->pos[2]; | ||
267 | } | ||
268 | } | ||
269 | |||
270 | |||
271 | static void getAnchor2 (dxJoint *j, dVector3 result, dVector3 anchor2) | ||
272 | { | ||
273 | if (j->node[1].body) { | ||
274 | dMULTIPLY0_331 (result,j->node[1].body->R,anchor2); | ||
275 | result[0] += j->node[1].body->pos[0]; | ||
276 | result[1] += j->node[1].body->pos[1]; | ||
277 | result[2] += j->node[1].body->pos[2]; | ||
278 | } | ||
279 | else { | ||
280 | result[0] = anchor2[0]; | ||
281 | result[1] = anchor2[1]; | ||
282 | result[2] = anchor2[2]; | ||
283 | } | ||
284 | } | ||
285 | |||
286 | |||
287 | static void getAxis (dxJoint *j, dVector3 result, dVector3 axis1) | ||
288 | { | ||
289 | if (j->node[0].body) { | ||
290 | dMULTIPLY0_331 (result,j->node[0].body->R,axis1); | ||
291 | } | ||
292 | } | ||
293 | |||
294 | |||
295 | static void getAxis2 (dxJoint *j, dVector3 result, dVector3 axis2) | ||
296 | { | ||
297 | if (j->node[1].body) { | ||
298 | dMULTIPLY0_331 (result,j->node[1].body->R,axis2); | ||
299 | } | ||
300 | else { | ||
301 | result[0] = axis2[0]; | ||
302 | result[1] = axis2[1]; | ||
303 | result[2] = axis2[2]; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | |||
308 | static dReal getHingeAngleFromRelativeQuat (dQuaternion qrel, dVector3 axis) | ||
309 | { | ||
310 | // the angle between the two bodies is extracted from the quaternion that | ||
311 | // represents the relative rotation between them. recall that a quaternion | ||
312 | // q is: | ||
313 | // [s,v] = [ cos(theta/2) , sin(theta/2) * u ] | ||
314 | // where s is a scalar and v is a 3-vector. u is a unit length axis and | ||
315 | // theta is a rotation along that axis. we can get theta/2 by: | ||
316 | // theta/2 = atan2 ( sin(theta/2) , cos(theta/2) ) | ||
317 | // but we can't get sin(theta/2) directly, only its absolute value, i.e.: | ||
318 | // |v| = |sin(theta/2)| * |u| | ||
319 | // = |sin(theta/2)| | ||
320 | // using this value will have a strange effect. recall that there are two | ||
321 | // quaternion representations of a given rotation, q and -q. typically as | ||
322 | // a body rotates along the axis it will go through a complete cycle using | ||
323 | // one representation and then the next cycle will use the other | ||
324 | // representation. this corresponds to u pointing in the direction of the | ||
325 | // hinge axis and then in the opposite direction. the result is that theta | ||
326 | // will appear to go "backwards" every other cycle. here is a fix: if u | ||
327 | // points "away" from the direction of the hinge (motor) axis (i.e. more | ||
328 | // than 90 degrees) then use -q instead of q. this represents the same | ||
329 | // rotation, but results in the cos(theta/2) value being sign inverted. | ||
330 | |||
331 | // extract the angle from the quaternion. cost2 = cos(theta/2), | ||
332 | // sint2 = |sin(theta/2)| | ||
333 | dReal cost2 = qrel[0]; | ||
334 | dReal sint2 = dSqrt (qrel[1]*qrel[1]+qrel[2]*qrel[2]+qrel[3]*qrel[3]); | ||
335 | dReal theta = (dDOT(qrel+1,axis) >= 0) ? // @@@ padding assumptions | ||
336 | (2 * dAtan2(sint2,cost2)) : // if u points in direction of axis | ||
337 | (2 * dAtan2(sint2,-cost2)); // if u points in opposite direction | ||
338 | |||
339 | // the angle we get will be between 0..2*pi, but we want to return angles | ||
340 | // between -pi..pi | ||
341 | if (theta > M_PI) theta -= 2*M_PI; | ||
342 | |||
343 | // the angle we've just extracted has the wrong sign | ||
344 | theta = -theta; | ||
345 | |||
346 | return theta; | ||
347 | } | ||
348 | |||
349 | |||
350 | // given two bodies (body1,body2), the hinge axis that they are connected by | ||
351 | // w.r.t. body1 (axis), and the initial relative orientation between them | ||
352 | // (q_initial), return the relative rotation angle. the initial relative | ||
353 | // orientation corresponds to an angle of zero. if body2 is 0 then measure the | ||
354 | // angle between body1 and the static frame. | ||
355 | // | ||
356 | // this will not return the correct angle if the bodies rotate along any axis | ||
357 | // other than the given hinge axis. | ||
358 | |||
359 | static dReal getHingeAngle (dxBody *body1, dxBody *body2, dVector3 axis, | ||
360 | dQuaternion q_initial) | ||
361 | { | ||
362 | // get qrel = relative rotation between the two bodies | ||
363 | dQuaternion qrel; | ||
364 | if (body2) { | ||
365 | dQuaternion qq; | ||
366 | dQMultiply1 (qq,body1->q,body2->q); | ||
367 | dQMultiply2 (qrel,qq,q_initial); | ||
368 | } | ||
369 | else { | ||
370 | // pretend body2->q is the identity | ||
371 | dQMultiply3 (qrel,body1->q,q_initial); | ||
372 | } | ||
373 | |||
374 | return getHingeAngleFromRelativeQuat (qrel,axis); | ||
375 | } | ||
376 | |||
377 | //**************************************************************************** | ||
378 | // dxJointLimitMotor | ||
379 | |||
380 | void dxJointLimitMotor::init (dxWorld *world) | ||
381 | { | ||
382 | vel = 0; | ||
383 | fmax = 0; | ||
384 | lostop = -dInfinity; | ||
385 | histop = dInfinity; | ||
386 | fudge_factor = 1; | ||
387 | normal_cfm = world->global_cfm; | ||
388 | stop_erp = world->global_erp; | ||
389 | stop_cfm = world->global_cfm; | ||
390 | bounce = 0; | ||
391 | limit = 0; | ||
392 | limit_err = 0; | ||
393 | } | ||
394 | |||
395 | |||
396 | void dxJointLimitMotor::set (int num, dReal value) | ||
397 | { | ||
398 | switch (num) { | ||
399 | case dParamLoStop: | ||
400 | if (value <= histop) lostop = value; | ||
401 | break; | ||
402 | case dParamHiStop: | ||
403 | if (value >= lostop) histop = value; | ||
404 | break; | ||
405 | case dParamVel: | ||
406 | vel = value; | ||
407 | break; | ||
408 | case dParamFMax: | ||
409 | if (value >= 0) fmax = value; | ||
410 | break; | ||
411 | case dParamFudgeFactor: | ||
412 | if (value >= 0 && value <= 1) fudge_factor = value; | ||
413 | break; | ||
414 | case dParamBounce: | ||
415 | bounce = value; | ||
416 | break; | ||
417 | case dParamCFM: | ||
418 | normal_cfm = value; | ||
419 | break; | ||
420 | case dParamStopERP: | ||
421 | stop_erp = value; | ||
422 | break; | ||
423 | case dParamStopCFM: | ||
424 | stop_cfm = value; | ||
425 | break; | ||
426 | } | ||
427 | } | ||
428 | |||
429 | |||
430 | dReal dxJointLimitMotor::get (int num) | ||
431 | { | ||
432 | switch (num) { | ||
433 | case dParamLoStop: return lostop; | ||
434 | case dParamHiStop: return histop; | ||
435 | case dParamVel: return vel; | ||
436 | case dParamFMax: return fmax; | ||
437 | case dParamFudgeFactor: return fudge_factor; | ||
438 | case dParamBounce: return bounce; | ||
439 | case dParamCFM: return normal_cfm; | ||
440 | case dParamStopERP: return stop_erp; | ||
441 | case dParamStopCFM: return stop_cfm; | ||
442 | default: return 0; | ||
443 | } | ||
444 | } | ||
445 | |||
446 | |||
447 | int dxJointLimitMotor::testRotationalLimit (dReal angle) | ||
448 | { | ||
449 | if (angle <= lostop) { | ||
450 | limit = 1; | ||
451 | limit_err = angle - lostop; | ||
452 | return 1; | ||
453 | } | ||
454 | else if (angle >= histop) { | ||
455 | limit = 2; | ||
456 | limit_err = angle - histop; | ||
457 | return 1; | ||
458 | } | ||
459 | else { | ||
460 | limit = 0; | ||
461 | return 0; | ||
462 | } | ||
463 | } | ||
464 | |||
465 | |||
466 | int dxJointLimitMotor::addLimot (dxJoint *joint, | ||
467 | dxJoint::Info2 *info, int row, | ||
468 | dVector3 ax1, int rotational) | ||
469 | { | ||
470 | int srow = row * info->rowskip; | ||
471 | |||
472 | // if the joint is powered, or has joint limits, add in the extra row | ||
473 | int powered = fmax > 0; | ||
474 | if (powered || limit) { | ||
475 | dReal *J1 = rotational ? info->J1a : info->J1l; | ||
476 | dReal *J2 = rotational ? info->J2a : info->J2l; | ||
477 | |||
478 | J1[srow+0] = ax1[0]; | ||
479 | J1[srow+1] = ax1[1]; | ||
480 | J1[srow+2] = ax1[2]; | ||
481 | if (joint->node[1].body) { | ||
482 | J2[srow+0] = -ax1[0]; | ||
483 | J2[srow+1] = -ax1[1]; | ||
484 | J2[srow+2] = -ax1[2]; | ||
485 | } | ||
486 | |||
487 | // linear limot torque decoupling step: | ||
488 | // | ||
489 | // if this is a linear limot (e.g. from a slider), we have to be careful | ||
490 | // that the linear constraint forces (+/- ax1) applied to the two bodies | ||
491 | // do not create a torque couple. in other words, the points that the | ||
492 | // constraint force is applied at must lie along the same ax1 axis. | ||
493 | // a torque couple will result in powered or limited slider-jointed free | ||
494 | // bodies from gaining angular momentum. | ||
495 | // the solution used here is to apply the constraint forces at the point | ||
496 | // halfway between the body centers. there is no penalty (other than an | ||
497 | // extra tiny bit of computation) in doing this adjustment. note that we | ||
498 | // only need to do this if the constraint connects two bodies. | ||
499 | |||
500 | dVector3 ltd; // Linear Torque Decoupling vector (a torque) | ||
501 | if (!rotational && joint->node[1].body) { | ||
502 | dVector3 c; | ||
503 | c[0]=REAL(0.5)*(joint->node[1].body->pos[0]-joint->node[0].body->pos[0]); | ||
504 | c[1]=REAL(0.5)*(joint->node[1].body->pos[1]-joint->node[0].body->pos[1]); | ||
505 | c[2]=REAL(0.5)*(joint->node[1].body->pos[2]-joint->node[0].body->pos[2]); | ||
506 | dCROSS (ltd,=,c,ax1); | ||
507 | info->J1a[srow+0] = ltd[0]; | ||
508 | info->J1a[srow+1] = ltd[1]; | ||
509 | info->J1a[srow+2] = ltd[2]; | ||
510 | info->J2a[srow+0] = ltd[0]; | ||
511 | info->J2a[srow+1] = ltd[1]; | ||
512 | info->J2a[srow+2] = ltd[2]; | ||
513 | } | ||
514 | |||
515 | // if we're limited low and high simultaneously, the joint motor is | ||
516 | // ineffective | ||
517 | if (limit && (lostop == histop)) powered = 0; | ||
518 | |||
519 | if (powered) { | ||
520 | info->cfm[row] = normal_cfm; | ||
521 | if (! limit) { | ||
522 | info->c[row] = vel; | ||
523 | info->lo[row] = -fmax; | ||
524 | info->hi[row] = fmax; | ||
525 | } | ||
526 | else { | ||
527 | // the joint is at a limit, AND is being powered. if the joint is | ||
528 | // being powered into the limit then we apply the maximum motor force | ||
529 | // in that direction, because the motor is working against the | ||
530 | // immovable limit. if the joint is being powered away from the limit | ||
531 | // then we have problems because actually we need *two* lcp | ||
532 | // constraints to handle this case. so we fake it and apply some | ||
533 | // fraction of the maximum force. the fraction to use can be set as | ||
534 | // a fudge factor. | ||
535 | |||
536 | dReal fm = fmax; | ||
537 | if (vel > 0) fm = -fm; | ||
538 | |||
539 | // if we're powering away from the limit, apply the fudge factor | ||
540 | if ((limit==1 && vel > 0) || (limit==2 && vel < 0)) fm *= fudge_factor; | ||
541 | |||
542 | if (rotational) { | ||
543 | dBodyAddTorque (joint->node[0].body,-fm*ax1[0],-fm*ax1[1], | ||
544 | -fm*ax1[2]); | ||
545 | if (joint->node[1].body) | ||
546 | dBodyAddTorque (joint->node[1].body,fm*ax1[0],fm*ax1[1],fm*ax1[2]); | ||
547 | } | ||
548 | else { | ||
549 | dBodyAddForce (joint->node[0].body,-fm*ax1[0],-fm*ax1[1],-fm*ax1[2]); | ||
550 | if (joint->node[1].body) { | ||
551 | dBodyAddForce (joint->node[1].body,fm*ax1[0],fm*ax1[1],fm*ax1[2]); | ||
552 | |||
553 | // linear limot torque decoupling step: refer to above discussion | ||
554 | dBodyAddTorque (joint->node[0].body,-fm*ltd[0],-fm*ltd[1], | ||
555 | -fm*ltd[2]); | ||
556 | dBodyAddTorque (joint->node[1].body,-fm*ltd[0],-fm*ltd[1], | ||
557 | -fm*ltd[2]); | ||
558 | } | ||
559 | } | ||
560 | } | ||
561 | } | ||
562 | |||
563 | if (limit) { | ||
564 | dReal k = info->fps * stop_erp; | ||
565 | info->c[row] = -k * limit_err; | ||
566 | info->cfm[row] = stop_cfm; | ||
567 | |||
568 | if (lostop == histop) { | ||
569 | // limited low and high simultaneously | ||
570 | info->lo[row] = -dInfinity; | ||
571 | info->hi[row] = dInfinity; | ||
572 | } | ||
573 | else { | ||
574 | if (limit == 1) { | ||
575 | // low limit | ||
576 | info->lo[row] = 0; | ||
577 | info->hi[row] = dInfinity; | ||
578 | } | ||
579 | else { | ||
580 | // high limit | ||
581 | info->lo[row] = -dInfinity; | ||
582 | info->hi[row] = 0; | ||
583 | } | ||
584 | |||
585 | // deal with bounce | ||
586 | if (bounce > 0) { | ||
587 | // calculate joint velocity | ||
588 | dReal vel; | ||
589 | if (rotational) { | ||
590 | vel = dDOT(joint->node[0].body->avel,ax1); | ||
591 | if (joint->node[1].body) | ||
592 | vel -= dDOT(joint->node[1].body->avel,ax1); | ||
593 | } | ||
594 | else { | ||
595 | vel = dDOT(joint->node[0].body->lvel,ax1); | ||
596 | if (joint->node[1].body) | ||
597 | vel -= dDOT(joint->node[1].body->lvel,ax1); | ||
598 | } | ||
599 | |||
600 | // only apply bounce if the velocity is incoming, and if the | ||
601 | // resulting c[] exceeds what we already have. | ||
602 | if (limit == 1) { | ||
603 | // low limit | ||
604 | if (vel < 0) { | ||
605 | dReal newc = -bounce * vel; | ||
606 | if (newc > info->c[row]) info->c[row] = newc; | ||
607 | } | ||
608 | } | ||
609 | else { | ||
610 | // high limit - all those computations are reversed | ||
611 | if (vel > 0) { | ||
612 | dReal newc = -bounce * vel; | ||
613 | if (newc < info->c[row]) info->c[row] = newc; | ||
614 | } | ||
615 | } | ||
616 | } | ||
617 | } | ||
618 | } | ||
619 | return 1; | ||
620 | } | ||
621 | else return 0; | ||
622 | } | ||
623 | |||
624 | //**************************************************************************** | ||
625 | // ball and socket | ||
626 | |||
627 | static void ballInit (dxJointBall *j) | ||
628 | { | ||
629 | dSetZero (j->anchor1,4); | ||
630 | dSetZero (j->anchor2,4); | ||
631 | } | ||
632 | |||
633 | |||
634 | static void ballGetInfo1 (dxJointBall *j, dxJoint::Info1 *info) | ||
635 | { | ||
636 | info->m = 3; | ||
637 | info->nub = 3; | ||
638 | } | ||
639 | |||
640 | |||
641 | static void ballGetInfo2 (dxJointBall *joint, dxJoint::Info2 *info) | ||
642 | { | ||
643 | setBall (joint,info,joint->anchor1,joint->anchor2); | ||
644 | } | ||
645 | |||
646 | |||
647 | extern "C" void dJointSetBallAnchor (dxJointBall *joint, | ||
648 | dReal x, dReal y, dReal z) | ||
649 | { | ||
650 | dUASSERT(joint,"bad joint argument"); | ||
651 | dUASSERT(joint->vtable == &__dball_vtable,"joint is not a ball"); | ||
652 | setAnchors (joint,x,y,z,joint->anchor1,joint->anchor2); | ||
653 | } | ||
654 | |||
655 | |||
656 | extern "C" void dJointGetBallAnchor (dxJointBall *joint, dVector3 result) | ||
657 | { | ||
658 | dUASSERT(joint,"bad joint argument"); | ||
659 | dUASSERT(result,"bad result argument"); | ||
660 | dUASSERT(joint->vtable == &__dball_vtable,"joint is not a ball"); | ||
661 | if (joint->flags & dJOINT_REVERSE) | ||
662 | getAnchor2 (joint,result,joint->anchor2); | ||
663 | else | ||
664 | getAnchor (joint,result,joint->anchor1); | ||
665 | } | ||
666 | |||
667 | |||
668 | extern "C" void dJointGetBallAnchor2 (dxJointBall *joint, dVector3 result) | ||
669 | { | ||
670 | dUASSERT(joint,"bad joint argument"); | ||
671 | dUASSERT(result,"bad result argument"); | ||
672 | dUASSERT(joint->vtable == &__dball_vtable,"joint is not a ball"); | ||
673 | if (joint->flags & dJOINT_REVERSE) | ||
674 | getAnchor (joint,result,joint->anchor1); | ||
675 | else | ||
676 | getAnchor2 (joint,result,joint->anchor2); | ||
677 | } | ||
678 | |||
679 | |||
680 | dxJoint::Vtable __dball_vtable = { | ||
681 | sizeof(dxJointBall), | ||
682 | (dxJoint::init_fn*) ballInit, | ||
683 | (dxJoint::getInfo1_fn*) ballGetInfo1, | ||
684 | (dxJoint::getInfo2_fn*) ballGetInfo2, | ||
685 | dJointTypeBall}; | ||
686 | |||
687 | //**************************************************************************** | ||
688 | // hinge | ||
689 | |||
690 | static void hingeInit (dxJointHinge *j) | ||
691 | { | ||
692 | dSetZero (j->anchor1,4); | ||
693 | dSetZero (j->anchor2,4); | ||
694 | dSetZero (j->axis1,4); | ||
695 | j->axis1[0] = 1; | ||
696 | dSetZero (j->axis2,4); | ||
697 | j->axis2[0] = 1; | ||
698 | dSetZero (j->qrel,4); | ||
699 | j->limot.init (j->world); | ||
700 | } | ||
701 | |||
702 | |||
703 | static void hingeGetInfo1 (dxJointHinge *j, dxJoint::Info1 *info) | ||
704 | { | ||
705 | info->nub = 5; | ||
706 | |||
707 | // see if joint is powered | ||
708 | if (j->limot.fmax > 0) | ||
709 | info->m = 6; // powered hinge needs an extra constraint row | ||
710 | else info->m = 5; | ||
711 | |||
712 | // see if we're at a joint limit. | ||
713 | if ((j->limot.lostop >= -M_PI || j->limot.histop <= M_PI) && | ||
714 | j->limot.lostop <= j->limot.histop) { | ||
715 | dReal angle = getHingeAngle (j->node[0].body,j->node[1].body,j->axis1, | ||
716 | j->qrel); | ||
717 | if (j->limot.testRotationalLimit (angle)) info->m = 6; | ||
718 | } | ||
719 | } | ||
720 | |||
721 | |||
722 | static void hingeGetInfo2 (dxJointHinge *joint, dxJoint::Info2 *info) | ||
723 | { | ||
724 | // set the three ball-and-socket rows | ||
725 | setBall (joint,info,joint->anchor1,joint->anchor2); | ||
726 | |||
727 | // set the two hinge rows. the hinge axis should be the only unconstrained | ||
728 | // rotational axis, the angular velocity of the two bodies perpendicular to | ||
729 | // the hinge axis should be equal. thus the constraint equations are | ||
730 | // p*w1 - p*w2 = 0 | ||
731 | // q*w1 - q*w2 = 0 | ||
732 | // where p and q are unit vectors normal to the hinge axis, and w1 and w2 | ||
733 | // are the angular velocity vectors of the two bodies. | ||
734 | |||
735 | dVector3 ax1; // length 1 joint axis in global coordinates, from 1st body | ||
736 | dVector3 p,q; // plane space vectors for ax1 | ||
737 | dMULTIPLY0_331 (ax1,joint->node[0].body->R,joint->axis1); | ||
738 | dPlaneSpace (ax1,p,q); | ||
739 | |||
740 | int s3=3*info->rowskip; | ||
741 | int s4=4*info->rowskip; | ||
742 | |||
743 | info->J1a[s3+0] = p[0]; | ||
744 | info->J1a[s3+1] = p[1]; | ||
745 | info->J1a[s3+2] = p[2]; | ||
746 | info->J1a[s4+0] = q[0]; | ||
747 | info->J1a[s4+1] = q[1]; | ||
748 | info->J1a[s4+2] = q[2]; | ||
749 | |||
750 | if (joint->node[1].body) { | ||
751 | info->J2a[s3+0] = -p[0]; | ||
752 | info->J2a[s3+1] = -p[1]; | ||
753 | info->J2a[s3+2] = -p[2]; | ||
754 | info->J2a[s4+0] = -q[0]; | ||
755 | info->J2a[s4+1] = -q[1]; | ||
756 | info->J2a[s4+2] = -q[2]; | ||
757 | } | ||
758 | |||
759 | // compute the right hand side of the constraint equation. set relative | ||
760 | // body velocities along p and q to bring the hinge back into alignment. | ||
761 | // if ax1,ax2 are the unit length hinge axes as computed from body1 and | ||
762 | // body2, we need to rotate both bodies along the axis u = (ax1 x ax2). | ||
763 | // if `theta' is the angle between ax1 and ax2, we need an angular velocity | ||
764 | // along u to cover angle erp*theta in one step : | ||
765 | // |angular_velocity| = angle/time = erp*theta / stepsize | ||
766 | // = (erp*fps) * theta | ||
767 | // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2| | ||
768 | // = (erp*fps) * theta * (ax1 x ax2) / sin(theta) | ||
769 | // ...as ax1 and ax2 are unit length. if theta is smallish, | ||
770 | // theta ~= sin(theta), so | ||
771 | // angular_velocity = (erp*fps) * (ax1 x ax2) | ||
772 | // ax1 x ax2 is in the plane space of ax1, so we project the angular | ||
773 | // velocity to p and q to find the right hand side. | ||
774 | |||
775 | dVector3 ax2,b; | ||
776 | if (joint->node[1].body) { | ||
777 | dMULTIPLY0_331 (ax2,joint->node[1].body->R,joint->axis2); | ||
778 | } | ||
779 | else { | ||
780 | ax2[0] = joint->axis2[0]; | ||
781 | ax2[1] = joint->axis2[1]; | ||
782 | ax2[2] = joint->axis2[2]; | ||
783 | } | ||
784 | dCROSS (b,=,ax1,ax2); | ||
785 | dReal k = info->fps * info->erp; | ||
786 | info->c[3] = k * dDOT(b,p); | ||
787 | info->c[4] = k * dDOT(b,q); | ||
788 | |||
789 | // if the hinge is powered, or has joint limits, add in the stuff | ||
790 | joint->limot.addLimot (joint,info,5,ax1,1); | ||
791 | } | ||
792 | |||
793 | |||
794 | // compute initial relative rotation body1 -> body2, or env -> body1 | ||
795 | |||
796 | static void hingeComputeInitialRelativeRotation (dxJointHinge *joint) | ||
797 | { | ||
798 | if (joint->node[0].body) { | ||
799 | if (joint->node[1].body) { | ||
800 | dQMultiply1 (joint->qrel,joint->node[0].body->q,joint->node[1].body->q); | ||
801 | } | ||
802 | else { | ||
803 | // set joint->qrel to the transpose of the first body q | ||
804 | joint->qrel[0] = joint->node[0].body->q[0]; | ||
805 | for (int i=1; i<4; i++) joint->qrel[i] = -joint->node[0].body->q[i]; | ||
806 | } | ||
807 | } | ||
808 | } | ||
809 | |||
810 | |||
811 | extern "C" void dJointSetHingeAnchor (dxJointHinge *joint, | ||
812 | dReal x, dReal y, dReal z) | ||
813 | { | ||
814 | dUASSERT(joint,"bad joint argument"); | ||
815 | dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge"); | ||
816 | setAnchors (joint,x,y,z,joint->anchor1,joint->anchor2); | ||
817 | hingeComputeInitialRelativeRotation (joint); | ||
818 | } | ||
819 | |||
820 | |||
821 | extern "C" void dJointSetHingeAxis (dxJointHinge *joint, | ||
822 | dReal x, dReal y, dReal z) | ||
823 | { | ||
824 | dUASSERT(joint,"bad joint argument"); | ||
825 | dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge"); | ||
826 | setAxes (joint,x,y,z,joint->axis1,joint->axis2); | ||
827 | hingeComputeInitialRelativeRotation (joint); | ||
828 | } | ||
829 | |||
830 | |||
831 | extern "C" void dJointGetHingeAnchor (dxJointHinge *joint, dVector3 result) | ||
832 | { | ||
833 | dUASSERT(joint,"bad joint argument"); | ||
834 | dUASSERT(result,"bad result argument"); | ||
835 | dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge"); | ||
836 | if (joint->flags & dJOINT_REVERSE) | ||
837 | getAnchor2 (joint,result,joint->anchor2); | ||
838 | else | ||
839 | getAnchor (joint,result,joint->anchor1); | ||
840 | } | ||
841 | |||
842 | |||
843 | extern "C" void dJointGetHingeAnchor2 (dxJointHinge *joint, dVector3 result) | ||
844 | { | ||
845 | dUASSERT(joint,"bad joint argument"); | ||
846 | dUASSERT(result,"bad result argument"); | ||
847 | dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge"); | ||
848 | if (joint->flags & dJOINT_REVERSE) | ||
849 | getAnchor (joint,result,joint->anchor1); | ||
850 | else | ||
851 | getAnchor2 (joint,result,joint->anchor2); | ||
852 | } | ||
853 | |||
854 | |||
855 | extern "C" void dJointGetHingeAxis (dxJointHinge *joint, dVector3 result) | ||
856 | { | ||
857 | dUASSERT(joint,"bad joint argument"); | ||
858 | dUASSERT(result,"bad result argument"); | ||
859 | dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge"); | ||
860 | getAxis (joint,result,joint->axis1); | ||
861 | } | ||
862 | |||
863 | |||
864 | extern "C" void dJointSetHingeParam (dxJointHinge *joint, | ||
865 | int parameter, dReal value) | ||
866 | { | ||
867 | dUASSERT(joint,"bad joint argument"); | ||
868 | dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge"); | ||
869 | joint->limot.set (parameter,value); | ||
870 | } | ||
871 | |||
872 | |||
873 | extern "C" dReal dJointGetHingeParam (dxJointHinge *joint, int parameter) | ||
874 | { | ||
875 | dUASSERT(joint,"bad joint argument"); | ||
876 | dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge"); | ||
877 | return joint->limot.get (parameter); | ||
878 | } | ||
879 | |||
880 | |||
881 | extern "C" dReal dJointGetHingeAngle (dxJointHinge *joint) | ||
882 | { | ||
883 | dAASSERT(joint); | ||
884 | dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge"); | ||
885 | if (joint->node[0].body) { | ||
886 | dReal ang = getHingeAngle (joint->node[0].body,joint->node[1].body,joint->axis1, | ||
887 | joint->qrel); | ||
888 | if (joint->flags & dJOINT_REVERSE) | ||
889 | return -ang; | ||
890 | else | ||
891 | return ang; | ||
892 | } | ||
893 | else return 0; | ||
894 | } | ||
895 | |||
896 | |||
897 | extern "C" dReal dJointGetHingeAngleRate (dxJointHinge *joint) | ||
898 | { | ||
899 | dAASSERT(joint); | ||
900 | dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a Hinge"); | ||
901 | if (joint->node[0].body) { | ||
902 | dVector3 axis; | ||
903 | dMULTIPLY0_331 (axis,joint->node[0].body->R,joint->axis1); | ||
904 | dReal rate = dDOT(axis,joint->node[0].body->avel); | ||
905 | if (joint->node[1].body) rate -= dDOT(axis,joint->node[1].body->avel); | ||
906 | if (joint->flags & dJOINT_REVERSE) rate = - rate; | ||
907 | return rate; | ||
908 | } | ||
909 | else return 0; | ||
910 | } | ||
911 | |||
912 | |||
913 | extern "C" void dJointAddHingeTorque (dxJointHinge *joint, dReal torque) | ||
914 | { | ||
915 | dVector3 axis; | ||
916 | dAASSERT(joint); | ||
917 | dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a Hinge"); | ||
918 | |||
919 | if (joint->flags & dJOINT_REVERSE) | ||
920 | torque = -torque; | ||
921 | |||
922 | getAxis (joint,axis,joint->axis1); | ||
923 | axis[0] *= torque; | ||
924 | axis[1] *= torque; | ||
925 | axis[2] *= torque; | ||
926 | |||
927 | if (joint->node[0].body != 0) | ||
928 | dBodyAddTorque (joint->node[0].body, axis[0], axis[1], axis[2]); | ||
929 | if (joint->node[1].body != 0) | ||
930 | dBodyAddTorque(joint->node[1].body, -axis[0], -axis[1], -axis[2]); | ||
931 | } | ||
932 | |||
933 | |||
934 | dxJoint::Vtable __dhinge_vtable = { | ||
935 | sizeof(dxJointHinge), | ||
936 | (dxJoint::init_fn*) hingeInit, | ||
937 | (dxJoint::getInfo1_fn*) hingeGetInfo1, | ||
938 | (dxJoint::getInfo2_fn*) hingeGetInfo2, | ||
939 | dJointTypeHinge}; | ||
940 | |||
941 | //**************************************************************************** | ||
942 | // slider | ||
943 | |||
944 | static void sliderInit (dxJointSlider *j) | ||
945 | { | ||
946 | dSetZero (j->axis1,4); | ||
947 | j->axis1[0] = 1; | ||
948 | dSetZero (j->qrel,4); | ||
949 | dSetZero (j->offset,4); | ||
950 | j->limot.init (j->world); | ||
951 | } | ||
952 | |||
953 | |||
954 | extern "C" dReal dJointGetSliderPosition (dxJointSlider *joint) | ||
955 | { | ||
956 | dUASSERT(joint,"bad joint argument"); | ||
957 | dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider"); | ||
958 | |||
959 | // get axis1 in global coordinates | ||
960 | dVector3 ax1,q; | ||
961 | dMULTIPLY0_331 (ax1,joint->node[0].body->R,joint->axis1); | ||
962 | |||
963 | if (joint->node[1].body) { | ||
964 | // get body2 + offset point in global coordinates | ||
965 | dMULTIPLY0_331 (q,joint->node[1].body->R,joint->offset); | ||
966 | for (int i=0; i<3; i++) q[i] = joint->node[0].body->pos[i] - q[i] - | ||
967 | joint->node[1].body->pos[i]; | ||
968 | } | ||
969 | else { | ||
970 | for (int i=0; i<3; i++) q[i] = joint->node[0].body->pos[i] - | ||
971 | joint->offset[i]; | ||
972 | |||
973 | } | ||
974 | return dDOT(ax1,q); | ||
975 | } | ||
976 | |||
977 | |||
978 | extern "C" dReal dJointGetSliderPositionRate (dxJointSlider *joint) | ||
979 | { | ||
980 | dUASSERT(joint,"bad joint argument"); | ||
981 | dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider"); | ||
982 | |||
983 | // get axis1 in global coordinates | ||
984 | dVector3 ax1; | ||
985 | dMULTIPLY0_331 (ax1,joint->node[0].body->R,joint->axis1); | ||
986 | |||
987 | if (joint->node[1].body) { | ||
988 | return dDOT(ax1,joint->node[0].body->lvel) - | ||
989 | dDOT(ax1,joint->node[1].body->lvel); | ||
990 | } | ||
991 | else { | ||
992 | return dDOT(ax1,joint->node[0].body->lvel); | ||
993 | } | ||
994 | } | ||
995 | |||
996 | |||
997 | static void sliderGetInfo1 (dxJointSlider *j, dxJoint::Info1 *info) | ||
998 | { | ||
999 | info->nub = 5; | ||
1000 | |||
1001 | // see if joint is powered | ||
1002 | if (j->limot.fmax > 0) | ||
1003 | info->m = 6; // powered slider needs an extra constraint row | ||
1004 | else info->m = 5; | ||
1005 | |||
1006 | // see if we're at a joint limit. | ||
1007 | j->limot.limit = 0; | ||
1008 | if ((j->limot.lostop > -dInfinity || j->limot.histop < dInfinity) && | ||
1009 | j->limot.lostop <= j->limot.histop) { | ||
1010 | // measure joint position | ||
1011 | dReal pos = dJointGetSliderPosition (j); | ||
1012 | if (pos <= j->limot.lostop) { | ||
1013 | j->limot.limit = 1; | ||
1014 | j->limot.limit_err = pos - j->limot.lostop; | ||
1015 | info->m = 6; | ||
1016 | } | ||
1017 | else if (pos >= j->limot.histop) { | ||
1018 | j->limot.limit = 2; | ||
1019 | j->limot.limit_err = pos - j->limot.histop; | ||
1020 | info->m = 6; | ||
1021 | } | ||
1022 | } | ||
1023 | } | ||
1024 | |||
1025 | |||
1026 | static void sliderGetInfo2 (dxJointSlider *joint, dxJoint::Info2 *info) | ||
1027 | { | ||
1028 | int i,s = info->rowskip; | ||
1029 | int s2=2*s,s3=3*s,s4=4*s; | ||
1030 | |||
1031 | // pull out pos and R for both bodies. also get the `connection' | ||
1032 | // vector pos2-pos1. | ||
1033 | |||
1034 | dReal *pos1,*pos2,*R1,*R2; | ||
1035 | dVector3 c; | ||
1036 | pos1 = joint->node[0].body->pos; | ||
1037 | R1 = joint->node[0].body->R; | ||
1038 | if (joint->node[1].body) { | ||
1039 | pos2 = joint->node[1].body->pos; | ||
1040 | R2 = joint->node[1].body->R; | ||
1041 | for (i=0; i<3; i++) c[i] = pos2[i] - pos1[i]; | ||
1042 | } | ||
1043 | else { | ||
1044 | pos2 = 0; | ||
1045 | R2 = 0; | ||
1046 | } | ||
1047 | |||
1048 | // 3 rows to make body rotations equal | ||
1049 | setFixedOrientation(joint, info, joint->qrel, 0); | ||
1050 | |||
1051 | // remaining two rows. we want: vel2 = vel1 + w1 x c ... but this would | ||
1052 | // result in three equations, so we project along the planespace vectors | ||
1053 | // so that sliding along the slider axis is disregarded. for symmetry we | ||
1054 | // also substitute (w1+w2)/2 for w1, as w1 is supposed to equal w2. | ||
1055 | |||
1056 | dVector3 ax1; // joint axis in global coordinates (unit length) | ||
1057 | dVector3 p,q; // plane space of ax1 | ||
1058 | dMULTIPLY0_331 (ax1,R1,joint->axis1); | ||
1059 | dPlaneSpace (ax1,p,q); | ||
1060 | if (joint->node[1].body) { | ||
1061 | dVector3 tmp; | ||
1062 | dCROSS (tmp, = REAL(0.5) * ,c,p); | ||
1063 | for (i=0; i<3; i++) info->J2a[s3+i] = tmp[i]; | ||
1064 | for (i=0; i<3; i++) info->J2a[s3+i] = tmp[i]; | ||
1065 | dCROSS (tmp, = REAL(0.5) * ,c,q); | ||
1066 | for (i=0; i<3; i++) info->J2a[s4+i] = tmp[i]; | ||
1067 | for (i=0; i<3; i++) info->J2a[s4+i] = tmp[i]; | ||
1068 | for (i=0; i<3; i++) info->J2l[s3+i] = -p[i]; | ||
1069 | for (i=0; i<3; i++) info->J2l[s4+i] = -q[i]; | ||
1070 | } | ||
1071 | for (i=0; i<3; i++) info->J1l[s3+i] = p[i]; | ||
1072 | for (i=0; i<3; i++) info->J1l[s4+i] = q[i]; | ||
1073 | |||
1074 | // compute last two elements of right hand side. we want to align the offset | ||
1075 | // point (in body 2's frame) with the center of body 1. | ||
1076 | dReal k = info->fps * info->erp; | ||
1077 | if (joint->node[1].body) { | ||
1078 | dVector3 ofs; // offset point in global coordinates | ||
1079 | dMULTIPLY0_331 (ofs,R2,joint->offset); | ||
1080 | for (i=0; i<3; i++) c[i] += ofs[i]; | ||
1081 | info->c[3] = k * dDOT(p,c); | ||
1082 | info->c[4] = k * dDOT(q,c); | ||
1083 | } | ||
1084 | else { | ||
1085 | dVector3 ofs; // offset point in global coordinates | ||
1086 | for (i=0; i<3; i++) ofs[i] = joint->offset[i] - pos1[i]; | ||
1087 | info->c[3] = k * dDOT(p,ofs); | ||
1088 | info->c[4] = k * dDOT(q,ofs); | ||
1089 | } | ||
1090 | |||
1091 | // if the slider is powered, or has joint limits, add in the extra row | ||
1092 | joint->limot.addLimot (joint,info,5,ax1,0); | ||
1093 | } | ||
1094 | |||
1095 | |||
1096 | extern "C" void dJointSetSliderAxis (dxJointSlider *joint, | ||
1097 | dReal x, dReal y, dReal z) | ||
1098 | { | ||
1099 | int i; | ||
1100 | dUASSERT(joint,"bad joint argument"); | ||
1101 | dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider"); | ||
1102 | setAxes (joint,x,y,z,joint->axis1,0); | ||
1103 | |||
1104 | // compute initial relative rotation body1 -> body2, or env -> body1 | ||
1105 | // also compute center of body1 w.r.t body 2 | ||
1106 | if (joint->node[1].body) { | ||
1107 | dQMultiply1 (joint->qrel,joint->node[0].body->q,joint->node[1].body->q); | ||
1108 | dVector3 c; | ||
1109 | for (i=0; i<3; i++) | ||
1110 | c[i] = joint->node[0].body->pos[i] - joint->node[1].body->pos[i]; | ||
1111 | dMULTIPLY1_331 (joint->offset,joint->node[1].body->R,c); | ||
1112 | } | ||
1113 | else { | ||
1114 | // set joint->qrel to the transpose of the first body's q | ||
1115 | joint->qrel[0] = joint->node[0].body->q[0]; | ||
1116 | for (i=1; i<4; i++) joint->qrel[i] = -joint->node[0].body->q[i]; | ||
1117 | for (i=0; i<3; i++) joint->offset[i] = joint->node[0].body->pos[i]; | ||
1118 | } | ||
1119 | } | ||
1120 | |||
1121 | |||
1122 | extern "C" void dJointGetSliderAxis (dxJointSlider *joint, dVector3 result) | ||
1123 | { | ||
1124 | dUASSERT(joint,"bad joint argument"); | ||
1125 | dUASSERT(result,"bad result argument"); | ||
1126 | dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider"); | ||
1127 | getAxis (joint,result,joint->axis1); | ||
1128 | } | ||
1129 | |||
1130 | |||
1131 | extern "C" void dJointSetSliderParam (dxJointSlider *joint, | ||
1132 | int parameter, dReal value) | ||
1133 | { | ||
1134 | dUASSERT(joint,"bad joint argument"); | ||
1135 | dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider"); | ||
1136 | joint->limot.set (parameter,value); | ||
1137 | } | ||
1138 | |||
1139 | |||
1140 | extern "C" dReal dJointGetSliderParam (dxJointSlider *joint, int parameter) | ||
1141 | { | ||
1142 | dUASSERT(joint,"bad joint argument"); | ||
1143 | dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider"); | ||
1144 | return joint->limot.get (parameter); | ||
1145 | } | ||
1146 | |||
1147 | |||
1148 | extern "C" void dJointAddSliderForce (dxJointSlider *joint, dReal force) | ||
1149 | { | ||
1150 | dVector3 axis; | ||
1151 | dUASSERT(joint,"bad joint argument"); | ||
1152 | dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider"); | ||
1153 | |||
1154 | if (joint->flags & dJOINT_REVERSE) | ||
1155 | force -= force; | ||
1156 | |||
1157 | getAxis (joint,axis,joint->axis1); | ||
1158 | axis[0] *= force; | ||
1159 | axis[1] *= force; | ||
1160 | axis[2] *= force; | ||
1161 | |||
1162 | if (joint->node[0].body != 0) | ||
1163 | dBodyAddForce (joint->node[0].body,axis[0],axis[1],axis[2]); | ||
1164 | if (joint->node[1].body != 0) | ||
1165 | dBodyAddForce(joint->node[1].body, -axis[0], -axis[1], -axis[2]); | ||
1166 | } | ||
1167 | |||
1168 | |||
1169 | dxJoint::Vtable __dslider_vtable = { | ||
1170 | sizeof(dxJointSlider), | ||
1171 | (dxJoint::init_fn*) sliderInit, | ||
1172 | (dxJoint::getInfo1_fn*) sliderGetInfo1, | ||
1173 | (dxJoint::getInfo2_fn*) sliderGetInfo2, | ||
1174 | dJointTypeSlider}; | ||
1175 | |||
1176 | //**************************************************************************** | ||
1177 | // contact | ||
1178 | |||
1179 | static void contactInit (dxJointContact *j) | ||
1180 | { | ||
1181 | // default frictionless contact. hmmm, this info gets overwritten straight | ||
1182 | // away anyway, so why bother? | ||
1183 | #if 0 /* so don't bother ;) */ | ||
1184 | j->contact.surface.mode = 0; | ||
1185 | j->contact.surface.mu = 0; | ||
1186 | dSetZero (j->contact.geom.pos,4); | ||
1187 | dSetZero (j->contact.geom.normal,4); | ||
1188 | j->contact.geom.depth = 0; | ||
1189 | #endif | ||
1190 | } | ||
1191 | |||
1192 | |||
1193 | static void contactGetInfo1 (dxJointContact *j, dxJoint::Info1 *info) | ||
1194 | { | ||
1195 | // make sure mu's >= 0, then calculate number of constraint rows and number | ||
1196 | // of unbounded rows. | ||
1197 | int m = 1, nub=0; | ||
1198 | if (j->contact.surface.mu < 0) j->contact.surface.mu = 0; | ||
1199 | if (j->contact.surface.mode & dContactMu2) { | ||
1200 | if (j->contact.surface.mu > 0) m++; | ||
1201 | if (j->contact.surface.mu2 < 0) j->contact.surface.mu2 = 0; | ||
1202 | if (j->contact.surface.mu2 > 0) m++; | ||
1203 | if (j->contact.surface.mu == dInfinity) nub ++; | ||
1204 | if (j->contact.surface.mu2 == dInfinity) nub ++; | ||
1205 | } | ||
1206 | else { | ||
1207 | if (j->contact.surface.mu > 0) m += 2; | ||
1208 | if (j->contact.surface.mu == dInfinity) nub += 2; | ||
1209 | } | ||
1210 | |||
1211 | j->the_m = m; | ||
1212 | info->m = m; | ||
1213 | info->nub = nub; | ||
1214 | } | ||
1215 | |||
1216 | |||
1217 | static void contactGetInfo2 (dxJointContact *j, dxJoint::Info2 *info) | ||
1218 | { | ||
1219 | int i,s = info->rowskip; | ||
1220 | int s2 = 2*s; | ||
1221 | |||
1222 | // get normal, with sign adjusted for body1/body2 polarity | ||
1223 | dVector3 normal; | ||
1224 | if (j->flags & dJOINT_REVERSE) { | ||
1225 | normal[0] = - j->contact.geom.normal[0]; | ||
1226 | normal[1] = - j->contact.geom.normal[1]; | ||
1227 | normal[2] = - j->contact.geom.normal[2]; | ||
1228 | } | ||
1229 | else { | ||
1230 | normal[0] = j->contact.geom.normal[0]; | ||
1231 | normal[1] = j->contact.geom.normal[1]; | ||
1232 | normal[2] = j->contact.geom.normal[2]; | ||
1233 | } | ||
1234 | normal[3] = 0; // @@@ hmmm | ||
1235 | |||
1236 | // c1,c2 = contact points with respect to body PORs | ||
1237 | dVector3 c1,c2; | ||
1238 | for (i=0; i<3; i++) c1[i] = j->contact.geom.pos[i] - j->node[0].body->pos[i]; | ||
1239 | |||
1240 | // set jacobian for normal | ||
1241 | info->J1l[0] = normal[0]; | ||
1242 | info->J1l[1] = normal[1]; | ||
1243 | info->J1l[2] = normal[2]; | ||
1244 | dCROSS (info->J1a,=,c1,normal); | ||
1245 | if (j->node[1].body) { | ||
1246 | for (i=0; i<3; i++) c2[i] = j->contact.geom.pos[i] - | ||
1247 | j->node[1].body->pos[i]; | ||
1248 | info->J2l[0] = -normal[0]; | ||
1249 | info->J2l[1] = -normal[1]; | ||
1250 | info->J2l[2] = -normal[2]; | ||
1251 | dCROSS (info->J2a,= -,c2,normal); | ||
1252 | } | ||
1253 | |||
1254 | // set right hand side and cfm value for normal | ||
1255 | dReal erp = info->erp; | ||
1256 | if (j->contact.surface.mode & dContactSoftERP) | ||
1257 | erp = j->contact.surface.soft_erp; | ||
1258 | dReal k = info->fps * erp; | ||
1259 | info->c[0] = k*j->contact.geom.depth; | ||
1260 | if (j->contact.surface.mode & dContactSoftCFM) | ||
1261 | info->cfm[0] = j->contact.surface.soft_cfm; | ||
1262 | |||
1263 | // deal with bounce | ||
1264 | if (j->contact.surface.mode & dContactBounce) { | ||
1265 | // calculate outgoing velocity (-ve for incoming contact) | ||
1266 | dReal outgoing = dDOT(info->J1l,j->node[0].body->lvel) + | ||
1267 | dDOT(info->J1a,j->node[0].body->avel); | ||
1268 | if (j->node[1].body) { | ||
1269 | outgoing += dDOT(info->J2l,j->node[1].body->lvel) + | ||
1270 | dDOT(info->J2a,j->node[1].body->avel); | ||
1271 | } | ||
1272 | // only apply bounce if the outgoing velocity is greater than the | ||
1273 | // threshold, and if the resulting c[0] exceeds what we already have. | ||
1274 | if (j->contact.surface.bounce_vel >= 0 && | ||
1275 | (-outgoing) > j->contact.surface.bounce_vel) { | ||
1276 | dReal newc = - j->contact.surface.bounce * outgoing; | ||
1277 | if (newc > info->c[0]) info->c[0] = newc; | ||
1278 | } | ||
1279 | } | ||
1280 | |||
1281 | // set LCP limits for normal | ||
1282 | info->lo[0] = 0; | ||
1283 | info->hi[0] = dInfinity; | ||
1284 | |||
1285 | // now do jacobian for tangential forces | ||
1286 | dVector3 t1,t2; // two vectors tangential to normal | ||
1287 | |||
1288 | // first friction direction | ||
1289 | if (j->the_m >= 2) { | ||
1290 | if (j->contact.surface.mode & dContactFDir1) { // use fdir1 ? | ||
1291 | t1[0] = j->contact.fdir1[0]; | ||
1292 | t1[1] = j->contact.fdir1[1]; | ||
1293 | t1[2] = j->contact.fdir1[2]; | ||
1294 | dCROSS (t2,=,normal,t1); | ||
1295 | } | ||
1296 | else { | ||
1297 | dPlaneSpace (normal,t1,t2); | ||
1298 | } | ||
1299 | info->J1l[s+0] = t1[0]; | ||
1300 | info->J1l[s+1] = t1[1]; | ||
1301 | info->J1l[s+2] = t1[2]; | ||
1302 | dCROSS (info->J1a+s,=,c1,t1); | ||
1303 | if (j->node[1].body) { | ||
1304 | info->J2l[s+0] = -t1[0]; | ||
1305 | info->J2l[s+1] = -t1[1]; | ||
1306 | info->J2l[s+2] = -t1[2]; | ||
1307 | dCROSS (info->J2a+s,= -,c2,t1); | ||
1308 | } | ||
1309 | // set right hand side | ||
1310 | if (j->contact.surface.mode & dContactMotion1) { | ||
1311 | info->c[1] = j->contact.surface.motion1; | ||
1312 | } | ||
1313 | // set LCP bounds and friction index. this depends on the approximation | ||
1314 | // mode | ||
1315 | info->lo[1] = -j->contact.surface.mu; | ||
1316 | info->hi[1] = j->contact.surface.mu; | ||
1317 | if (j->contact.surface.mode & dContactApprox1_1) info->findex[1] = 0; | ||
1318 | |||
1319 | // set slip (constraint force mixing) | ||
1320 | if (j->contact.surface.mode & dContactSlip1) | ||
1321 | info->cfm[1] = j->contact.surface.slip1; | ||
1322 | } | ||
1323 | |||
1324 | // second friction direction | ||
1325 | if (j->the_m >= 3) { | ||
1326 | info->J1l[s2+0] = t2[0]; | ||
1327 | info->J1l[s2+1] = t2[1]; | ||
1328 | info->J1l[s2+2] = t2[2]; | ||
1329 | dCROSS (info->J1a+s2,=,c1,t2); | ||
1330 | if (j->node[1].body) { | ||
1331 | info->J2l[s2+0] = -t2[0]; | ||
1332 | info->J2l[s2+1] = -t2[1]; | ||
1333 | info->J2l[s2+2] = -t2[2]; | ||
1334 | dCROSS (info->J2a+s2,= -,c2,t2); | ||
1335 | } | ||
1336 | // set right hand side | ||
1337 | if (j->contact.surface.mode & dContactMotion2) { | ||
1338 | info->c[2] = j->contact.surface.motion2; | ||
1339 | } | ||
1340 | // set LCP bounds and friction index. this depends on the approximation | ||
1341 | // mode | ||
1342 | if (j->contact.surface.mode & dContactMu2) { | ||
1343 | info->lo[2] = -j->contact.surface.mu2; | ||
1344 | info->hi[2] = j->contact.surface.mu2; | ||
1345 | } | ||
1346 | else { | ||
1347 | info->lo[2] = -j->contact.surface.mu; | ||
1348 | info->hi[2] = j->contact.surface.mu; | ||
1349 | } | ||
1350 | if (j->contact.surface.mode & dContactApprox1_2) info->findex[2] = 0; | ||
1351 | |||
1352 | // set slip (constraint force mixing) | ||
1353 | if (j->contact.surface.mode & dContactSlip2) | ||
1354 | info->cfm[2] = j->contact.surface.slip2; | ||
1355 | } | ||
1356 | } | ||
1357 | |||
1358 | |||
1359 | dxJoint::Vtable __dcontact_vtable = { | ||
1360 | sizeof(dxJointContact), | ||
1361 | (dxJoint::init_fn*) contactInit, | ||
1362 | (dxJoint::getInfo1_fn*) contactGetInfo1, | ||
1363 | (dxJoint::getInfo2_fn*) contactGetInfo2, | ||
1364 | dJointTypeContact}; | ||
1365 | |||
1366 | //**************************************************************************** | ||
1367 | // hinge 2. note that this joint must be attached to two bodies for it to work | ||
1368 | |||
1369 | static dReal measureHinge2Angle (dxJointHinge2 *joint) | ||
1370 | { | ||
1371 | dVector3 a1,a2; | ||
1372 | dMULTIPLY0_331 (a1,joint->node[1].body->R,joint->axis2); | ||
1373 | dMULTIPLY1_331 (a2,joint->node[0].body->R,a1); | ||
1374 | dReal x = dDOT(joint->v1,a2); | ||
1375 | dReal y = dDOT(joint->v2,a2); | ||
1376 | return -dAtan2 (y,x); | ||
1377 | } | ||
1378 | |||
1379 | |||
1380 | static void hinge2Init (dxJointHinge2 *j) | ||
1381 | { | ||
1382 | dSetZero (j->anchor1,4); | ||
1383 | dSetZero (j->anchor2,4); | ||
1384 | dSetZero (j->axis1,4); | ||
1385 | j->axis1[0] = 1; | ||
1386 | dSetZero (j->axis2,4); | ||
1387 | j->axis2[1] = 1; | ||
1388 | j->c0 = 0; | ||
1389 | j->s0 = 0; | ||
1390 | |||
1391 | dSetZero (j->v1,4); | ||
1392 | j->v1[0] = 1; | ||
1393 | dSetZero (j->v2,4); | ||
1394 | j->v2[1] = 1; | ||
1395 | |||
1396 | j->limot1.init (j->world); | ||
1397 | j->limot2.init (j->world); | ||
1398 | |||
1399 | j->susp_erp = j->world->global_erp; | ||
1400 | j->susp_cfm = j->world->global_cfm; | ||
1401 | |||
1402 | j->flags |= dJOINT_TWOBODIES; | ||
1403 | } | ||
1404 | |||
1405 | |||
1406 | static void hinge2GetInfo1 (dxJointHinge2 *j, dxJoint::Info1 *info) | ||
1407 | { | ||
1408 | info->m = 4; | ||
1409 | info->nub = 4; | ||
1410 | |||
1411 | // see if we're powered or at a joint limit for axis 1 | ||
1412 | int atlimit=0; | ||
1413 | if ((j->limot1.lostop >= -M_PI || j->limot1.histop <= M_PI) && | ||
1414 | j->limot1.lostop <= j->limot1.histop) { | ||
1415 | dReal angle = measureHinge2Angle (j); | ||
1416 | if (j->limot1.testRotationalLimit (angle)) atlimit = 1; | ||
1417 | } | ||
1418 | if (atlimit || j->limot1.fmax > 0) info->m++; | ||
1419 | |||
1420 | // see if we're powering axis 2 (we currently never limit this axis) | ||
1421 | j->limot2.limit = 0; | ||
1422 | if (j->limot2.fmax > 0) info->m++; | ||
1423 | } | ||
1424 | |||
1425 | |||
1426 | // macro that computes ax1,ax2 = axis 1 and 2 in global coordinates (they are | ||
1427 | // relative to body 1 and 2 initially) and then computes the constrained | ||
1428 | // rotational axis as the cross product of ax1 and ax2. | ||
1429 | // the sin and cos of the angle between axis 1 and 2 is computed, this comes | ||
1430 | // from dot and cross product rules. | ||
1431 | |||
1432 | #define HINGE2_GET_AXIS_INFO(axis,sin_angle,cos_angle) \ | ||
1433 | dVector3 ax1,ax2; \ | ||
1434 | dMULTIPLY0_331 (ax1,joint->node[0].body->R,joint->axis1); \ | ||
1435 | dMULTIPLY0_331 (ax2,joint->node[1].body->R,joint->axis2); \ | ||
1436 | dCROSS (axis,=,ax1,ax2); \ | ||
1437 | sin_angle = dSqrt (axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]); \ | ||
1438 | cos_angle = dDOT (ax1,ax2); | ||
1439 | |||
1440 | |||
1441 | static void hinge2GetInfo2 (dxJointHinge2 *joint, dxJoint::Info2 *info) | ||
1442 | { | ||
1443 | // get information we need to set the hinge row | ||
1444 | dReal s,c; | ||
1445 | dVector3 q; | ||
1446 | HINGE2_GET_AXIS_INFO (q,s,c); | ||
1447 | dNormalize3 (q); // @@@ quicker: divide q by s ? | ||
1448 | |||
1449 | // set the three ball-and-socket rows (aligned to the suspension axis ax1) | ||
1450 | setBall2 (joint,info,joint->anchor1,joint->anchor2,ax1,joint->susp_erp); | ||
1451 | |||
1452 | // set the hinge row | ||
1453 | int s3=3*info->rowskip; | ||
1454 | info->J1a[s3+0] = q[0]; | ||
1455 | info->J1a[s3+1] = q[1]; | ||
1456 | info->J1a[s3+2] = q[2]; | ||
1457 | if (joint->node[1].body) { | ||
1458 | info->J2a[s3+0] = -q[0]; | ||
1459 | info->J2a[s3+1] = -q[1]; | ||
1460 | info->J2a[s3+2] = -q[2]; | ||
1461 | } | ||
1462 | |||
1463 | // compute the right hand side for the constrained rotational DOF. | ||
1464 | // axis 1 and axis 2 are separated by an angle `theta'. the desired | ||
1465 | // separation angle is theta0. sin(theta0) and cos(theta0) are recorded | ||
1466 | // in the joint structure. the correcting angular velocity is: | ||
1467 | // |angular_velocity| = angle/time = erp*(theta0-theta) / stepsize | ||
1468 | // = (erp*fps) * (theta0-theta) | ||
1469 | // (theta0-theta) can be computed using the following small-angle-difference | ||
1470 | // approximation: | ||
1471 | // theta0-theta ~= tan(theta0-theta) | ||
1472 | // = sin(theta0-theta)/cos(theta0-theta) | ||
1473 | // = (c*s0 - s*c0) / (c*c0 + s*s0) | ||
1474 | // = c*s0 - s*c0 assuming c*c0 + s*s0 ~= 1 | ||
1475 | // where c = cos(theta), s = sin(theta) | ||
1476 | // c0 = cos(theta0), s0 = sin(theta0) | ||
1477 | |||
1478 | dReal k = info->fps * info->erp; | ||
1479 | info->c[3] = k * (joint->c0 * s - joint->s0 * c); | ||
1480 | |||
1481 | // if the axis1 hinge is powered, or has joint limits, add in more stuff | ||
1482 | int row = 4 + joint->limot1.addLimot (joint,info,4,ax1,1); | ||
1483 | |||
1484 | // if the axis2 hinge is powered, add in more stuff | ||
1485 | joint->limot2.addLimot (joint,info,row,ax2,1); | ||
1486 | |||
1487 | // set parameter for the suspension | ||
1488 | info->cfm[0] = joint->susp_cfm; | ||
1489 | } | ||
1490 | |||
1491 | |||
1492 | // compute vectors v1 and v2 (embedded in body1), used to measure angle | ||
1493 | // between body 1 and body 2 | ||
1494 | |||
1495 | static void makeHinge2V1andV2 (dxJointHinge2 *joint) | ||
1496 | { | ||
1497 | if (joint->node[0].body) { | ||
1498 | // get axis 1 and 2 in global coords | ||
1499 | dVector3 ax1,ax2,v; | ||
1500 | dMULTIPLY0_331 (ax1,joint->node[0].body->R,joint->axis1); | ||
1501 | dMULTIPLY0_331 (ax2,joint->node[1].body->R,joint->axis2); | ||
1502 | |||
1503 | // don't do anything if the axis1 or axis2 vectors are zero or the same | ||
1504 | if ((ax1[0]==0 && ax1[1]==0 && ax1[2]==0) || | ||
1505 | (ax2[0]==0 && ax2[1]==0 && ax2[2]==0) || | ||
1506 | (ax1[0]==ax2[0] && ax1[1]==ax2[1] && ax1[2]==ax2[2])) return; | ||
1507 | |||
1508 | // modify axis 2 so it's perpendicular to axis 1 | ||
1509 | dReal k = dDOT(ax1,ax2); | ||
1510 | for (int i=0; i<3; i++) ax2[i] -= k*ax1[i]; | ||
1511 | dNormalize3 (ax2); | ||
1512 | |||
1513 | // make v1 = modified axis2, v2 = axis1 x (modified axis2) | ||
1514 | dCROSS (v,=,ax1,ax2); | ||
1515 | dMULTIPLY1_331 (joint->v1,joint->node[0].body->R,ax2); | ||
1516 | dMULTIPLY1_331 (joint->v2,joint->node[0].body->R,v); | ||
1517 | } | ||
1518 | } | ||
1519 | |||
1520 | |||
1521 | extern "C" void dJointSetHinge2Anchor (dxJointHinge2 *joint, | ||
1522 | dReal x, dReal y, dReal z) | ||
1523 | { | ||
1524 | dUASSERT(joint,"bad joint argument"); | ||
1525 | dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2"); | ||
1526 | setAnchors (joint,x,y,z,joint->anchor1,joint->anchor2); | ||
1527 | makeHinge2V1andV2 (joint); | ||
1528 | } | ||
1529 | |||
1530 | |||
1531 | extern "C" void dJointSetHinge2Axis1 (dxJointHinge2 *joint, | ||
1532 | dReal x, dReal y, dReal z) | ||
1533 | { | ||
1534 | dUASSERT(joint,"bad joint argument"); | ||
1535 | dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2"); | ||
1536 | if (joint->node[0].body) { | ||
1537 | dReal q[4]; | ||
1538 | q[0] = x; | ||
1539 | q[1] = y; | ||
1540 | q[2] = z; | ||
1541 | q[3] = 0; | ||
1542 | dNormalize3 (q); | ||
1543 | dMULTIPLY1_331 (joint->axis1,joint->node[0].body->R,q); | ||
1544 | joint->axis1[3] = 0; | ||
1545 | |||
1546 | // compute the sin and cos of the angle between axis 1 and axis 2 | ||
1547 | dVector3 ax; | ||
1548 | HINGE2_GET_AXIS_INFO(ax,joint->s0,joint->c0); | ||
1549 | } | ||
1550 | makeHinge2V1andV2 (joint); | ||
1551 | } | ||
1552 | |||
1553 | |||
1554 | extern "C" void dJointSetHinge2Axis2 (dxJointHinge2 *joint, | ||
1555 | dReal x, dReal y, dReal z) | ||
1556 | { | ||
1557 | dUASSERT(joint,"bad joint argument"); | ||
1558 | dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2"); | ||
1559 | if (joint->node[1].body) { | ||
1560 | dReal q[4]; | ||
1561 | q[0] = x; | ||
1562 | q[1] = y; | ||
1563 | q[2] = z; | ||
1564 | q[3] = 0; | ||
1565 | dNormalize3 (q); | ||
1566 | dMULTIPLY1_331 (joint->axis2,joint->node[1].body->R,q); | ||
1567 | joint->axis1[3] = 0; | ||
1568 | |||
1569 | // compute the sin and cos of the angle between axis 1 and axis 2 | ||
1570 | dVector3 ax; | ||
1571 | HINGE2_GET_AXIS_INFO(ax,joint->s0,joint->c0); | ||
1572 | } | ||
1573 | makeHinge2V1andV2 (joint); | ||
1574 | } | ||
1575 | |||
1576 | |||
1577 | extern "C" void dJointSetHinge2Param (dxJointHinge2 *joint, | ||
1578 | int parameter, dReal value) | ||
1579 | { | ||
1580 | dUASSERT(joint,"bad joint argument"); | ||
1581 | dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2"); | ||
1582 | if ((parameter & 0xff00) == 0x100) { | ||
1583 | joint->limot2.set (parameter & 0xff,value); | ||
1584 | } | ||
1585 | else { | ||
1586 | if (parameter == dParamSuspensionERP) joint->susp_erp = value; | ||
1587 | else if (parameter == dParamSuspensionCFM) joint->susp_cfm = value; | ||
1588 | else joint->limot1.set (parameter,value); | ||
1589 | } | ||
1590 | } | ||
1591 | |||
1592 | |||
1593 | extern "C" void dJointGetHinge2Anchor (dxJointHinge2 *joint, dVector3 result) | ||
1594 | { | ||
1595 | dUASSERT(joint,"bad joint argument"); | ||
1596 | dUASSERT(result,"bad result argument"); | ||
1597 | dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2"); | ||
1598 | if (joint->flags & dJOINT_REVERSE) | ||
1599 | getAnchor2 (joint,result,joint->anchor2); | ||
1600 | else | ||
1601 | getAnchor (joint,result,joint->anchor1); | ||
1602 | } | ||
1603 | |||
1604 | |||
1605 | extern "C" void dJointGetHinge2Anchor2 (dxJointHinge2 *joint, dVector3 result) | ||
1606 | { | ||
1607 | dUASSERT(joint,"bad joint argument"); | ||
1608 | dUASSERT(result,"bad result argument"); | ||
1609 | dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2"); | ||
1610 | if (joint->flags & dJOINT_REVERSE) | ||
1611 | getAnchor (joint,result,joint->anchor1); | ||
1612 | else | ||
1613 | getAnchor2 (joint,result,joint->anchor2); | ||
1614 | } | ||
1615 | |||
1616 | |||
1617 | extern "C" void dJointGetHinge2Axis1 (dxJointHinge2 *joint, dVector3 result) | ||
1618 | { | ||
1619 | dUASSERT(joint,"bad joint argument"); | ||
1620 | dUASSERT(result,"bad result argument"); | ||
1621 | dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2"); | ||
1622 | if (joint->node[0].body) { | ||
1623 | dMULTIPLY0_331 (result,joint->node[0].body->R,joint->axis1); | ||
1624 | } | ||
1625 | } | ||
1626 | |||
1627 | |||
1628 | extern "C" void dJointGetHinge2Axis2 (dxJointHinge2 *joint, dVector3 result) | ||
1629 | { | ||
1630 | dUASSERT(joint,"bad joint argument"); | ||
1631 | dUASSERT(result,"bad result argument"); | ||
1632 | dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2"); | ||
1633 | if (joint->node[1].body) { | ||
1634 | dMULTIPLY0_331 (result,joint->node[1].body->R,joint->axis2); | ||
1635 | } | ||
1636 | } | ||
1637 | |||
1638 | |||
1639 | extern "C" dReal dJointGetHinge2Param (dxJointHinge2 *joint, int parameter) | ||
1640 | { | ||
1641 | dUASSERT(joint,"bad joint argument"); | ||
1642 | dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2"); | ||
1643 | if ((parameter & 0xff00) == 0x100) { | ||
1644 | return joint->limot2.get (parameter & 0xff); | ||
1645 | } | ||
1646 | else { | ||
1647 | if (parameter == dParamSuspensionERP) return joint->susp_erp; | ||
1648 | else if (parameter == dParamSuspensionCFM) return joint->susp_cfm; | ||
1649 | else return joint->limot1.get (parameter); | ||
1650 | } | ||
1651 | } | ||
1652 | |||
1653 | |||
1654 | extern "C" dReal dJointGetHinge2Angle1 (dxJointHinge2 *joint) | ||
1655 | { | ||
1656 | dUASSERT(joint,"bad joint argument"); | ||
1657 | dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2"); | ||
1658 | if (joint->node[0].body) return measureHinge2Angle (joint); | ||
1659 | else return 0; | ||
1660 | } | ||
1661 | |||
1662 | |||
1663 | extern "C" dReal dJointGetHinge2Angle1Rate (dxJointHinge2 *joint) | ||
1664 | { | ||
1665 | dUASSERT(joint,"bad joint argument"); | ||
1666 | dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2"); | ||
1667 | if (joint->node[0].body) { | ||
1668 | dVector3 axis; | ||
1669 | dMULTIPLY0_331 (axis,joint->node[0].body->R,joint->axis1); | ||
1670 | dReal rate = dDOT(axis,joint->node[0].body->avel); | ||
1671 | if (joint->node[1].body) rate -= dDOT(axis,joint->node[1].body->avel); | ||
1672 | return rate; | ||
1673 | } | ||
1674 | else return 0; | ||
1675 | } | ||
1676 | |||
1677 | |||
1678 | extern "C" dReal dJointGetHinge2Angle2Rate (dxJointHinge2 *joint) | ||
1679 | { | ||
1680 | dUASSERT(joint,"bad joint argument"); | ||
1681 | dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2"); | ||
1682 | if (joint->node[0].body && joint->node[1].body) { | ||
1683 | dVector3 axis; | ||
1684 | dMULTIPLY0_331 (axis,joint->node[1].body->R,joint->axis2); | ||
1685 | dReal rate = dDOT(axis,joint->node[0].body->avel); | ||
1686 | if (joint->node[1].body) rate -= dDOT(axis,joint->node[1].body->avel); | ||
1687 | return rate; | ||
1688 | } | ||
1689 | else return 0; | ||
1690 | } | ||
1691 | |||
1692 | |||
1693 | extern "C" void dJointAddHinge2Torques (dxJointHinge2 *joint, dReal torque1, dReal torque2) | ||
1694 | { | ||
1695 | dVector3 axis1, axis2; | ||
1696 | dUASSERT(joint,"bad joint argument"); | ||
1697 | dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2"); | ||
1698 | |||
1699 | if (joint->node[0].body && joint->node[1].body) { | ||
1700 | dMULTIPLY0_331 (axis1,joint->node[0].body->R,joint->axis1); | ||
1701 | dMULTIPLY0_331 (axis2,joint->node[1].body->R,joint->axis2); | ||
1702 | axis1[0] = axis1[0] * torque1 + axis2[0] * torque2; | ||
1703 | axis1[1] = axis1[1] * torque1 + axis2[1] * torque2; | ||
1704 | axis1[2] = axis1[2] * torque1 + axis2[2] * torque2; | ||
1705 | dBodyAddTorque (joint->node[0].body,axis1[0],axis1[1],axis1[2]); | ||
1706 | dBodyAddTorque(joint->node[1].body, -axis1[0], -axis1[1], -axis1[2]); | ||
1707 | } | ||
1708 | } | ||
1709 | |||
1710 | |||
1711 | dxJoint::Vtable __dhinge2_vtable = { | ||
1712 | sizeof(dxJointHinge2), | ||
1713 | (dxJoint::init_fn*) hinge2Init, | ||
1714 | (dxJoint::getInfo1_fn*) hinge2GetInfo1, | ||
1715 | (dxJoint::getInfo2_fn*) hinge2GetInfo2, | ||
1716 | dJointTypeHinge2}; | ||
1717 | |||
1718 | //**************************************************************************** | ||
1719 | // universal | ||
1720 | |||
1721 | // I just realized that the universal joint is equivalent to a hinge 2 joint with | ||
1722 | // perfectly stiff suspension. By comparing the hinge 2 implementation to | ||
1723 | // the universal implementation, you may be able to improve this | ||
1724 | // implementation (or, less likely, the hinge2 implementation). | ||
1725 | |||
1726 | static void universalInit (dxJointUniversal *j) | ||
1727 | { | ||
1728 | dSetZero (j->anchor1,4); | ||
1729 | dSetZero (j->anchor2,4); | ||
1730 | dSetZero (j->axis1,4); | ||
1731 | j->axis1[0] = 1; | ||
1732 | dSetZero (j->axis2,4); | ||
1733 | j->axis2[1] = 1; | ||
1734 | dSetZero(j->qrel1,4); | ||
1735 | dSetZero(j->qrel2,4); | ||
1736 | j->limot1.init (j->world); | ||
1737 | j->limot2.init (j->world); | ||
1738 | } | ||
1739 | |||
1740 | |||
1741 | static void getUniversalAxes(dxJointUniversal *joint, dVector3 ax1, dVector3 ax2) | ||
1742 | { | ||
1743 | // This says "ax1 = joint->node[0].body->R * joint->axis1" | ||
1744 | dMULTIPLY0_331 (ax1,joint->node[0].body->R,joint->axis1); | ||
1745 | |||
1746 | if (joint->node[1].body) { | ||
1747 | dMULTIPLY0_331 (ax2,joint->node[1].body->R,joint->axis2); | ||
1748 | } | ||
1749 | else { | ||
1750 | ax2[0] = joint->axis2[0]; | ||
1751 | ax2[1] = joint->axis2[1]; | ||
1752 | ax2[2] = joint->axis2[2]; | ||
1753 | } | ||
1754 | } | ||
1755 | |||
1756 | |||
1757 | static dReal getUniversalAngle1(dxJointUniversal *joint) | ||
1758 | { | ||
1759 | if (joint->node[0].body) { | ||
1760 | // length 1 joint axis in global coordinates, from each body | ||
1761 | dVector3 ax1, ax2; | ||
1762 | dMatrix3 R; | ||
1763 | dQuaternion qcross, qq, qrel; | ||
1764 | |||
1765 | getUniversalAxes (joint,ax1,ax2); | ||
1766 | |||
1767 | // It should be possible to get both angles without explicitly | ||
1768 | // constructing the rotation matrix of the cross. Basically, | ||
1769 | // orientation of the cross about axis1 comes from body 2, | ||
1770 | // about axis 2 comes from body 1, and the perpendicular | ||
1771 | // axis can come from the two bodies somehow. (We don't really | ||
1772 | // want to assume it's 90 degrees, because in general the | ||
1773 | // constraints won't be perfectly satisfied, or even very well | ||
1774 | // satisfied.) | ||
1775 | // | ||
1776 | // However, we'd need a version of getHingeAngleFromRElativeQuat() | ||
1777 | // that CAN handle when its relative quat is rotated along a direction | ||
1778 | // other than the given axis. What I have here works, | ||
1779 | // although it's probably much slower than need be. | ||
1780 | |||
1781 | dRFrom2Axes(R, ax1[0], ax1[1], ax1[2], ax2[0], ax2[1], ax2[2]); | ||
1782 | dRtoQ (R,qcross); | ||
1783 | |||
1784 | // This code is essential the same as getHingeAngle(), see the comments | ||
1785 | // there for details. | ||
1786 | |||
1787 | // get qrel = relative rotation between node[0] and the cross | ||
1788 | dQMultiply1 (qq,joint->node[0].body->q,qcross); | ||
1789 | dQMultiply2 (qrel,qq,joint->qrel1); | ||
1790 | |||
1791 | return getHingeAngleFromRelativeQuat(qrel, joint->axis1); | ||
1792 | } | ||
1793 | return 0; | ||
1794 | } | ||
1795 | |||
1796 | |||
1797 | static dReal getUniversalAngle2(dxJointUniversal *joint) | ||
1798 | { | ||
1799 | if (joint->node[0].body) { | ||
1800 | // length 1 joint axis in global coordinates, from each body | ||
1801 | dVector3 ax1, ax2; | ||
1802 | dMatrix3 R; | ||
1803 | dQuaternion qcross, qq, qrel; | ||
1804 | |||
1805 | getUniversalAxes (joint,ax1,ax2); | ||
1806 | |||
1807 | // It should be possible to get both angles without explicitly | ||
1808 | // constructing the rotation matrix of the cross. Basically, | ||
1809 | // orientation of the cross about axis1 comes from body 2, | ||
1810 | // about axis 2 comes from body 1, and the perpendicular | ||
1811 | // axis can come from the two bodies somehow. (We don't really | ||
1812 | // want to assume it's 90 degrees, because in general the | ||
1813 | // constraints won't be perfectly satisfied, or even very well | ||
1814 | // satisfied.) | ||
1815 | // | ||
1816 | // However, we'd need a version of getHingeAngleFromRElativeQuat() | ||
1817 | // that CAN handle when its relative quat is rotated along a direction | ||
1818 | // other than the given axis. What I have here works, | ||
1819 | // although it's probably much slower than need be. | ||
1820 | |||
1821 | dRFrom2Axes(R, ax2[0], ax2[1], ax2[2], ax1[0], ax1[1], ax1[2]); | ||
1822 | dRtoQ(R, qcross); | ||
1823 | |||
1824 | if (joint->node[1].body) { | ||
1825 | dQMultiply1 (qq, joint->node[1].body->q, qcross); | ||
1826 | dQMultiply2 (qrel,qq,joint->qrel2); | ||
1827 | } | ||
1828 | else { | ||
1829 | // pretend joint->node[1].body->q is the identity | ||
1830 | dQMultiply2 (qrel,qcross, joint->qrel2); | ||
1831 | } | ||
1832 | |||
1833 | return - getHingeAngleFromRelativeQuat(qrel, joint->axis2); | ||
1834 | } | ||
1835 | return 0; | ||
1836 | } | ||
1837 | |||
1838 | |||
1839 | static void universalGetInfo1 (dxJointUniversal *j, dxJoint::Info1 *info) | ||
1840 | { | ||
1841 | info->nub = 4; | ||
1842 | info->m = 4; | ||
1843 | |||
1844 | // see if we're powered or at a joint limit. | ||
1845 | bool constraint1 = j->limot1.fmax > 0; | ||
1846 | bool constraint2 = j->limot2.fmax > 0; | ||
1847 | |||
1848 | bool limiting1 = (j->limot1.lostop >= -M_PI || j->limot1.histop <= M_PI) && | ||
1849 | j->limot1.lostop <= j->limot1.histop; | ||
1850 | bool limiting2 = (j->limot2.lostop >= -M_PI || j->limot2.histop <= M_PI) && | ||
1851 | j->limot2.lostop <= j->limot2.histop; | ||
1852 | |||
1853 | // We need to call testRotationLimit() even if we're motored, since it | ||
1854 | // records the result. | ||
1855 | if (limiting1 || limiting2) { | ||
1856 | dReal angle1, angle2; | ||
1857 | angle1 = getUniversalAngle1(j); | ||
1858 | angle2 = getUniversalAngle2(j); | ||
1859 | if (limiting1 && j->limot1.testRotationalLimit (angle1)) constraint1 = true; | ||
1860 | if (limiting2 && j->limot2.testRotationalLimit (angle2)) constraint2 = true; | ||
1861 | } | ||
1862 | if (constraint1) | ||
1863 | info->m++; | ||
1864 | if (constraint2) | ||
1865 | info->m++; | ||
1866 | } | ||
1867 | |||
1868 | |||
1869 | static void universalGetInfo2 (dxJointUniversal *joint, dxJoint::Info2 *info) | ||
1870 | { | ||
1871 | // set the three ball-and-socket rows | ||
1872 | setBall (joint,info,joint->anchor1,joint->anchor2); | ||
1873 | |||
1874 | // set the universal joint row. the angular velocity about an axis | ||
1875 | // perpendicular to both joint axes should be equal. thus the constraint | ||
1876 | // equation is | ||
1877 | // p*w1 - p*w2 = 0 | ||
1878 | // where p is a vector normal to both joint axes, and w1 and w2 | ||
1879 | // are the angular velocity vectors of the two bodies. | ||
1880 | |||
1881 | // length 1 joint axis in global coordinates, from each body | ||
1882 | dVector3 ax1, ax2; | ||
1883 | dVector3 ax2_temp; | ||
1884 | // length 1 vector perpendicular to ax1 and ax2. Neither body can rotate | ||
1885 | // about this. | ||
1886 | dVector3 p; | ||
1887 | dReal k; | ||
1888 | |||
1889 | getUniversalAxes(joint, ax1, ax2); | ||
1890 | k = dDOT(ax1, ax2); | ||
1891 | ax2_temp[0] = ax2[0] - k*ax1[0]; | ||
1892 | ax2_temp[1] = ax2[1] - k*ax1[1]; | ||
1893 | ax2_temp[2] = ax2[2] - k*ax1[2]; | ||
1894 | dCROSS(p, =, ax1, ax2_temp); | ||
1895 | dNormalize3(p); | ||
1896 | |||
1897 | int s3=3*info->rowskip; | ||
1898 | |||
1899 | info->J1a[s3+0] = p[0]; | ||
1900 | info->J1a[s3+1] = p[1]; | ||
1901 | info->J1a[s3+2] = p[2]; | ||
1902 | |||
1903 | if (joint->node[1].body) { | ||
1904 | info->J2a[s3+0] = -p[0]; | ||
1905 | info->J2a[s3+1] = -p[1]; | ||
1906 | info->J2a[s3+2] = -p[2]; | ||
1907 | } | ||
1908 | |||
1909 | // compute the right hand side of the constraint equation. set relative | ||
1910 | // body velocities along p to bring the axes back to perpendicular. | ||
1911 | // If ax1, ax2 are unit length joint axes as computed from body1 and | ||
1912 | // body2, we need to rotate both bodies along the axis p. If theta | ||
1913 | // is the angle between ax1 and ax2, we need an angular velocity | ||
1914 | // along p to cover the angle erp * (theta - Pi/2) in one step: | ||
1915 | // | ||
1916 | // |angular_velocity| = angle/time = erp*(theta - Pi/2) / stepsize | ||
1917 | // = (erp*fps) * (theta - Pi/2) | ||
1918 | // | ||
1919 | // if theta is close to Pi/2, | ||
1920 | // theta - Pi/2 ~= cos(theta), so | ||
1921 | // |angular_velocity| ~= (erp*fps) * (ax1 dot ax2) | ||
1922 | |||
1923 | info->c[3] = info->fps * info->erp * - dDOT(ax1, ax2); | ||
1924 | |||
1925 | // if the first angle is powered, or has joint limits, add in the stuff | ||
1926 | int row = 4 + joint->limot1.addLimot (joint,info,4,ax1,1); | ||
1927 | |||
1928 | // if the second angle is powered, or has joint limits, add in more stuff | ||
1929 | joint->limot2.addLimot (joint,info,row,ax2,1); | ||
1930 | } | ||
1931 | |||
1932 | |||
1933 | static void universalComputeInitialRelativeRotations (dxJointUniversal *joint) | ||
1934 | { | ||
1935 | if (joint->node[0].body) { | ||
1936 | dVector3 ax1, ax2; | ||
1937 | dMatrix3 R; | ||
1938 | dQuaternion qcross; | ||
1939 | |||
1940 | getUniversalAxes(joint, ax1, ax2); | ||
1941 | |||
1942 | // Axis 1. | ||
1943 | dRFrom2Axes(R, ax1[0], ax1[1], ax1[2], ax2[0], ax2[1], ax2[2]); | ||
1944 | dRtoQ(R, qcross); | ||
1945 | dQMultiply1 (joint->qrel1, joint->node[0].body->q, qcross); | ||
1946 | |||
1947 | // Axis 2. | ||
1948 | dRFrom2Axes(R, ax2[0], ax2[1], ax2[2], ax1[0], ax1[1], ax1[2]); | ||
1949 | dRtoQ(R, qcross); | ||
1950 | if (joint->node[1].body) { | ||
1951 | dQMultiply1 (joint->qrel2, joint->node[1].body->q, qcross); | ||
1952 | } | ||
1953 | else { | ||
1954 | // set joint->qrel to qcross | ||
1955 | for (int i=0; i<4; i++) joint->qrel2[i] = qcross[i]; | ||
1956 | } | ||
1957 | } | ||
1958 | } | ||
1959 | |||
1960 | |||
1961 | extern "C" void dJointSetUniversalAnchor (dxJointUniversal *joint, | ||
1962 | dReal x, dReal y, dReal z) | ||
1963 | { | ||
1964 | dUASSERT(joint,"bad joint argument"); | ||
1965 | dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal"); | ||
1966 | setAnchors (joint,x,y,z,joint->anchor1,joint->anchor2); | ||
1967 | universalComputeInitialRelativeRotations(joint); | ||
1968 | } | ||
1969 | |||
1970 | |||
1971 | extern "C" void dJointSetUniversalAxis1 (dxJointUniversal *joint, | ||
1972 | dReal x, dReal y, dReal z) | ||
1973 | { | ||
1974 | dUASSERT(joint,"bad joint argument"); | ||
1975 | dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal"); | ||
1976 | if (joint->flags & dJOINT_REVERSE) | ||
1977 | setAxes (joint,x,y,z,NULL,joint->axis2); | ||
1978 | else | ||
1979 | setAxes (joint,x,y,z,joint->axis1,NULL); | ||
1980 | universalComputeInitialRelativeRotations(joint); | ||
1981 | } | ||
1982 | |||
1983 | |||
1984 | extern "C" void dJointSetUniversalAxis2 (dxJointUniversal *joint, | ||
1985 | dReal x, dReal y, dReal z) | ||
1986 | { | ||
1987 | dUASSERT(joint,"bad joint argument"); | ||
1988 | dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal"); | ||
1989 | if (joint->flags & dJOINT_REVERSE) | ||
1990 | setAxes (joint,x,y,z,joint->axis1,NULL); | ||
1991 | else | ||
1992 | setAxes (joint,x,y,z,NULL,joint->axis2); | ||
1993 | universalComputeInitialRelativeRotations(joint); | ||
1994 | } | ||
1995 | |||
1996 | |||
1997 | extern "C" void dJointGetUniversalAnchor (dxJointUniversal *joint, | ||
1998 | dVector3 result) | ||
1999 | { | ||
2000 | dUASSERT(joint,"bad joint argument"); | ||
2001 | dUASSERT(result,"bad result argument"); | ||
2002 | dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal"); | ||
2003 | if (joint->flags & dJOINT_REVERSE) | ||
2004 | getAnchor2 (joint,result,joint->anchor2); | ||
2005 | else | ||
2006 | getAnchor (joint,result,joint->anchor1); | ||
2007 | } | ||
2008 | |||
2009 | |||
2010 | extern "C" void dJointGetUniversalAnchor2 (dxJointUniversal *joint, | ||
2011 | dVector3 result) | ||
2012 | { | ||
2013 | dUASSERT(joint,"bad joint argument"); | ||
2014 | dUASSERT(result,"bad result argument"); | ||
2015 | dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal"); | ||
2016 | if (joint->flags & dJOINT_REVERSE) | ||
2017 | getAnchor (joint,result,joint->anchor1); | ||
2018 | else | ||
2019 | getAnchor2 (joint,result,joint->anchor2); | ||
2020 | } | ||
2021 | |||
2022 | |||
2023 | extern "C" void dJointGetUniversalAxis1 (dxJointUniversal *joint, | ||
2024 | dVector3 result) | ||
2025 | { | ||
2026 | dUASSERT(joint,"bad joint argument"); | ||
2027 | dUASSERT(result,"bad result argument"); | ||
2028 | dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal"); | ||
2029 | if (joint->flags & dJOINT_REVERSE) | ||
2030 | getAxis2 (joint,result,joint->axis2); | ||
2031 | else | ||
2032 | getAxis (joint,result,joint->axis1); | ||
2033 | } | ||
2034 | |||
2035 | |||
2036 | extern "C" void dJointGetUniversalAxis2 (dxJointUniversal *joint, | ||
2037 | dVector3 result) | ||
2038 | { | ||
2039 | dUASSERT(joint,"bad joint argument"); | ||
2040 | dUASSERT(result,"bad result argument"); | ||
2041 | dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal"); | ||
2042 | if (joint->flags & dJOINT_REVERSE) | ||
2043 | getAxis (joint,result,joint->axis1); | ||
2044 | else | ||
2045 | getAxis2 (joint,result,joint->axis2); | ||
2046 | } | ||
2047 | |||
2048 | |||
2049 | extern "C" void dJointSetUniversalParam (dxJointUniversal *joint, | ||
2050 | int parameter, dReal value) | ||
2051 | { | ||
2052 | dUASSERT(joint,"bad joint argument"); | ||
2053 | dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal"); | ||
2054 | if ((parameter & 0xff00) == 0x100) { | ||
2055 | joint->limot2.set (parameter & 0xff,value); | ||
2056 | } | ||
2057 | else { | ||
2058 | joint->limot1.set (parameter,value); | ||
2059 | } | ||
2060 | } | ||
2061 | |||
2062 | |||
2063 | extern "C" dReal dJointGetUniversalParam (dxJointUniversal *joint, int parameter) | ||
2064 | { | ||
2065 | dUASSERT(joint,"bad joint argument"); | ||
2066 | dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal"); | ||
2067 | if ((parameter & 0xff00) == 0x100) { | ||
2068 | return joint->limot2.get (parameter & 0xff); | ||
2069 | } | ||
2070 | else { | ||
2071 | return joint->limot1.get (parameter); | ||
2072 | } | ||
2073 | } | ||
2074 | |||
2075 | |||
2076 | extern "C" dReal dJointGetUniversalAngle1 (dxJointUniversal *joint) | ||
2077 | { | ||
2078 | dUASSERT(joint,"bad joint argument"); | ||
2079 | dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal"); | ||
2080 | if (joint->flags & dJOINT_REVERSE) | ||
2081 | return getUniversalAngle2 (joint); | ||
2082 | else | ||
2083 | return getUniversalAngle1 (joint); | ||
2084 | } | ||
2085 | |||
2086 | |||
2087 | extern "C" dReal dJointGetUniversalAngle2 (dxJointUniversal *joint) | ||
2088 | { | ||
2089 | dUASSERT(joint,"bad joint argument"); | ||
2090 | dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal"); | ||
2091 | if (joint->flags & dJOINT_REVERSE) | ||
2092 | return getUniversalAngle1 (joint); | ||
2093 | else | ||
2094 | return getUniversalAngle2 (joint); | ||
2095 | } | ||
2096 | |||
2097 | |||
2098 | extern "C" dReal dJointGetUniversalAngle1Rate (dxJointUniversal *joint) | ||
2099 | { | ||
2100 | dUASSERT(joint,"bad joint argument"); | ||
2101 | dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal"); | ||
2102 | |||
2103 | if (joint->node[0].body) { | ||
2104 | dVector3 axis; | ||
2105 | |||
2106 | if (joint->flags & dJOINT_REVERSE) | ||
2107 | getAxis2 (joint,axis,joint->axis2); | ||
2108 | else | ||
2109 | getAxis (joint,axis,joint->axis1); | ||
2110 | |||
2111 | dReal rate = dDOT(axis, joint->node[0].body->avel); | ||
2112 | if (joint->node[1].body) rate -= dDOT(axis, joint->node[1].body->avel); | ||
2113 | return rate; | ||
2114 | } | ||
2115 | return 0; | ||
2116 | } | ||
2117 | |||
2118 | |||
2119 | extern "C" dReal dJointGetUniversalAngle2Rate (dxJointUniversal *joint) | ||
2120 | { | ||
2121 | dUASSERT(joint,"bad joint argument"); | ||
2122 | dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal"); | ||
2123 | |||
2124 | if (joint->node[0].body) { | ||
2125 | dVector3 axis; | ||
2126 | |||
2127 | if (joint->flags & dJOINT_REVERSE) | ||
2128 | getAxis (joint,axis,joint->axis1); | ||
2129 | else | ||
2130 | getAxis2 (joint,axis,joint->axis2); | ||
2131 | |||
2132 | dReal rate = dDOT(axis, joint->node[0].body->avel); | ||
2133 | if (joint->node[1].body) rate -= dDOT(axis, joint->node[1].body->avel); | ||
2134 | return rate; | ||
2135 | } | ||
2136 | return 0; | ||
2137 | } | ||
2138 | |||
2139 | |||
2140 | extern "C" void dJointAddUniversalTorques (dxJointUniversal *joint, dReal torque1, dReal torque2) | ||
2141 | { | ||
2142 | dVector3 axis1, axis2; | ||
2143 | dAASSERT(joint); | ||
2144 | dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal"); | ||
2145 | |||
2146 | if (joint->flags & dJOINT_REVERSE) { | ||
2147 | dReal temp = torque1; | ||
2148 | torque1 = - torque2; | ||
2149 | torque2 = - temp; | ||
2150 | } | ||
2151 | |||
2152 | getAxis (joint,axis1,joint->axis1); | ||
2153 | getAxis2 (joint,axis2,joint->axis2); | ||
2154 | axis1[0] = axis1[0] * torque1 + axis2[0] * torque2; | ||
2155 | axis1[1] = axis1[1] * torque1 + axis2[1] * torque2; | ||
2156 | axis1[2] = axis1[2] * torque1 + axis2[2] * torque2; | ||
2157 | |||
2158 | if (joint->node[0].body != 0) | ||
2159 | dBodyAddTorque (joint->node[0].body,axis1[0],axis1[1],axis1[2]); | ||
2160 | if (joint->node[1].body != 0) | ||
2161 | dBodyAddTorque(joint->node[1].body, -axis1[0], -axis1[1], -axis1[2]); | ||
2162 | } | ||
2163 | |||
2164 | |||
2165 | |||
2166 | |||
2167 | |||
2168 | dxJoint::Vtable __duniversal_vtable = { | ||
2169 | sizeof(dxJointUniversal), | ||
2170 | (dxJoint::init_fn*) universalInit, | ||
2171 | (dxJoint::getInfo1_fn*) universalGetInfo1, | ||
2172 | (dxJoint::getInfo2_fn*) universalGetInfo2, | ||
2173 | dJointTypeUniversal}; | ||
2174 | |||
2175 | //**************************************************************************** | ||
2176 | // angular motor | ||
2177 | |||
2178 | static void amotorInit (dxJointAMotor *j) | ||
2179 | { | ||
2180 | int i; | ||
2181 | j->num = 0; | ||
2182 | j->mode = dAMotorUser; | ||
2183 | for (i=0; i<3; i++) { | ||
2184 | j->rel[i] = 0; | ||
2185 | dSetZero (j->axis[i],4); | ||
2186 | j->limot[i].init (j->world); | ||
2187 | j->angle[i] = 0; | ||
2188 | } | ||
2189 | dSetZero (j->reference1,4); | ||
2190 | dSetZero (j->reference2,4); | ||
2191 | |||
2192 | j->flags |= dJOINT_TWOBODIES; | ||
2193 | } | ||
2194 | |||
2195 | |||
2196 | // compute the 3 axes in global coordinates | ||
2197 | |||
2198 | static void amotorComputeGlobalAxes (dxJointAMotor *joint, dVector3 ax[3]) | ||
2199 | { | ||
2200 | if (joint->mode == dAMotorEuler) { | ||
2201 | // special handling for euler mode | ||
2202 | dMULTIPLY0_331 (ax[0],joint->node[0].body->R,joint->axis[0]); | ||
2203 | dMULTIPLY0_331 (ax[2],joint->node[1].body->R,joint->axis[2]); | ||
2204 | dCROSS (ax[1],=,ax[2],ax[0]); | ||
2205 | dNormalize3 (ax[1]); | ||
2206 | } | ||
2207 | else { | ||
2208 | for (int i=0; i < joint->num; i++) { | ||
2209 | if (joint->rel[i] == 1) { | ||
2210 | // relative to b1 | ||
2211 | dMULTIPLY0_331 (ax[i],joint->node[0].body->R,joint->axis[i]); | ||
2212 | } | ||
2213 | if (joint->rel[i] == 2) { | ||
2214 | // relative to b2 | ||
2215 | dMULTIPLY0_331 (ax[i],joint->node[1].body->R,joint->axis[i]); | ||
2216 | } | ||
2217 | else { | ||
2218 | // global - just copy it | ||
2219 | ax[i][0] = joint->axis[i][0]; | ||
2220 | ax[i][1] = joint->axis[i][1]; | ||
2221 | ax[i][2] = joint->axis[i][2]; | ||
2222 | } | ||
2223 | } | ||
2224 | } | ||
2225 | } | ||
2226 | |||
2227 | |||
2228 | static void amotorComputeEulerAngles (dxJointAMotor *joint, dVector3 ax[3]) | ||
2229 | { | ||
2230 | // assumptions: | ||
2231 | // global axes already calculated --> ax | ||
2232 | // axis[0] is relative to body 1 --> global ax[0] | ||
2233 | // axis[2] is relative to body 2 --> global ax[2] | ||
2234 | // ax[1] = ax[2] x ax[0] | ||
2235 | // original ax[0] and ax[2] are perpendicular | ||
2236 | // reference1 is perpendicular to ax[0] (in body 1 frame) | ||
2237 | // reference2 is perpendicular to ax[2] (in body 2 frame) | ||
2238 | // all ax[] and reference vectors are unit length | ||
2239 | |||
2240 | // calculate references in global frame | ||
2241 | dVector3 ref1,ref2; | ||
2242 | dMULTIPLY0_331 (ref1,joint->node[0].body->R,joint->reference1); | ||
2243 | dMULTIPLY0_331 (ref2,joint->node[1].body->R,joint->reference2); | ||
2244 | |||
2245 | // get q perpendicular to both ax[0] and ref1, get first euler angle | ||
2246 | dVector3 q; | ||
2247 | dCROSS (q,=,ax[0],ref1); | ||
2248 | joint->angle[0] = -dAtan2 (dDOT(ax[2],q),dDOT(ax[2],ref1)); | ||
2249 | |||
2250 | // get q perpendicular to both ax[0] and ax[1], get second euler angle | ||
2251 | dCROSS (q,=,ax[0],ax[1]); | ||
2252 | joint->angle[1] = -dAtan2 (dDOT(ax[2],ax[0]),dDOT(ax[2],q)); | ||
2253 | |||
2254 | // get q perpendicular to both ax[1] and ax[2], get third euler angle | ||
2255 | dCROSS (q,=,ax[1],ax[2]); | ||
2256 | joint->angle[2] = -dAtan2 (dDOT(ref2,ax[1]), dDOT(ref2,q)); | ||
2257 | } | ||
2258 | |||
2259 | |||
2260 | // set the reference vectors as follows: | ||
2261 | // * reference1 = current axis[2] relative to body 1 | ||
2262 | // * reference2 = current axis[0] relative to body 2 | ||
2263 | // this assumes that: | ||
2264 | // * axis[0] is relative to body 1 | ||
2265 | // * axis[2] is relative to body 2 | ||
2266 | |||
2267 | static void amotorSetEulerReferenceVectors (dxJointAMotor *j) | ||
2268 | { | ||
2269 | if (j->node[0].body && j->node[1].body) { | ||
2270 | dVector3 r; // axis[2] and axis[0] in global coordinates | ||
2271 | dMULTIPLY0_331 (r,j->node[1].body->R,j->axis[2]); | ||
2272 | dMULTIPLY1_331 (j->reference1,j->node[0].body->R,r); | ||
2273 | dMULTIPLY0_331 (r,j->node[0].body->R,j->axis[0]); | ||
2274 | dMULTIPLY1_331 (j->reference2,j->node[1].body->R,r); | ||
2275 | } | ||
2276 | } | ||
2277 | |||
2278 | |||
2279 | static void amotorGetInfo1 (dxJointAMotor *j, dxJoint::Info1 *info) | ||
2280 | { | ||
2281 | info->m = 0; | ||
2282 | info->nub = 0; | ||
2283 | |||
2284 | // compute the axes and angles, if in euler mode | ||
2285 | if (j->mode == dAMotorEuler) { | ||
2286 | dVector3 ax[3]; | ||
2287 | amotorComputeGlobalAxes (j,ax); | ||
2288 | amotorComputeEulerAngles (j,ax); | ||
2289 | } | ||
2290 | |||
2291 | // see if we're powered or at a joint limit for each axis | ||
2292 | for (int i=0; i < j->num; i++) { | ||
2293 | if (j->limot[i].testRotationalLimit (j->angle[i]) || | ||
2294 | j->limot[i].fmax > 0) { | ||
2295 | info->m++; | ||
2296 | } | ||
2297 | } | ||
2298 | } | ||
2299 | |||
2300 | |||
2301 | static void amotorGetInfo2 (dxJointAMotor *joint, dxJoint::Info2 *info) | ||
2302 | { | ||
2303 | int i; | ||
2304 | |||
2305 | // compute the axes (if not global) | ||
2306 | dVector3 ax[3]; | ||
2307 | amotorComputeGlobalAxes (joint,ax); | ||
2308 | |||
2309 | // in euler angle mode we do not actually constrain the angular velocity | ||
2310 | // along the axes axis[0] and axis[2] (although we do use axis[1]) : | ||
2311 | // | ||
2312 | // to get constrain w2-w1 along ...not | ||
2313 | // ------ --------------------- ------ | ||
2314 | // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0] | ||
2315 | // d(angle[1])/dt = 0 ax[1] | ||
2316 | // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2] | ||
2317 | // | ||
2318 | // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0. | ||
2319 | // to prove the result for angle[0], write the expression for angle[0] from | ||
2320 | // GetInfo1 then take the derivative. to prove this for angle[2] it is | ||
2321 | // easier to take the euler rate expression for d(angle[2])/dt with respect | ||
2322 | // to the components of w and set that to 0. | ||
2323 | |||
2324 | dVector3 *axptr[3]; | ||
2325 | axptr[0] = &ax[0]; | ||
2326 | axptr[1] = &ax[1]; | ||
2327 | axptr[2] = &ax[2]; | ||
2328 | |||
2329 | dVector3 ax0_cross_ax1; | ||
2330 | dVector3 ax1_cross_ax2; | ||
2331 | if (joint->mode == dAMotorEuler) { | ||
2332 | dCROSS (ax0_cross_ax1,=,ax[0],ax[1]); | ||
2333 | axptr[2] = &ax0_cross_ax1; | ||
2334 | dCROSS (ax1_cross_ax2,=,ax[1],ax[2]); | ||
2335 | axptr[0] = &ax1_cross_ax2; | ||
2336 | } | ||
2337 | |||
2338 | int row=0; | ||
2339 | for (i=0; i < joint->num; i++) { | ||
2340 | row += joint->limot[i].addLimot (joint,info,row,*(axptr[i]),1); | ||
2341 | } | ||
2342 | } | ||
2343 | |||
2344 | |||
2345 | extern "C" void dJointSetAMotorNumAxes (dxJointAMotor *joint, int num) | ||
2346 | { | ||
2347 | dAASSERT(joint && num >= 0 && num <= 3); | ||
2348 | dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor"); | ||
2349 | if (joint->mode == dAMotorEuler) { | ||
2350 | joint->num = 3; | ||
2351 | } | ||
2352 | else { | ||
2353 | if (num < 0) num = 0; | ||
2354 | if (num > 3) num = 3; | ||
2355 | joint->num = num; | ||
2356 | } | ||
2357 | } | ||
2358 | |||
2359 | |||
2360 | extern "C" void dJointSetAMotorAxis (dxJointAMotor *joint, int anum, int rel, | ||
2361 | dReal x, dReal y, dReal z) | ||
2362 | { | ||
2363 | dAASSERT(joint && anum >= 0 && anum <= 2 && rel >= 0 && rel <= 2); | ||
2364 | dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor"); | ||
2365 | if (anum < 0) anum = 0; | ||
2366 | if (anum > 2) anum = 2; | ||
2367 | joint->rel[anum] = rel; | ||
2368 | |||
2369 | // x,y,z is always in global coordinates regardless of rel, so we may have | ||
2370 | // to convert it to be relative to a body | ||
2371 | dVector3 r; | ||
2372 | r[0] = x; | ||
2373 | r[1] = y; | ||
2374 | r[2] = z; | ||
2375 | r[3] = 0; | ||
2376 | if (rel > 0) { | ||
2377 | if (rel==1) { | ||
2378 | dMULTIPLY1_331 (joint->axis[anum],joint->node[0].body->R,r); | ||
2379 | } | ||
2380 | else { | ||
2381 | dMULTIPLY1_331 (joint->axis[anum],joint->node[1].body->R,r); | ||
2382 | } | ||
2383 | } | ||
2384 | else { | ||
2385 | joint->axis[anum][0] = r[0]; | ||
2386 | joint->axis[anum][1] = r[1]; | ||
2387 | joint->axis[anum][2] = r[2]; | ||
2388 | } | ||
2389 | dNormalize3 (joint->axis[anum]); | ||
2390 | if (joint->mode == dAMotorEuler) amotorSetEulerReferenceVectors (joint); | ||
2391 | } | ||
2392 | |||
2393 | |||
2394 | extern "C" void dJointSetAMotorAngle (dxJointAMotor *joint, int anum, | ||
2395 | dReal angle) | ||
2396 | { | ||
2397 | dAASSERT(joint && anum >= 0 && anum < 3); | ||
2398 | dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor"); | ||
2399 | if (joint->mode == dAMotorUser) { | ||
2400 | if (anum < 0) anum = 0; | ||
2401 | if (anum > 3) anum = 3; | ||
2402 | joint->angle[anum] = angle; | ||
2403 | } | ||
2404 | } | ||
2405 | |||
2406 | |||
2407 | extern "C" void dJointSetAMotorParam (dxJointAMotor *joint, int parameter, | ||
2408 | dReal value) | ||
2409 | { | ||
2410 | dAASSERT(joint); | ||
2411 | dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor"); | ||
2412 | int anum = parameter >> 8; | ||
2413 | if (anum < 0) anum = 0; | ||
2414 | if (anum > 2) anum = 2; | ||
2415 | parameter &= 0xff; | ||
2416 | joint->limot[anum].set (parameter, value); | ||
2417 | } | ||
2418 | |||
2419 | |||
2420 | extern "C" void dJointSetAMotorMode (dxJointAMotor *joint, int mode) | ||
2421 | { | ||
2422 | dAASSERT(joint); | ||
2423 | dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor"); | ||
2424 | joint->mode = mode; | ||
2425 | if (joint->mode == dAMotorEuler) { | ||
2426 | joint->num = 3; | ||
2427 | amotorSetEulerReferenceVectors (joint); | ||
2428 | } | ||
2429 | } | ||
2430 | |||
2431 | |||
2432 | extern "C" int dJointGetAMotorNumAxes (dxJointAMotor *joint) | ||
2433 | { | ||
2434 | dAASSERT(joint); | ||
2435 | dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor"); | ||
2436 | return joint->num; | ||
2437 | } | ||
2438 | |||
2439 | |||
2440 | extern "C" void dJointGetAMotorAxis (dxJointAMotor *joint, int anum, | ||
2441 | dVector3 result) | ||
2442 | { | ||
2443 | dAASSERT(joint && anum >= 0 && anum < 3); | ||
2444 | dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor"); | ||
2445 | if (anum < 0) anum = 0; | ||
2446 | if (anum > 2) anum = 2; | ||
2447 | if (joint->rel[anum] > 0) { | ||
2448 | if (joint->rel[anum]==1) { | ||
2449 | dMULTIPLY0_331 (result,joint->node[0].body->R,joint->axis[anum]); | ||
2450 | } | ||
2451 | else { | ||
2452 | dMULTIPLY0_331 (result,joint->node[1].body->R,joint->axis[anum]); | ||
2453 | } | ||
2454 | } | ||
2455 | else { | ||
2456 | result[0] = joint->axis[anum][0]; | ||
2457 | result[1] = joint->axis[anum][1]; | ||
2458 | result[2] = joint->axis[anum][2]; | ||
2459 | } | ||
2460 | } | ||
2461 | |||
2462 | |||
2463 | extern "C" int dJointGetAMotorAxisRel (dxJointAMotor *joint, int anum) | ||
2464 | { | ||
2465 | dAASSERT(joint && anum >= 0 && anum < 3); | ||
2466 | dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor"); | ||
2467 | if (anum < 0) anum = 0; | ||
2468 | if (anum > 2) anum = 2; | ||
2469 | return joint->rel[anum]; | ||
2470 | } | ||
2471 | |||
2472 | |||
2473 | extern "C" dReal dJointGetAMotorAngle (dxJointAMotor *joint, int anum) | ||
2474 | { | ||
2475 | dAASSERT(joint && anum >= 0 && anum < 3); | ||
2476 | dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor"); | ||
2477 | if (anum < 0) anum = 0; | ||
2478 | if (anum > 3) anum = 3; | ||
2479 | return joint->angle[anum]; | ||
2480 | } | ||
2481 | |||
2482 | |||
2483 | extern "C" dReal dJointGetAMotorAngleRate (dxJointAMotor *joint, int anum) | ||
2484 | { | ||
2485 | // @@@ | ||
2486 | dDebug (0,"not yet implemented"); | ||
2487 | return 0; | ||
2488 | } | ||
2489 | |||
2490 | |||
2491 | extern "C" dReal dJointGetAMotorParam (dxJointAMotor *joint, int parameter) | ||
2492 | { | ||
2493 | dAASSERT(joint); | ||
2494 | dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor"); | ||
2495 | int anum = parameter >> 8; | ||
2496 | if (anum < 0) anum = 0; | ||
2497 | if (anum > 2) anum = 2; | ||
2498 | parameter &= 0xff; | ||
2499 | return joint->limot[anum].get (parameter); | ||
2500 | } | ||
2501 | |||
2502 | |||
2503 | extern "C" int dJointGetAMotorMode (dxJointAMotor *joint) | ||
2504 | { | ||
2505 | dAASSERT(joint); | ||
2506 | dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor"); | ||
2507 | return joint->mode; | ||
2508 | } | ||
2509 | |||
2510 | |||
2511 | extern "C" void dJointAddAMotorTorques (dxJointAMotor *joint, dReal torque1, dReal torque2, dReal torque3) | ||
2512 | { | ||
2513 | dVector3 axes[3]; | ||
2514 | dAASSERT(joint); | ||
2515 | dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor"); | ||
2516 | |||
2517 | if (joint->num == 0) | ||
2518 | return; | ||
2519 | dUASSERT((joint->flags & dJOINT_REVERSE) == 0, "dJointAddAMotorTorques not yet implemented for reverse AMotor joints"); | ||
2520 | |||
2521 | amotorComputeGlobalAxes (joint,axes); | ||
2522 | axes[0][0] *= torque1; | ||
2523 | axes[0][1] *= torque1; | ||
2524 | axes[0][2] *= torque1; | ||
2525 | if (joint->num >= 2) { | ||
2526 | axes[0][0] += axes[1][0] * torque2; | ||
2527 | axes[0][1] += axes[1][0] * torque2; | ||
2528 | axes[0][2] += axes[1][0] * torque2; | ||
2529 | if (joint->num >= 3) { | ||
2530 | axes[0][0] += axes[2][0] * torque3; | ||
2531 | axes[0][1] += axes[2][0] * torque3; | ||
2532 | axes[0][2] += axes[2][0] * torque3; | ||
2533 | } | ||
2534 | } | ||
2535 | |||
2536 | if (joint->node[0].body != 0) | ||
2537 | dBodyAddTorque (joint->node[0].body,axes[0][0],axes[0][1],axes[0][2]); | ||
2538 | if (joint->node[1].body != 0) | ||
2539 | dBodyAddTorque(joint->node[1].body, -axes[0][0], -axes[0][1], -axes[0][2]); | ||
2540 | } | ||
2541 | |||
2542 | |||
2543 | dxJoint::Vtable __damotor_vtable = { | ||
2544 | sizeof(dxJointAMotor), | ||
2545 | (dxJoint::init_fn*) amotorInit, | ||
2546 | (dxJoint::getInfo1_fn*) amotorGetInfo1, | ||
2547 | (dxJoint::getInfo2_fn*) amotorGetInfo2, | ||
2548 | dJointTypeAMotor}; | ||
2549 | |||
2550 | //**************************************************************************** | ||
2551 | // fixed joint | ||
2552 | |||
2553 | static void fixedInit (dxJointFixed *j) | ||
2554 | { | ||
2555 | dSetZero (j->offset,4); | ||
2556 | dSetZero (j->qrel,4); | ||
2557 | } | ||
2558 | |||
2559 | |||
2560 | static void fixedGetInfo1 (dxJointFixed *j, dxJoint::Info1 *info) | ||
2561 | { | ||
2562 | info->m = 6; | ||
2563 | info->nub = 6; | ||
2564 | } | ||
2565 | |||
2566 | |||
2567 | static void fixedGetInfo2 (dxJointFixed *joint, dxJoint::Info2 *info) | ||
2568 | { | ||
2569 | int s = info->rowskip; | ||
2570 | |||
2571 | // Three rows for orientation | ||
2572 | setFixedOrientation(joint, info, joint->qrel, 3); | ||
2573 | |||
2574 | // Three rows for position. | ||
2575 | // set jacobian | ||
2576 | info->J1l[0] = 1; | ||
2577 | info->J1l[s+1] = 1; | ||
2578 | info->J1l[2*s+2] = 1; | ||
2579 | |||
2580 | dVector3 ofs; | ||
2581 | dMULTIPLY0_331 (ofs,joint->node[0].body->R,joint->offset); | ||
2582 | if (joint->node[1].body) { | ||
2583 | dCROSSMAT (info->J1a,ofs,s,+,-); | ||
2584 | info->J2l[0] = -1; | ||
2585 | info->J2l[s+1] = -1; | ||
2586 | info->J2l[2*s+2] = -1; | ||
2587 | } | ||
2588 | |||
2589 | // set right hand side for the first three rows (linear) | ||
2590 | dReal k = info->fps * info->erp; | ||
2591 | if (joint->node[1].body) { | ||
2592 | for (int j=0; j<3; j++) | ||
2593 | info->c[j] = k * (joint->node[1].body->pos[j] - | ||
2594 | joint->node[0].body->pos[j] + ofs[j]); | ||
2595 | } | ||
2596 | else { | ||
2597 | for (int j=0; j<3; j++) | ||
2598 | info->c[j] = k * (joint->offset[j] - joint->node[0].body->pos[j]); | ||
2599 | } | ||
2600 | } | ||
2601 | |||
2602 | |||
2603 | extern "C" void dJointSetFixed (dxJointFixed *joint) | ||
2604 | { | ||
2605 | dUASSERT(joint,"bad joint argument"); | ||
2606 | dUASSERT(joint->vtable == &__dfixed_vtable,"joint is not fixed"); | ||
2607 | int i; | ||
2608 | |||
2609 | // This code is taken from sJointSetSliderAxis(), we should really put the | ||
2610 | // common code in its own function. | ||
2611 | // compute the offset between the bodies | ||
2612 | if (joint->node[0].body) { | ||
2613 | if (joint->node[1].body) { | ||
2614 | dQMultiply1 (joint->qrel,joint->node[0].body->q,joint->node[1].body->q); | ||
2615 | dReal ofs[4]; | ||
2616 | for (i=0; i<4; i++) ofs[i] = joint->node[0].body->pos[i]; | ||
2617 | for (i=0; i<4; i++) ofs[i] -= joint->node[1].body->pos[i]; | ||
2618 | dMULTIPLY1_331 (joint->offset,joint->node[0].body->R,ofs); | ||
2619 | } | ||
2620 | else { | ||
2621 | // set joint->qrel to the transpose of the first body's q | ||
2622 | joint->qrel[0] = joint->node[0].body->q[0]; | ||
2623 | for (i=1; i<4; i++) joint->qrel[i] = -joint->node[0].body->q[i]; | ||
2624 | for (i=0; i<4; i++) joint->offset[i] = joint->node[0].body->pos[i]; | ||
2625 | } | ||
2626 | } | ||
2627 | } | ||
2628 | |||
2629 | |||
2630 | dxJoint::Vtable __dfixed_vtable = { | ||
2631 | sizeof(dxJointFixed), | ||
2632 | (dxJoint::init_fn*) fixedInit, | ||
2633 | (dxJoint::getInfo1_fn*) fixedGetInfo1, | ||
2634 | (dxJoint::getInfo2_fn*) fixedGetInfo2, | ||
2635 | dJointTypeFixed}; | ||
2636 | |||
2637 | //**************************************************************************** | ||
2638 | // null joint | ||
2639 | |||
2640 | static void nullGetInfo1 (dxJointNull *j, dxJoint::Info1 *info) | ||
2641 | { | ||
2642 | info->m = 0; | ||
2643 | info->nub = 0; | ||
2644 | } | ||
2645 | |||
2646 | |||
2647 | static void nullGetInfo2 (dxJointNull *joint, dxJoint::Info2 *info) | ||
2648 | { | ||
2649 | dDebug (0,"this should never get called"); | ||
2650 | } | ||
2651 | |||
2652 | |||
2653 | dxJoint::Vtable __dnull_vtable = { | ||
2654 | sizeof(dxJointNull), | ||
2655 | (dxJoint::init_fn*) 0, | ||
2656 | (dxJoint::getInfo1_fn*) nullGetInfo1, | ||
2657 | (dxJoint::getInfo2_fn*) nullGetInfo2, | ||
2658 | dJointTypeNull}; | ||
2659 | |||
2660 | /******************** breakable joint contribution ***********************/ | ||
2661 | extern "C" void dJointSetBreakable (dxJoint *joint, int b) { | ||
2662 | dAASSERT(joint); | ||
2663 | if (b) { | ||
2664 | // we want this joint to be breakable but we must first check if it | ||
2665 | // was already breakable | ||
2666 | if (!joint->breakInfo) { | ||
2667 | // allocate a dxJointBreakInfo struct | ||
2668 | joint->breakInfo = new dxJointBreakInfo; | ||
2669 | joint->breakInfo->flags = 0; | ||
2670 | for (int i = 0; i < 3; i++) { | ||
2671 | joint->breakInfo->b1MaxF[0] = 0; | ||
2672 | joint->breakInfo->b1MaxT[0] = 0; | ||
2673 | joint->breakInfo->b2MaxF[0] = 0; | ||
2674 | joint->breakInfo->b2MaxT[0] = 0; | ||
2675 | } | ||
2676 | joint->breakInfo->callback = 0; | ||
2677 | } | ||
2678 | else { | ||
2679 | // the joint was already breakable | ||
2680 | return; | ||
2681 | } | ||
2682 | } | ||
2683 | else { | ||
2684 | // we want this joint to be unbreakable mut we must first check if | ||
2685 | // it is alreay unbreakable | ||
2686 | if (joint->breakInfo) { | ||
2687 | // deallocate the dxJointBreakInfo struct | ||
2688 | delete joint->breakInfo; | ||
2689 | joint->breakInfo = 0; | ||
2690 | } | ||
2691 | else { | ||
2692 | // the joint was already unbreakable | ||
2693 | return; | ||
2694 | } | ||
2695 | } | ||
2696 | } | ||
2697 | |||
2698 | extern "C" void dJointSetBreakCallback (dxJoint *joint, dJointBreakCallback *callbackFunc) { | ||
2699 | dAASSERT(joint); | ||
2700 | # ifndef dNODEBUG | ||
2701 | // only works for a breakable joint | ||
2702 | if (!joint->breakInfo) { | ||
2703 | dDebug (0, "dJointSetBreakCallback called on unbreakable joint"); | ||
2704 | } | ||
2705 | # endif | ||
2706 | joint->breakInfo->callback = callbackFunc; | ||
2707 | } | ||
2708 | |||
2709 | extern "C" void dJointSetBreakMode (dxJoint *joint, int mode) { | ||
2710 | dAASSERT(joint); | ||
2711 | # ifndef dNODEBUG | ||
2712 | // only works for a breakable joint | ||
2713 | if (!joint->breakInfo) { | ||
2714 | dDebug (0, "dJointSetBreakMode called on unbreakable joint"); | ||
2715 | } | ||
2716 | # endif | ||
2717 | joint->breakInfo->flags = mode; | ||
2718 | } | ||
2719 | |||
2720 | extern "C" int dJointGetBreakMode (dxJoint *joint) { | ||
2721 | dAASSERT(joint); | ||
2722 | # ifndef dNODEBUG | ||
2723 | // only works for a breakable joint | ||
2724 | if (!joint->breakInfo) { | ||
2725 | dDebug (0, "dJointGetBreakMode called on unbreakable joint"); | ||
2726 | } | ||
2727 | # endif | ||
2728 | return joint->breakInfo->flags; | ||
2729 | } | ||
2730 | |||
2731 | extern "C" void dJointSetBreakForce (dxJoint *joint, int body, dReal x, dReal y, dReal z) { | ||
2732 | dAASSERT(joint); | ||
2733 | # ifndef dNODEBUG | ||
2734 | // only works for a breakable joint | ||
2735 | if (!joint->breakInfo) { | ||
2736 | dDebug (0, "dJointSetBreakForce called on unbreakable joint"); | ||
2737 | } | ||
2738 | # endif | ||
2739 | if (body) { | ||
2740 | joint->breakInfo->b2MaxF[0] = x; | ||
2741 | joint->breakInfo->b2MaxF[1] = y; | ||
2742 | joint->breakInfo->b2MaxF[2] = z; | ||
2743 | } | ||
2744 | else { | ||
2745 | joint->breakInfo->b1MaxF[0] = x; | ||
2746 | joint->breakInfo->b1MaxF[1] = y; | ||
2747 | joint->breakInfo->b1MaxF[2] = z; | ||
2748 | } | ||
2749 | } | ||
2750 | |||
2751 | extern "C" void dJointSetBreakTorque (dxJoint *joint, int body, dReal x, dReal y, dReal z) { | ||
2752 | dAASSERT(joint); | ||
2753 | # ifndef dNODEBUG | ||
2754 | // only works for a breakable joint | ||
2755 | if (!joint->breakInfo) { | ||
2756 | dDebug (0, "dJointSetBreakTorque called on unbreakable joint"); | ||
2757 | } | ||
2758 | # endif | ||
2759 | if (body) { | ||
2760 | joint->breakInfo->b2MaxT[0] = x; | ||
2761 | joint->breakInfo->b2MaxT[1] = y; | ||
2762 | joint->breakInfo->b2MaxT[2] = z; | ||
2763 | } | ||
2764 | else { | ||
2765 | joint->breakInfo->b1MaxT[0] = x; | ||
2766 | joint->breakInfo->b1MaxT[1] = y; | ||
2767 | joint->breakInfo->b1MaxT[2] = z; | ||
2768 | } | ||
2769 | } | ||
2770 | |||
2771 | extern "C" int dJointIsBreakable (dxJoint *joint) { | ||
2772 | dAASSERT(joint); | ||
2773 | return joint->breakInfo != 0; | ||
2774 | } | ||
2775 | |||
2776 | extern "C" void dJointGetBreakForce (dxJoint *joint, int body, dReal *force) { | ||
2777 | dAASSERT(joint); | ||
2778 | # ifndef dNODEBUG | ||
2779 | // only works for a breakable joint | ||
2780 | if (!joint->breakInfo) { | ||
2781 | dDebug (0, "dJointGetBreakForce called on unbreakable joint"); | ||
2782 | } | ||
2783 | # endif | ||
2784 | if (body) | ||
2785 | for (int i=0; i<3; i++) force[i]=joint->breakInfo->b2MaxF[i]; | ||
2786 | else | ||
2787 | for (int i=0; i<3; i++) force[i]=joint->breakInfo->b1MaxF[i]; | ||
2788 | } | ||
2789 | |||
2790 | extern "C" void dJointGetBreakTorque (dxJoint *joint, int body, dReal *torque) { | ||
2791 | dAASSERT(joint); | ||
2792 | # ifndef dNODEBUG | ||
2793 | // only works for a breakable joint | ||
2794 | if (!joint->breakInfo) { | ||
2795 | dDebug (0, "dJointGetBreakTorque called on unbreakable joint"); | ||
2796 | } | ||
2797 | # endif | ||
2798 | if (body) | ||
2799 | for (int i=0; i<3; i++) torque[i]=joint->breakInfo->b2MaxT[i]; | ||
2800 | else | ||
2801 | for (int i=0; i<3; i++) torque[i]=joint->breakInfo->b1MaxT[i]; | ||
2802 | } | ||
2803 | /*************************************************************************/ | ||
diff --git a/libraries/ode-0.9/contrib/BreakableJoints/joint.h b/libraries/ode-0.9/contrib/BreakableJoints/joint.h new file mode 100644 index 0000000..0573119 --- /dev/null +++ b/libraries/ode-0.9/contrib/BreakableJoints/joint.h | |||
@@ -0,0 +1,282 @@ | |||
1 | /************************************************************************* | ||
2 | * * | ||
3 | * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * | ||
4 | * All rights reserved. Email: russ@q12.org Web: www.q12.org * | ||
5 | * * | ||
6 | * This library is free software; you can redistribute it and/or * | ||
7 | * modify it under the terms of EITHER: * | ||
8 | * (1) The GNU Lesser General Public License as published by the Free * | ||
9 | * Software Foundation; either version 2.1 of the License, or (at * | ||
10 | * your option) any later version. The text of the GNU Lesser * | ||
11 | * General Public License is included with this library in the * | ||
12 | * file LICENSE.TXT. * | ||
13 | * (2) The BSD-style license that is included with this library in * | ||
14 | * the file LICENSE-BSD.TXT. * | ||
15 | * * | ||
16 | * This library is distributed in the hope that it will be useful, * | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * | ||
19 | * LICENSE.TXT and LICENSE-BSD.TXT for more details. * | ||
20 | * * | ||
21 | *************************************************************************/ | ||
22 | |||
23 | #ifndef _ODE_JOINT_H_ | ||
24 | #define _ODE_JOINT_H_ | ||
25 | |||
26 | |||
27 | #include "objects.h" | ||
28 | #include <ode/contact.h> | ||
29 | #include "obstack.h" | ||
30 | |||
31 | |||
32 | // joint flags | ||
33 | enum { | ||
34 | // if this flag is set, the joint was allocated in a joint group | ||
35 | dJOINT_INGROUP = 1, | ||
36 | |||
37 | // if this flag is set, the joint was attached with arguments (0,body). | ||
38 | // our convention is to treat all attaches as (body,0), i.e. so node[0].body | ||
39 | // is always nonzero, so this flag records the fact that the arguments were | ||
40 | // swapped. | ||
41 | dJOINT_REVERSE = 2, | ||
42 | |||
43 | // if this flag is set, the joint can not have just one body attached to it, | ||
44 | // it must have either zero or two bodies attached. | ||
45 | dJOINT_TWOBODIES = 4 | ||
46 | }; | ||
47 | |||
48 | |||
49 | // there are two of these nodes in the joint, one for each connection to a | ||
50 | // body. these are node of a linked list kept by each body of it's connecting | ||
51 | // joints. but note that the body pointer in each node points to the body that | ||
52 | // makes use of the *other* node, not this node. this trick makes it a bit | ||
53 | // easier to traverse the body/joint graph. | ||
54 | |||
55 | struct dxJointNode { | ||
56 | dxJoint *joint; // pointer to enclosing dxJoint object | ||
57 | dxBody *body; // *other* body this joint is connected to | ||
58 | dxJointNode *next; // next node in body's list of connected joints | ||
59 | }; | ||
60 | |||
61 | /******************** breakable joint contribution ***********************/ | ||
62 | struct dxJointBreakInfo : public dBase { | ||
63 | int flags; | ||
64 | dReal b1MaxF[3]; // maximum force on body 1 | ||
65 | dReal b1MaxT[3]; // maximum torque on body 1 | ||
66 | dReal b2MaxF[3]; // maximum force on body 2 | ||
67 | dReal b2MaxT[3]; // maximum torque on body 2 | ||
68 | dJointBreakCallback *callback; // function that is called when this joint breaks | ||
69 | }; | ||
70 | /*************************************************************************/ | ||
71 | |||
72 | struct dxJoint : public dObject { | ||
73 | // naming convention: the "first" body this is connected to is node[0].body, | ||
74 | // and the "second" body is node[1].body. if this joint is only connected | ||
75 | // to one body then the second body is 0. | ||
76 | |||
77 | // info returned by getInfo1 function. the constraint dimension is m (<=6). | ||
78 | // i.e. that is the total number of rows in the jacobian. `nub' is the | ||
79 | // number of unbounded variables (which have lo,hi = -/+ infinity). | ||
80 | |||
81 | struct Info1 { | ||
82 | int m,nub; | ||
83 | }; | ||
84 | |||
85 | // info returned by getInfo2 function | ||
86 | |||
87 | struct Info2 { | ||
88 | // integrator parameters: frames per second (1/stepsize), default error | ||
89 | // reduction parameter (0..1). | ||
90 | dReal fps,erp; | ||
91 | |||
92 | // for the first and second body, pointers to two (linear and angular) | ||
93 | // n*3 jacobian sub matrices, stored by rows. these matrices will have | ||
94 | // been initialized to 0 on entry. if the second body is zero then the | ||
95 | // J2xx pointers may be 0. | ||
96 | dReal *J1l,*J1a,*J2l,*J2a; | ||
97 | |||
98 | // elements to jump from one row to the next in J's | ||
99 | int rowskip; | ||
100 | |||
101 | // right hand sides of the equation J*v = c + cfm * lambda. cfm is the | ||
102 | // "constraint force mixing" vector. c is set to zero on entry, cfm is | ||
103 | // set to a constant value (typically very small or zero) value on entry. | ||
104 | dReal *c,*cfm; | ||
105 | |||
106 | // lo and hi limits for variables (set to -/+ infinity on entry). | ||
107 | dReal *lo,*hi; | ||
108 | |||
109 | // findex vector for variables. see the LCP solver interface for a | ||
110 | // description of what this does. this is set to -1 on entry. | ||
111 | // note that the returned indexes are relative to the first index of | ||
112 | // the constraint. | ||
113 | int *findex; | ||
114 | }; | ||
115 | |||
116 | // virtual function table: size of the joint structure, function pointers. | ||
117 | // we do it this way instead of using C++ virtual functions because | ||
118 | // sometimes we need to allocate joints ourself within a memory pool. | ||
119 | |||
120 | typedef void init_fn (dxJoint *joint); | ||
121 | typedef void getInfo1_fn (dxJoint *joint, Info1 *info); | ||
122 | typedef void getInfo2_fn (dxJoint *joint, Info2 *info); | ||
123 | struct Vtable { | ||
124 | int size; | ||
125 | init_fn *init; | ||
126 | getInfo1_fn *getInfo1; | ||
127 | getInfo2_fn *getInfo2; | ||
128 | int typenum; // a dJointTypeXXX type number | ||
129 | }; | ||
130 | |||
131 | Vtable *vtable; // virtual function table | ||
132 | int flags; // dJOINT_xxx flags | ||
133 | dxJointNode node[2]; // connections to bodies. node[1].body can be 0 | ||
134 | dJointFeedback *feedback; // optional feedback structure | ||
135 | |||
136 | /******************** breakable joint contribution ***********************/ | ||
137 | // optional break info structure. if this is not NULL the the joint is | ||
138 | // breakable. | ||
139 | dxJointBreakInfo *breakInfo; | ||
140 | /*************************************************************************/ | ||
141 | }; | ||
142 | |||
143 | |||
144 | // joint group. NOTE: any joints in the group that have their world destroyed | ||
145 | // will have their world pointer set to 0. | ||
146 | |||
147 | struct dxJointGroup : public dBase { | ||
148 | int num; // number of joints on the stack | ||
149 | dObStack stack; // a stack of (possibly differently sized) dxJoint | ||
150 | }; // objects. | ||
151 | |||
152 | |||
153 | // common limit and motor information for a single joint axis of movement | ||
154 | struct dxJointLimitMotor { | ||
155 | dReal vel,fmax; // powered joint: velocity, max force | ||
156 | dReal lostop,histop; // joint limits, relative to initial position | ||
157 | dReal fudge_factor; // when powering away from joint limits | ||
158 | dReal normal_cfm; // cfm to use when not at a stop | ||
159 | dReal stop_erp,stop_cfm; // erp and cfm for when at joint limit | ||
160 | dReal bounce; // restitution factor | ||
161 | // variables used between getInfo1() and getInfo2() | ||
162 | int limit; // 0=free, 1=at lo limit, 2=at hi limit | ||
163 | dReal limit_err; // if at limit, amount over limit | ||
164 | |||
165 | void init (dxWorld *); | ||
166 | void set (int num, dReal value); | ||
167 | dReal get (int num); | ||
168 | int testRotationalLimit (dReal angle); | ||
169 | int addLimot (dxJoint *joint, dxJoint::Info2 *info, int row, | ||
170 | dVector3 ax1, int rotational); | ||
171 | }; | ||
172 | |||
173 | |||
174 | // ball and socket | ||
175 | |||
176 | struct dxJointBall : public dxJoint { | ||
177 | dVector3 anchor1; // anchor w.r.t first body | ||
178 | dVector3 anchor2; // anchor w.r.t second body | ||
179 | }; | ||
180 | extern struct dxJoint::Vtable __dball_vtable; | ||
181 | |||
182 | |||
183 | // hinge | ||
184 | |||
185 | struct dxJointHinge : public dxJoint { | ||
186 | dVector3 anchor1; // anchor w.r.t first body | ||
187 | dVector3 anchor2; // anchor w.r.t second body | ||
188 | dVector3 axis1; // axis w.r.t first body | ||
189 | dVector3 axis2; // axis w.r.t second body | ||
190 | dQuaternion qrel; // initial relative rotation body1 -> body2 | ||
191 | dxJointLimitMotor limot; // limit and motor information | ||
192 | }; | ||
193 | extern struct dxJoint::Vtable __dhinge_vtable; | ||
194 | |||
195 | |||
196 | // universal | ||
197 | |||
198 | struct dxJointUniversal : public dxJoint { | ||
199 | dVector3 anchor1; // anchor w.r.t first body | ||
200 | dVector3 anchor2; // anchor w.r.t second body | ||
201 | dVector3 axis1; // axis w.r.t first body | ||
202 | dVector3 axis2; // axis w.r.t second body | ||
203 | dQuaternion qrel1; // initial relative rotation body1 -> virtual cross piece | ||
204 | dQuaternion qrel2; // initial relative rotation virtual cross piece -> body2 | ||
205 | dxJointLimitMotor limot1; // limit and motor information for axis1 | ||
206 | dxJointLimitMotor limot2; // limit and motor information for axis2 | ||
207 | }; | ||
208 | extern struct dxJoint::Vtable __duniversal_vtable; | ||
209 | |||
210 | |||
211 | // slider. if body2 is 0 then qrel is the absolute rotation of body1 and | ||
212 | // offset is the position of body1 center along axis1. | ||
213 | |||
214 | struct dxJointSlider : public dxJoint { | ||
215 | dVector3 axis1; // axis w.r.t first body | ||
216 | dQuaternion qrel; // initial relative rotation body1 -> body2 | ||
217 | dVector3 offset; // point relative to body2 that should be | ||
218 | // aligned with body1 center along axis1 | ||
219 | dxJointLimitMotor limot; // limit and motor information | ||
220 | }; | ||
221 | extern struct dxJoint::Vtable __dslider_vtable; | ||
222 | |||
223 | |||
224 | // contact | ||
225 | |||
226 | struct dxJointContact : public dxJoint { | ||
227 | int the_m; // number of rows computed by getInfo1 | ||
228 | dContact contact; | ||
229 | }; | ||
230 | extern struct dxJoint::Vtable __dcontact_vtable; | ||
231 | |||
232 | |||
233 | // hinge 2 | ||
234 | |||
235 | struct dxJointHinge2 : public dxJoint { | ||
236 | dVector3 anchor1; // anchor w.r.t first body | ||
237 | dVector3 anchor2; // anchor w.r.t second body | ||
238 | dVector3 axis1; // axis 1 w.r.t first body | ||
239 | dVector3 axis2; // axis 2 w.r.t second body | ||
240 | dReal c0,s0; // cos,sin of desired angle between axis 1,2 | ||
241 | dVector3 v1,v2; // angle ref vectors embedded in first body | ||
242 | dxJointLimitMotor limot1; // limit+motor info for axis 1 | ||
243 | dxJointLimitMotor limot2; // limit+motor info for axis 2 | ||
244 | dReal susp_erp,susp_cfm; // suspension parameters (erp,cfm) | ||
245 | }; | ||
246 | extern struct dxJoint::Vtable __dhinge2_vtable; | ||
247 | |||
248 | |||
249 | // angular motor | ||
250 | |||
251 | struct dxJointAMotor : public dxJoint { | ||
252 | int num; // number of axes (0..3) | ||
253 | int mode; // a dAMotorXXX constant | ||
254 | int rel[3]; // what the axes are relative to (global,b1,b2) | ||
255 | dVector3 axis[3]; // three axes | ||
256 | dxJointLimitMotor limot[3]; // limit+motor info for axes | ||
257 | dReal angle[3]; // user-supplied angles for axes | ||
258 | // these vectors are used for calculating euler angles | ||
259 | dVector3 reference1; // original axis[2], relative to body 1 | ||
260 | dVector3 reference2; // original axis[0], relative to body 2 | ||
261 | }; | ||
262 | extern struct dxJoint::Vtable __damotor_vtable; | ||
263 | |||
264 | |||
265 | // fixed | ||
266 | |||
267 | struct dxJointFixed : public dxJoint { | ||
268 | dQuaternion qrel; // initial relative rotation body1 -> body2 | ||
269 | dVector3 offset; // relative offset between the bodies | ||
270 | }; | ||
271 | extern struct dxJoint::Vtable __dfixed_vtable; | ||
272 | |||
273 | |||
274 | // null joint, for testing only | ||
275 | |||
276 | struct dxJointNull : public dxJoint { | ||
277 | }; | ||
278 | extern struct dxJoint::Vtable __dnull_vtable; | ||
279 | |||
280 | |||
281 | |||
282 | #endif | ||
diff --git a/libraries/ode-0.9/contrib/BreakableJoints/objects.h b/libraries/ode-0.9/contrib/BreakableJoints/objects.h new file mode 100644 index 0000000..de08391 --- /dev/null +++ b/libraries/ode-0.9/contrib/BreakableJoints/objects.h | |||
@@ -0,0 +1,252 @@ | |||
1 | /************************************************************************* | ||
2 | * * | ||
3 | * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * | ||
4 | * All rights reserved. Email: russ@q12.org Web: www.q12.org * | ||
5 | * * | ||
6 | * This library is free software; you can redistribute it and/or * | ||
7 | * modify it under the terms of EITHER: * | ||
8 | * (1) The GNU Lesser General Public License as published by the Free * | ||
9 | * Software Foundation; either version 2.1 of the License, or (at * | ||
10 | * your option) any later version. The text of the GNU Lesser * | ||
11 | * General Public License is included with this library in the * | ||
12 | * file LICENSE.TXT. * | ||
13 | * (2) The BSD-style license that is included with this library in * | ||
14 | * the file LICENSE-BSD.TXT. * | ||
15 | * * | ||
16 | * This library is distributed in the hope that it will be useful, * | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * | ||
19 | * LICENSE.TXT and LICENSE-BSD.TXT for more details. * | ||
20 | * * | ||
21 | *************************************************************************/ | ||
22 | |||
23 | #ifndef _ODE_OBJECTS_H_ | ||
24 | #define _ODE_OBJECTS_H_ | ||
25 | |||
26 | #include <ode/common.h> | ||
27 | #include <ode/mass.h> | ||
28 | #include <ode/contact.h> | ||
29 | |||
30 | #ifdef __cplusplus | ||
31 | extern "C" { | ||
32 | #endif | ||
33 | |||
34 | /* world */ | ||
35 | |||
36 | dWorldID dWorldCreate(); | ||
37 | void dWorldDestroy (dWorldID); | ||
38 | |||
39 | void dWorldSetGravity (dWorldID, dReal x, dReal y, dReal z); | ||
40 | void dWorldGetGravity (dWorldID, dVector3 gravity); | ||
41 | void dWorldSetERP (dWorldID, dReal erp); | ||
42 | dReal dWorldGetERP (dWorldID); | ||
43 | void dWorldSetCFM (dWorldID, dReal cfm); | ||
44 | dReal dWorldGetCFM (dWorldID); | ||
45 | void dWorldStep (dWorldID, dReal stepsize); | ||
46 | void dWorldImpulseToForce (dWorldID, dReal stepsize, | ||
47 | dReal ix, dReal iy, dReal iz, dVector3 force); | ||
48 | |||
49 | /* StepFast1 functions */ | ||
50 | |||
51 | void dWorldStepFast1(dWorldID, dReal stepsize, int maxiterations); | ||
52 | void dWorldSetAutoEnableDepthSF1(dWorldID, int autoEnableDepth); | ||
53 | |||
54 | int dWorldGetAutoEnableDepthSF1(dWorldID); | ||
55 | |||
56 | void dBodySetAutoDisableThresholdSF1(dBodyID, dReal autoDisableThreshold); | ||
57 | |||
58 | /* These functions are not yet implemented by ODE. */ | ||
59 | /* | ||
60 | dReal dBodyGetAutoDisableThresholdSF1(dBodyID); | ||
61 | |||
62 | void dBodySetAutoDisableStepsSF1(dBodyID, int AutoDisableSteps); | ||
63 | |||
64 | int dBodyGetAutoDisableStepsSF1(dBodyID); | ||
65 | |||
66 | void dBodySetAutoDisableSF1(dBodyID, int doAutoDisable); | ||
67 | |||
68 | int dBodyGetAutoDisableSF1(dBodyID); | ||
69 | */ | ||
70 | |||
71 | /* bodies */ | ||
72 | |||
73 | dBodyID dBodyCreate (dWorldID); | ||
74 | void dBodyDestroy (dBodyID); | ||
75 | |||
76 | void dBodySetData (dBodyID, void *data); | ||
77 | void *dBodyGetData (dBodyID); | ||
78 | |||
79 | void dBodySetPosition (dBodyID, dReal x, dReal y, dReal z); | ||
80 | void dBodySetRotation (dBodyID, const dMatrix3 R); | ||
81 | void dBodySetQuaternion (dBodyID, const dQuaternion q); | ||
82 | void dBodySetLinearVel (dBodyID, dReal x, dReal y, dReal z); | ||
83 | void dBodySetAngularVel (dBodyID, dReal x, dReal y, dReal z); | ||
84 | const dReal * dBodyGetPosition (dBodyID); | ||
85 | const dReal * dBodyGetRotation (dBodyID); /* ptr to 4x3 rot matrix */ | ||
86 | const dReal * dBodyGetQuaternion (dBodyID); | ||
87 | const dReal * dBodyGetLinearVel (dBodyID); | ||
88 | const dReal * dBodyGetAngularVel (dBodyID); | ||
89 | |||
90 | void dBodySetMass (dBodyID, const dMass *mass); | ||
91 | void dBodyGetMass (dBodyID, dMass *mass); | ||
92 | |||
93 | void dBodyAddForce (dBodyID, dReal fx, dReal fy, dReal fz); | ||
94 | void dBodyAddTorque (dBodyID, dReal fx, dReal fy, dReal fz); | ||
95 | void dBodyAddRelForce (dBodyID, dReal fx, dReal fy, dReal fz); | ||
96 | void dBodyAddRelTorque (dBodyID, dReal fx, dReal fy, dReal fz); | ||
97 | void dBodyAddForceAtPos (dBodyID, dReal fx, dReal fy, dReal fz, | ||
98 | dReal px, dReal py, dReal pz); | ||
99 | void dBodyAddForceAtRelPos (dBodyID, dReal fx, dReal fy, dReal fz, | ||
100 | dReal px, dReal py, dReal pz); | ||
101 | void dBodyAddRelForceAtPos (dBodyID, dReal fx, dReal fy, dReal fz, | ||
102 | dReal px, dReal py, dReal pz); | ||
103 | void dBodyAddRelForceAtRelPos (dBodyID, dReal fx, dReal fy, dReal fz, | ||
104 | dReal px, dReal py, dReal pz); | ||
105 | |||
106 | const dReal * dBodyGetForce (dBodyID); | ||
107 | const dReal * dBodyGetTorque (dBodyID); | ||
108 | void dBodySetForce (dBodyID b, dReal x, dReal y, dReal z); | ||
109 | void dBodySetTorque (dBodyID b, dReal x, dReal y, dReal z); | ||
110 | |||
111 | void dBodyGetRelPointPos (dBodyID, dReal px, dReal py, dReal pz, | ||
112 | dVector3 result); | ||
113 | void dBodyGetRelPointVel (dBodyID, dReal px, dReal py, dReal pz, | ||
114 | dVector3 result); | ||
115 | void dBodyGetPointVel (dBodyID, dReal px, dReal py, dReal pz, | ||
116 | dVector3 result); | ||
117 | void dBodyGetPosRelPoint (dBodyID, dReal px, dReal py, dReal pz, | ||
118 | dVector3 result); | ||
119 | void dBodyVectorToWorld (dBodyID, dReal px, dReal py, dReal pz, | ||
120 | dVector3 result); | ||
121 | void dBodyVectorFromWorld (dBodyID, dReal px, dReal py, dReal pz, | ||
122 | dVector3 result); | ||
123 | |||
124 | void dBodySetFiniteRotationMode (dBodyID, int mode); | ||
125 | void dBodySetFiniteRotationAxis (dBodyID, dReal x, dReal y, dReal z); | ||
126 | |||
127 | int dBodyGetFiniteRotationMode (dBodyID); | ||
128 | void dBodyGetFiniteRotationAxis (dBodyID, dVector3 result); | ||
129 | |||
130 | int dBodyGetNumJoints (dBodyID b); | ||
131 | dJointID dBodyGetJoint (dBodyID, int index); | ||
132 | |||
133 | void dBodyEnable (dBodyID); | ||
134 | void dBodyDisable (dBodyID); | ||
135 | int dBodyIsEnabled (dBodyID); | ||
136 | |||
137 | void dBodySetGravityMode (dBodyID b, int mode); | ||
138 | int dBodyGetGravityMode (dBodyID b); | ||
139 | |||
140 | |||
141 | /* joints */ | ||
142 | |||
143 | dJointID dJointCreateBall (dWorldID, dJointGroupID); | ||
144 | dJointID dJointCreateHinge (dWorldID, dJointGroupID); | ||
145 | dJointID dJointCreateSlider (dWorldID, dJointGroupID); | ||
146 | dJointID dJointCreateContact (dWorldID, dJointGroupID, const dContact *); | ||
147 | dJointID dJointCreateHinge2 (dWorldID, dJointGroupID); | ||
148 | dJointID dJointCreateUniversal (dWorldID, dJointGroupID); | ||
149 | dJointID dJointCreateFixed (dWorldID, dJointGroupID); | ||
150 | dJointID dJointCreateNull (dWorldID, dJointGroupID); | ||
151 | dJointID dJointCreateAMotor (dWorldID, dJointGroupID); | ||
152 | |||
153 | void dJointDestroy (dJointID); | ||
154 | |||
155 | dJointGroupID dJointGroupCreate (int max_size); | ||
156 | void dJointGroupDestroy (dJointGroupID); | ||
157 | void dJointGroupEmpty (dJointGroupID); | ||
158 | |||
159 | void dJointAttach (dJointID, dBodyID body1, dBodyID body2); | ||
160 | void dJointSetData (dJointID, void *data); | ||
161 | void *dJointGetData (dJointID); | ||
162 | int dJointGetType (dJointID); | ||
163 | dBodyID dJointGetBody (dJointID, int index); | ||
164 | |||
165 | void dJointSetFeedback (dJointID, dJointFeedback *); | ||
166 | dJointFeedback *dJointGetFeedback (dJointID); | ||
167 | |||
168 | /******************** breakable joint contribution ***********************/ | ||
169 | void dJointSetBreakable (dJointID, int b); | ||
170 | void dJointSetBreakCallback (dJointID, dJointBreakCallback *callbackFunc); | ||
171 | void dJointSetBreakMode (dJointID, int mode); | ||
172 | int dJointGetBreakMode (dJointID); | ||
173 | void dJointSetBreakForce (dJointID, int body, dReal x, dReal y, dReal z); | ||
174 | void dJointSetBreakTorque (dJointID, int body, dReal x, dReal y, dReal z); | ||
175 | int dJointIsBreakable (dJointID); | ||
176 | void dJointGetBreakForce (dJointID, int body, dReal *force); | ||
177 | void dJointGetBreakTorque (dJointID, int body, dReal *torque); | ||
178 | /*************************************************************************/ | ||
179 | |||
180 | void dJointSetBallAnchor (dJointID, dReal x, dReal y, dReal z); | ||
181 | void dJointSetHingeAnchor (dJointID, dReal x, dReal y, dReal z); | ||
182 | void dJointSetHingeAxis (dJointID, dReal x, dReal y, dReal z); | ||
183 | void dJointSetHingeParam (dJointID, int parameter, dReal value); | ||
184 | void dJointAddHingeTorque(dJointID joint, dReal torque); | ||
185 | void dJointSetSliderAxis (dJointID, dReal x, dReal y, dReal z); | ||
186 | void dJointSetSliderParam (dJointID, int parameter, dReal value); | ||
187 | void dJointAddSliderForce(dJointID joint, dReal force); | ||
188 | void dJointSetHinge2Anchor (dJointID, dReal x, dReal y, dReal z); | ||
189 | void dJointSetHinge2Axis1 (dJointID, dReal x, dReal y, dReal z); | ||
190 | void dJointSetHinge2Axis2 (dJointID, dReal x, dReal y, dReal z); | ||
191 | void dJointSetHinge2Param (dJointID, int parameter, dReal value); | ||
192 | void dJointAddHinge2Torques(dJointID joint, dReal torque1, dReal torque2); | ||
193 | void dJointSetUniversalAnchor (dJointID, dReal x, dReal y, dReal z); | ||
194 | void dJointSetUniversalAxis1 (dJointID, dReal x, dReal y, dReal z); | ||
195 | void dJointSetUniversalAxis2 (dJointID, dReal x, dReal y, dReal z); | ||
196 | void dJointSetUniversalParam (dJointID, int parameter, dReal value); | ||
197 | void dJointAddUniversalTorques(dJointID joint, dReal torque1, dReal torque2); | ||
198 | void dJointSetFixed (dJointID); | ||
199 | void dJointSetAMotorNumAxes (dJointID, int num); | ||
200 | void dJointSetAMotorAxis (dJointID, int anum, int rel, | ||
201 | dReal x, dReal y, dReal z); | ||
202 | void dJointSetAMotorAngle (dJointID, int anum, dReal angle); | ||
203 | void dJointSetAMotorParam (dJointID, int parameter, dReal value); | ||
204 | void dJointSetAMotorMode (dJointID, int mode); | ||
205 | void dJointAddAMotorTorques (dJointID, dReal torque1, dReal torque2, dReal torque3); | ||
206 | |||
207 | void dJointGetBallAnchor (dJointID, dVector3 result); | ||
208 | void dJointGetBallAnchor2 (dJointID, dVector3 result); | ||
209 | void dJointGetHingeAnchor (dJointID, dVector3 result); | ||
210 | void dJointGetHingeAnchor2 (dJointID, dVector3 result); | ||
211 | void dJointGetHingeAxis (dJointID, dVector3 result); | ||
212 | dReal dJointGetHingeParam (dJointID, int parameter); | ||
213 | dReal dJointGetHingeAngle (dJointID); | ||
214 | dReal dJointGetHingeAngleRate (dJointID); | ||
215 | dReal dJointGetSliderPosition (dJointID); | ||
216 | dReal dJointGetSliderPositionRate (dJointID); | ||
217 | void dJointGetSliderAxis (dJointID, dVector3 result); | ||
218 | dReal dJointGetSliderParam (dJointID, int parameter); | ||
219 | void dJointGetHinge2Anchor (dJointID, dVector3 result); | ||
220 | void dJointGetHinge2Anchor2 (dJointID, dVector3 result); | ||
221 | void dJointGetHinge2Axis1 (dJointID, dVector3 result); | ||
222 | void dJointGetHinge2Axis2 (dJointID, dVector3 result); | ||
223 | dReal dJointGetHinge2Param (dJointID, int parameter); | ||
224 | dReal dJointGetHinge2Angle1 (dJointID); | ||
225 | dReal dJointGetHinge2Angle1Rate (dJointID); | ||
226 | dReal dJointGetHinge2Angle2Rate (dJointID); | ||
227 | void dJointGetUniversalAnchor (dJointID, dVector3 result); | ||
228 | void dJointGetUniversalAnchor2 (dJointID, dVector3 result); | ||
229 | void dJointGetUniversalAxis1 (dJointID, dVector3 result); | ||
230 | void dJointGetUniversalAxis2 (dJointID, dVector3 result); | ||
231 | dReal dJointGetUniversalParam (dJointID, int parameter); | ||
232 | dReal dJointGetUniversalAngle1 (dJointID); | ||
233 | dReal dJointGetUniversalAngle2 (dJointID); | ||
234 | dReal dJointGetUniversalAngle1Rate (dJointID); | ||
235 | dReal dJointGetUniversalAngle2Rate (dJointID); | ||
236 | int dJointGetAMotorNumAxes (dJointID); | ||
237 | void dJointGetAMotorAxis (dJointID, int anum, dVector3 result); | ||
238 | int dJointGetAMotorAxisRel (dJointID, int anum); | ||
239 | dReal dJointGetAMotorAngle (dJointID, int anum); | ||
240 | dReal dJointGetAMotorAngleRate (dJointID, int anum); | ||
241 | dReal dJointGetAMotorParam (dJointID, int parameter); | ||
242 | int dJointGetAMotorMode (dJointID); | ||
243 | |||
244 | int dAreConnected (dBodyID, dBodyID); | ||
245 | int dAreConnectedExcluding (dBodyID, dBodyID, int joint_type); | ||
246 | |||
247 | |||
248 | #ifdef __cplusplus | ||
249 | } | ||
250 | #endif | ||
251 | |||
252 | #endif | ||
diff --git a/libraries/ode-0.9/contrib/BreakableJoints/ode.cpp b/libraries/ode-0.9/contrib/BreakableJoints/ode.cpp new file mode 100644 index 0000000..7137960 --- /dev/null +++ b/libraries/ode-0.9/contrib/BreakableJoints/ode.cpp | |||
@@ -0,0 +1,1404 @@ | |||
1 | /************************************************************************* | ||
2 | * * | ||
3 | * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * | ||
4 | * All rights reserved. Email: russ@q12.org Web: www.q12.org * | ||
5 | * * | ||
6 | * This library is free software; you can redistribute it and/or * | ||
7 | * modify it under the terms of EITHER: * | ||
8 | * (1) The GNU Lesser General Public License as published by the Free * | ||
9 | * Software Foundation; either version 2.1 of the License, or (at * | ||
10 | * your option) any later version. The text of the GNU Lesser * | ||
11 | * General Public License is included with this library in the * | ||
12 | * file LICENSE.TXT. * | ||
13 | * (2) The BSD-style license that is included with this library in * | ||
14 | * the file LICENSE-BSD.TXT. * | ||
15 | * * | ||
16 | * This library is distributed in the hope that it will be useful, * | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * | ||
19 | * LICENSE.TXT and LICENSE-BSD.TXT for more details. * | ||
20 | * * | ||
21 | *************************************************************************/ | ||
22 | |||
23 | #ifdef _MSC_VER | ||
24 | #pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found" | ||
25 | #endif | ||
26 | |||
27 | // this source file is mostly concerned with the data structures, not the | ||
28 | // numerics. | ||
29 | |||
30 | #include "objects.h" | ||
31 | #include <ode/ode.h> | ||
32 | #include "joint.h" | ||
33 | #include <ode/odemath.h> | ||
34 | #include <ode/matrix.h> | ||
35 | #include "step.h" | ||
36 | #include <ode/memory.h> | ||
37 | #include <ode/error.h> | ||
38 | |||
39 | // misc defines | ||
40 | #define ALLOCA dALLOCA16 | ||
41 | |||
42 | //**************************************************************************** | ||
43 | // utility | ||
44 | |||
45 | static inline void initObject (dObject *obj, dxWorld *w) | ||
46 | { | ||
47 | obj->world = w; | ||
48 | obj->next = 0; | ||
49 | obj->tome = 0; | ||
50 | obj->userdata = 0; | ||
51 | obj->tag = 0; | ||
52 | } | ||
53 | |||
54 | |||
55 | // add an object `obj' to the list who's head pointer is pointed to by `first'. | ||
56 | |||
57 | static inline void addObjectToList (dObject *obj, dObject **first) | ||
58 | { | ||
59 | obj->next = *first; | ||
60 | obj->tome = first; | ||
61 | if (*first) (*first)->tome = &obj->next; | ||
62 | (*first) = obj; | ||
63 | } | ||
64 | |||
65 | |||
66 | // remove the object from the linked list | ||
67 | |||
68 | static inline void removeObjectFromList (dObject *obj) | ||
69 | { | ||
70 | if (obj->next) obj->next->tome = obj->tome; | ||
71 | *(obj->tome) = obj->next; | ||
72 | // safeguard | ||
73 | obj->next = 0; | ||
74 | obj->tome = 0; | ||
75 | } | ||
76 | |||
77 | |||
78 | // remove the joint from neighbour lists of all connected bodies | ||
79 | |||
80 | static void removeJointReferencesFromAttachedBodies (dxJoint *j) | ||
81 | { | ||
82 | for (int i=0; i<2; i++) { | ||
83 | dxBody *body = j->node[i].body; | ||
84 | if (body) { | ||
85 | dxJointNode *n = body->firstjoint; | ||
86 | dxJointNode *last = 0; | ||
87 | while (n) { | ||
88 | if (n->joint == j) { | ||
89 | if (last) last->next = n->next; | ||
90 | else body->firstjoint = n->next; | ||
91 | break; | ||
92 | } | ||
93 | last = n; | ||
94 | n = n->next; | ||
95 | } | ||
96 | } | ||
97 | } | ||
98 | j->node[0].body = 0; | ||
99 | j->node[0].next = 0; | ||
100 | j->node[1].body = 0; | ||
101 | j->node[1].next = 0; | ||
102 | } | ||
103 | |||
104 | //**************************************************************************** | ||
105 | // island processing | ||
106 | |||
107 | // this groups all joints and bodies in a world into islands. all objects | ||
108 | // in an island are reachable by going through connected bodies and joints. | ||
109 | // each island can be simulated separately. | ||
110 | // note that joints that are not attached to anything will not be included | ||
111 | // in any island, an so they do not affect the simulation. | ||
112 | // | ||
113 | // this function starts new island from unvisited bodies. however, it will | ||
114 | // never start a new islands from a disabled body. thus islands of disabled | ||
115 | // bodies will not be included in the simulation. disabled bodies are | ||
116 | // re-enabled if they are found to be part of an active island. | ||
117 | |||
118 | static void processIslands (dxWorld *world, dReal stepsize) | ||
119 | { | ||
120 | dxBody *b,*bb,**body; | ||
121 | dxJoint *j,**joint; | ||
122 | |||
123 | // nothing to do if no bodies | ||
124 | if (world->nb <= 0) return; | ||
125 | |||
126 | // make arrays for body and joint lists (for a single island) to go into | ||
127 | body = (dxBody**) ALLOCA (world->nb * sizeof(dxBody*)); | ||
128 | joint = (dxJoint**) ALLOCA (world->nj * sizeof(dxJoint*)); | ||
129 | int bcount = 0; // number of bodies in `body' | ||
130 | int jcount = 0; // number of joints in `joint' | ||
131 | |||
132 | // set all body/joint tags to 0 | ||
133 | for (b=world->firstbody; b; b=(dxBody*)b->next) b->tag = 0; | ||
134 | for (j=world->firstjoint; j; j=(dxJoint*)j->next) j->tag = 0; | ||
135 | |||
136 | // allocate a stack of unvisited bodies in the island. the maximum size of | ||
137 | // the stack can be the lesser of the number of bodies or joints, because | ||
138 | // new bodies are only ever added to the stack by going through untagged | ||
139 | // joints. all the bodies in the stack must be tagged! | ||
140 | int stackalloc = (world->nj < world->nb) ? world->nj : world->nb; | ||
141 | dxBody **stack = (dxBody**) ALLOCA (stackalloc * sizeof(dxBody*)); | ||
142 | |||
143 | for (bb=world->firstbody; bb; bb=(dxBody*)bb->next) { | ||
144 | // get bb = the next enabled, untagged body, and tag it | ||
145 | if (bb->tag || (bb->flags & dxBodyDisabled)) continue; | ||
146 | bb->tag = 1; | ||
147 | |||
148 | // tag all bodies and joints starting from bb. | ||
149 | int stacksize = 0; | ||
150 | b = bb; | ||
151 | body[0] = bb; | ||
152 | bcount = 1; | ||
153 | jcount = 0; | ||
154 | goto quickstart; | ||
155 | while (stacksize > 0) { | ||
156 | b = stack[--stacksize]; // pop body off stack | ||
157 | body[bcount++] = b; // put body on body list | ||
158 | quickstart: | ||
159 | |||
160 | // traverse and tag all body's joints, add untagged connected bodies | ||
161 | // to stack | ||
162 | for (dxJointNode *n=b->firstjoint; n; n=n->next) { | ||
163 | if (!n->joint->tag) { | ||
164 | n->joint->tag = 1; | ||
165 | joint[jcount++] = n->joint; | ||
166 | if (n->body && !n->body->tag) { | ||
167 | n->body->tag = 1; | ||
168 | stack[stacksize++] = n->body; | ||
169 | } | ||
170 | } | ||
171 | } | ||
172 | dIASSERT(stacksize <= world->nb); | ||
173 | dIASSERT(stacksize <= world->nj); | ||
174 | } | ||
175 | |||
176 | // now do something with body and joint lists | ||
177 | dInternalStepIsland (world,body,bcount,joint,jcount,stepsize); | ||
178 | |||
179 | // what we've just done may have altered the body/joint tag values. | ||
180 | // we must make sure that these tags are nonzero. | ||
181 | // also make sure all bodies are in the enabled state. | ||
182 | int i; | ||
183 | for (i=0; i<bcount; i++) { | ||
184 | body[i]->tag = 1; | ||
185 | body[i]->flags &= ~dxBodyDisabled; | ||
186 | } | ||
187 | for (i=0; i<jcount; i++) joint[i]->tag = 1; | ||
188 | } | ||
189 | |||
190 | // if debugging, check that all objects (except for disabled bodies, | ||
191 | // unconnected joints, and joints that are connected to disabled bodies) | ||
192 | // were tagged. | ||
193 | # ifndef dNODEBUG | ||
194 | for (b=world->firstbody; b; b=(dxBody*)b->next) { | ||
195 | if (b->flags & dxBodyDisabled) { | ||
196 | if (b->tag) dDebug (0,"disabled body tagged"); | ||
197 | } | ||
198 | else { | ||
199 | if (!b->tag) dDebug (0,"enabled body not tagged"); | ||
200 | } | ||
201 | } | ||
202 | for (j=world->firstjoint; j; j=(dxJoint*)j->next) { | ||
203 | if ((j->node[0].body && (j->node[0].body->flags & dxBodyDisabled)==0) || | ||
204 | (j->node[1].body && (j->node[1].body->flags & dxBodyDisabled)==0)) { | ||
205 | if (!j->tag) dDebug (0,"attached enabled joint not tagged"); | ||
206 | } | ||
207 | else { | ||
208 | if (j->tag) dDebug (0,"unattached or disabled joint tagged"); | ||
209 | } | ||
210 | } | ||
211 | # endif | ||
212 | /******************** breakable joint contribution ***********************/ | ||
213 | dxJoint* nextJ; | ||
214 | if (!world->firstjoint) | ||
215 | nextJ = 0; | ||
216 | else | ||
217 | nextJ = (dxJoint*)world->firstjoint->next; | ||
218 | for (j=world->firstjoint; j; j=nextJ) { | ||
219 | nextJ = (dxJoint*)j->next; | ||
220 | // check if joint is breakable and broken | ||
221 | if (j->breakInfo && j->breakInfo->flags & dJOINT_BROKEN) { | ||
222 | // detach (break) the joint | ||
223 | dJointAttach (j, 0, 0); | ||
224 | // call the callback function if it is set | ||
225 | if (j->breakInfo->callback) j->breakInfo->callback (j); | ||
226 | // finally destroy the joint if the dJOINT_DELETE_ON_BREAK is set | ||
227 | if (j->breakInfo->flags & dJOINT_DELETE_ON_BREAK) dJointDestroy (j); | ||
228 | } | ||
229 | } | ||
230 | /*************************************************************************/ | ||
231 | } | ||
232 | |||
233 | //**************************************************************************** | ||
234 | // debugging | ||
235 | |||
236 | // see if an object list loops on itself (if so, it's bad). | ||
237 | |||
238 | static int listHasLoops (dObject *first) | ||
239 | { | ||
240 | if (first==0 || first->next==0) return 0; | ||
241 | dObject *a=first,*b=first->next; | ||
242 | int skip=0; | ||
243 | while (b) { | ||
244 | if (a==b) return 1; | ||
245 | b = b->next; | ||
246 | if (skip) a = a->next; | ||
247 | skip ^= 1; | ||
248 | } | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | |||
253 | // check the validity of the world data structures | ||
254 | |||
255 | static void checkWorld (dxWorld *w) | ||
256 | { | ||
257 | dxBody *b; | ||
258 | dxJoint *j; | ||
259 | |||
260 | // check there are no loops | ||
261 | if (listHasLoops (w->firstbody)) dDebug (0,"body list has loops"); | ||
262 | if (listHasLoops (w->firstjoint)) dDebug (0,"joint list has loops"); | ||
263 | |||
264 | // check lists are well formed (check `tome' pointers) | ||
265 | for (b=w->firstbody; b; b=(dxBody*)b->next) { | ||
266 | if (b->next && b->next->tome != &b->next) | ||
267 | dDebug (0,"bad tome pointer in body list"); | ||
268 | } | ||
269 | for (j=w->firstjoint; j; j=(dxJoint*)j->next) { | ||
270 | if (j->next && j->next->tome != &j->next) | ||
271 | dDebug (0,"bad tome pointer in joint list"); | ||
272 | } | ||
273 | |||
274 | // check counts | ||
275 | int n = 0; | ||
276 | for (b=w->firstbody; b; b=(dxBody*)b->next) n++; | ||
277 | if (w->nb != n) dDebug (0,"body count incorrect"); | ||
278 | n = 0; | ||
279 | for (j=w->firstjoint; j; j=(dxJoint*)j->next) n++; | ||
280 | if (w->nj != n) dDebug (0,"joint count incorrect"); | ||
281 | |||
282 | // set all tag values to a known value | ||
283 | static int count = 0; | ||
284 | count++; | ||
285 | for (b=w->firstbody; b; b=(dxBody*)b->next) b->tag = count; | ||
286 | for (j=w->firstjoint; j; j=(dxJoint*)j->next) j->tag = count; | ||
287 | |||
288 | // check all body/joint world pointers are ok | ||
289 | for (b=w->firstbody; b; b=(dxBody*)b->next) if (b->world != w) | ||
290 | dDebug (0,"bad world pointer in body list"); | ||
291 | for (j=w->firstjoint; j; j=(dxJoint*)j->next) if (j->world != w) | ||
292 | dDebug (0,"bad world pointer in joint list"); | ||
293 | |||
294 | /* | ||
295 | // check for half-connected joints - actually now these are valid | ||
296 | for (j=w->firstjoint; j; j=(dxJoint*)j->next) { | ||
297 | if (j->node[0].body || j->node[1].body) { | ||
298 | if (!(j->node[0].body && j->node[1].body)) | ||
299 | dDebug (0,"half connected joint found"); | ||
300 | } | ||
301 | } | ||
302 | */ | ||
303 | |||
304 | // check that every joint node appears in the joint lists of both bodies it | ||
305 | // attaches | ||
306 | for (j=w->firstjoint; j; j=(dxJoint*)j->next) { | ||
307 | for (int i=0; i<2; i++) { | ||
308 | if (j->node[i].body) { | ||
309 | int ok = 0; | ||
310 | for (dxJointNode *n=j->node[i].body->firstjoint; n; n=n->next) { | ||
311 | if (n->joint == j) ok = 1; | ||
312 | } | ||
313 | if (ok==0) dDebug (0,"joint not in joint list of attached body"); | ||
314 | } | ||
315 | } | ||
316 | } | ||
317 | |||
318 | // check all body joint lists (correct body ptrs) | ||
319 | for (b=w->firstbody; b; b=(dxBody*)b->next) { | ||
320 | for (dxJointNode *n=b->firstjoint; n; n=n->next) { | ||
321 | if (&n->joint->node[0] == n) { | ||
322 | if (n->joint->node[1].body != b) | ||
323 | dDebug (0,"bad body pointer in joint node of body list (1)"); | ||
324 | } | ||
325 | else { | ||
326 | if (n->joint->node[0].body != b) | ||
327 | dDebug (0,"bad body pointer in joint node of body list (2)"); | ||
328 | } | ||
329 | if (n->joint->tag != count) dDebug (0,"bad joint node pointer in body"); | ||
330 | } | ||
331 | } | ||
332 | |||
333 | // check all body pointers in joints, check they are distinct | ||
334 | for (j=w->firstjoint; j; j=(dxJoint*)j->next) { | ||
335 | if (j->node[0].body && (j->node[0].body == j->node[1].body)) | ||
336 | dDebug (0,"non-distinct body pointers in joint"); | ||
337 | if ((j->node[0].body && j->node[0].body->tag != count) || | ||
338 | (j->node[1].body && j->node[1].body->tag != count)) | ||
339 | dDebug (0,"bad body pointer in joint"); | ||
340 | } | ||
341 | } | ||
342 | |||
343 | |||
344 | void dWorldCheck (dxWorld *w) | ||
345 | { | ||
346 | checkWorld (w); | ||
347 | } | ||
348 | |||
349 | //**************************************************************************** | ||
350 | // body | ||
351 | |||
352 | dxBody *dBodyCreate (dxWorld *w) | ||
353 | { | ||
354 | dAASSERT (w); | ||
355 | dxBody *b = new dxBody; | ||
356 | initObject (b,w); | ||
357 | b->firstjoint = 0; | ||
358 | b->flags = 0; | ||
359 | b->geom = 0; | ||
360 | dMassSetParameters (&b->mass,1,0,0,0,1,1,1,0,0,0); | ||
361 | dSetZero (b->invI,4*3); | ||
362 | b->invI[0] = 1; | ||
363 | b->invI[5] = 1; | ||
364 | b->invI[10] = 1; | ||
365 | b->invMass = 1; | ||
366 | dSetZero (b->pos,4); | ||
367 | dSetZero (b->q,4); | ||
368 | b->q[0] = 1; | ||
369 | dRSetIdentity (b->R); | ||
370 | dSetZero (b->lvel,4); | ||
371 | dSetZero (b->avel,4); | ||
372 | dSetZero (b->facc,4); | ||
373 | dSetZero (b->tacc,4); | ||
374 | dSetZero (b->finite_rot_axis,4); | ||
375 | addObjectToList (b,(dObject **) &w->firstbody); | ||
376 | w->nb++; | ||
377 | return b; | ||
378 | } | ||
379 | |||
380 | |||
381 | void dBodyDestroy (dxBody *b) | ||
382 | { | ||
383 | dAASSERT (b); | ||
384 | |||
385 | // all geoms that link to this body must be notified that the body is about | ||
386 | // to disappear. note that the call to dGeomSetBody(geom,0) will result in | ||
387 | // dGeomGetBodyNext() returning 0 for the body, so we must get the next body | ||
388 | // before setting the body to 0. | ||
389 | dxGeom *next_geom = 0; | ||
390 | for (dxGeom *geom = b->geom; geom; geom = next_geom) { | ||
391 | next_geom = dGeomGetBodyNext (geom); | ||
392 | dGeomSetBody (geom,0); | ||
393 | } | ||
394 | |||
395 | // detach all neighbouring joints, then delete this body. | ||
396 | dxJointNode *n = b->firstjoint; | ||
397 | while (n) { | ||
398 | // sneaky trick to speed up removal of joint references (black magic) | ||
399 | n->joint->node[(n == n->joint->node)].body = 0; | ||
400 | |||
401 | dxJointNode *next = n->next; | ||
402 | n->next = 0; | ||
403 | removeJointReferencesFromAttachedBodies (n->joint); | ||
404 | n = next; | ||
405 | } | ||
406 | removeObjectFromList (b); | ||
407 | b->world->nb--; | ||
408 | delete b; | ||
409 | } | ||
410 | |||
411 | |||
412 | void dBodySetData (dBodyID b, void *data) | ||
413 | { | ||
414 | dAASSERT (b); | ||
415 | b->userdata = data; | ||
416 | } | ||
417 | |||
418 | |||
419 | void *dBodyGetData (dBodyID b) | ||
420 | { | ||
421 | dAASSERT (b); | ||
422 | return b->userdata; | ||
423 | } | ||
424 | |||
425 | |||
426 | void dBodySetPosition (dBodyID b, dReal x, dReal y, dReal z) | ||
427 | { | ||
428 | dAASSERT (b); | ||
429 | b->pos[0] = x; | ||
430 | b->pos[1] = y; | ||
431 | b->pos[2] = z; | ||
432 | |||
433 | // notify all attached geoms that this body has moved | ||
434 | for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom)) | ||
435 | dGeomMoved (geom); | ||
436 | } | ||
437 | |||
438 | |||
439 | void dBodySetRotation (dBodyID b, const dMatrix3 R) | ||
440 | { | ||
441 | dAASSERT (b && R); | ||
442 | dQuaternion q; | ||
443 | dRtoQ (R,q); | ||
444 | dNormalize4 (q); | ||
445 | b->q[0] = q[0]; | ||
446 | b->q[1] = q[1]; | ||
447 | b->q[2] = q[2]; | ||
448 | b->q[3] = q[3]; | ||
449 | dQtoR (b->q,b->R); | ||
450 | |||
451 | // notify all attached geoms that this body has moved | ||
452 | for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom)) | ||
453 | dGeomMoved (geom); | ||
454 | } | ||
455 | |||
456 | |||
457 | void dBodySetQuaternion (dBodyID b, const dQuaternion q) | ||
458 | { | ||
459 | dAASSERT (b && q); | ||
460 | b->q[0] = q[0]; | ||
461 | b->q[1] = q[1]; | ||
462 | b->q[2] = q[2]; | ||
463 | b->q[3] = q[3]; | ||
464 | dNormalize4 (b->q); | ||
465 | dQtoR (b->q,b->R); | ||
466 | |||
467 | // notify all attached geoms that this body has moved | ||
468 | for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom)) | ||
469 | dGeomMoved (geom); | ||
470 | } | ||
471 | |||
472 | |||
473 | void dBodySetLinearVel (dBodyID b, dReal x, dReal y, dReal z) | ||
474 | { | ||
475 | dAASSERT (b); | ||
476 | b->lvel[0] = x; | ||
477 | b->lvel[1] = y; | ||
478 | b->lvel[2] = z; | ||
479 | } | ||
480 | |||
481 | |||
482 | void dBodySetAngularVel (dBodyID b, dReal x, dReal y, dReal z) | ||
483 | { | ||
484 | dAASSERT (b); | ||
485 | b->avel[0] = x; | ||
486 | b->avel[1] = y; | ||
487 | b->avel[2] = z; | ||
488 | } | ||
489 | |||
490 | |||
491 | const dReal * dBodyGetPosition (dBodyID b) | ||
492 | { | ||
493 | dAASSERT (b); | ||
494 | return b->pos; | ||
495 | } | ||
496 | |||
497 | |||
498 | const dReal * dBodyGetRotation (dBodyID b) | ||
499 | { | ||
500 | dAASSERT (b); | ||
501 | return b->R; | ||
502 | } | ||
503 | |||
504 | |||
505 | const dReal * dBodyGetQuaternion (dBodyID b) | ||
506 | { | ||
507 | dAASSERT (b); | ||
508 | return b->q; | ||
509 | } | ||
510 | |||
511 | |||
512 | const dReal * dBodyGetLinearVel (dBodyID b) | ||
513 | { | ||
514 | dAASSERT (b); | ||
515 | return b->lvel; | ||
516 | } | ||
517 | |||
518 | |||
519 | const dReal * dBodyGetAngularVel (dBodyID b) | ||
520 | { | ||
521 | dAASSERT (b); | ||
522 | return b->avel; | ||
523 | } | ||
524 | |||
525 | |||
526 | void dBodySetMass (dBodyID b, const dMass *mass) | ||
527 | { | ||
528 | dAASSERT (b && mass); | ||
529 | memcpy (&b->mass,mass,sizeof(dMass)); | ||
530 | if (dInvertPDMatrix (b->mass.I,b->invI,3)==0) { | ||
531 | dDEBUGMSG ("inertia must be positive definite"); | ||
532 | dRSetIdentity (b->invI); | ||
533 | } | ||
534 | b->invMass = dRecip(b->mass.mass); | ||
535 | } | ||
536 | |||
537 | |||
538 | void dBodyGetMass (dBodyID b, dMass *mass) | ||
539 | { | ||
540 | dAASSERT (b && mass); | ||
541 | memcpy (mass,&b->mass,sizeof(dMass)); | ||
542 | } | ||
543 | |||
544 | |||
545 | void dBodyAddForce (dBodyID b, dReal fx, dReal fy, dReal fz) | ||
546 | { | ||
547 | dAASSERT (b); | ||
548 | b->facc[0] += fx; | ||
549 | b->facc[1] += fy; | ||
550 | b->facc[2] += fz; | ||
551 | } | ||
552 | |||
553 | |||
554 | void dBodyAddTorque (dBodyID b, dReal fx, dReal fy, dReal fz) | ||
555 | { | ||
556 | dAASSERT (b); | ||
557 | b->tacc[0] += fx; | ||
558 | b->tacc[1] += fy; | ||
559 | b->tacc[2] += fz; | ||
560 | } | ||
561 | |||
562 | |||
563 | void dBodyAddRelForce (dBodyID b, dReal fx, dReal fy, dReal fz) | ||
564 | { | ||
565 | dAASSERT (b); | ||
566 | dVector3 t1,t2; | ||
567 | t1[0] = fx; | ||
568 | t1[1] = fy; | ||
569 | t1[2] = fz; | ||
570 | t1[3] = 0; | ||
571 | dMULTIPLY0_331 (t2,b->R,t1); | ||
572 | b->facc[0] += t2[0]; | ||
573 | b->facc[1] += t2[1]; | ||
574 | b->facc[2] += t2[2]; | ||
575 | } | ||
576 | |||
577 | |||
578 | void dBodyAddRelTorque (dBodyID b, dReal fx, dReal fy, dReal fz) | ||
579 | { | ||
580 | dAASSERT (b); | ||
581 | dVector3 t1,t2; | ||
582 | t1[0] = fx; | ||
583 | t1[1] = fy; | ||
584 | t1[2] = fz; | ||
585 | t1[3] = 0; | ||
586 | dMULTIPLY0_331 (t2,b->R,t1); | ||
587 | b->tacc[0] += t2[0]; | ||
588 | b->tacc[1] += t2[1]; | ||
589 | b->tacc[2] += t2[2]; | ||
590 | } | ||
591 | |||
592 | |||
593 | void dBodyAddForceAtPos (dBodyID b, dReal fx, dReal fy, dReal fz, | ||
594 | dReal px, dReal py, dReal pz) | ||
595 | { | ||
596 | dAASSERT (b); | ||
597 | b->facc[0] += fx; | ||
598 | b->facc[1] += fy; | ||
599 | b->facc[2] += fz; | ||
600 | dVector3 f,q; | ||
601 | f[0] = fx; | ||
602 | f[1] = fy; | ||
603 | f[2] = fz; | ||
604 | q[0] = px - b->pos[0]; | ||
605 | q[1] = py - b->pos[1]; | ||
606 | q[2] = pz - b->pos[2]; | ||
607 | dCROSS (b->tacc,+=,q,f); | ||
608 | } | ||
609 | |||
610 | |||
611 | void dBodyAddForceAtRelPos (dBodyID b, dReal fx, dReal fy, dReal fz, | ||
612 | dReal px, dReal py, dReal pz) | ||
613 | { | ||
614 | dAASSERT (b); | ||
615 | dVector3 prel,f,p; | ||
616 | f[0] = fx; | ||
617 | f[1] = fy; | ||
618 | f[2] = fz; | ||
619 | f[3] = 0; | ||
620 | prel[0] = px; | ||
621 | prel[1] = py; | ||
622 | prel[2] = pz; | ||
623 | prel[3] = 0; | ||
624 | dMULTIPLY0_331 (p,b->R,prel); | ||
625 | b->facc[0] += f[0]; | ||
626 | b->facc[1] += f[1]; | ||
627 | b->facc[2] += f[2]; | ||
628 | dCROSS (b->tacc,+=,p,f); | ||
629 | } | ||
630 | |||
631 | |||
632 | void dBodyAddRelForceAtPos (dBodyID b, dReal fx, dReal fy, dReal fz, | ||
633 | dReal px, dReal py, dReal pz) | ||
634 | { | ||
635 | dAASSERT (b); | ||
636 | dVector3 frel,f; | ||
637 | frel[0] = fx; | ||
638 | frel[1] = fy; | ||
639 | frel[2] = fz; | ||
640 | frel[3] = 0; | ||
641 | dMULTIPLY0_331 (f,b->R,frel); | ||
642 | b->facc[0] += f[0]; | ||
643 | b->facc[1] += f[1]; | ||
644 | b->facc[2] += f[2]; | ||
645 | dVector3 q; | ||
646 | q[0] = px - b->pos[0]; | ||
647 | q[1] = py - b->pos[1]; | ||
648 | q[2] = pz - b->pos[2]; | ||
649 | dCROSS (b->tacc,+=,q,f); | ||
650 | } | ||
651 | |||
652 | |||
653 | void dBodyAddRelForceAtRelPos (dBodyID b, dReal fx, dReal fy, dReal fz, | ||
654 | dReal px, dReal py, dReal pz) | ||
655 | { | ||
656 | dAASSERT (b); | ||
657 | dVector3 frel,prel,f,p; | ||
658 | frel[0] = fx; | ||
659 | frel[1] = fy; | ||
660 | frel[2] = fz; | ||
661 | frel[3] = 0; | ||
662 | prel[0] = px; | ||
663 | prel[1] = py; | ||
664 | prel[2] = pz; | ||
665 | prel[3] = 0; | ||
666 | dMULTIPLY0_331 (f,b->R,frel); | ||
667 | dMULTIPLY0_331 (p,b->R,prel); | ||
668 | b->facc[0] += f[0]; | ||
669 | b->facc[1] += f[1]; | ||
670 | b->facc[2] += f[2]; | ||
671 | dCROSS (b->tacc,+=,p,f); | ||
672 | } | ||
673 | |||
674 | |||
675 | const dReal * dBodyGetForce (dBodyID b) | ||
676 | { | ||
677 | dAASSERT (b); | ||
678 | return b->facc; | ||
679 | } | ||
680 | |||
681 | |||
682 | const dReal * dBodyGetTorque (dBodyID b) | ||
683 | { | ||
684 | dAASSERT (b); | ||
685 | return b->tacc; | ||
686 | } | ||
687 | |||
688 | |||
689 | void dBodySetForce (dBodyID b, dReal x, dReal y, dReal z) | ||
690 | { | ||
691 | dAASSERT (b); | ||
692 | b->facc[0] = x; | ||
693 | b->facc[1] = y; | ||
694 | b->facc[2] = z; | ||
695 | } | ||
696 | |||
697 | |||
698 | void dBodySetTorque (dBodyID b, dReal x, dReal y, dReal z) | ||
699 | { | ||
700 | dAASSERT (b); | ||
701 | b->tacc[0] = x; | ||
702 | b->tacc[1] = y; | ||
703 | b->tacc[2] = z; | ||
704 | } | ||
705 | |||
706 | |||
707 | void dBodyGetRelPointPos (dBodyID b, dReal px, dReal py, dReal pz, | ||
708 | dVector3 result) | ||
709 | { | ||
710 | dAASSERT (b); | ||
711 | dVector3 prel,p; | ||
712 | prel[0] = px; | ||
713 | prel[1] = py; | ||
714 | prel[2] = pz; | ||
715 | prel[3] = 0; | ||
716 | dMULTIPLY0_331 (p,b->R,prel); | ||
717 | result[0] = p[0] + b->pos[0]; | ||
718 | result[1] = p[1] + b->pos[1]; | ||
719 | result[2] = p[2] + b->pos[2]; | ||
720 | } | ||
721 | |||
722 | |||
723 | void dBodyGetRelPointVel (dBodyID b, dReal px, dReal py, dReal pz, | ||
724 | dVector3 result) | ||
725 | { | ||
726 | dAASSERT (b); | ||
727 | dVector3 prel,p; | ||
728 | prel[0] = px; | ||
729 | prel[1] = py; | ||
730 | prel[2] = pz; | ||
731 | prel[3] = 0; | ||
732 | dMULTIPLY0_331 (p,b->R,prel); | ||
733 | result[0] = b->lvel[0]; | ||
734 | result[1] = b->lvel[1]; | ||
735 | result[2] = b->lvel[2]; | ||
736 | dCROSS (result,+=,b->avel,p); | ||
737 | } | ||
738 | |||
739 | |||
740 | void dBodyGetPointVel (dBodyID b, dReal px, dReal py, dReal pz, | ||
741 | dVector3 result) | ||
742 | { | ||
743 | dAASSERT (b); | ||
744 | dVector3 p; | ||
745 | p[0] = px - b->pos[0]; | ||
746 | p[1] = py - b->pos[1]; | ||
747 | p[2] = pz - b->pos[2]; | ||
748 | p[3] = 0; | ||
749 | result[0] = b->lvel[0]; | ||
750 | result[1] = b->lvel[1]; | ||
751 | result[2] = b->lvel[2]; | ||
752 | dCROSS (result,+=,b->avel,p); | ||
753 | } | ||
754 | |||
755 | |||
756 | void dBodyGetPosRelPoint (dBodyID b, dReal px, dReal py, dReal pz, | ||
757 | dVector3 result) | ||
758 | { | ||
759 | dAASSERT (b); | ||
760 | dVector3 prel; | ||
761 | prel[0] = px - b->pos[0]; | ||
762 | prel[1] = py - b->pos[1]; | ||
763 | prel[2] = pz - b->pos[2]; | ||
764 | prel[3] = 0; | ||
765 | dMULTIPLY1_331 (result,b->R,prel); | ||
766 | } | ||
767 | |||
768 | |||
769 | void dBodyVectorToWorld (dBodyID b, dReal px, dReal py, dReal pz, | ||
770 | dVector3 result) | ||
771 | { | ||
772 | dAASSERT (b); | ||
773 | dVector3 p; | ||
774 | p[0] = px; | ||
775 | p[1] = py; | ||
776 | p[2] = pz; | ||
777 | p[3] = 0; | ||
778 | dMULTIPLY0_331 (result,b->R,p); | ||
779 | } | ||
780 | |||
781 | |||
782 | void dBodyVectorFromWorld (dBodyID b, dReal px, dReal py, dReal pz, | ||
783 | dVector3 result) | ||
784 | { | ||
785 | dAASSERT (b); | ||
786 | dVector3 p; | ||
787 | p[0] = px; | ||
788 | p[1] = py; | ||
789 | p[2] = pz; | ||
790 | p[3] = 0; | ||
791 | dMULTIPLY1_331 (result,b->R,p); | ||
792 | } | ||
793 | |||
794 | |||
795 | void dBodySetFiniteRotationMode (dBodyID b, int mode) | ||
796 | { | ||
797 | dAASSERT (b); | ||
798 | b->flags &= ~(dxBodyFlagFiniteRotation | dxBodyFlagFiniteRotationAxis); | ||
799 | if (mode) { | ||
800 | b->flags |= dxBodyFlagFiniteRotation; | ||
801 | if (b->finite_rot_axis[0] != 0 || b->finite_rot_axis[1] != 0 || | ||
802 | b->finite_rot_axis[2] != 0) { | ||
803 | b->flags |= dxBodyFlagFiniteRotationAxis; | ||
804 | } | ||
805 | } | ||
806 | } | ||
807 | |||
808 | |||
809 | void dBodySetFiniteRotationAxis (dBodyID b, dReal x, dReal y, dReal z) | ||
810 | { | ||
811 | dAASSERT (b); | ||
812 | b->finite_rot_axis[0] = x; | ||
813 | b->finite_rot_axis[1] = y; | ||
814 | b->finite_rot_axis[2] = z; | ||
815 | if (x != 0 || y != 0 || z != 0) { | ||
816 | dNormalize3 (b->finite_rot_axis); | ||
817 | b->flags |= dxBodyFlagFiniteRotationAxis; | ||
818 | } | ||
819 | else { | ||
820 | b->flags &= ~dxBodyFlagFiniteRotationAxis; | ||
821 | } | ||
822 | } | ||
823 | |||
824 | |||
825 | int dBodyGetFiniteRotationMode (dBodyID b) | ||
826 | { | ||
827 | dAASSERT (b); | ||
828 | return ((b->flags & dxBodyFlagFiniteRotation) != 0); | ||
829 | } | ||
830 | |||
831 | |||
832 | void dBodyGetFiniteRotationAxis (dBodyID b, dVector3 result) | ||
833 | { | ||
834 | dAASSERT (b); | ||
835 | result[0] = b->finite_rot_axis[0]; | ||
836 | result[1] = b->finite_rot_axis[1]; | ||
837 | result[2] = b->finite_rot_axis[2]; | ||
838 | } | ||
839 | |||
840 | |||
841 | int dBodyGetNumJoints (dBodyID b) | ||
842 | { | ||
843 | dAASSERT (b); | ||
844 | int count=0; | ||
845 | for (dxJointNode *n=b->firstjoint; n; n=n->next, count++); | ||
846 | return count; | ||
847 | } | ||
848 | |||
849 | |||
850 | dJointID dBodyGetJoint (dBodyID b, int index) | ||
851 | { | ||
852 | dAASSERT (b); | ||
853 | int i=0; | ||
854 | for (dxJointNode *n=b->firstjoint; n; n=n->next, i++) { | ||
855 | if (i == index) return n->joint; | ||
856 | } | ||
857 | return 0; | ||
858 | } | ||
859 | |||
860 | |||
861 | void dBodyEnable (dBodyID b) | ||
862 | { | ||
863 | dAASSERT (b); | ||
864 | b->flags &= ~dxBodyDisabled; | ||
865 | } | ||
866 | |||
867 | |||
868 | void dBodyDisable (dBodyID b) | ||
869 | { | ||
870 | dAASSERT (b); | ||
871 | b->flags |= dxBodyDisabled; | ||
872 | } | ||
873 | |||
874 | |||
875 | int dBodyIsEnabled (dBodyID b) | ||
876 | { | ||
877 | dAASSERT (b); | ||
878 | return ((b->flags & dxBodyDisabled) == 0); | ||
879 | } | ||
880 | |||
881 | |||
882 | void dBodySetGravityMode (dBodyID b, int mode) | ||
883 | { | ||
884 | dAASSERT (b); | ||
885 | if (mode) b->flags &= ~dxBodyNoGravity; | ||
886 | else b->flags |= dxBodyNoGravity; | ||
887 | } | ||
888 | |||
889 | |||
890 | int dBodyGetGravityMode (dBodyID b) | ||
891 | { | ||
892 | dAASSERT (b); | ||
893 | return ((b->flags & dxBodyNoGravity) == 0); | ||
894 | } | ||
895 | |||
896 | //**************************************************************************** | ||
897 | // joints | ||
898 | |||
899 | static void dJointInit (dxWorld *w, dxJoint *j) | ||
900 | { | ||
901 | dIASSERT (w && j); | ||
902 | initObject (j,w); | ||
903 | j->vtable = 0; | ||
904 | j->flags = 0; | ||
905 | j->node[0].joint = j; | ||
906 | j->node[0].body = 0; | ||
907 | j->node[0].next = 0; | ||
908 | j->node[1].joint = j; | ||
909 | j->node[1].body = 0; | ||
910 | j->node[1].next = 0; | ||
911 | addObjectToList (j,(dObject **) &w->firstjoint); | ||
912 | w->nj++; | ||
913 | } | ||
914 | |||
915 | |||
916 | static dxJoint *createJoint (dWorldID w, dJointGroupID group, | ||
917 | dxJoint::Vtable *vtable) | ||
918 | { | ||
919 | dIASSERT (w && vtable); | ||
920 | dxJoint *j; | ||
921 | if (group) { | ||
922 | j = (dxJoint*) group->stack.alloc (vtable->size); | ||
923 | group->num++; | ||
924 | } | ||
925 | else j = (dxJoint*) dAlloc (vtable->size); | ||
926 | dJointInit (w,j); | ||
927 | j->vtable = vtable; | ||
928 | if (group) j->flags |= dJOINT_INGROUP; | ||
929 | if (vtable->init) vtable->init (j); | ||
930 | j->feedback = 0; | ||
931 | /******************** breakable joint contribution ***********************/ | ||
932 | j->breakInfo = 0; | ||
933 | /*************************************************************************/ | ||
934 | return j; | ||
935 | } | ||
936 | |||
937 | |||
938 | dxJoint * dJointCreateBall (dWorldID w, dJointGroupID group) | ||
939 | { | ||
940 | dAASSERT (w); | ||
941 | return createJoint (w,group,&__dball_vtable); | ||
942 | } | ||
943 | |||
944 | |||
945 | dxJoint * dJointCreateHinge (dWorldID w, dJointGroupID group) | ||
946 | { | ||
947 | dAASSERT (w); | ||
948 | return createJoint (w,group,&__dhinge_vtable); | ||
949 | } | ||
950 | |||
951 | |||
952 | dxJoint * dJointCreateSlider (dWorldID w, dJointGroupID group) | ||
953 | { | ||
954 | dAASSERT (w); | ||
955 | return createJoint (w,group,&__dslider_vtable); | ||
956 | } | ||
957 | |||
958 | |||
959 | dxJoint * dJointCreateContact (dWorldID w, dJointGroupID group, | ||
960 | const dContact *c) | ||
961 | { | ||
962 | dAASSERT (w && c); | ||
963 | dxJointContact *j = (dxJointContact *) | ||
964 | createJoint (w,group,&__dcontact_vtable); | ||
965 | j->contact = *c; | ||
966 | return j; | ||
967 | } | ||
968 | |||
969 | |||
970 | dxJoint * dJointCreateHinge2 (dWorldID w, dJointGroupID group) | ||
971 | { | ||
972 | dAASSERT (w); | ||
973 | return createJoint (w,group,&__dhinge2_vtable); | ||
974 | } | ||
975 | |||
976 | |||
977 | dxJoint * dJointCreateUniversal (dWorldID w, dJointGroupID group) | ||
978 | { | ||
979 | dAASSERT (w); | ||
980 | return createJoint (w,group,&__duniversal_vtable); | ||
981 | } | ||
982 | |||
983 | |||
984 | dxJoint * dJointCreateFixed (dWorldID w, dJointGroupID group) | ||
985 | { | ||
986 | dAASSERT (w); | ||
987 | return createJoint (w,group,&__dfixed_vtable); | ||
988 | } | ||
989 | |||
990 | |||
991 | dxJoint * dJointCreateNull (dWorldID w, dJointGroupID group) | ||
992 | { | ||
993 | dAASSERT (w); | ||
994 | return createJoint (w,group,&__dnull_vtable); | ||
995 | } | ||
996 | |||
997 | |||
998 | dxJoint * dJointCreateAMotor (dWorldID w, dJointGroupID group) | ||
999 | { | ||
1000 | dAASSERT (w); | ||
1001 | return createJoint (w,group,&__damotor_vtable); | ||
1002 | } | ||
1003 | |||
1004 | |||
1005 | void dJointDestroy (dxJoint *j) | ||
1006 | { | ||
1007 | dAASSERT (j); | ||
1008 | if (j->flags & dJOINT_INGROUP) return; | ||
1009 | removeJointReferencesFromAttachedBodies (j); | ||
1010 | removeObjectFromList (j); | ||
1011 | /******************** breakable joint contribution ***********************/ | ||
1012 | if (j->breakInfo) delete j->breakInfo; | ||
1013 | /*************************************************************************/ | ||
1014 | j->world->nj--; | ||
1015 | dFree (j,j->vtable->size); | ||
1016 | } | ||
1017 | |||
1018 | |||
1019 | dJointGroupID dJointGroupCreate (int max_size) | ||
1020 | { | ||
1021 | // not any more ... dUASSERT (max_size > 0,"max size must be > 0"); | ||
1022 | dxJointGroup *group = new dxJointGroup; | ||
1023 | group->num = 0; | ||
1024 | return group; | ||
1025 | } | ||
1026 | |||
1027 | |||
1028 | void dJointGroupDestroy (dJointGroupID group) | ||
1029 | { | ||
1030 | dAASSERT (group); | ||
1031 | dJointGroupEmpty (group); | ||
1032 | delete group; | ||
1033 | } | ||
1034 | |||
1035 | |||
1036 | void dJointGroupEmpty (dJointGroupID group) | ||
1037 | { | ||
1038 | // the joints in this group are detached starting from the most recently | ||
1039 | // added (at the top of the stack). this helps ensure that the various | ||
1040 | // linked lists are not traversed too much, as the joints will hopefully | ||
1041 | // be at the start of those lists. | ||
1042 | // if any group joints have their world pointer set to 0, their world was | ||
1043 | // previously destroyed. no special handling is required for these joints. | ||
1044 | |||
1045 | dAASSERT (group); | ||
1046 | int i; | ||
1047 | dxJoint **jlist = (dxJoint**) ALLOCA (group->num * sizeof(dxJoint*)); | ||
1048 | dxJoint *j = (dxJoint*) group->stack.rewind(); | ||
1049 | for (i=0; i < group->num; i++) { | ||
1050 | jlist[i] = j; | ||
1051 | j = (dxJoint*) (group->stack.next (j->vtable->size)); | ||
1052 | } | ||
1053 | for (i=group->num-1; i >= 0; i--) { | ||
1054 | if (jlist[i]->world) { | ||
1055 | removeJointReferencesFromAttachedBodies (jlist[i]); | ||
1056 | removeObjectFromList (jlist[i]); | ||
1057 | jlist[i]->world->nj--; | ||
1058 | } | ||
1059 | } | ||
1060 | group->num = 0; | ||
1061 | group->stack.freeAll(); | ||
1062 | } | ||
1063 | |||
1064 | |||
1065 | void dJointAttach (dxJoint *joint, dxBody *body1, dxBody *body2) | ||
1066 | { | ||
1067 | // check arguments | ||
1068 | dUASSERT (joint,"bad joint argument"); | ||
1069 | dUASSERT (body1 == 0 || body1 != body2,"can't have body1==body2"); | ||
1070 | dxWorld *world = joint->world; | ||
1071 | dUASSERT ( (!body1 || body1->world == world) && | ||
1072 | (!body2 || body2->world == world), | ||
1073 | "joint and bodies must be in same world"); | ||
1074 | |||
1075 | // check if the joint can not be attached to just one body | ||
1076 | dUASSERT (!((joint->flags & dJOINT_TWOBODIES) && | ||
1077 | ((body1 != 0) ^ (body2 != 0))), | ||
1078 | "joint can not be attached to just one body"); | ||
1079 | |||
1080 | // remove any existing body attachments | ||
1081 | if (joint->node[0].body || joint->node[1].body) { | ||
1082 | removeJointReferencesFromAttachedBodies (joint); | ||
1083 | } | ||
1084 | |||
1085 | // if a body is zero, make sure that it is body2, so 0 --> node[1].body | ||
1086 | if (body1==0) { | ||
1087 | body1 = body2; | ||
1088 | body2 = 0; | ||
1089 | joint->flags |= dJOINT_REVERSE; | ||
1090 | } | ||
1091 | else { | ||
1092 | joint->flags &= (~dJOINT_REVERSE); | ||
1093 | } | ||
1094 | |||
1095 | // attach to new bodies | ||
1096 | joint->node[0].body = body1; | ||
1097 | joint->node[1].body = body2; | ||
1098 | if (body1) { | ||
1099 | joint->node[1].next = body1->firstjoint; | ||
1100 | body1->firstjoint = &joint->node[1]; | ||
1101 | } | ||
1102 | else joint->node[1].next = 0; | ||
1103 | if (body2) { | ||
1104 | joint->node[0].next = body2->firstjoint; | ||
1105 | body2->firstjoint = &joint->node[0]; | ||
1106 | } | ||
1107 | else { | ||
1108 | joint->node[0].next = 0; | ||
1109 | } | ||
1110 | } | ||
1111 | |||
1112 | |||
1113 | void dJointSetData (dxJoint *joint, void *data) | ||
1114 | { | ||
1115 | dAASSERT (joint); | ||
1116 | joint->userdata = data; | ||
1117 | } | ||
1118 | |||
1119 | |||
1120 | void *dJointGetData (dxJoint *joint) | ||
1121 | { | ||
1122 | dAASSERT (joint); | ||
1123 | return joint->userdata; | ||
1124 | } | ||
1125 | |||
1126 | |||
1127 | int dJointGetType (dxJoint *joint) | ||
1128 | { | ||
1129 | dAASSERT (joint); | ||
1130 | return joint->vtable->typenum; | ||
1131 | } | ||
1132 | |||
1133 | |||
1134 | dBodyID dJointGetBody (dxJoint *joint, int index) | ||
1135 | { | ||
1136 | dAASSERT (joint); | ||
1137 | if (index >= 0 && index < 2) return joint->node[index].body; | ||
1138 | else return 0; | ||
1139 | } | ||
1140 | |||
1141 | |||
1142 | void dJointSetFeedback (dxJoint *joint, dJointFeedback *f) | ||
1143 | { | ||
1144 | dAASSERT (joint); | ||
1145 | joint->feedback = f; | ||
1146 | } | ||
1147 | |||
1148 | |||
1149 | dJointFeedback *dJointGetFeedback (dxJoint *joint) | ||
1150 | { | ||
1151 | dAASSERT (joint); | ||
1152 | return joint->feedback; | ||
1153 | } | ||
1154 | |||
1155 | |||
1156 | int dAreConnected (dBodyID b1, dBodyID b2) | ||
1157 | { | ||
1158 | dAASSERT (b1 && b2); | ||
1159 | // look through b1's neighbour list for b2 | ||
1160 | for (dxJointNode *n=b1->firstjoint; n; n=n->next) { | ||
1161 | if (n->body == b2) return 1; | ||
1162 | } | ||
1163 | return 0; | ||
1164 | } | ||
1165 | |||
1166 | |||
1167 | int dAreConnectedExcluding (dBodyID b1, dBodyID b2, int joint_type) | ||
1168 | { | ||
1169 | dAASSERT (b1 && b2); | ||
1170 | // look through b1's neighbour list for b2 | ||
1171 | for (dxJointNode *n=b1->firstjoint; n; n=n->next) { | ||
1172 | if (dJointGetType (n->joint) != joint_type && n->body == b2) return 1; | ||
1173 | } | ||
1174 | return 0; | ||
1175 | } | ||
1176 | |||
1177 | //**************************************************************************** | ||
1178 | // world | ||
1179 | |||
1180 | dxWorld * dWorldCreate() | ||
1181 | { | ||
1182 | dxWorld *w = new dxWorld; | ||
1183 | w->firstbody = 0; | ||
1184 | w->firstjoint = 0; | ||
1185 | w->nb = 0; | ||
1186 | w->nj = 0; | ||
1187 | dSetZero (w->gravity,4); | ||
1188 | w->global_erp = REAL(0.2); | ||
1189 | #if defined(dSINGLE) | ||
1190 | w->global_cfm = 1e-5f; | ||
1191 | #elif defined(dDOUBLE) | ||
1192 | w->global_cfm = 1e-10; | ||
1193 | #else | ||
1194 | #error dSINGLE or dDOUBLE must be defined | ||
1195 | #endif | ||
1196 | return w; | ||
1197 | } | ||
1198 | |||
1199 | |||
1200 | void dWorldDestroy (dxWorld *w) | ||
1201 | { | ||
1202 | // delete all bodies and joints | ||
1203 | dAASSERT (w); | ||
1204 | dxBody *nextb, *b = w->firstbody; | ||
1205 | while (b) { | ||
1206 | nextb = (dxBody*) b->next; | ||
1207 | delete b; | ||
1208 | b = nextb; | ||
1209 | } | ||
1210 | dxJoint *nextj, *j = w->firstjoint; | ||
1211 | while (j) { | ||
1212 | nextj = (dxJoint*)j->next; | ||
1213 | if (j->flags & dJOINT_INGROUP) { | ||
1214 | // the joint is part of a group, so "deactivate" it instead | ||
1215 | j->world = 0; | ||
1216 | j->node[0].body = 0; | ||
1217 | j->node[0].next = 0; | ||
1218 | j->node[1].body = 0; | ||
1219 | j->node[1].next = 0; | ||
1220 | dMessage (0,"warning: destroying world containing grouped joints"); | ||
1221 | } | ||
1222 | else { | ||
1223 | dFree (j,j->vtable->size); | ||
1224 | } | ||
1225 | j = nextj; | ||
1226 | } | ||
1227 | delete w; | ||
1228 | } | ||
1229 | |||
1230 | |||
1231 | void dWorldSetGravity (dWorldID w, dReal x, dReal y, dReal z) | ||
1232 | { | ||
1233 | dAASSERT (w); | ||
1234 | w->gravity[0] = x; | ||
1235 | w->gravity[1] = y; | ||
1236 | w->gravity[2] = z; | ||
1237 | } | ||
1238 | |||
1239 | |||
1240 | void dWorldGetGravity (dWorldID w, dVector3 g) | ||
1241 | { | ||
1242 | dAASSERT (w); | ||
1243 | g[0] = w->gravity[0]; | ||
1244 | g[1] = w->gravity[1]; | ||
1245 | g[2] = w->gravity[2]; | ||
1246 | } | ||
1247 | |||
1248 | |||
1249 | void dWorldSetERP (dWorldID w, dReal erp) | ||
1250 | { | ||
1251 | dAASSERT (w); | ||
1252 | w->global_erp = erp; | ||
1253 | } | ||
1254 | |||
1255 | |||
1256 | dReal dWorldGetERP (dWorldID w) | ||
1257 | { | ||
1258 | dAASSERT (w); | ||
1259 | return w->global_erp; | ||
1260 | } | ||
1261 | |||
1262 | |||
1263 | void dWorldSetCFM (dWorldID w, dReal cfm) | ||
1264 | { | ||
1265 | dAASSERT (w); | ||
1266 | w->global_cfm = cfm; | ||
1267 | } | ||
1268 | |||
1269 | |||
1270 | dReal dWorldGetCFM (dWorldID w) | ||
1271 | { | ||
1272 | dAASSERT (w); | ||
1273 | return w->global_cfm; | ||
1274 | } | ||
1275 | |||
1276 | |||
1277 | void dWorldStep (dWorldID w, dReal stepsize) | ||
1278 | { | ||
1279 | dUASSERT (w,"bad world argument"); | ||
1280 | dUASSERT (stepsize > 0,"stepsize must be > 0"); | ||
1281 | processIslands (w,stepsize); | ||
1282 | } | ||
1283 | |||
1284 | |||
1285 | void dWorldImpulseToForce (dWorldID w, dReal stepsize, | ||
1286 | dReal ix, dReal iy, dReal iz, | ||
1287 | dVector3 force) | ||
1288 | { | ||
1289 | dAASSERT (w); | ||
1290 | stepsize = dRecip(stepsize); | ||
1291 | force[0] = stepsize * ix; | ||
1292 | force[1] = stepsize * iy; | ||
1293 | force[2] = stepsize * iz; | ||
1294 | // @@@ force[3] = 0; | ||
1295 | } | ||
1296 | |||
1297 | //**************************************************************************** | ||
1298 | // testing | ||
1299 | |||
1300 | #define NUM 100 | ||
1301 | |||
1302 | #define DO(x) | ||
1303 | |||
1304 | |||
1305 | extern "C" void dTestDataStructures() | ||
1306 | { | ||
1307 | int i; | ||
1308 | DO(printf ("testDynamicsStuff()\n")); | ||
1309 | |||
1310 | dBodyID body [NUM]; | ||
1311 | int nb = 0; | ||
1312 | dJointID joint [NUM]; | ||
1313 | int nj = 0; | ||
1314 | |||
1315 | for (i=0; i<NUM; i++) body[i] = 0; | ||
1316 | for (i=0; i<NUM; i++) joint[i] = 0; | ||
1317 | |||
1318 | DO(printf ("creating world\n")); | ||
1319 | dWorldID w = dWorldCreate(); | ||
1320 | checkWorld (w); | ||
1321 | |||
1322 | for (;;) { | ||
1323 | if (nb < NUM && dRandReal() > 0.5) { | ||
1324 | DO(printf ("creating body\n")); | ||
1325 | body[nb] = dBodyCreate (w); | ||
1326 | DO(printf ("\t--> %p\n",body[nb])); | ||
1327 | nb++; | ||
1328 | checkWorld (w); | ||
1329 | DO(printf ("%d BODIES, %d JOINTS\n",nb,nj)); | ||
1330 | } | ||
1331 | if (nj < NUM && nb > 2 && dRandReal() > 0.5) { | ||
1332 | dBodyID b1 = body [dRand() % nb]; | ||
1333 | dBodyID b2 = body [dRand() % nb]; | ||
1334 | if (b1 != b2) { | ||
1335 | DO(printf ("creating joint, attaching to %p,%p\n",b1,b2)); | ||
1336 | joint[nj] = dJointCreateBall (w,0); | ||
1337 | DO(printf ("\t-->%p\n",joint[nj])); | ||
1338 | checkWorld (w); | ||
1339 | dJointAttach (joint[nj],b1,b2); | ||
1340 | nj++; | ||
1341 | checkWorld (w); | ||
1342 | DO(printf ("%d BODIES, %d JOINTS\n",nb,nj)); | ||
1343 | } | ||
1344 | } | ||
1345 | if (nj > 0 && nb > 2 && dRandReal() > 0.5) { | ||
1346 | dBodyID b1 = body [dRand() % nb]; | ||
1347 | dBodyID b2 = body [dRand() % nb]; | ||
1348 | if (b1 != b2) { | ||
1349 | int k = dRand() % nj; | ||
1350 | DO(printf ("reattaching joint %p\n",joint[k])); | ||
1351 | dJointAttach (joint[k],b1,b2); | ||
1352 | checkWorld (w); | ||
1353 | DO(printf ("%d BODIES, %d JOINTS\n",nb,nj)); | ||
1354 | } | ||
1355 | } | ||
1356 | if (nb > 0 && dRandReal() > 0.5) { | ||
1357 | int k = dRand() % nb; | ||
1358 | DO(printf ("destroying body %p\n",body[k])); | ||
1359 | dBodyDestroy (body[k]); | ||
1360 | checkWorld (w); | ||
1361 | for (; k < (NUM-1); k++) body[k] = body[k+1]; | ||
1362 | nb--; | ||
1363 | DO(printf ("%d BODIES, %d JOINTS\n",nb,nj)); | ||
1364 | } | ||
1365 | if (nj > 0 && dRandReal() > 0.5) { | ||
1366 | int k = dRand() % nj; | ||
1367 | DO(printf ("destroying joint %p\n",joint[k])); | ||
1368 | dJointDestroy (joint[k]); | ||
1369 | checkWorld (w); | ||
1370 | for (; k < (NUM-1); k++) joint[k] = joint[k+1]; | ||
1371 | nj--; | ||
1372 | DO(printf ("%d BODIES, %d JOINTS\n",nb,nj)); | ||
1373 | } | ||
1374 | } | ||
1375 | |||
1376 | /* | ||
1377 | printf ("creating world\n"); | ||
1378 | dWorldID w = dWorldCreate(); | ||
1379 | checkWorld (w); | ||
1380 | printf ("creating body\n"); | ||
1381 | dBodyID b1 = dBodyCreate (w); | ||
1382 | checkWorld (w); | ||
1383 | printf ("creating body\n"); | ||
1384 | dBodyID b2 = dBodyCreate (w); | ||
1385 | checkWorld (w); | ||
1386 | printf ("creating joint\n"); | ||
1387 | dJointID j = dJointCreateBall (w); | ||
1388 | checkWorld (w); | ||
1389 | printf ("attaching joint\n"); | ||
1390 | dJointAttach (j,b1,b2); | ||
1391 | checkWorld (w); | ||
1392 | printf ("destroying joint\n"); | ||
1393 | dJointDestroy (j); | ||
1394 | checkWorld (w); | ||
1395 | printf ("destroying body\n"); | ||
1396 | dBodyDestroy (b1); | ||
1397 | checkWorld (w); | ||
1398 | printf ("destroying body\n"); | ||
1399 | dBodyDestroy (b2); | ||
1400 | checkWorld (w); | ||
1401 | printf ("destroying world\n"); | ||
1402 | dWorldDestroy (w); | ||
1403 | */ | ||
1404 | } | ||
diff --git a/libraries/ode-0.9/contrib/BreakableJoints/step.cpp b/libraries/ode-0.9/contrib/BreakableJoints/step.cpp new file mode 100644 index 0000000..38aed6c --- /dev/null +++ b/libraries/ode-0.9/contrib/BreakableJoints/step.cpp | |||
@@ -0,0 +1,1170 @@ | |||
1 | /************************************************************************* | ||
2 | * * | ||
3 | * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * | ||
4 | * All rights reserved. Email: russ@q12.org Web: www.q12.org * | ||
5 | * * | ||
6 | * This library is free software; you can redistribute it and/or * | ||
7 | * modify it under the terms of EITHER: * | ||
8 | * (1) The GNU Lesser General Public License as published by the Free * | ||
9 | * Software Foundation; either version 2.1 of the License, or (at * | ||
10 | * your option) any later version. The text of the GNU Lesser * | ||
11 | * General Public License is included with this library in the * | ||
12 | * file LICENSE.TXT. * | ||
13 | * (2) The BSD-style license that is included with this library in * | ||
14 | * the file LICENSE-BSD.TXT. * | ||
15 | * * | ||
16 | * This library is distributed in the hope that it will be useful, * | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * | ||
19 | * LICENSE.TXT and LICENSE-BSD.TXT for more details. * | ||
20 | * * | ||
21 | *************************************************************************/ | ||
22 | |||
23 | #include "objects.h" | ||
24 | #include "joint.h" | ||
25 | #include <ode/config.h> | ||
26 | #include <ode/odemath.h> | ||
27 | #include <ode/rotation.h> | ||
28 | #include <ode/timer.h> | ||
29 | #include <ode/error.h> | ||
30 | #include <ode/matrix.h> | ||
31 | #include "lcp.h" | ||
32 | |||
33 | //**************************************************************************** | ||
34 | // misc defines | ||
35 | |||
36 | #define FAST_FACTOR | ||
37 | //#define TIMING | ||
38 | |||
39 | #define ALLOCA dALLOCA16 | ||
40 | |||
41 | //**************************************************************************** | ||
42 | // debugging - comparison of various vectors and matrices produced by the | ||
43 | // slow and fast versions of the stepper. | ||
44 | |||
45 | //#define COMPARE_METHODS | ||
46 | |||
47 | #ifdef COMPARE_METHODS | ||
48 | #include "testing.h" | ||
49 | dMatrixComparison comparator; | ||
50 | #endif | ||
51 | |||
52 | //**************************************************************************** | ||
53 | // special matrix multipliers | ||
54 | |||
55 | // this assumes the 4th and 8th rows of B and C are zero. | ||
56 | |||
57 | static void Multiply2_p8r (dReal *A, dReal *B, dReal *C, | ||
58 | int p, int r, int Askip) | ||
59 | { | ||
60 | int i,j; | ||
61 | dReal sum,*bb,*cc; | ||
62 | dIASSERT (p>0 && r>0 && A && B && C); | ||
63 | bb = B; | ||
64 | for (i=p; i; i--) { | ||
65 | cc = C; | ||
66 | for (j=r; j; j--) { | ||
67 | sum = bb[0]*cc[0]; | ||
68 | sum += bb[1]*cc[1]; | ||
69 | sum += bb[2]*cc[2]; | ||
70 | sum += bb[4]*cc[4]; | ||
71 | sum += bb[5]*cc[5]; | ||
72 | sum += bb[6]*cc[6]; | ||
73 | *(A++) = sum; | ||
74 | cc += 8; | ||
75 | } | ||
76 | A += Askip - r; | ||
77 | bb += 8; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | |||
82 | // this assumes the 4th and 8th rows of B and C are zero. | ||
83 | |||
84 | static void MultiplyAdd2_p8r (dReal *A, dReal *B, dReal *C, | ||
85 | int p, int r, int Askip) | ||
86 | { | ||
87 | int i,j; | ||
88 | dReal sum,*bb,*cc; | ||
89 | dIASSERT (p>0 && r>0 && A && B && C); | ||
90 | bb = B; | ||
91 | for (i=p; i; i--) { | ||
92 | cc = C; | ||
93 | for (j=r; j; j--) { | ||
94 | sum = bb[0]*cc[0]; | ||
95 | sum += bb[1]*cc[1]; | ||
96 | sum += bb[2]*cc[2]; | ||
97 | sum += bb[4]*cc[4]; | ||
98 | sum += bb[5]*cc[5]; | ||
99 | sum += bb[6]*cc[6]; | ||
100 | *(A++) += sum; | ||
101 | cc += 8; | ||
102 | } | ||
103 | A += Askip - r; | ||
104 | bb += 8; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | |||
109 | // this assumes the 4th and 8th rows of B are zero. | ||
110 | |||
111 | static void Multiply0_p81 (dReal *A, dReal *B, dReal *C, int p) | ||
112 | { | ||
113 | int i; | ||
114 | dIASSERT (p>0 && A && B && C); | ||
115 | dReal sum; | ||
116 | for (i=p; i; i--) { | ||
117 | sum = B[0]*C[0]; | ||
118 | sum += B[1]*C[1]; | ||
119 | sum += B[2]*C[2]; | ||
120 | sum += B[4]*C[4]; | ||
121 | sum += B[5]*C[5]; | ||
122 | sum += B[6]*C[6]; | ||
123 | *(A++) = sum; | ||
124 | B += 8; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | |||
129 | // this assumes the 4th and 8th rows of B are zero. | ||
130 | |||
131 | static void MultiplyAdd0_p81 (dReal *A, dReal *B, dReal *C, int p) | ||
132 | { | ||
133 | int i; | ||
134 | dIASSERT (p>0 && A && B && C); | ||
135 | dReal sum; | ||
136 | for (i=p; i; i--) { | ||
137 | sum = B[0]*C[0]; | ||
138 | sum += B[1]*C[1]; | ||
139 | sum += B[2]*C[2]; | ||
140 | sum += B[4]*C[4]; | ||
141 | sum += B[5]*C[5]; | ||
142 | sum += B[6]*C[6]; | ||
143 | *(A++) += sum; | ||
144 | B += 8; | ||
145 | } | ||
146 | } | ||
147 | |||
148 | |||
149 | // this assumes the 4th and 8th rows of B are zero. | ||
150 | |||
151 | static void MultiplyAdd1_8q1 (dReal *A, dReal *B, dReal *C, int q) | ||
152 | { | ||
153 | int k; | ||
154 | dReal sum; | ||
155 | dIASSERT (q>0 && A && B && C); | ||
156 | sum = 0; | ||
157 | for (k=0; k<q; k++) sum += B[k*8] * C[k]; | ||
158 | A[0] += sum; | ||
159 | sum = 0; | ||
160 | for (k=0; k<q; k++) sum += B[1+k*8] * C[k]; | ||
161 | A[1] += sum; | ||
162 | sum = 0; | ||
163 | for (k=0; k<q; k++) sum += B[2+k*8] * C[k]; | ||
164 | A[2] += sum; | ||
165 | sum = 0; | ||
166 | for (k=0; k<q; k++) sum += B[4+k*8] * C[k]; | ||
167 | A[4] += sum; | ||
168 | sum = 0; | ||
169 | for (k=0; k<q; k++) sum += B[5+k*8] * C[k]; | ||
170 | A[5] += sum; | ||
171 | sum = 0; | ||
172 | for (k=0; k<q; k++) sum += B[6+k*8] * C[k]; | ||
173 | A[6] += sum; | ||
174 | } | ||
175 | |||
176 | |||
177 | // this assumes the 4th and 8th rows of B are zero. | ||
178 | |||
179 | static void Multiply1_8q1 (dReal *A, dReal *B, dReal *C, int q) | ||
180 | { | ||
181 | int k; | ||
182 | dReal sum; | ||
183 | dIASSERT (q>0 && A && B && C); | ||
184 | sum = 0; | ||
185 | for (k=0; k<q; k++) sum += B[k*8] * C[k]; | ||
186 | A[0] = sum; | ||
187 | sum = 0; | ||
188 | for (k=0; k<q; k++) sum += B[1+k*8] * C[k]; | ||
189 | A[1] = sum; | ||
190 | sum = 0; | ||
191 | for (k=0; k<q; k++) sum += B[2+k*8] * C[k]; | ||
192 | A[2] = sum; | ||
193 | sum = 0; | ||
194 | for (k=0; k<q; k++) sum += B[4+k*8] * C[k]; | ||
195 | A[4] = sum; | ||
196 | sum = 0; | ||
197 | for (k=0; k<q; k++) sum += B[5+k*8] * C[k]; | ||
198 | A[5] = sum; | ||
199 | sum = 0; | ||
200 | for (k=0; k<q; k++) sum += B[6+k*8] * C[k]; | ||
201 | A[6] = sum; | ||
202 | } | ||
203 | |||
204 | //**************************************************************************** | ||
205 | // body rotation | ||
206 | |||
207 | // return sin(x)/x. this has a singularity at 0 so special handling is needed | ||
208 | // for small arguments. | ||
209 | |||
210 | static inline dReal sinc (dReal x) | ||
211 | { | ||
212 | // if |x| < 1e-4 then use a taylor series expansion. this two term expansion | ||
213 | // is actually accurate to one LS bit within this range if double precision | ||
214 | // is being used - so don't worry! | ||
215 | if (dFabs(x) < 1.0e-4) return REAL(1.0) - x*x*REAL(0.166666666666666666667); | ||
216 | else return dSin(x)/x; | ||
217 | } | ||
218 | |||
219 | |||
220 | // given a body b, apply its linear and angular rotation over the time | ||
221 | // interval h, thereby adjusting its position and orientation. | ||
222 | |||
223 | static inline void moveAndRotateBody (dxBody *b, dReal h) | ||
224 | { | ||
225 | int j; | ||
226 | |||
227 | // handle linear velocity | ||
228 | for (j=0; j<3; j++) b->pos[j] += h * b->lvel[j]; | ||
229 | |||
230 | if (b->flags & dxBodyFlagFiniteRotation) { | ||
231 | dVector3 irv; // infitesimal rotation vector | ||
232 | dQuaternion q; // quaternion for finite rotation | ||
233 | |||
234 | if (b->flags & dxBodyFlagFiniteRotationAxis) { | ||
235 | // split the angular velocity vector into a component along the finite | ||
236 | // rotation axis, and a component orthogonal to it. | ||
237 | dVector3 frv,irv; // finite rotation vector | ||
238 | dReal k = dDOT (b->finite_rot_axis,b->avel); | ||
239 | frv[0] = b->finite_rot_axis[0] * k; | ||
240 | frv[1] = b->finite_rot_axis[1] * k; | ||
241 | frv[2] = b->finite_rot_axis[2] * k; | ||
242 | irv[0] = b->avel[0] - frv[0]; | ||
243 | irv[1] = b->avel[1] - frv[1]; | ||
244 | irv[2] = b->avel[2] - frv[2]; | ||
245 | |||
246 | // make a rotation quaternion q that corresponds to frv * h. | ||
247 | // compare this with the full-finite-rotation case below. | ||
248 | h *= REAL(0.5); | ||
249 | dReal theta = k * h; | ||
250 | q[0] = dCos(theta); | ||
251 | dReal s = sinc(theta) * h; | ||
252 | q[1] = frv[0] * s; | ||
253 | q[2] = frv[1] * s; | ||
254 | q[3] = frv[2] * s; | ||
255 | } | ||
256 | else { | ||
257 | // make a rotation quaternion q that corresponds to w * h | ||
258 | dReal wlen = dSqrt (b->avel[0]*b->avel[0] + b->avel[1]*b->avel[1] + | ||
259 | b->avel[2]*b->avel[2]); | ||
260 | h *= REAL(0.5); | ||
261 | dReal theta = wlen * h; | ||
262 | q[0] = dCos(theta); | ||
263 | dReal s = sinc(theta) * h; | ||
264 | q[1] = b->avel[0] * s; | ||
265 | q[2] = b->avel[1] * s; | ||
266 | q[3] = b->avel[2] * s; | ||
267 | } | ||
268 | |||
269 | // do the finite rotation | ||
270 | dQuaternion q2; | ||
271 | dQMultiply0 (q2,q,b->q); | ||
272 | for (j=0; j<4; j++) b->q[j] = q2[j]; | ||
273 | |||
274 | // do the infitesimal rotation if required | ||
275 | if (b->flags & dxBodyFlagFiniteRotationAxis) { | ||
276 | dReal dq[4]; | ||
277 | dWtoDQ (irv,b->q,dq); | ||
278 | for (j=0; j<4; j++) b->q[j] += h * dq[j]; | ||
279 | } | ||
280 | } | ||
281 | else { | ||
282 | // the normal way - do an infitesimal rotation | ||
283 | dReal dq[4]; | ||
284 | dWtoDQ (b->avel,b->q,dq); | ||
285 | for (j=0; j<4; j++) b->q[j] += h * dq[j]; | ||
286 | } | ||
287 | |||
288 | // normalize the quaternion and convert it to a rotation matrix | ||
289 | dNormalize4 (b->q); | ||
290 | dQtoR (b->q,b->R); | ||
291 | |||
292 | // notify all attached geoms that this body has moved | ||
293 | for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom)) | ||
294 | dGeomMoved (geom); | ||
295 | } | ||
296 | |||
297 | //**************************************************************************** | ||
298 | // the slow, but sure way | ||
299 | // note that this does not do any joint feedback! | ||
300 | |||
301 | // given lists of bodies and joints that form an island, perform a first | ||
302 | // order timestep. | ||
303 | // | ||
304 | // `body' is the body array, `nb' is the size of the array. | ||
305 | // `_joint' is the body array, `nj' is the size of the array. | ||
306 | |||
307 | void dInternalStepIsland_x1 (dxWorld *world, dxBody * const *body, int nb, | ||
308 | dxJoint * const *_joint, int nj, dReal stepsize) | ||
309 | { | ||
310 | int i,j,k; | ||
311 | int n6 = 6*nb; | ||
312 | |||
313 | # ifdef TIMING | ||
314 | dTimerStart("preprocessing"); | ||
315 | # endif | ||
316 | |||
317 | // number all bodies in the body list - set their tag values | ||
318 | for (i=0; i<nb; i++) body[i]->tag = i; | ||
319 | |||
320 | // make a local copy of the joint array, because we might want to modify it. | ||
321 | // (the "dxJoint *const*" declaration says we're allowed to modify the joints | ||
322 | // but not the joint array, because the caller might need it unchanged). | ||
323 | dxJoint **joint = (dxJoint**) ALLOCA (nj * sizeof(dxJoint*)); | ||
324 | memcpy (joint,_joint,nj * sizeof(dxJoint*)); | ||
325 | |||
326 | // for all bodies, compute the inertia tensor and its inverse in the global | ||
327 | // frame, and compute the rotational force and add it to the torque | ||
328 | // accumulator. | ||
329 | // @@@ check computation of rotational force. | ||
330 | dReal *I = (dReal*) ALLOCA (3*nb*4 * sizeof(dReal)); | ||
331 | dReal *invI = (dReal*) ALLOCA (3*nb*4 * sizeof(dReal)); | ||
332 | |||
333 | //dSetZero (I,3*nb*4); | ||
334 | //dSetZero (invI,3*nb*4); | ||
335 | for (i=0; i<nb; i++) { | ||
336 | dReal tmp[12]; | ||
337 | // compute inertia tensor in global frame | ||
338 | dMULTIPLY2_333 (tmp,body[i]->mass.I,body[i]->R); | ||
339 | dMULTIPLY0_333 (I+i*12,body[i]->R,tmp); | ||
340 | // compute inverse inertia tensor in global frame | ||
341 | dMULTIPLY2_333 (tmp,body[i]->invI,body[i]->R); | ||
342 | dMULTIPLY0_333 (invI+i*12,body[i]->R,tmp); | ||
343 | // compute rotational force | ||
344 | dMULTIPLY0_331 (tmp,I+i*12,body[i]->avel); | ||
345 | dCROSS (body[i]->tacc,-=,body[i]->avel,tmp); | ||
346 | } | ||
347 | |||
348 | // add the gravity force to all bodies | ||
349 | for (i=0; i<nb; i++) { | ||
350 | if ((body[i]->flags & dxBodyNoGravity)==0) { | ||
351 | body[i]->facc[0] += body[i]->mass.mass * world->gravity[0]; | ||
352 | body[i]->facc[1] += body[i]->mass.mass * world->gravity[1]; | ||
353 | body[i]->facc[2] += body[i]->mass.mass * world->gravity[2]; | ||
354 | } | ||
355 | } | ||
356 | |||
357 | // get m = total constraint dimension, nub = number of unbounded variables. | ||
358 | // create constraint offset array and number-of-rows array for all joints. | ||
359 | // the constraints are re-ordered as follows: the purely unbounded | ||
360 | // constraints, the mixed unbounded + LCP constraints, and last the purely | ||
361 | // LCP constraints. | ||
362 | // | ||
363 | // joints with m=0 are inactive and are removed from the joints array | ||
364 | // entirely, so that the code that follows does not consider them. | ||
365 | int m = 0; | ||
366 | dxJoint::Info1 *info = (dxJoint::Info1*) ALLOCA (nj*sizeof(dxJoint::Info1)); | ||
367 | int *ofs = (int*) ALLOCA (nj*sizeof(int)); | ||
368 | for (i=0, j=0; j<nj; j++) { // i=dest, j=src | ||
369 | joint[j]->vtable->getInfo1 (joint[j],info+i); | ||
370 | dIASSERT (info[i].m >= 0 && info[i].m <= 6 && | ||
371 | info[i].nub >= 0 && info[i].nub <= info[i].m); | ||
372 | if (info[i].m > 0) { | ||
373 | joint[i] = joint[j]; | ||
374 | i++; | ||
375 | } | ||
376 | } | ||
377 | nj = i; | ||
378 | |||
379 | // the purely unbounded constraints | ||
380 | for (i=0; i<nj; i++) if (info[i].nub == info[i].m) { | ||
381 | ofs[i] = m; | ||
382 | m += info[i].m; | ||
383 | } | ||
384 | int nub = m; | ||
385 | // the mixed unbounded + LCP constraints | ||
386 | for (i=0; i<nj; i++) if (info[i].nub > 0 && info[i].nub < info[i].m) { | ||
387 | ofs[i] = m; | ||
388 | m += info[i].m; | ||
389 | } | ||
390 | // the purely LCP constraints | ||
391 | for (i=0; i<nj; i++) if (info[i].nub == 0) { | ||
392 | ofs[i] = m; | ||
393 | m += info[i].m; | ||
394 | } | ||
395 | |||
396 | // create (6*nb,6*nb) inverse mass matrix `invM', and fill it with mass | ||
397 | // parameters | ||
398 | # ifdef TIMING | ||
399 | dTimerNow ("create mass matrix"); | ||
400 | # endif | ||
401 | int nskip = dPAD (n6); | ||
402 | dReal *invM = (dReal*) ALLOCA (n6*nskip*sizeof(dReal)); | ||
403 | dSetZero (invM,n6*nskip); | ||
404 | for (i=0; i<nb; i++) { | ||
405 | dReal *MM = invM+(i*6)*nskip+(i*6); | ||
406 | MM[0] = body[i]->invMass; | ||
407 | MM[nskip+1] = body[i]->invMass; | ||
408 | MM[2*nskip+2] = body[i]->invMass; | ||
409 | MM += 3*nskip+3; | ||
410 | for (j=0; j<3; j++) for (k=0; k<3; k++) { | ||
411 | MM[j*nskip+k] = invI[i*12+j*4+k]; | ||
412 | } | ||
413 | } | ||
414 | |||
415 | // assemble some body vectors: fe = external forces, v = velocities | ||
416 | dReal *fe = (dReal*) ALLOCA (n6 * sizeof(dReal)); | ||
417 | dReal *v = (dReal*) ALLOCA (n6 * sizeof(dReal)); | ||
418 | //dSetZero (fe,n6); | ||
419 | //dSetZero (v,n6); | ||
420 | for (i=0; i<nb; i++) { | ||
421 | for (j=0; j<3; j++) fe[i*6+j] = body[i]->facc[j]; | ||
422 | for (j=0; j<3; j++) fe[i*6+3+j] = body[i]->tacc[j]; | ||
423 | for (j=0; j<3; j++) v[i*6+j] = body[i]->lvel[j]; | ||
424 | for (j=0; j<3; j++) v[i*6+3+j] = body[i]->avel[j]; | ||
425 | } | ||
426 | |||
427 | // this will be set to the velocity update | ||
428 | dReal *vnew = (dReal*) ALLOCA (n6 * sizeof(dReal)); | ||
429 | dSetZero (vnew,n6); | ||
430 | |||
431 | // if there are constraints, compute cforce | ||
432 | if (m > 0) { | ||
433 | // create a constraint equation right hand side vector `c', a constraint | ||
434 | // force mixing vector `cfm', and LCP low and high bound vectors, and an | ||
435 | // 'findex' vector. | ||
436 | dReal *c = (dReal*) ALLOCA (m*sizeof(dReal)); | ||
437 | dReal *cfm = (dReal*) ALLOCA (m*sizeof(dReal)); | ||
438 | dReal *lo = (dReal*) ALLOCA (m*sizeof(dReal)); | ||
439 | dReal *hi = (dReal*) ALLOCA (m*sizeof(dReal)); | ||
440 | int *findex = (int*) alloca (m*sizeof(int)); | ||
441 | dSetZero (c,m); | ||
442 | dSetValue (cfm,m,world->global_cfm); | ||
443 | dSetValue (lo,m,-dInfinity); | ||
444 | dSetValue (hi,m, dInfinity); | ||
445 | for (i=0; i<m; i++) findex[i] = -1; | ||
446 | |||
447 | // create (m,6*nb) jacobian mass matrix `J', and fill it with constraint | ||
448 | // data. also fill the c vector. | ||
449 | # ifdef TIMING | ||
450 | dTimerNow ("create J"); | ||
451 | # endif | ||
452 | dReal *J = (dReal*) ALLOCA (m*nskip*sizeof(dReal)); | ||
453 | dSetZero (J,m*nskip); | ||
454 | dxJoint::Info2 Jinfo; | ||
455 | Jinfo.rowskip = nskip; | ||
456 | Jinfo.fps = dRecip(stepsize); | ||
457 | Jinfo.erp = world->global_erp; | ||
458 | for (i=0; i<nj; i++) { | ||
459 | Jinfo.J1l = J + nskip*ofs[i] + 6*joint[i]->node[0].body->tag; | ||
460 | Jinfo.J1a = Jinfo.J1l + 3; | ||
461 | if (joint[i]->node[1].body) { | ||
462 | Jinfo.J2l = J + nskip*ofs[i] + 6*joint[i]->node[1].body->tag; | ||
463 | Jinfo.J2a = Jinfo.J2l + 3; | ||
464 | } | ||
465 | else { | ||
466 | Jinfo.J2l = 0; | ||
467 | Jinfo.J2a = 0; | ||
468 | } | ||
469 | Jinfo.c = c + ofs[i]; | ||
470 | Jinfo.cfm = cfm + ofs[i]; | ||
471 | Jinfo.lo = lo + ofs[i]; | ||
472 | Jinfo.hi = hi + ofs[i]; | ||
473 | Jinfo.findex = findex + ofs[i]; | ||
474 | joint[i]->vtable->getInfo2 (joint[i],&Jinfo); | ||
475 | // adjust returned findex values for global index numbering | ||
476 | for (j=0; j<info[i].m; j++) { | ||
477 | if (findex[ofs[i] + j] >= 0) findex[ofs[i] + j] += ofs[i]; | ||
478 | } | ||
479 | } | ||
480 | |||
481 | // compute A = J*invM*J' | ||
482 | # ifdef TIMING | ||
483 | dTimerNow ("compute A"); | ||
484 | # endif | ||
485 | dReal *JinvM = (dReal*) ALLOCA (m*nskip*sizeof(dReal)); | ||
486 | //dSetZero (JinvM,m*nskip); | ||
487 | dMultiply0 (JinvM,J,invM,m,n6,n6); | ||
488 | int mskip = dPAD(m); | ||
489 | dReal *A = (dReal*) ALLOCA (m*mskip*sizeof(dReal)); | ||
490 | //dSetZero (A,m*mskip); | ||
491 | dMultiply2 (A,JinvM,J,m,n6,m); | ||
492 | |||
493 | // add cfm to the diagonal of A | ||
494 | for (i=0; i<m; i++) A[i*mskip+i] += cfm[i] * Jinfo.fps; | ||
495 | |||
496 | # ifdef COMPARE_METHODS | ||
497 | comparator.nextMatrix (A,m,m,1,"A"); | ||
498 | # endif | ||
499 | |||
500 | // compute `rhs', the right hand side of the equation J*a=c | ||
501 | # ifdef TIMING | ||
502 | dTimerNow ("compute rhs"); | ||
503 | # endif | ||
504 | dReal *tmp1 = (dReal*) ALLOCA (n6 * sizeof(dReal)); | ||
505 | //dSetZero (tmp1,n6); | ||
506 | dMultiply0 (tmp1,invM,fe,n6,n6,1); | ||
507 | for (i=0; i<n6; i++) tmp1[i] += v[i]/stepsize; | ||
508 | dReal *rhs = (dReal*) ALLOCA (m * sizeof(dReal)); | ||
509 | //dSetZero (rhs,m); | ||
510 | dMultiply0 (rhs,J,tmp1,m,n6,1); | ||
511 | for (i=0; i<m; i++) rhs[i] = c[i]/stepsize - rhs[i]; | ||
512 | |||
513 | # ifdef COMPARE_METHODS | ||
514 | comparator.nextMatrix (c,m,1,0,"c"); | ||
515 | comparator.nextMatrix (rhs,m,1,0,"rhs"); | ||
516 | # endif | ||
517 | |||
518 | // solve the LCP problem and get lambda. | ||
519 | // this will destroy A but that's okay | ||
520 | # ifdef TIMING | ||
521 | dTimerNow ("solving LCP problem"); | ||
522 | # endif | ||
523 | dReal *lambda = (dReal*) ALLOCA (m * sizeof(dReal)); | ||
524 | dReal *residual = (dReal*) ALLOCA (m * sizeof(dReal)); | ||
525 | dSolveLCP (m,A,lambda,rhs,residual,nub,lo,hi,findex); | ||
526 | |||
527 | // OLD WAY - direct factor and solve | ||
528 | // | ||
529 | // // factorize A (L*L'=A) | ||
530 | //# ifdef TIMING | ||
531 | // dTimerNow ("factorize A"); | ||
532 | //# endif | ||
533 | // dReal *L = (dReal*) ALLOCA (m*mskip*sizeof(dReal)); | ||
534 | // memcpy (L,A,m*mskip*sizeof(dReal)); | ||
535 | // if (dFactorCholesky (L,m)==0) dDebug (0,"A is not positive definite"); | ||
536 | // | ||
537 | // // compute lambda | ||
538 | //# ifdef TIMING | ||
539 | // dTimerNow ("compute lambda"); | ||
540 | //# endif | ||
541 | // dReal *lambda = (dReal*) ALLOCA (m * sizeof(dReal)); | ||
542 | // memcpy (lambda,rhs,m * sizeof(dReal)); | ||
543 | // dSolveCholesky (L,lambda,m); | ||
544 | |||
545 | # ifdef COMPARE_METHODS | ||
546 | comparator.nextMatrix (lambda,m,1,0,"lambda"); | ||
547 | # endif | ||
548 | |||
549 | // compute the velocity update `vnew' | ||
550 | # ifdef TIMING | ||
551 | dTimerNow ("compute velocity update"); | ||
552 | # endif | ||
553 | dMultiply1 (tmp1,J,lambda,n6,m,1); | ||
554 | for (i=0; i<n6; i++) tmp1[i] += fe[i]; | ||
555 | dMultiply0 (vnew,invM,tmp1,n6,n6,1); | ||
556 | for (i=0; i<n6; i++) vnew[i] = v[i] + stepsize*vnew[i]; | ||
557 | |||
558 | // see if the constraint has worked: compute J*vnew and make sure it equals | ||
559 | // `c' (to within a certain tolerance). | ||
560 | # ifdef TIMING | ||
561 | dTimerNow ("verify constraint equation"); | ||
562 | # endif | ||
563 | dMultiply0 (tmp1,J,vnew,m,n6,1); | ||
564 | dReal err = 0; | ||
565 | for (i=0; i<m; i++) err += dFabs(tmp1[i]-c[i]); | ||
566 | printf ("%.6e\n",err); | ||
567 | } | ||
568 | else { | ||
569 | // no constraints | ||
570 | dMultiply0 (vnew,invM,fe,n6,n6,1); | ||
571 | for (i=0; i<n6; i++) vnew[i] = v[i] + stepsize*vnew[i]; | ||
572 | } | ||
573 | |||
574 | # ifdef COMPARE_METHODS | ||
575 | comparator.nextMatrix (vnew,n6,1,0,"vnew"); | ||
576 | # endif | ||
577 | |||
578 | // apply the velocity update to the bodies | ||
579 | # ifdef TIMING | ||
580 | dTimerNow ("update velocity"); | ||
581 | # endif | ||
582 | for (i=0; i<nb; i++) { | ||
583 | for (j=0; j<3; j++) body[i]->lvel[j] = vnew[i*6+j]; | ||
584 | for (j=0; j<3; j++) body[i]->avel[j] = vnew[i*6+3+j]; | ||
585 | } | ||
586 | |||
587 | // update the position and orientation from the new linear/angular velocity | ||
588 | // (over the given timestep) | ||
589 | # ifdef TIMING | ||
590 | dTimerNow ("update position"); | ||
591 | # endif | ||
592 | for (i=0; i<nb; i++) moveAndRotateBody (body[i],stepsize); | ||
593 | |||
594 | # ifdef TIMING | ||
595 | dTimerNow ("tidy up"); | ||
596 | # endif | ||
597 | |||
598 | // zero all force accumulators | ||
599 | for (i=0; i<nb; i++) { | ||
600 | body[i]->facc[0] = 0; | ||
601 | body[i]->facc[1] = 0; | ||
602 | body[i]->facc[2] = 0; | ||
603 | body[i]->facc[3] = 0; | ||
604 | body[i]->tacc[0] = 0; | ||
605 | body[i]->tacc[1] = 0; | ||
606 | body[i]->tacc[2] = 0; | ||
607 | body[i]->tacc[3] = 0; | ||
608 | } | ||
609 | |||
610 | # ifdef TIMING | ||
611 | dTimerEnd(); | ||
612 | if (m > 0) dTimerReport (stdout,1); | ||
613 | # endif | ||
614 | } | ||
615 | |||
616 | //**************************************************************************** | ||
617 | // an optimized version of dInternalStepIsland1() | ||
618 | |||
619 | void dInternalStepIsland_x2 (dxWorld *world, dxBody * const *body, int nb, | ||
620 | dxJoint * const *_joint, int nj, dReal stepsize) | ||
621 | { | ||
622 | int i,j,k; | ||
623 | # ifdef TIMING | ||
624 | dTimerStart("preprocessing"); | ||
625 | # endif | ||
626 | |||
627 | dReal stepsize1 = dRecip(stepsize); | ||
628 | |||
629 | // number all bodies in the body list - set their tag values | ||
630 | for (i=0; i<nb; i++) body[i]->tag = i; | ||
631 | |||
632 | // make a local copy of the joint array, because we might want to modify it. | ||
633 | // (the "dxJoint *const*" declaration says we're allowed to modify the joints | ||
634 | // but not the joint array, because the caller might need it unchanged). | ||
635 | dxJoint **joint = (dxJoint**) ALLOCA (nj * sizeof(dxJoint*)); | ||
636 | memcpy (joint,_joint,nj * sizeof(dxJoint*)); | ||
637 | |||
638 | // for all bodies, compute the inertia tensor and its inverse in the global | ||
639 | // frame, and compute the rotational force and add it to the torque | ||
640 | // accumulator. I and invI are vertically stacked 3x4 matrices, one per body. | ||
641 | // @@@ check computation of rotational force. | ||
642 | dReal *I = (dReal*) ALLOCA (3*nb*4 * sizeof(dReal)); | ||
643 | dReal *invI = (dReal*) ALLOCA (3*nb*4 * sizeof(dReal)); | ||
644 | |||
645 | //dSetZero (I,3*nb*4); | ||
646 | //dSetZero (invI,3*nb*4); | ||
647 | for (i=0; i<nb; i++) { | ||
648 | dReal tmp[12]; | ||
649 | // compute inertia tensor in global frame | ||
650 | dMULTIPLY2_333 (tmp,body[i]->mass.I,body[i]->R); | ||
651 | dMULTIPLY0_333 (I+i*12,body[i]->R,tmp); | ||
652 | // compute inverse inertia tensor in global frame | ||
653 | dMULTIPLY2_333 (tmp,body[i]->invI,body[i]->R); | ||
654 | dMULTIPLY0_333 (invI+i*12,body[i]->R,tmp); | ||
655 | // compute rotational force | ||
656 | dMULTIPLY0_331 (tmp,I+i*12,body[i]->avel); | ||
657 | dCROSS (body[i]->tacc,-=,body[i]->avel,tmp); | ||
658 | } | ||
659 | |||
660 | // add the gravity force to all bodies | ||
661 | for (i=0; i<nb; i++) { | ||
662 | if ((body[i]->flags & dxBodyNoGravity)==0) { | ||
663 | body[i]->facc[0] += body[i]->mass.mass * world->gravity[0]; | ||
664 | body[i]->facc[1] += body[i]->mass.mass * world->gravity[1]; | ||
665 | body[i]->facc[2] += body[i]->mass.mass * world->gravity[2]; | ||
666 | } | ||
667 | } | ||
668 | |||
669 | // get m = total constraint dimension, nub = number of unbounded variables. | ||
670 | // create constraint offset array and number-of-rows array for all joints. | ||
671 | // the constraints are re-ordered as follows: the purely unbounded | ||
672 | // constraints, the mixed unbounded + LCP constraints, and last the purely | ||
673 | // LCP constraints. this assists the LCP solver to put all unbounded | ||
674 | // variables at the start for a quick factorization. | ||
675 | // | ||
676 | // joints with m=0 are inactive and are removed from the joints array | ||
677 | // entirely, so that the code that follows does not consider them. | ||
678 | // also number all active joints in the joint list (set their tag values). | ||
679 | // inactive joints receive a tag value of -1. | ||
680 | |||
681 | int m = 0; | ||
682 | dxJoint::Info1 *info = (dxJoint::Info1*) ALLOCA (nj*sizeof(dxJoint::Info1)); | ||
683 | int *ofs = (int*) ALLOCA (nj*sizeof(int)); | ||
684 | for (i=0, j=0; j<nj; j++) { // i=dest, j=src | ||
685 | joint[j]->vtable->getInfo1 (joint[j],info+i); | ||
686 | dIASSERT (info[i].m >= 0 && info[i].m <= 6 && | ||
687 | info[i].nub >= 0 && info[i].nub <= info[i].m); | ||
688 | if (info[i].m > 0) { | ||
689 | joint[i] = joint[j]; | ||
690 | joint[i]->tag = i; | ||
691 | i++; | ||
692 | } | ||
693 | else { | ||
694 | joint[j]->tag = -1; | ||
695 | } | ||
696 | } | ||
697 | nj = i; | ||
698 | |||
699 | // the purely unbounded constraints | ||
700 | for (i=0; i<nj; i++) if (info[i].nub == info[i].m) { | ||
701 | ofs[i] = m; | ||
702 | m += info[i].m; | ||
703 | } | ||
704 | int nub = m; | ||
705 | // the mixed unbounded + LCP constraints | ||
706 | for (i=0; i<nj; i++) if (info[i].nub > 0 && info[i].nub < info[i].m) { | ||
707 | ofs[i] = m; | ||
708 | m += info[i].m; | ||
709 | } | ||
710 | // the purely LCP constraints | ||
711 | for (i=0; i<nj; i++) if (info[i].nub == 0) { | ||
712 | ofs[i] = m; | ||
713 | m += info[i].m; | ||
714 | } | ||
715 | |||
716 | // this will be set to the force due to the constraints | ||
717 | dReal *cforce = (dReal*) ALLOCA (nb*8 * sizeof(dReal)); | ||
718 | dSetZero (cforce,nb*8); | ||
719 | |||
720 | // if there are constraints, compute cforce | ||
721 | if (m > 0) { | ||
722 | // create a constraint equation right hand side vector `c', a constraint | ||
723 | // force mixing vector `cfm', and LCP low and high bound vectors, and an | ||
724 | // 'findex' vector. | ||
725 | dReal *c = (dReal*) ALLOCA (m*sizeof(dReal)); | ||
726 | dReal *cfm = (dReal*) ALLOCA (m*sizeof(dReal)); | ||
727 | dReal *lo = (dReal*) ALLOCA (m*sizeof(dReal)); | ||
728 | dReal *hi = (dReal*) ALLOCA (m*sizeof(dReal)); | ||
729 | int *findex = (int*) alloca (m*sizeof(int)); | ||
730 | dSetZero (c,m); | ||
731 | dSetValue (cfm,m,world->global_cfm); | ||
732 | dSetValue (lo,m,-dInfinity); | ||
733 | dSetValue (hi,m, dInfinity); | ||
734 | for (i=0; i<m; i++) findex[i] = -1; | ||
735 | |||
736 | // get jacobian data from constraints. a (2*m)x8 matrix will be created | ||
737 | // to store the two jacobian blocks from each constraint. it has this | ||
738 | // format: | ||
739 | // | ||
740 | // l l l 0 a a a 0 \ . | ||
741 | // l l l 0 a a a 0 }-- jacobian body 1 block for joint 0 (3 rows) | ||
742 | // l l l 0 a a a 0 / | ||
743 | // l l l 0 a a a 0 \ . | ||
744 | // l l l 0 a a a 0 }-- jacobian body 2 block for joint 0 (3 rows) | ||
745 | // l l l 0 a a a 0 / | ||
746 | // l l l 0 a a a 0 }--- jacobian body 1 block for joint 1 (1 row) | ||
747 | // l l l 0 a a a 0 }--- jacobian body 2 block for joint 1 (1 row) | ||
748 | // etc... | ||
749 | // | ||
750 | // (lll) = linear jacobian data | ||
751 | // (aaa) = angular jacobian data | ||
752 | // | ||
753 | # ifdef TIMING | ||
754 | dTimerNow ("create J"); | ||
755 | # endif | ||
756 | dReal *J = (dReal*) ALLOCA (2*m*8*sizeof(dReal)); | ||
757 | dSetZero (J,2*m*8); | ||
758 | dxJoint::Info2 Jinfo; | ||
759 | Jinfo.rowskip = 8; | ||
760 | Jinfo.fps = stepsize1; | ||
761 | Jinfo.erp = world->global_erp; | ||
762 | for (i=0; i<nj; i++) { | ||
763 | Jinfo.J1l = J + 2*8*ofs[i]; | ||
764 | Jinfo.J1a = Jinfo.J1l + 4; | ||
765 | Jinfo.J2l = Jinfo.J1l + 8*info[i].m; | ||
766 | Jinfo.J2a = Jinfo.J2l + 4; | ||
767 | Jinfo.c = c + ofs[i]; | ||
768 | Jinfo.cfm = cfm + ofs[i]; | ||
769 | Jinfo.lo = lo + ofs[i]; | ||
770 | Jinfo.hi = hi + ofs[i]; | ||
771 | Jinfo.findex = findex + ofs[i]; | ||
772 | joint[i]->vtable->getInfo2 (joint[i],&Jinfo); | ||
773 | // adjust returned findex values for global index numbering | ||
774 | for (j=0; j<info[i].m; j++) { | ||
775 | if (findex[ofs[i] + j] >= 0) findex[ofs[i] + j] += ofs[i]; | ||
776 | } | ||
777 | } | ||
778 | |||
779 | // compute A = J*invM*J'. first compute JinvM = J*invM. this has the same | ||
780 | // format as J so we just go through the constraints in J multiplying by | ||
781 | // the appropriate scalars and matrices. | ||
782 | # ifdef TIMING | ||
783 | dTimerNow ("compute A"); | ||
784 | # endif | ||
785 | dReal *JinvM = (dReal*) ALLOCA (2*m*8*sizeof(dReal)); | ||
786 | dSetZero (JinvM,2*m*8); | ||
787 | for (i=0; i<nj; i++) { | ||
788 | int b = joint[i]->node[0].body->tag; | ||
789 | dReal body_invMass = body[b]->invMass; | ||
790 | dReal *body_invI = invI + b*12; | ||
791 | dReal *Jsrc = J + 2*8*ofs[i]; | ||
792 | dReal *Jdst = JinvM + 2*8*ofs[i]; | ||
793 | for (j=info[i].m-1; j>=0; j--) { | ||
794 | for (k=0; k<3; k++) Jdst[k] = Jsrc[k] * body_invMass; | ||
795 | dMULTIPLY0_133 (Jdst+4,Jsrc+4,body_invI); | ||
796 | Jsrc += 8; | ||
797 | Jdst += 8; | ||
798 | } | ||
799 | if (joint[i]->node[1].body) { | ||
800 | b = joint[i]->node[1].body->tag; | ||
801 | body_invMass = body[b]->invMass; | ||
802 | body_invI = invI + b*12; | ||
803 | for (j=info[i].m-1; j>=0; j--) { | ||
804 | for (k=0; k<3; k++) Jdst[k] = Jsrc[k] * body_invMass; | ||
805 | dMULTIPLY0_133 (Jdst+4,Jsrc+4,body_invI); | ||
806 | Jsrc += 8; | ||
807 | Jdst += 8; | ||
808 | } | ||
809 | } | ||
810 | } | ||
811 | |||
812 | // now compute A = JinvM * J'. A's rows and columns are grouped by joint, | ||
813 | // i.e. in the same way as the rows of J. block (i,j) of A is only nonzero | ||
814 | // if joints i and j have at least one body in common. this fact suggests | ||
815 | // the algorithm used to fill A: | ||
816 | // | ||
817 | // for b = all bodies | ||
818 | // n = number of joints attached to body b | ||
819 | // for i = 1..n | ||
820 | // for j = i+1..n | ||
821 | // ii = actual joint number for i | ||
822 | // jj = actual joint number for j | ||
823 | // // (ii,jj) will be set to all pairs of joints around body b | ||
824 | // compute blockwise: A(ii,jj) += JinvM(ii) * J(jj)' | ||
825 | // | ||
826 | // this algorithm catches all pairs of joints that have at least one body | ||
827 | // in common. it does not compute the diagonal blocks of A however - | ||
828 | // another similar algorithm does that. | ||
829 | |||
830 | int mskip = dPAD(m); | ||
831 | dReal *A = (dReal*) ALLOCA (m*mskip*sizeof(dReal)); | ||
832 | dSetZero (A,m*mskip); | ||
833 | for (i=0; i<nb; i++) { | ||
834 | for (dxJointNode *n1=body[i]->firstjoint; n1; n1=n1->next) { | ||
835 | for (dxJointNode *n2=n1->next; n2; n2=n2->next) { | ||
836 | // get joint numbers and ensure ofs[j1] >= ofs[j2] | ||
837 | int j1 = n1->joint->tag; | ||
838 | int j2 = n2->joint->tag; | ||
839 | if (ofs[j1] < ofs[j2]) { | ||
840 | int tmp = j1; | ||
841 | j1 = j2; | ||
842 | j2 = tmp; | ||
843 | } | ||
844 | |||
845 | // if either joint was tagged as -1 then it is an inactive (m=0) | ||
846 | // joint that should not be considered | ||
847 | if (j1==-1 || j2==-1) continue; | ||
848 | |||
849 | // determine if body i is the 1st or 2nd body of joints j1 and j2 | ||
850 | int jb1 = (joint[j1]->node[1].body == body[i]); | ||
851 | int jb2 = (joint[j2]->node[1].body == body[i]); | ||
852 | // jb1/jb2 must be 0 for joints with only one body | ||
853 | dIASSERT(joint[j1]->node[1].body || jb1==0); | ||
854 | dIASSERT(joint[j2]->node[1].body || jb2==0); | ||
855 | |||
856 | // set block of A | ||
857 | MultiplyAdd2_p8r (A + ofs[j1]*mskip + ofs[j2], | ||
858 | JinvM + 2*8*ofs[j1] + jb1*8*info[j1].m, | ||
859 | J + 2*8*ofs[j2] + jb2*8*info[j2].m, | ||
860 | info[j1].m,info[j2].m, mskip); | ||
861 | } | ||
862 | } | ||
863 | } | ||
864 | // compute diagonal blocks of A | ||
865 | for (i=0; i<nj; i++) { | ||
866 | Multiply2_p8r (A + ofs[i]*(mskip+1), | ||
867 | JinvM + 2*8*ofs[i], | ||
868 | J + 2*8*ofs[i], | ||
869 | info[i].m,info[i].m, mskip); | ||
870 | if (joint[i]->node[1].body) { | ||
871 | MultiplyAdd2_p8r (A + ofs[i]*(mskip+1), | ||
872 | JinvM + 2*8*ofs[i] + 8*info[i].m, | ||
873 | J + 2*8*ofs[i] + 8*info[i].m, | ||
874 | info[i].m,info[i].m, mskip); | ||
875 | } | ||
876 | } | ||
877 | |||
878 | // add cfm to the diagonal of A | ||
879 | for (i=0; i<m; i++) A[i*mskip+i] += cfm[i] * stepsize1; | ||
880 | |||
881 | # ifdef COMPARE_METHODS | ||
882 | comparator.nextMatrix (A,m,m,1,"A"); | ||
883 | # endif | ||
884 | |||
885 | // compute the right hand side `rhs' | ||
886 | # ifdef TIMING | ||
887 | dTimerNow ("compute rhs"); | ||
888 | # endif | ||
889 | dReal *tmp1 = (dReal*) ALLOCA (nb*8 * sizeof(dReal)); | ||
890 | //dSetZero (tmp1,nb*8); | ||
891 | // put v/h + invM*fe into tmp1 | ||
892 | for (i=0; i<nb; i++) { | ||
893 | dReal body_invMass = body[i]->invMass; | ||
894 | dReal *body_invI = invI + i*12; | ||
895 | for (j=0; j<3; j++) tmp1[i*8+j] = body[i]->facc[j] * body_invMass + | ||
896 | body[i]->lvel[j] * stepsize1; | ||
897 | dMULTIPLY0_331 (tmp1 + i*8 + 4,body_invI,body[i]->tacc); | ||
898 | for (j=0; j<3; j++) tmp1[i*8+4+j] += body[i]->avel[j] * stepsize1; | ||
899 | } | ||
900 | // put J*tmp1 into rhs | ||
901 | dReal *rhs = (dReal*) ALLOCA (m * sizeof(dReal)); | ||
902 | //dSetZero (rhs,m); | ||
903 | for (i=0; i<nj; i++) { | ||
904 | dReal *JJ = J + 2*8*ofs[i]; | ||
905 | Multiply0_p81 (rhs+ofs[i],JJ, | ||
906 | tmp1 + 8*joint[i]->node[0].body->tag, info[i].m); | ||
907 | if (joint[i]->node[1].body) { | ||
908 | MultiplyAdd0_p81 (rhs+ofs[i],JJ + 8*info[i].m, | ||
909 | tmp1 + 8*joint[i]->node[1].body->tag, info[i].m); | ||
910 | } | ||
911 | } | ||
912 | // complete rhs | ||
913 | for (i=0; i<m; i++) rhs[i] = c[i]*stepsize1 - rhs[i]; | ||
914 | |||
915 | # ifdef COMPARE_METHODS | ||
916 | comparator.nextMatrix (c,m,1,0,"c"); | ||
917 | comparator.nextMatrix (rhs,m,1,0,"rhs"); | ||
918 | # endif | ||
919 | |||
920 | // solve the LCP problem and get lambda. | ||
921 | // this will destroy A but that's okay | ||
922 | # ifdef TIMING | ||
923 | dTimerNow ("solving LCP problem"); | ||
924 | # endif | ||
925 | dReal *lambda = (dReal*) ALLOCA (m * sizeof(dReal)); | ||
926 | dReal *residual = (dReal*) ALLOCA (m * sizeof(dReal)); | ||
927 | dSolveLCP (m,A,lambda,rhs,residual,nub,lo,hi,findex); | ||
928 | |||
929 | // OLD WAY - direct factor and solve | ||
930 | // | ||
931 | // // factorize A (L*L'=A) | ||
932 | //# ifdef TIMING | ||
933 | // dTimerNow ("factorize A"); | ||
934 | //# endif | ||
935 | // dReal *L = (dReal*) ALLOCA (m*mskip*sizeof(dReal)); | ||
936 | // memcpy (L,A,m*mskip*sizeof(dReal)); | ||
937 | //# ifdef FAST_FACTOR | ||
938 | // dFastFactorCholesky (L,m); // does not report non positive definiteness | ||
939 | //# else | ||
940 | // if (dFactorCholesky (L,m)==0) dDebug (0,"A is not positive definite"); | ||
941 | //# endif | ||
942 | // | ||
943 | // // compute lambda | ||
944 | //# ifdef TIMING | ||
945 | // dTimerNow ("compute lambda"); | ||
946 | //# endif | ||
947 | // dReal *lambda = (dReal*) ALLOCA (m * sizeof(dReal)); | ||
948 | // memcpy (lambda,rhs,m * sizeof(dReal)); | ||
949 | // dSolveCholesky (L,lambda,m); | ||
950 | |||
951 | # ifdef COMPARE_METHODS | ||
952 | comparator.nextMatrix (lambda,m,1,0,"lambda"); | ||
953 | # endif | ||
954 | |||
955 | // compute the constraint force `cforce' | ||
956 | # ifdef TIMING | ||
957 | dTimerNow ("compute constraint force"); | ||
958 | # endif | ||
959 | // compute cforce = J'*lambda | ||
960 | for (i=0; i<nj; i++) { | ||
961 | dReal *JJ = J + 2*8*ofs[i]; | ||
962 | dxBody* b1 = joint[i]->node[0].body; | ||
963 | dxBody* b2 = joint[i]->node[1].body; | ||
964 | dJointFeedback *fb = joint[i]->feedback; | ||
965 | |||
966 | /******************** breakable joint contribution ***********************/ | ||
967 | // this saves us a few dereferences | ||
968 | dxJointBreakInfo *jBI = joint[i]->breakInfo; | ||
969 | // we need joint feedback if the joint is breakable or if the user | ||
970 | // requested feedback. | ||
971 | if (jBI||fb) { | ||
972 | // we need feedback on the amount of force that this joint is | ||
973 | // applying to the bodies. we use a slightly slower computation | ||
974 | // that splits out the force components and puts them in the | ||
975 | // feedback structure. | ||
976 | dJointFeedback temp_fb; // temporary storage for joint feedback | ||
977 | dReal data1[8],data2[8]; | ||
978 | Multiply1_8q1 (data1, JJ, lambda+ofs[i], info[i].m); | ||
979 | dReal *cf1 = cforce + 8*b1->tag; | ||
980 | cf1[0] += (temp_fb.f1[0] = data1[0]); | ||
981 | cf1[1] += (temp_fb.f1[1] = data1[1]); | ||
982 | cf1[2] += (temp_fb.f1[2] = data1[2]); | ||
983 | cf1[4] += (temp_fb.t1[0] = data1[4]); | ||
984 | cf1[5] += (temp_fb.t1[1] = data1[5]); | ||
985 | cf1[6] += (temp_fb.t1[2] = data1[6]); | ||
986 | if (b2) { | ||
987 | Multiply1_8q1 (data2, JJ + 8*info[i].m, lambda+ofs[i], info[i].m); | ||
988 | dReal *cf2 = cforce + 8*b2->tag; | ||
989 | cf2[0] += (temp_fb.f2[0] = data2[0]); | ||
990 | cf2[1] += (temp_fb.f2[1] = data2[1]); | ||
991 | cf2[2] += (temp_fb.f2[2] = data2[2]); | ||
992 | cf2[4] += (temp_fb.t2[0] = data2[4]); | ||
993 | cf2[5] += (temp_fb.t2[1] = data2[5]); | ||
994 | cf2[6] += (temp_fb.t2[2] = data2[6]); | ||
995 | } | ||
996 | // if the user requested so we must copy the feedback information to | ||
997 | // the feedback struct that the user suplied. | ||
998 | if (fb) { | ||
999 | // copy temp_fb to fb | ||
1000 | fb->f1[0] = temp_fb.f1[0]; | ||
1001 | fb->f1[1] = temp_fb.f1[1]; | ||
1002 | fb->f1[2] = temp_fb.f1[2]; | ||
1003 | fb->t1[0] = temp_fb.t1[0]; | ||
1004 | fb->t1[1] = temp_fb.t1[1]; | ||
1005 | fb->t1[2] = temp_fb.t1[2]; | ||
1006 | if (b2) { | ||
1007 | fb->f2[0] = temp_fb.f2[0]; | ||
1008 | fb->f2[1] = temp_fb.f2[1]; | ||
1009 | fb->f2[2] = temp_fb.f2[2]; | ||
1010 | fb->t2[0] = temp_fb.t2[0]; | ||
1011 | fb->t2[1] = temp_fb.t2[1]; | ||
1012 | fb->t2[2] = temp_fb.t2[2]; | ||
1013 | } | ||
1014 | } | ||
1015 | // if the joint is breakable we need to check the breaking conditions | ||
1016 | if (jBI) { | ||
1017 | dReal relCF1[3]; | ||
1018 | dReal relCT1[3]; | ||
1019 | // multiply the force and torque vectors by the rotation matrix of body 1 | ||
1020 | dMULTIPLY1_331 (&relCF1[0],b1->R,&temp_fb.f1[0]); | ||
1021 | dMULTIPLY1_331 (&relCT1[0],b1->R,&temp_fb.t1[0]); | ||
1022 | if (jBI->flags & dJOINT_BREAK_AT_B1_FORCE) { | ||
1023 | // check if the force is to high | ||
1024 | for (int i = 0; i < 3; i++) { | ||
1025 | if (relCF1[i] > jBI->b1MaxF[i]) { | ||
1026 | jBI->flags |= dJOINT_BROKEN; | ||
1027 | goto doneCheckingBreaks; | ||
1028 | } | ||
1029 | } | ||
1030 | } | ||
1031 | if (jBI->flags & dJOINT_BREAK_AT_B1_TORQUE) { | ||
1032 | // check if the torque is to high | ||
1033 | for (int i = 0; i < 3; i++) { | ||
1034 | if (relCT1[i] > jBI->b1MaxT[i]) { | ||
1035 | jBI->flags |= dJOINT_BROKEN; | ||
1036 | goto doneCheckingBreaks; | ||
1037 | } | ||
1038 | } | ||
1039 | } | ||
1040 | if (b2) { | ||
1041 | dReal relCF2[3]; | ||
1042 | dReal relCT2[3]; | ||
1043 | // multiply the force and torque vectors by the rotation matrix of body 2 | ||
1044 | dMULTIPLY1_331 (&relCF2[0],b2->R,&temp_fb.f2[0]); | ||
1045 | dMULTIPLY1_331 (&relCT2[0],b2->R,&temp_fb.t2[0]); | ||
1046 | if (jBI->flags & dJOINT_BREAK_AT_B2_FORCE) { | ||
1047 | // check if the force is to high | ||
1048 | for (int i = 0; i < 3; i++) { | ||
1049 | if (relCF2[i] > jBI->b2MaxF[i]) { | ||
1050 | jBI->flags |= dJOINT_BROKEN; | ||
1051 | goto doneCheckingBreaks; | ||
1052 | } | ||
1053 | } | ||
1054 | } | ||
1055 | if (jBI->flags & dJOINT_BREAK_AT_B2_TORQUE) { | ||
1056 | // check if the torque is to high | ||
1057 | for (int i = 0; i < 3; i++) { | ||
1058 | if (relCT2[i] > jBI->b2MaxT[i]) { | ||
1059 | jBI->flags |= dJOINT_BROKEN; | ||
1060 | goto doneCheckingBreaks; | ||
1061 | } | ||
1062 | } | ||
1063 | } | ||
1064 | } | ||
1065 | doneCheckingBreaks: | ||
1066 | ; | ||
1067 | } | ||
1068 | } | ||
1069 | /*************************************************************************/ | ||
1070 | else { | ||
1071 | // no feedback is required, let's compute cforce the faster way | ||
1072 | MultiplyAdd1_8q1 (cforce + 8*b1->tag,JJ, lambda+ofs[i], info[i].m); | ||
1073 | if (b2) { | ||
1074 | MultiplyAdd1_8q1 (cforce + 8*b2->tag, | ||
1075 | JJ + 8*info[i].m, lambda+ofs[i], info[i].m); | ||
1076 | } | ||
1077 | } | ||
1078 | } | ||
1079 | } | ||
1080 | |||
1081 | // compute the velocity update | ||
1082 | # ifdef TIMING | ||
1083 | dTimerNow ("compute velocity update"); | ||
1084 | # endif | ||
1085 | |||
1086 | // add fe to cforce | ||
1087 | for (i=0; i<nb; i++) { | ||
1088 | for (j=0; j<3; j++) cforce[i*8+j] += body[i]->facc[j]; | ||
1089 | for (j=0; j<3; j++) cforce[i*8+4+j] += body[i]->tacc[j]; | ||
1090 | } | ||
1091 | // multiply cforce by stepsize | ||
1092 | for (i=0; i < nb*8; i++) cforce[i] *= stepsize; | ||
1093 | // add invM * cforce to the body velocity | ||
1094 | for (i=0; i<nb; i++) { | ||
1095 | dReal body_invMass = body[i]->invMass; | ||
1096 | dReal *body_invI = invI + i*12; | ||
1097 | for (j=0; j<3; j++) body[i]->lvel[j] += body_invMass * cforce[i*8+j]; | ||
1098 | dMULTIPLYADD0_331 (body[i]->avel,body_invI,cforce+i*8+4); | ||
1099 | } | ||
1100 | |||
1101 | // update the position and orientation from the new linear/angular velocity | ||
1102 | // (over the given timestep) | ||
1103 | # ifdef TIMING | ||
1104 | dTimerNow ("update position"); | ||
1105 | # endif | ||
1106 | for (i=0; i<nb; i++) moveAndRotateBody (body[i],stepsize); | ||
1107 | |||
1108 | # ifdef COMPARE_METHODS | ||
1109 | dReal *tmp_vnew = (dReal*) ALLOCA (nb*6*sizeof(dReal)); | ||
1110 | for (i=0; i<nb; i++) { | ||
1111 | for (j=0; j<3; j++) tmp_vnew[i*6+j] = body[i]->lvel[j]; | ||
1112 | for (j=0; j<3; j++) tmp_vnew[i*6+3+j] = body[i]->avel[j]; | ||
1113 | } | ||
1114 | comparator.nextMatrix (tmp_vnew,nb*6,1,0,"vnew"); | ||
1115 | # endif | ||
1116 | |||
1117 | # ifdef TIMING | ||
1118 | dTimerNow ("tidy up"); | ||
1119 | # endif | ||
1120 | |||
1121 | // zero all force accumulators | ||
1122 | for (i=0; i<nb; i++) { | ||
1123 | body[i]->facc[0] = 0; | ||
1124 | body[i]->facc[1] = 0; | ||
1125 | body[i]->facc[2] = 0; | ||
1126 | body[i]->facc[3] = 0; | ||
1127 | body[i]->tacc[0] = 0; | ||
1128 | body[i]->tacc[1] = 0; | ||
1129 | body[i]->tacc[2] = 0; | ||
1130 | body[i]->tacc[3] = 0; | ||
1131 | } | ||
1132 | |||
1133 | # ifdef TIMING | ||
1134 | dTimerEnd(); | ||
1135 | if (m > 0) dTimerReport (stdout,1); | ||
1136 | # endif | ||
1137 | } | ||
1138 | |||
1139 | //**************************************************************************** | ||
1140 | |||
1141 | void dInternalStepIsland (dxWorld *world, dxBody * const *body, int nb, | ||
1142 | dxJoint * const *joint, int nj, dReal stepsize) | ||
1143 | { | ||
1144 | # ifndef COMPARE_METHODS | ||
1145 | dInternalStepIsland_x2 (world,body,nb,joint,nj,stepsize); | ||
1146 | # endif | ||
1147 | |||
1148 | # ifdef COMPARE_METHODS | ||
1149 | int i; | ||
1150 | |||
1151 | // save body state | ||
1152 | dxBody *state = (dxBody*) ALLOCA (nb*sizeof(dxBody)); | ||
1153 | for (i=0; i<nb; i++) memcpy (state+i,body[i],sizeof(dxBody)); | ||
1154 | |||
1155 | // take slow step | ||
1156 | comparator.reset(); | ||
1157 | dInternalStepIsland_x1 (world,body,nb,joint,nj,stepsize); | ||
1158 | comparator.end(); | ||
1159 | |||
1160 | // restore state | ||
1161 | for (i=0; i<nb; i++) memcpy (body[i],state+i,sizeof(dxBody)); | ||
1162 | |||
1163 | // take fast step | ||
1164 | dInternalStepIsland_x2 (world,body,nb,joint,nj,stepsize); | ||
1165 | comparator.end(); | ||
1166 | |||
1167 | //comparator.dump(); | ||
1168 | //_exit (1); | ||
1169 | # endif | ||
1170 | } | ||
diff --git a/libraries/ode-0.9/contrib/BreakableJoints/stepfast.cpp b/libraries/ode-0.9/contrib/BreakableJoints/stepfast.cpp new file mode 100755 index 0000000..a0eb9ae --- /dev/null +++ b/libraries/ode-0.9/contrib/BreakableJoints/stepfast.cpp | |||
@@ -0,0 +1,1212 @@ | |||
1 | /************************************************************************* | ||
2 | * * | ||
3 | * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * | ||
4 | * All rights reserved. Email: russ@q12.org Web: www.q12.org * | ||
5 | * * | ||
6 | * Fast iterative solver, David Whittaker. Email: david@csworkbench.com * | ||
7 | * * | ||
8 | * This library is free software; you can redistribute it and/or * | ||
9 | * modify it under the terms of EITHER: * | ||
10 | * (1) The GNU Lesser General Public License as published by the Free * | ||
11 | * Software Foundation; either version 2.1 of the License, or (at * | ||
12 | * your option) any later version. The text of the GNU Lesser * | ||
13 | * General Public License is included with this library in the * | ||
14 | * file LICENSE.TXT. * | ||
15 | * (2) The BSD-style license that is included with this library in * | ||
16 | * the file LICENSE-BSD.TXT. * | ||
17 | * * | ||
18 | * This library is distributed in the hope that it will be useful, * | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * | ||
21 | * LICENSE.TXT and LICENSE-BSD.TXT for more details. * | ||
22 | * * | ||
23 | *************************************************************************/ | ||
24 | |||
25 | // This is the StepFast code by David Whittaker. This code is faster, but | ||
26 | // sometimes less stable than, the original "big matrix" code. | ||
27 | // Refer to the user's manual for more information. | ||
28 | // Note that this source file duplicates a lot of stuff from step.cpp, | ||
29 | // eventually we should move the common code to a third file. | ||
30 | |||
31 | #include "objects.h" | ||
32 | #include "joint.h" | ||
33 | #include <ode/config.h> | ||
34 | #include <ode/objects.h> | ||
35 | #include <ode/odemath.h> | ||
36 | #include <ode/rotation.h> | ||
37 | #include <ode/timer.h> | ||
38 | #include <ode/error.h> | ||
39 | #include <ode/matrix.h> | ||
40 | #include "lcp.h" | ||
41 | #include "step.h" | ||
42 | |||
43 | |||
44 | // misc defines | ||
45 | |||
46 | #define ALLOCA dALLOCA16 | ||
47 | |||
48 | #define RANDOM_JOINT_ORDER | ||
49 | //#define FAST_FACTOR //use a factorization approximation to the LCP solver (fast, theoretically less accurate) | ||
50 | #define SLOW_LCP //use the old LCP solver | ||
51 | //#define NO_ISLANDS //does not perform island creation code (3~4% of simulation time), body disabling doesn't work | ||
52 | //#define TIMING | ||
53 | |||
54 | |||
55 | static int autoEnableDepth = 2; | ||
56 | |||
57 | void dWorldSetAutoEnableDepthSF1 (dxWorld *world, int autodepth) | ||
58 | { | ||
59 | if (autodepth > 0) | ||
60 | autoEnableDepth = autodepth; | ||
61 | else | ||
62 | autoEnableDepth = 0; | ||
63 | } | ||
64 | |||
65 | int dWorldGetAutoEnableDepthSF1 (dxWorld *world) | ||
66 | { | ||
67 | return autoEnableDepth; | ||
68 | } | ||
69 | |||
70 | //little bit of math.... the _sym_ functions assume the return matrix will be symmetric | ||
71 | static void | ||
72 | Multiply2_sym_p8p (dReal * A, dReal * B, dReal * C, int p, int Askip) | ||
73 | { | ||
74 | int i, j; | ||
75 | dReal sum, *aa, *ad, *bb, *cc; | ||
76 | dIASSERT (p > 0 && A && B && C); | ||
77 | bb = B; | ||
78 | for (i = 0; i < p; i++) | ||
79 | { | ||
80 | //aa is going accross the matrix, ad down | ||
81 | aa = ad = A; | ||
82 | cc = C; | ||
83 | for (j = i; j < p; j++) | ||
84 | { | ||
85 | sum = bb[0] * cc[0]; | ||
86 | sum += bb[1] * cc[1]; | ||
87 | sum += bb[2] * cc[2]; | ||
88 | sum += bb[4] * cc[4]; | ||
89 | sum += bb[5] * cc[5]; | ||
90 | sum += bb[6] * cc[6]; | ||
91 | *(aa++) = *ad = sum; | ||
92 | ad += Askip; | ||
93 | cc += 8; | ||
94 | } | ||
95 | bb += 8; | ||
96 | A += Askip + 1; | ||
97 | C += 8; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | static void | ||
102 | MultiplyAdd2_sym_p8p (dReal * A, dReal * B, dReal * C, int p, int Askip) | ||
103 | { | ||
104 | int i, j; | ||
105 | dReal sum, *aa, *ad, *bb, *cc; | ||
106 | dIASSERT (p > 0 && A && B && C); | ||
107 | bb = B; | ||
108 | for (i = 0; i < p; i++) | ||
109 | { | ||
110 | //aa is going accross the matrix, ad down | ||
111 | aa = ad = A; | ||
112 | cc = C; | ||
113 | for (j = i; j < p; j++) | ||
114 | { | ||
115 | sum = bb[0] * cc[0]; | ||
116 | sum += bb[1] * cc[1]; | ||
117 | sum += bb[2] * cc[2]; | ||
118 | sum += bb[4] * cc[4]; | ||
119 | sum += bb[5] * cc[5]; | ||
120 | sum += bb[6] * cc[6]; | ||
121 | *(aa++) += sum; | ||
122 | *ad += sum; | ||
123 | ad += Askip; | ||
124 | cc += 8; | ||
125 | } | ||
126 | bb += 8; | ||
127 | A += Askip + 1; | ||
128 | C += 8; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | |||
133 | // this assumes the 4th and 8th rows of B are zero. | ||
134 | |||
135 | static void | ||
136 | Multiply0_p81 (dReal * A, dReal * B, dReal * C, int p) | ||
137 | { | ||
138 | int i; | ||
139 | dIASSERT (p > 0 && A && B && C); | ||
140 | dReal sum; | ||
141 | for (i = p; i; i--) | ||
142 | { | ||
143 | sum = B[0] * C[0]; | ||
144 | sum += B[1] * C[1]; | ||
145 | sum += B[2] * C[2]; | ||
146 | sum += B[4] * C[4]; | ||
147 | sum += B[5] * C[5]; | ||
148 | sum += B[6] * C[6]; | ||
149 | *(A++) = sum; | ||
150 | B += 8; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | |||
155 | // this assumes the 4th and 8th rows of B are zero. | ||
156 | |||
157 | static void | ||
158 | MultiplyAdd0_p81 (dReal * A, dReal * B, dReal * C, int p) | ||
159 | { | ||
160 | int i; | ||
161 | dIASSERT (p > 0 && A && B && C); | ||
162 | dReal sum; | ||
163 | for (i = p; i; i--) | ||
164 | { | ||
165 | sum = B[0] * C[0]; | ||
166 | sum += B[1] * C[1]; | ||
167 | sum += B[2] * C[2]; | ||
168 | sum += B[4] * C[4]; | ||
169 | sum += B[5] * C[5]; | ||
170 | sum += B[6] * C[6]; | ||
171 | *(A++) += sum; | ||
172 | B += 8; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | |||
177 | // this assumes the 4th and 8th rows of B are zero. | ||
178 | |||
179 | static void | ||
180 | Multiply1_8q1 (dReal * A, dReal * B, dReal * C, int q) | ||
181 | { | ||
182 | int k; | ||
183 | dReal sum; | ||
184 | dIASSERT (q > 0 && A && B && C); | ||
185 | sum = 0; | ||
186 | for (k = 0; k < q; k++) | ||
187 | sum += B[k * 8] * C[k]; | ||
188 | A[0] = sum; | ||
189 | sum = 0; | ||
190 | for (k = 0; k < q; k++) | ||
191 | sum += B[1 + k * 8] * C[k]; | ||
192 | A[1] = sum; | ||
193 | sum = 0; | ||
194 | for (k = 0; k < q; k++) | ||
195 | sum += B[2 + k * 8] * C[k]; | ||
196 | A[2] = sum; | ||
197 | sum = 0; | ||
198 | for (k = 0; k < q; k++) | ||
199 | sum += B[4 + k * 8] * C[k]; | ||
200 | A[4] = sum; | ||
201 | sum = 0; | ||
202 | for (k = 0; k < q; k++) | ||
203 | sum += B[5 + k * 8] * C[k]; | ||
204 | A[5] = sum; | ||
205 | sum = 0; | ||
206 | for (k = 0; k < q; k++) | ||
207 | sum += B[6 + k * 8] * C[k]; | ||
208 | A[6] = sum; | ||
209 | } | ||
210 | |||
211 | //**************************************************************************** | ||
212 | // body rotation | ||
213 | |||
214 | // return sin(x)/x. this has a singularity at 0 so special handling is needed | ||
215 | // for small arguments. | ||
216 | |||
217 | static inline dReal | ||
218 | sinc (dReal x) | ||
219 | { | ||
220 | // if |x| < 1e-4 then use a taylor series expansion. this two term expansion | ||
221 | // is actually accurate to one LS bit within this range if double precision | ||
222 | // is being used - so don't worry! | ||
223 | if (dFabs (x) < 1.0e-4) | ||
224 | return REAL (1.0) - x * x * REAL (0.166666666666666666667); | ||
225 | else | ||
226 | return dSin (x) / x; | ||
227 | } | ||
228 | |||
229 | |||
230 | // given a body b, apply its linear and angular rotation over the time | ||
231 | // interval h, thereby adjusting its position and orientation. | ||
232 | |||
233 | static inline void | ||
234 | moveAndRotateBody (dxBody * b, dReal h) | ||
235 | { | ||
236 | int j; | ||
237 | |||
238 | // handle linear velocity | ||
239 | for (j = 0; j < 3; j++) | ||
240 | b->pos[j] += h * b->lvel[j]; | ||
241 | |||
242 | if (b->flags & dxBodyFlagFiniteRotation) | ||
243 | { | ||
244 | dVector3 irv; // infitesimal rotation vector | ||
245 | dQuaternion q; // quaternion for finite rotation | ||
246 | |||
247 | if (b->flags & dxBodyFlagFiniteRotationAxis) | ||
248 | { | ||
249 | // split the angular velocity vector into a component along the finite | ||
250 | // rotation axis, and a component orthogonal to it. | ||
251 | dVector3 frv, irv; // finite rotation vector | ||
252 | dReal k = dDOT (b->finite_rot_axis, b->avel); | ||
253 | frv[0] = b->finite_rot_axis[0] * k; | ||
254 | frv[1] = b->finite_rot_axis[1] * k; | ||
255 | frv[2] = b->finite_rot_axis[2] * k; | ||
256 | irv[0] = b->avel[0] - frv[0]; | ||
257 | irv[1] = b->avel[1] - frv[1]; | ||
258 | irv[2] = b->avel[2] - frv[2]; | ||
259 | |||
260 | // make a rotation quaternion q that corresponds to frv * h. | ||
261 | // compare this with the full-finite-rotation case below. | ||
262 | h *= REAL (0.5); | ||
263 | dReal theta = k * h; | ||
264 | q[0] = dCos (theta); | ||
265 | dReal s = sinc (theta) * h; | ||
266 | q[1] = frv[0] * s; | ||
267 | q[2] = frv[1] * s; | ||
268 | q[3] = frv[2] * s; | ||
269 | } | ||
270 | else | ||
271 | { | ||
272 | // make a rotation quaternion q that corresponds to w * h | ||
273 | dReal wlen = dSqrt (b->avel[0] * b->avel[0] + b->avel[1] * b->avel[1] + b->avel[2] * b->avel[2]); | ||
274 | h *= REAL (0.5); | ||
275 | dReal theta = wlen * h; | ||
276 | q[0] = dCos (theta); | ||
277 | dReal s = sinc (theta) * h; | ||
278 | q[1] = b->avel[0] * s; | ||
279 | q[2] = b->avel[1] * s; | ||
280 | q[3] = b->avel[2] * s; | ||
281 | } | ||
282 | |||
283 | // do the finite rotation | ||
284 | dQuaternion q2; | ||
285 | dQMultiply0 (q2, q, b->q); | ||
286 | for (j = 0; j < 4; j++) | ||
287 | b->q[j] = q2[j]; | ||
288 | |||
289 | // do the infitesimal rotation if required | ||
290 | if (b->flags & dxBodyFlagFiniteRotationAxis) | ||
291 | { | ||
292 | dReal dq[4]; | ||
293 | dWtoDQ (irv, b->q, dq); | ||
294 | for (j = 0; j < 4; j++) | ||
295 | b->q[j] += h * dq[j]; | ||
296 | } | ||
297 | } | ||
298 | else | ||
299 | { | ||
300 | // the normal way - do an infitesimal rotation | ||
301 | dReal dq[4]; | ||
302 | dWtoDQ (b->avel, b->q, dq); | ||
303 | for (j = 0; j < 4; j++) | ||
304 | b->q[j] += h * dq[j]; | ||
305 | } | ||
306 | |||
307 | // normalize the quaternion and convert it to a rotation matrix | ||
308 | dNormalize4 (b->q); | ||
309 | dQtoR (b->q, b->R); | ||
310 | |||
311 | // notify all attached geoms that this body has moved | ||
312 | for (dxGeom * geom = b->geom; geom; geom = dGeomGetBodyNext (geom)) | ||
313 | dGeomMoved (geom); | ||
314 | } | ||
315 | |||
316 | //**************************************************************************** | ||
317 | //This is an implementation of the iterated/relaxation algorithm. | ||
318 | //Here is a quick overview of the algorithm per Sergi Valverde's posts to the | ||
319 | //mailing list: | ||
320 | // | ||
321 | // for i=0..N-1 do | ||
322 | // for c = 0..C-1 do | ||
323 | // Solve constraint c-th | ||
324 | // Apply forces to constraint bodies | ||
325 | // next | ||
326 | // next | ||
327 | // Integrate bodies | ||
328 | |||
329 | void | ||
330 | dInternalStepFast (dxWorld * world, dxBody * body[2], dReal * GI[2], dReal * GinvI[2], dxJoint * joint, dxJoint::Info1 info, dxJoint::Info2 Jinfo, dReal stepsize) | ||
331 | { | ||
332 | int i, j, k; | ||
333 | # ifdef TIMING | ||
334 | dTimerNow ("constraint preprocessing"); | ||
335 | # endif | ||
336 | |||
337 | dReal stepsize1 = dRecip (stepsize); | ||
338 | |||
339 | int m = info.m; | ||
340 | // nothing to do if no constraints. | ||
341 | if (m <= 0) | ||
342 | return; | ||
343 | |||
344 | int nub = 0; | ||
345 | if (info.nub == info.m) | ||
346 | nub = m; | ||
347 | |||
348 | // compute A = J*invM*J'. first compute JinvM = J*invM. this has the same | ||
349 | // format as J so we just go through the constraints in J multiplying by | ||
350 | // the appropriate scalars and matrices. | ||
351 | # ifdef TIMING | ||
352 | dTimerNow ("compute A"); | ||
353 | # endif | ||
354 | dReal JinvM[2 * 6 * 8]; | ||
355 | //dSetZero (JinvM, 2 * m * 8); | ||
356 | |||
357 | dReal *Jsrc = Jinfo.J1l; | ||
358 | dReal *Jdst = JinvM; | ||
359 | if (body[0]) | ||
360 | { | ||
361 | for (j = m - 1; j >= 0; j--) | ||
362 | { | ||
363 | for (k = 0; k < 3; k++) | ||
364 | Jdst[k] = Jsrc[k] * body[0]->invMass; | ||
365 | dMULTIPLY0_133 (Jdst + 4, Jsrc + 4, GinvI[0]); | ||
366 | Jsrc += 8; | ||
367 | Jdst += 8; | ||
368 | } | ||
369 | } | ||
370 | if (body[1]) | ||
371 | { | ||
372 | Jsrc = Jinfo.J2l; | ||
373 | Jdst = JinvM + 8 * m; | ||
374 | for (j = m - 1; j >= 0; j--) | ||
375 | { | ||
376 | for (k = 0; k < 3; k++) | ||
377 | Jdst[k] = Jsrc[k] * body[1]->invMass; | ||
378 | dMULTIPLY0_133 (Jdst + 4, Jsrc + 4, GinvI[1]); | ||
379 | Jsrc += 8; | ||
380 | Jdst += 8; | ||
381 | } | ||
382 | } | ||
383 | |||
384 | |||
385 | // now compute A = JinvM * J'. | ||
386 | int mskip = dPAD (m); | ||
387 | dReal A[6 * 8]; | ||
388 | //dSetZero (A, 6 * 8); | ||
389 | |||
390 | if (body[0]) | ||
391 | Multiply2_sym_p8p (A, JinvM, Jinfo.J1l, m, mskip); | ||
392 | if (body[1]) | ||
393 | MultiplyAdd2_sym_p8p (A, JinvM + 8 * m, Jinfo.J2l, m, mskip); | ||
394 | |||
395 | // add cfm to the diagonal of A | ||
396 | for (i = 0; i < m; i++) | ||
397 | A[i * mskip + i] += Jinfo.cfm[i] * stepsize1; | ||
398 | |||
399 | // compute the right hand side `rhs' | ||
400 | # ifdef TIMING | ||
401 | dTimerNow ("compute rhs"); | ||
402 | # endif | ||
403 | dReal tmp1[16]; | ||
404 | //dSetZero (tmp1, 16); | ||
405 | // put v/h + invM*fe into tmp1 | ||
406 | for (i = 0; i < 2; i++) | ||
407 | { | ||
408 | if (!body[i]) | ||
409 | continue; | ||
410 | for (j = 0; j < 3; j++) | ||
411 | tmp1[i * 8 + j] = body[i]->facc[j] * body[i]->invMass + body[i]->lvel[j] * stepsize1; | ||
412 | dMULTIPLY0_331 (tmp1 + i * 8 + 4, GinvI[i], body[i]->tacc); | ||
413 | for (j = 0; j < 3; j++) | ||
414 | tmp1[i * 8 + 4 + j] += body[i]->avel[j] * stepsize1; | ||
415 | } | ||
416 | // put J*tmp1 into rhs | ||
417 | dReal rhs[6]; | ||
418 | //dSetZero (rhs, 6); | ||
419 | |||
420 | if (body[0]) | ||
421 | Multiply0_p81 (rhs, Jinfo.J1l, tmp1, m); | ||
422 | if (body[1]) | ||
423 | MultiplyAdd0_p81 (rhs, Jinfo.J2l, tmp1 + 8, m); | ||
424 | |||
425 | // complete rhs | ||
426 | for (i = 0; i < m; i++) | ||
427 | rhs[i] = Jinfo.c[i] * stepsize1 - rhs[i]; | ||
428 | |||
429 | #ifdef SLOW_LCP | ||
430 | // solve the LCP problem and get lambda. | ||
431 | // this will destroy A but that's okay | ||
432 | # ifdef TIMING | ||
433 | dTimerNow ("solving LCP problem"); | ||
434 | # endif | ||
435 | dReal *lambda = (dReal *) ALLOCA (m * sizeof (dReal)); | ||
436 | dReal *residual = (dReal *) ALLOCA (m * sizeof (dReal)); | ||
437 | dReal lo[6], hi[6]; | ||
438 | memcpy (lo, Jinfo.lo, m * sizeof (dReal)); | ||
439 | memcpy (hi, Jinfo.hi, m * sizeof (dReal)); | ||
440 | dSolveLCP (m, A, lambda, rhs, residual, nub, lo, hi, Jinfo.findex); | ||
441 | #endif | ||
442 | |||
443 | // LCP Solver replacement: | ||
444 | // This algorithm goes like this: | ||
445 | // Do a straightforward LDLT factorization of the matrix A, solving for | ||
446 | // A*x = rhs | ||
447 | // For each x[i] that is outside of the bounds of lo[i] and hi[i], | ||
448 | // clamp x[i] into that range. | ||
449 | // Substitute into A the now known x's | ||
450 | // subtract the residual away from the rhs. | ||
451 | // Remove row and column i from L, updating the factorization | ||
452 | // place the known x's at the end of the array, keeping up with location in p | ||
453 | // Repeat until all constraints have been clamped or all are within bounds | ||
454 | // | ||
455 | // This is probably only faster in the single joint case where only one repeat is | ||
456 | // the norm. | ||
457 | |||
458 | #ifdef FAST_FACTOR | ||
459 | // factorize A (L*D*L'=A) | ||
460 | # ifdef TIMING | ||
461 | dTimerNow ("factorize A"); | ||
462 | # endif | ||
463 | dReal d[6]; | ||
464 | dReal L[6 * 8]; | ||
465 | memcpy (L, A, m * mskip * sizeof (dReal)); | ||
466 | dFactorLDLT (L, d, m, mskip); | ||
467 | |||
468 | // compute lambda | ||
469 | # ifdef TIMING | ||
470 | dTimerNow ("compute lambda"); | ||
471 | # endif | ||
472 | |||
473 | int left = m; //constraints left to solve. | ||
474 | int remove[6]; | ||
475 | dReal lambda[6]; | ||
476 | dReal x[6]; | ||
477 | int p[6]; | ||
478 | for (i = 0; i < 6; i++) | ||
479 | p[i] = i; | ||
480 | while (true) | ||
481 | { | ||
482 | memcpy (x, rhs, left * sizeof (dReal)); | ||
483 | dSolveLDLT (L, d, x, left, mskip); | ||
484 | |||
485 | int fixed = 0; | ||
486 | for (i = 0; i < left; i++) | ||
487 | { | ||
488 | j = p[i]; | ||
489 | remove[i] = false; | ||
490 | // This isn't the exact same use of findex as dSolveLCP.... since x[findex] | ||
491 | // may change after I've already clamped x[i], but it should be close | ||
492 | if (Jinfo.findex[j] > -1) | ||
493 | { | ||
494 | dReal f = fabs (Jinfo.hi[j] * x[p[Jinfo.findex[j]]]); | ||
495 | if (x[i] > f) | ||
496 | x[i] = f; | ||
497 | else if (x[i] < -f) | ||
498 | x[i] = -f; | ||
499 | else | ||
500 | continue; | ||
501 | } | ||
502 | else | ||
503 | { | ||
504 | if (x[i] > Jinfo.hi[j]) | ||
505 | x[i] = Jinfo.hi[j]; | ||
506 | else if (x[i] < Jinfo.lo[j]) | ||
507 | x[i] = Jinfo.lo[j]; | ||
508 | else | ||
509 | continue; | ||
510 | } | ||
511 | remove[i] = true; | ||
512 | fixed++; | ||
513 | } | ||
514 | if (fixed == 0 || fixed == left) //no change or all constraints solved | ||
515 | break; | ||
516 | |||
517 | for (i = 0; i < left; i++) //sub in to right hand side. | ||
518 | if (remove[i]) | ||
519 | for (j = 0; j < left; j++) | ||
520 | if (!remove[j]) | ||
521 | rhs[j] -= A[j * mskip + i] * x[i]; | ||
522 | |||
523 | for (int r = left - 1; r >= 0; r--) //eliminate row/col for fixed variables | ||
524 | { | ||
525 | if (remove[r]) | ||
526 | { | ||
527 | //dRemoveLDLT adapted for use without row pointers. | ||
528 | if (r == left - 1) | ||
529 | { | ||
530 | left--; | ||
531 | continue; // deleting last row/col is easy | ||
532 | } | ||
533 | else if (r == 0) | ||
534 | { | ||
535 | dReal a[6]; | ||
536 | for (i = 0; i < left; i++) | ||
537 | a[i] = -A[i * mskip]; | ||
538 | a[0] += REAL (1.0); | ||
539 | dLDLTAddTL (L, d, a, left, mskip); | ||
540 | } | ||
541 | else | ||
542 | { | ||
543 | dReal t[6]; | ||
544 | dReal a[6]; | ||
545 | for (i = 0; i < r; i++) | ||
546 | t[i] = L[r * mskip + i] / d[i]; | ||
547 | for (i = 0; i < left - r; i++) | ||
548 | a[i] = dDot (L + (r + i) * mskip, t, r) - A[(r + i) * mskip + r]; | ||
549 | a[0] += REAL (1.0); | ||
550 | dLDLTAddTL (L + r * mskip + r, d + r, a, left - r, mskip); | ||
551 | } | ||
552 | |||
553 | dRemoveRowCol (L, left, mskip, r); | ||
554 | //end dRemoveLDLT | ||
555 | |||
556 | left--; | ||
557 | if (r < (left - 1)) | ||
558 | { | ||
559 | dReal tx = x[r]; | ||
560 | memmove (d + r, d + r + 1, (left - r) * sizeof (dReal)); | ||
561 | memmove (rhs + r, rhs + r + 1, (left - r) * sizeof (dReal)); | ||
562 | //x will get written over by rhs anyway, no need to move it around | ||
563 | //just store the fixed value we just discovered in it. | ||
564 | x[left] = tx; | ||
565 | for (i = 0; i < m; i++) | ||
566 | if (p[i] > r && p[i] <= left) | ||
567 | p[i]--; | ||
568 | p[r] = left; | ||
569 | } | ||
570 | } | ||
571 | } | ||
572 | } | ||
573 | |||
574 | for (i = 0; i < m; i++) | ||
575 | lambda[i] = x[p[i]]; | ||
576 | # endif | ||
577 | // compute the constraint force `cforce' | ||
578 | # ifdef TIMING | ||
579 | dTimerNow ("compute constraint force"); | ||
580 | #endif | ||
581 | |||
582 | // compute cforce = J'*lambda | ||
583 | dJointFeedback *fb = joint->feedback; | ||
584 | dReal cforce[16]; | ||
585 | //dSetZero (cforce, 16); | ||
586 | |||
587 | /******************** breakable joint contribution ***********************/ | ||
588 | // this saves us a few dereferences | ||
589 | dxJointBreakInfo *jBI = joint->breakInfo; | ||
590 | // we need joint feedback if the joint is breakable or if the user | ||
591 | // requested feedback. | ||
592 | if (jBI||fb) { | ||
593 | // we need feedback on the amount of force that this joint is | ||
594 | // applying to the bodies. we use a slightly slower computation | ||
595 | // that splits out the force components and puts them in the | ||
596 | // feedback structure. | ||
597 | dJointFeedback temp_fb; // temporary storage for joint feedback | ||
598 | dReal data1[8],data2[8]; | ||
599 | if (body[0]) | ||
600 | { | ||
601 | Multiply1_8q1 (data1, Jinfo.J1l, lambda, m); | ||
602 | dReal *cf1 = cforce; | ||
603 | cf1[0] = (temp_fb.f1[0] = data1[0]); | ||
604 | cf1[1] = (temp_fb.f1[1] = data1[1]); | ||
605 | cf1[2] = (temp_fb.f1[2] = data1[2]); | ||
606 | cf1[4] = (temp_fb.t1[0] = data1[4]); | ||
607 | cf1[5] = (temp_fb.t1[1] = data1[5]); | ||
608 | cf1[6] = (temp_fb.t1[2] = data1[6]); | ||
609 | } | ||
610 | if (body[1]) | ||
611 | { | ||
612 | Multiply1_8q1 (data2, Jinfo.J2l, lambda, m); | ||
613 | dReal *cf2 = cforce + 8; | ||
614 | cf2[0] = (temp_fb.f2[0] = data2[0]); | ||
615 | cf2[1] = (temp_fb.f2[1] = data2[1]); | ||
616 | cf2[2] = (temp_fb.f2[2] = data2[2]); | ||
617 | cf2[4] = (temp_fb.t2[0] = data2[4]); | ||
618 | cf2[5] = (temp_fb.t2[1] = data2[5]); | ||
619 | cf2[6] = (temp_fb.t2[2] = data2[6]); | ||
620 | } | ||
621 | // if the user requested so we must copy the feedback information to | ||
622 | // the feedback struct that the user suplied. | ||
623 | if (fb) { | ||
624 | // copy temp_fb to fb | ||
625 | fb->f1[0] = temp_fb.f1[0]; | ||
626 | fb->f1[1] = temp_fb.f1[1]; | ||
627 | fb->f1[2] = temp_fb.f1[2]; | ||
628 | fb->t1[0] = temp_fb.t1[0]; | ||
629 | fb->t1[1] = temp_fb.t1[1]; | ||
630 | fb->t1[2] = temp_fb.t1[2]; | ||
631 | if (body[1]) { | ||
632 | fb->f2[0] = temp_fb.f2[0]; | ||
633 | fb->f2[1] = temp_fb.f2[1]; | ||
634 | fb->f2[2] = temp_fb.f2[2]; | ||
635 | fb->t2[0] = temp_fb.t2[0]; | ||
636 | fb->t2[1] = temp_fb.t2[1]; | ||
637 | fb->t2[2] = temp_fb.t2[2]; | ||
638 | } | ||
639 | } | ||
640 | // if the joint is breakable we need to check the breaking conditions | ||
641 | if (jBI) { | ||
642 | dReal relCF1[3]; | ||
643 | dReal relCT1[3]; | ||
644 | // multiply the force and torque vectors by the rotation matrix of body 1 | ||
645 | dMULTIPLY1_331 (&relCF1[0],body[0]->R,&temp_fb.f1[0]); | ||
646 | dMULTIPLY1_331 (&relCT1[0],body[0]->R,&temp_fb.t1[0]); | ||
647 | if (jBI->flags & dJOINT_BREAK_AT_B1_FORCE) { | ||
648 | // check if the force is to high | ||
649 | for (int i = 0; i < 3; i++) { | ||
650 | if (relCF1[i] > jBI->b1MaxF[i]) { | ||
651 | jBI->flags |= dJOINT_BROKEN; | ||
652 | goto doneCheckingBreaks; | ||
653 | } | ||
654 | } | ||
655 | } | ||
656 | if (jBI->flags & dJOINT_BREAK_AT_B1_TORQUE) { | ||
657 | // check if the torque is to high | ||
658 | for (int i = 0; i < 3; i++) { | ||
659 | if (relCT1[i] > jBI->b1MaxT[i]) { | ||
660 | jBI->flags |= dJOINT_BROKEN; | ||
661 | goto doneCheckingBreaks; | ||
662 | } | ||
663 | } | ||
664 | } | ||
665 | if (body[1]) { | ||
666 | dReal relCF2[3]; | ||
667 | dReal relCT2[3]; | ||
668 | // multiply the force and torque vectors by the rotation matrix of body 2 | ||
669 | dMULTIPLY1_331 (&relCF2[0],body[1]->R,&temp_fb.f2[0]); | ||
670 | dMULTIPLY1_331 (&relCT2[0],body[1]->R,&temp_fb.t2[0]); | ||
671 | if (jBI->flags & dJOINT_BREAK_AT_B2_FORCE) { | ||
672 | // check if the force is to high | ||
673 | for (int i = 0; i < 3; i++) { | ||
674 | if (relCF2[i] > jBI->b2MaxF[i]) { | ||
675 | jBI->flags |= dJOINT_BROKEN; | ||
676 | goto doneCheckingBreaks; | ||
677 | } | ||
678 | } | ||
679 | } | ||
680 | if (jBI->flags & dJOINT_BREAK_AT_B2_TORQUE) { | ||
681 | // check if the torque is to high | ||
682 | for (int i = 0; i < 3; i++) { | ||
683 | if (relCT2[i] > jBI->b2MaxT[i]) { | ||
684 | jBI->flags |= dJOINT_BROKEN; | ||
685 | goto doneCheckingBreaks; | ||
686 | } | ||
687 | } | ||
688 | } | ||
689 | } | ||
690 | doneCheckingBreaks: | ||
691 | ; | ||
692 | } | ||
693 | } | ||
694 | /*************************************************************************/ | ||
695 | else | ||
696 | { | ||
697 | // no feedback is required, let's compute cforce the faster way | ||
698 | if (body[0]) | ||
699 | Multiply1_8q1 (cforce, Jinfo.J1l, lambda, m); | ||
700 | if (body[1]) | ||
701 | Multiply1_8q1 (cforce + 8, Jinfo.J2l, lambda, m); | ||
702 | } | ||
703 | |||
704 | for (i = 0; i < 2; i++) | ||
705 | { | ||
706 | if (!body[i]) | ||
707 | continue; | ||
708 | for (j = 0; j < 3; j++) | ||
709 | { | ||
710 | body[i]->facc[j] += cforce[i * 8 + j]; | ||
711 | body[i]->tacc[j] += cforce[i * 8 + 4 + j]; | ||
712 | } | ||
713 | } | ||
714 | } | ||
715 | |||
716 | void | ||
717 | dInternalStepIslandFast (dxWorld * world, dxBody * const *bodies, int nb, dxJoint * const *_joints, int nj, dReal stepsize, int maxiterations) | ||
718 | { | ||
719 | # ifdef TIMING | ||
720 | dTimerNow ("preprocessing"); | ||
721 | # endif | ||
722 | dxBody *bodyPair[2], *body; | ||
723 | dReal *GIPair[2], *GinvIPair[2]; | ||
724 | dxJoint *joint; | ||
725 | int iter, b, j, i; | ||
726 | dReal ministep = stepsize / maxiterations; | ||
727 | |||
728 | // make a local copy of the joint array, because we might want to modify it. | ||
729 | // (the "dxJoint *const*" declaration says we're allowed to modify the joints | ||
730 | // but not the joint array, because the caller might need it unchanged). | ||
731 | dxJoint **joints = (dxJoint **) ALLOCA (nj * sizeof (dxJoint *)); | ||
732 | memcpy (joints, _joints, nj * sizeof (dxJoint *)); | ||
733 | |||
734 | // get m = total constraint dimension, nub = number of unbounded variables. | ||
735 | // create constraint offset array and number-of-rows array for all joints. | ||
736 | // the constraints are re-ordered as follows: the purely unbounded | ||
737 | // constraints, the mixed unbounded + LCP constraints, and last the purely | ||
738 | // LCP constraints. this assists the LCP solver to put all unbounded | ||
739 | // variables at the start for a quick factorization. | ||
740 | // | ||
741 | // joints with m=0 are inactive and are removed from the joints array | ||
742 | // entirely, so that the code that follows does not consider them. | ||
743 | // also number all active joints in the joint list (set their tag values). | ||
744 | // inactive joints receive a tag value of -1. | ||
745 | |||
746 | int m = 0; | ||
747 | dxJoint::Info1 * info = (dxJoint::Info1 *) ALLOCA (nj * sizeof (dxJoint::Info1)); | ||
748 | int *ofs = (int *) ALLOCA (nj * sizeof (int)); | ||
749 | for (i = 0, j = 0; j < nj; j++) | ||
750 | { // i=dest, j=src | ||
751 | joints[j]->vtable->getInfo1 (joints[j], info + i); | ||
752 | dIASSERT (info[i].m >= 0 && info[i].m <= 6 && info[i].nub >= 0 && info[i].nub <= info[i].m); | ||
753 | if (info[i].m > 0) | ||
754 | { | ||
755 | joints[i] = joints[j]; | ||
756 | joints[i]->tag = i; | ||
757 | i++; | ||
758 | } | ||
759 | else | ||
760 | { | ||
761 | joints[j]->tag = -1; | ||
762 | } | ||
763 | } | ||
764 | nj = i; | ||
765 | |||
766 | // the purely unbounded constraints | ||
767 | for (i = 0; i < nj; i++) | ||
768 | { | ||
769 | ofs[i] = m; | ||
770 | m += info[i].m; | ||
771 | } | ||
772 | dReal *c = NULL; | ||
773 | dReal *cfm = NULL; | ||
774 | dReal *lo = NULL; | ||
775 | dReal *hi = NULL; | ||
776 | int *findex = NULL; | ||
777 | |||
778 | dReal *J = NULL; | ||
779 | dxJoint::Info2 * Jinfo = NULL; | ||
780 | |||
781 | if (m) | ||
782 | { | ||
783 | // create a constraint equation right hand side vector `c', a constraint | ||
784 | // force mixing vector `cfm', and LCP low and high bound vectors, and an | ||
785 | // 'findex' vector. | ||
786 | c = (dReal *) ALLOCA (m * sizeof (dReal)); | ||
787 | cfm = (dReal *) ALLOCA (m * sizeof (dReal)); | ||
788 | lo = (dReal *) ALLOCA (m * sizeof (dReal)); | ||
789 | hi = (dReal *) ALLOCA (m * sizeof (dReal)); | ||
790 | findex = (int *) ALLOCA (m * sizeof (int)); | ||
791 | dSetZero (c, m); | ||
792 | dSetValue (cfm, m, world->global_cfm); | ||
793 | dSetValue (lo, m, -dInfinity); | ||
794 | dSetValue (hi, m, dInfinity); | ||
795 | for (i = 0; i < m; i++) | ||
796 | findex[i] = -1; | ||
797 | |||
798 | // get jacobian data from constraints. a (2*m)x8 matrix will be created | ||
799 | // to store the two jacobian blocks from each constraint. it has this | ||
800 | // format: | ||
801 | // | ||
802 | // l l l 0 a a a 0 \ . | ||
803 | // l l l 0 a a a 0 }-- jacobian body 1 block for joint 0 (3 rows) | ||
804 | // l l l 0 a a a 0 / | ||
805 | // l l l 0 a a a 0 \ . | ||
806 | // l l l 0 a a a 0 }-- jacobian body 2 block for joint 0 (3 rows) | ||
807 | // l l l 0 a a a 0 / | ||
808 | // l l l 0 a a a 0 }--- jacobian body 1 block for joint 1 (1 row) | ||
809 | // l l l 0 a a a 0 }--- jacobian body 2 block for joint 1 (1 row) | ||
810 | // etc... | ||
811 | // | ||
812 | // (lll) = linear jacobian data | ||
813 | // (aaa) = angular jacobian data | ||
814 | // | ||
815 | # ifdef TIMING | ||
816 | dTimerNow ("create J"); | ||
817 | # endif | ||
818 | J = (dReal *) ALLOCA (2 * m * 8 * sizeof (dReal)); | ||
819 | dSetZero (J, 2 * m * 8); | ||
820 | Jinfo = (dxJoint::Info2 *) ALLOCA (nj * sizeof (dxJoint::Info2)); | ||
821 | for (i = 0; i < nj; i++) | ||
822 | { | ||
823 | Jinfo[i].rowskip = 8; | ||
824 | Jinfo[i].fps = dRecip (stepsize); | ||
825 | Jinfo[i].erp = world->global_erp; | ||
826 | Jinfo[i].J1l = J + 2 * 8 * ofs[i]; | ||
827 | Jinfo[i].J1a = Jinfo[i].J1l + 4; | ||
828 | Jinfo[i].J2l = Jinfo[i].J1l + 8 * info[i].m; | ||
829 | Jinfo[i].J2a = Jinfo[i].J2l + 4; | ||
830 | Jinfo[i].c = c + ofs[i]; | ||
831 | Jinfo[i].cfm = cfm + ofs[i]; | ||
832 | Jinfo[i].lo = lo + ofs[i]; | ||
833 | Jinfo[i].hi = hi + ofs[i]; | ||
834 | Jinfo[i].findex = findex + ofs[i]; | ||
835 | //joints[i]->vtable->getInfo2 (joints[i], Jinfo+i); | ||
836 | } | ||
837 | |||
838 | } | ||
839 | |||
840 | dReal *saveFacc = (dReal *) ALLOCA (nb * 4 * sizeof (dReal)); | ||
841 | dReal *saveTacc = (dReal *) ALLOCA (nb * 4 * sizeof (dReal)); | ||
842 | dReal *globalI = (dReal *) ALLOCA (nb * 12 * sizeof (dReal)); | ||
843 | dReal *globalInvI = (dReal *) ALLOCA (nb * 12 * sizeof (dReal)); | ||
844 | for (b = 0; b < nb; b++) | ||
845 | { | ||
846 | for (i = 0; i < 4; i++) | ||
847 | { | ||
848 | saveFacc[b * 4 + i] = bodies[b]->facc[i]; | ||
849 | saveTacc[b * 4 + i] = bodies[b]->tacc[i]; | ||
850 | bodies[b]->tag = b; | ||
851 | } | ||
852 | } | ||
853 | |||
854 | for (iter = 0; iter < maxiterations; iter++) | ||
855 | { | ||
856 | # ifdef TIMING | ||
857 | dTimerNow ("applying inertia and gravity"); | ||
858 | # endif | ||
859 | dReal tmp[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
860 | |||
861 | for (b = 0; b < nb; b++) | ||
862 | { | ||
863 | body = bodies[b]; | ||
864 | |||
865 | // for all bodies, compute the inertia tensor and its inverse in the global | ||
866 | // frame, and compute the rotational force and add it to the torque | ||
867 | // accumulator. I and invI are vertically stacked 3x4 matrices, one per body. | ||
868 | // @@@ check computation of rotational force. | ||
869 | |||
870 | // compute inertia tensor in global frame | ||
871 | dMULTIPLY2_333 (tmp, body->mass.I, body->R); | ||
872 | dMULTIPLY0_333 (globalI + b * 12, body->R, tmp); | ||
873 | // compute inverse inertia tensor in global frame | ||
874 | dMULTIPLY2_333 (tmp, body->invI, body->R); | ||
875 | dMULTIPLY0_333 (globalInvI + b * 12, body->R, tmp); | ||
876 | |||
877 | for (i = 0; i < 4; i++) | ||
878 | body->tacc[i] = saveTacc[b * 4 + i]; | ||
879 | // compute rotational force | ||
880 | dMULTIPLY0_331 (tmp, globalI + b * 12, body->avel); | ||
881 | dCROSS (body->tacc, -=, body->avel, tmp); | ||
882 | |||
883 | // add the gravity force to all bodies | ||
884 | if ((body->flags & dxBodyNoGravity) == 0) | ||
885 | { | ||
886 | body->facc[0] = saveFacc[b * 4 + 0] + body->mass.mass * world->gravity[0]; | ||
887 | body->facc[1] = saveFacc[b * 4 + 1] + body->mass.mass * world->gravity[1]; | ||
888 | body->facc[2] = saveFacc[b * 4 + 2] + body->mass.mass * world->gravity[2]; | ||
889 | body->facc[3] = 0; | ||
890 | } | ||
891 | |||
892 | } | ||
893 | |||
894 | #ifdef RANDOM_JOINT_ORDER | ||
895 | #ifdef TIMING | ||
896 | dTimerNow ("randomizing joint order"); | ||
897 | #endif | ||
898 | //randomize the order of the joints by looping through the array | ||
899 | //and swapping the current joint pointer with a random one before it. | ||
900 | for (j = 0; j < nj; j++) | ||
901 | { | ||
902 | joint = joints[j]; | ||
903 | dxJoint::Info1 i1 = info[j]; | ||
904 | dxJoint::Info2 i2 = Jinfo[j]; | ||
905 | int r = rand () % (j + 1); | ||
906 | joints[j] = joints[r]; | ||
907 | info[j] = info[r]; | ||
908 | Jinfo[j] = Jinfo[r]; | ||
909 | joints[r] = joint; | ||
910 | info[r] = i1; | ||
911 | Jinfo[r] = i2; | ||
912 | } | ||
913 | #endif | ||
914 | |||
915 | //now iterate through the random ordered joint array we created. | ||
916 | for (j = 0; j < nj; j++) | ||
917 | { | ||
918 | #ifdef TIMING | ||
919 | dTimerNow ("setting up joint"); | ||
920 | #endif | ||
921 | joint = joints[j]; | ||
922 | bodyPair[0] = joint->node[0].body; | ||
923 | bodyPair[1] = joint->node[1].body; | ||
924 | |||
925 | if (bodyPair[0] && (bodyPair[0]->flags & dxBodyDisabled)) | ||
926 | bodyPair[0] = 0; | ||
927 | if (bodyPair[1] && (bodyPair[1]->flags & dxBodyDisabled)) | ||
928 | bodyPair[1] = 0; | ||
929 | |||
930 | //if this joint is not connected to any enabled bodies, skip it. | ||
931 | if (!bodyPair[0] && !bodyPair[1]) | ||
932 | continue; | ||
933 | |||
934 | if (bodyPair[0]) | ||
935 | { | ||
936 | GIPair[0] = globalI + bodyPair[0]->tag * 12; | ||
937 | GinvIPair[0] = globalInvI + bodyPair[0]->tag * 12; | ||
938 | } | ||
939 | if (bodyPair[1]) | ||
940 | { | ||
941 | GIPair[1] = globalI + bodyPair[1]->tag * 12; | ||
942 | GinvIPair[1] = globalInvI + bodyPair[1]->tag * 12; | ||
943 | } | ||
944 | |||
945 | joints[j]->vtable->getInfo2 (joints[j], Jinfo + j); | ||
946 | |||
947 | //dInternalStepIslandFast is an exact copy of the old routine with one | ||
948 | //modification: the calculated forces are added back to the facc and tacc | ||
949 | //vectors instead of applying them to the bodies and moving them. | ||
950 | if (info[j].m > 0) | ||
951 | { | ||
952 | dInternalStepFast (world, bodyPair, GIPair, GinvIPair, joint, info[j], Jinfo[j], ministep); | ||
953 | } | ||
954 | } | ||
955 | // } | ||
956 | # ifdef TIMING | ||
957 | dTimerNow ("moving bodies"); | ||
958 | # endif | ||
959 | //Now we can simulate all the free floating bodies, and move them. | ||
960 | for (b = 0; b < nb; b++) | ||
961 | { | ||
962 | body = bodies[b]; | ||
963 | |||
964 | for (i = 0; i < 4; i++) | ||
965 | { | ||
966 | body->facc[i] *= ministep; | ||
967 | body->tacc[i] *= ministep; | ||
968 | } | ||
969 | |||
970 | //apply torque | ||
971 | dMULTIPLYADD0_331 (body->avel, globalInvI + b * 12, body->tacc); | ||
972 | |||
973 | //apply force | ||
974 | for (i = 0; i < 3; i++) | ||
975 | body->lvel[i] += body->invMass * body->facc[i]; | ||
976 | |||
977 | //move It! | ||
978 | moveAndRotateBody (body, ministep); | ||
979 | } | ||
980 | } | ||
981 | for (b = 0; b < nb; b++) | ||
982 | for (j = 0; j < 4; j++) | ||
983 | bodies[b]->facc[j] = bodies[b]->tacc[j] = 0; | ||
984 | } | ||
985 | |||
986 | |||
987 | #ifdef NO_ISLANDS | ||
988 | |||
989 | // Since the iterative algorithm doesn't care about islands of bodies, this is a | ||
990 | // faster algorithm that just sends it all the joints and bodies in one array. | ||
991 | // It's downfall is it's inability to handle disabled bodies as well as the old one. | ||
992 | static void | ||
993 | processIslandsFast (dxWorld * world, dReal stepsize, int maxiterations) | ||
994 | { | ||
995 | // nothing to do if no bodies | ||
996 | if (world->nb <= 0) | ||
997 | return; | ||
998 | |||
999 | # ifdef TIMING | ||
1000 | dTimerStart ("creating joint and body arrays"); | ||
1001 | # endif | ||
1002 | dxBody **bodies, *body; | ||
1003 | dxJoint **joints, *joint; | ||
1004 | joints = (dxJoint **) ALLOCA (world->nj * sizeof (dxJoint *)); | ||
1005 | bodies = (dxBody **) ALLOCA (world->nb * sizeof (dxBody *)); | ||
1006 | |||
1007 | int nj = 0; | ||
1008 | for (joint = world->firstjoint; joint; joint = (dxJoint *) joint->next) | ||
1009 | joints[nj++] = joint; | ||
1010 | |||
1011 | int nb = 0; | ||
1012 | for (body = world->firstbody; body; body = (dxBody *) body->next) | ||
1013 | bodies[nb++] = body; | ||
1014 | |||
1015 | dInternalStepIslandFast (world, bodies, nb, joints, nj, stepsize, maxiterations); | ||
1016 | # ifdef TIMING | ||
1017 | dTimerEnd (); | ||
1018 | dTimerReport (stdout, 1); | ||
1019 | # endif | ||
1020 | } | ||
1021 | |||
1022 | #else | ||
1023 | |||
1024 | //**************************************************************************** | ||
1025 | // island processing | ||
1026 | |||
1027 | // this groups all joints and bodies in a world into islands. all objects | ||
1028 | // in an island are reachable by going through connected bodies and joints. | ||
1029 | // each island can be simulated separately. | ||
1030 | // note that joints that are not attached to anything will not be included | ||
1031 | // in any island, an so they do not affect the simulation. | ||
1032 | // | ||
1033 | // this function starts new island from unvisited bodies. however, it will | ||
1034 | // never start a new islands from a disabled body. thus islands of disabled | ||
1035 | // bodies will not be included in the simulation. disabled bodies are | ||
1036 | // re-enabled if they are found to be part of an active island. | ||
1037 | |||
1038 | static void | ||
1039 | processIslandsFast (dxWorld * world, dReal stepsize, int maxiterations) | ||
1040 | { | ||
1041 | #ifdef TIMING | ||
1042 | dTimerStart ("Island Setup"); | ||
1043 | #endif | ||
1044 | dxBody *b, *bb, **body; | ||
1045 | dxJoint *j, **joint; | ||
1046 | |||
1047 | // nothing to do if no bodies | ||
1048 | if (world->nb <= 0) | ||
1049 | return; | ||
1050 | |||
1051 | // make arrays for body and joint lists (for a single island) to go into | ||
1052 | body = (dxBody **) ALLOCA (world->nb * sizeof (dxBody *)); | ||
1053 | joint = (dxJoint **) ALLOCA (world->nj * sizeof (dxJoint *)); | ||
1054 | int bcount = 0; // number of bodies in `body' | ||
1055 | int jcount = 0; // number of joints in `joint' | ||
1056 | int tbcount = 0; | ||
1057 | int tjcount = 0; | ||
1058 | |||
1059 | // set all body/joint tags to 0 | ||
1060 | for (b = world->firstbody; b; b = (dxBody *) b->next) | ||
1061 | b->tag = 0; | ||
1062 | for (j = world->firstjoint; j; j = (dxJoint *) j->next) | ||
1063 | j->tag = 0; | ||
1064 | |||
1065 | // allocate a stack of unvisited bodies in the island. the maximum size of | ||
1066 | // the stack can be the lesser of the number of bodies or joints, because | ||
1067 | // new bodies are only ever added to the stack by going through untagged | ||
1068 | // joints. all the bodies in the stack must be tagged! | ||
1069 | int stackalloc = (world->nj < world->nb) ? world->nj : world->nb; | ||
1070 | dxBody **stack = (dxBody **) ALLOCA (stackalloc * sizeof (dxBody *)); | ||
1071 | int *autostack = (int *) ALLOCA (stackalloc * sizeof (int)); | ||
1072 | |||
1073 | for (bb = world->firstbody; bb; bb = (dxBody *) bb->next) | ||
1074 | { | ||
1075 | #ifdef TIMING | ||
1076 | dTimerNow ("Island Processing"); | ||
1077 | #endif | ||
1078 | // get bb = the next enabled, untagged body, and tag it | ||
1079 | if (bb->tag || (bb->flags & dxBodyDisabled)) | ||
1080 | continue; | ||
1081 | bb->tag = 1; | ||
1082 | |||
1083 | // tag all bodies and joints starting from bb. | ||
1084 | int stacksize = 0; | ||
1085 | int autoDepth = autoEnableDepth; | ||
1086 | b = bb; | ||
1087 | body[0] = bb; | ||
1088 | bcount = 1; | ||
1089 | jcount = 0; | ||
1090 | goto quickstart; | ||
1091 | while (stacksize > 0) | ||
1092 | { | ||
1093 | b = stack[--stacksize]; // pop body off stack | ||
1094 | autoDepth = autostack[stacksize]; | ||
1095 | body[bcount++] = b; // put body on body list | ||
1096 | quickstart: | ||
1097 | |||
1098 | // traverse and tag all body's joints, add untagged connected bodies | ||
1099 | // to stack | ||
1100 | for (dxJointNode * n = b->firstjoint; n; n = n->next) | ||
1101 | { | ||
1102 | if (!n->joint->tag) | ||
1103 | { | ||
1104 | int thisDepth = autoEnableDepth; | ||
1105 | n->joint->tag = 1; | ||
1106 | joint[jcount++] = n->joint; | ||
1107 | if (n->body && !n->body->tag) | ||
1108 | { | ||
1109 | if (n->body->flags & dxBodyDisabled) | ||
1110 | thisDepth = autoDepth - 1; | ||
1111 | if (thisDepth < 0) | ||
1112 | continue; | ||
1113 | n->body->flags &= ~dxBodyDisabled; | ||
1114 | n->body->tag = 1; | ||
1115 | autostack[stacksize] = thisDepth; | ||
1116 | stack[stacksize++] = n->body; | ||
1117 | } | ||
1118 | } | ||
1119 | } | ||
1120 | dIASSERT (stacksize <= world->nb); | ||
1121 | dIASSERT (stacksize <= world->nj); | ||
1122 | } | ||
1123 | |||
1124 | // now do something with body and joint lists | ||
1125 | dInternalStepIslandFast (world, body, bcount, joint, jcount, stepsize, maxiterations); | ||
1126 | |||
1127 | // what we've just done may have altered the body/joint tag values. | ||
1128 | // we must make sure that these tags are nonzero. | ||
1129 | // also make sure all bodies are in the enabled state. | ||
1130 | int i; | ||
1131 | for (i = 0; i < bcount; i++) | ||
1132 | { | ||
1133 | body[i]->tag = 1; | ||
1134 | body[i]->flags &= ~dxBodyDisabled; | ||
1135 | } | ||
1136 | for (i = 0; i < jcount; i++) | ||
1137 | joint[i]->tag = 1; | ||
1138 | |||
1139 | tbcount += bcount; | ||
1140 | tjcount += jcount; | ||
1141 | } | ||
1142 | |||
1143 | #ifdef TIMING | ||
1144 | dMessage(0, "Total joints processed: %i, bodies: %i", tjcount, tbcount); | ||
1145 | #endif | ||
1146 | |||
1147 | // if debugging, check that all objects (except for disabled bodies, | ||
1148 | // unconnected joints, and joints that are connected to disabled bodies) | ||
1149 | // were tagged. | ||
1150 | # ifndef dNODEBUG | ||
1151 | for (b = world->firstbody; b; b = (dxBody *) b->next) | ||
1152 | { | ||
1153 | if (b->flags & dxBodyDisabled) | ||
1154 | { | ||
1155 | if (b->tag) | ||
1156 | dDebug (0, "disabled body tagged"); | ||
1157 | } | ||
1158 | else | ||
1159 | { | ||
1160 | if (!b->tag) | ||
1161 | dDebug (0, "enabled body not tagged"); | ||
1162 | } | ||
1163 | } | ||
1164 | for (j = world->firstjoint; j; j = (dxJoint *) j->next) | ||
1165 | { | ||
1166 | if ((j->node[0].body && (j->node[0].body->flags & dxBodyDisabled) == 0) || (j->node[1].body && (j->node[1].body->flags & dxBodyDisabled) == 0)) | ||
1167 | { | ||
1168 | if (!j->tag) | ||
1169 | dDebug (0, "attached enabled joint not tagged"); | ||
1170 | } | ||
1171 | else | ||
1172 | { | ||
1173 | if (j->tag) | ||
1174 | dDebug (0, "unattached or disabled joint tagged"); | ||
1175 | } | ||
1176 | } | ||
1177 | # endif | ||
1178 | /******************** breakable joint contribution ***********************/ | ||
1179 | dxJoint* nextJ; | ||
1180 | if (!world->firstjoint) | ||
1181 | nextJ = 0; | ||
1182 | else | ||
1183 | nextJ = (dxJoint*)world->firstjoint->next; | ||
1184 | for (j=world->firstjoint; j; j=nextJ) { | ||
1185 | nextJ = (dxJoint*)j->next; | ||
1186 | // check if joint is breakable and broken | ||
1187 | if (j->breakInfo && j->breakInfo->flags & dJOINT_BROKEN) { | ||
1188 | // detach (break) the joint | ||
1189 | dJointAttach (j, 0, 0); | ||
1190 | // call the callback function if it is set | ||
1191 | if (j->breakInfo->callback) j->breakInfo->callback (j); | ||
1192 | // finally destroy the joint if the dJOINT_DELETE_ON_BREAK is set | ||
1193 | if (j->breakInfo->flags & dJOINT_DELETE_ON_BREAK) dJointDestroy (j); | ||
1194 | } | ||
1195 | } | ||
1196 | /*************************************************************************/ | ||
1197 | |||
1198 | # ifdef TIMING | ||
1199 | dTimerEnd (); | ||
1200 | dTimerReport (stdout, 1); | ||
1201 | # endif | ||
1202 | } | ||
1203 | |||
1204 | #endif | ||
1205 | |||
1206 | |||
1207 | void dWorldStepFast1 (dWorldID w, dReal stepsize, int maxiterations) | ||
1208 | { | ||
1209 | dUASSERT (w, "bad world argument"); | ||
1210 | dUASSERT (stepsize > 0, "stepsize must be > 0"); | ||
1211 | processIslandsFast (w, stepsize, maxiterations); | ||
1212 | } | ||
diff --git a/libraries/ode-0.9/contrib/BreakableJoints/test_breakable.cpp b/libraries/ode-0.9/contrib/BreakableJoints/test_breakable.cpp new file mode 100644 index 0000000..bfed3a3 --- /dev/null +++ b/libraries/ode-0.9/contrib/BreakableJoints/test_breakable.cpp | |||
@@ -0,0 +1,416 @@ | |||
1 | /************************************************************************* | ||
2 | * * | ||
3 | * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * | ||
4 | * All rights reserved. Email: russ@q12.org Web: www.q12.org * | ||
5 | * * | ||
6 | * This library is free software; you can redistribute it and/or * | ||
7 | * modify it under the terms of EITHER: * | ||
8 | * (1) The GNU Lesser General Public License as published by the Free * | ||
9 | * Software Foundation; either version 2.1 of the License, or (at * | ||
10 | * your option) any later version. The text of the GNU Lesser * | ||
11 | * General Public License is included with this library in the * | ||
12 | * file LICENSE.TXT. * | ||
13 | * (2) The BSD-style license that is included with this library in * | ||
14 | * the file LICENSE-BSD.TXT. * | ||
15 | * * | ||
16 | * This library is distributed in the hope that it will be useful, * | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * | ||
19 | * LICENSE.TXT and LICENSE-BSD.TXT for more details. * | ||
20 | * * | ||
21 | *************************************************************************/ | ||
22 | |||
23 | /* | ||
24 | |||
25 | buggy with suspension. | ||
26 | this also shows you how to use geom groups. | ||
27 | |||
28 | */ | ||
29 | |||
30 | |||
31 | #include <stdlib.h> | ||
32 | |||
33 | #include <ode/ode.h> | ||
34 | #include <drawstuff/drawstuff.h> | ||
35 | |||
36 | #ifdef _MSC_VER | ||
37 | #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints | ||
38 | #endif | ||
39 | |||
40 | // select correct drawing functions | ||
41 | |||
42 | #ifdef dDOUBLE | ||
43 | #define dsDrawBox dsDrawBoxD | ||
44 | #define dsDrawSphere dsDrawSphereD | ||
45 | #define dsDrawCylinder dsDrawCylinderD | ||
46 | #define dsDrawCappedCylinder dsDrawCappedCylinderD | ||
47 | #endif | ||
48 | |||
49 | |||
50 | // some constants | ||
51 | |||
52 | #define LENGTH 0.7 // chassis length | ||
53 | #define WIDTH 0.4 // chassis width | ||
54 | #define HEIGHT 0.2 // chassis height | ||
55 | #define RADIUS 0.22 // wheel radius | ||
56 | #define STARTZ 0.4 // starting height of chassis | ||
57 | #define CMASS 1 // chassis mass | ||
58 | #define WMASS 0.2 // wheel mass | ||
59 | |||
60 | // dynamics and collision objects (chassis, 4 wheels, environment, obstacles, chain) | ||
61 | static dWorldID world; | ||
62 | static dSpaceID space; | ||
63 | |||
64 | // chain stuff | ||
65 | static const float chain_radius = 0.1; | ||
66 | static const float chain_mass = 0.1; | ||
67 | static const int chain_num = 10; | ||
68 | static dBodyID chain_body[chain_num]; | ||
69 | static dGeomID chain_geom[chain_num]; | ||
70 | static dJointID chain_joint[chain_num-1]; | ||
71 | |||
72 | // 1 chasses, 4 wheels | ||
73 | static dBodyID body[5]; | ||
74 | // joint[0] is left front wheel, joint[1] is right front wheel | ||
75 | static dJointID joint[4]; | ||
76 | static int joint_exists[4]; | ||
77 | static dJointGroupID contactgroup; | ||
78 | static dGeomID ground; | ||
79 | static dSpaceID car_space; | ||
80 | static dGeomID box[1]; | ||
81 | static dGeomID sphere[4]; | ||
82 | static dGeomID ground_box; | ||
83 | static const int obstacle_num = 25; | ||
84 | static dGeomID obstacle[obstacle_num]; | ||
85 | |||
86 | // things that the user controls | ||
87 | |||
88 | static dReal speed=0,steer=0; // user commands | ||
89 | |||
90 | |||
91 | |||
92 | // this is called by dSpaceCollide when two objects in space are | ||
93 | // potentially colliding. | ||
94 | |||
95 | static void nearCallback (void *data, dGeomID o1, dGeomID o2) | ||
96 | { | ||
97 | int i,n; | ||
98 | |||
99 | // // do not collide objects that are connected | ||
100 | // dBodyID b1 = dGeomGetBody (o1), | ||
101 | // b2 = dGeomGetBody (o2); | ||
102 | // if (b1 && b2 && dAreConnected(b1, b2)) return; | ||
103 | |||
104 | const int N = 10; | ||
105 | dContact contact[N]; | ||
106 | n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact)); | ||
107 | if (n > 0) { | ||
108 | for (i=0; i<n; i++) { | ||
109 | contact[i].surface.mode = dContactSlip1 | dContactSlip2 | | ||
110 | dContactSoftERP | dContactSoftCFM | dContactApprox1; | ||
111 | contact[i].surface.mu = dInfinity; | ||
112 | contact[i].surface.slip1 = 0.1; | ||
113 | contact[i].surface.slip2 = 0.1; | ||
114 | contact[i].surface.soft_erp = 0.5; | ||
115 | contact[i].surface.soft_cfm = 0.3; | ||
116 | dJointID c = dJointCreateContact (world,contactgroup,&contact[i]); | ||
117 | dJointAttach (c, | ||
118 | dGeomGetBody(contact[i].geom.g1), | ||
119 | dGeomGetBody(contact[i].geom.g2)); | ||
120 | } | ||
121 | } | ||
122 | } | ||
123 | |||
124 | // callback function for joints that break | ||
125 | static void jointBreakCallback (dJointID j) | ||
126 | { | ||
127 | if (j == joint[0]) joint_exists[0] = 0; | ||
128 | else if (j == joint[1]) joint_exists[1] = 0; | ||
129 | else if (j == joint[2]) joint_exists[2] = 0; | ||
130 | else if (j == joint[3]) joint_exists[3] = 0; | ||
131 | printf ("A joint just broke\n"); | ||
132 | } | ||
133 | |||
134 | // start simulation - set viewpoint | ||
135 | |||
136 | static void start() | ||
137 | { | ||
138 | static float xyz[3] = {0.8317f,-0.9817f,0.8000f}; | ||
139 | static float hpr[3] = {121.0000f,-27.5000f,0.0000f}; | ||
140 | dsSetViewpoint (xyz,hpr); | ||
141 | printf ("Press:\t'a' to increase speed.\n" | ||
142 | "\t'z' to decrease speed.\n" | ||
143 | "\t',' to steer left.\n" | ||
144 | "\t'.' to steer right.\n" | ||
145 | "\t' ' to reset speed and steering.\n"); | ||
146 | } | ||
147 | |||
148 | |||
149 | // called when a key pressed | ||
150 | |||
151 | static void command (int cmd) | ||
152 | { | ||
153 | switch (cmd) { | ||
154 | case 'a': case 'A': | ||
155 | speed += 0.3; | ||
156 | break; | ||
157 | case 'z': case 'Z': | ||
158 | speed -= 0.3; | ||
159 | break; | ||
160 | case ',': | ||
161 | steer -= 0.5; | ||
162 | break; | ||
163 | case '.': | ||
164 | steer += 0.5; | ||
165 | break; | ||
166 | case ' ': | ||
167 | speed = 0; | ||
168 | steer = 0; | ||
169 | break; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | |||
174 | // simulation loop | ||
175 | |||
176 | static void simLoop (int pause) | ||
177 | { | ||
178 | int i; | ||
179 | if (!pause) { | ||
180 | for (i=0; i<2; i++) { | ||
181 | if (joint_exists[i]) { | ||
182 | // motor | ||
183 | dJointSetHinge2Param (joint[i],dParamVel2,-speed); | ||
184 | dJointSetHinge2Param (joint[i],dParamFMax2,0.1); | ||
185 | |||
186 | // steering | ||
187 | dReal v = steer - dJointGetHinge2Angle1 (joint[i]); | ||
188 | if (v > 0.1) v = 0.1; | ||
189 | if (v < -0.1) v = -0.1; | ||
190 | v *= 10.0; | ||
191 | dJointSetHinge2Param (joint[i],dParamVel,v); | ||
192 | dJointSetHinge2Param (joint[i],dParamFMax,0.2); | ||
193 | dJointSetHinge2Param (joint[i],dParamLoStop,-0.75); | ||
194 | dJointSetHinge2Param (joint[i],dParamHiStop,0.75); | ||
195 | dJointSetHinge2Param (joint[i],dParamFudgeFactor,0.1); | ||
196 | } | ||
197 | } | ||
198 | |||
199 | dSpaceCollide (space,0,&nearCallback); | ||
200 | //dWorldStep (world,0.05); | ||
201 | dWorldStepFast1 (world,0.05,5); | ||
202 | |||
203 | // remove all contact joints | ||
204 | dJointGroupEmpty (contactgroup); | ||
205 | } | ||
206 | |||
207 | dsSetColor (0,1,1); | ||
208 | dsSetTexture (DS_WOOD); | ||
209 | dReal sides[3] = {LENGTH,WIDTH,HEIGHT}; | ||
210 | dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides); | ||
211 | dsSetColor (1,1,1); | ||
212 | for (i=1; i<=4; i++) | ||
213 | dsDrawCylinder (dBodyGetPosition(body[i]), | ||
214 | dBodyGetRotation(body[i]), | ||
215 | 0.2, | ||
216 | RADIUS); | ||
217 | |||
218 | dVector3 ss; | ||
219 | dGeomBoxGetLengths (ground_box,ss); | ||
220 | dsDrawBox (dGeomGetPosition(ground_box),dGeomGetRotation(ground_box),ss); | ||
221 | |||
222 | dsSetColor (1,0,0); | ||
223 | for (i=0; i<obstacle_num; i++) { | ||
224 | dVector3 ss; | ||
225 | dGeomBoxGetLengths (obstacle[i],ss); | ||
226 | dsDrawBox (dGeomGetPosition(obstacle[i]),dGeomGetRotation(obstacle[i]),ss); | ||
227 | } | ||
228 | |||
229 | dsSetColor (1,1,0); | ||
230 | for (i=0; i<chain_num; i++) { | ||
231 | dsDrawSphere (dGeomGetPosition(chain_geom[i]),dGeomGetRotation(chain_geom[i]),chain_radius); | ||
232 | } | ||
233 | |||
234 | /* | ||
235 | printf ("%.10f %.10f %.10f %.10f\n", | ||
236 | dJointGetHingeAngle (joint[1]), | ||
237 | dJointGetHingeAngle (joint[2]), | ||
238 | dJointGetHingeAngleRate (joint[1]), | ||
239 | dJointGetHingeAngleRate (joint[2])); | ||
240 | */ | ||
241 | } | ||
242 | |||
243 | int main (int argc, char **argv) | ||
244 | { | ||
245 | int i; | ||
246 | dMass m; | ||
247 | |||
248 | // setup pointers to drawstuff callback functions | ||
249 | dsFunctions fn; | ||
250 | fn.version = DS_VERSION; | ||
251 | fn.start = &start; | ||
252 | fn.step = &simLoop; | ||
253 | fn.command = &command; | ||
254 | fn.stop = 0; | ||
255 | fn.path_to_textures = "../../drawstuff/textures"; | ||
256 | if(argc==2) | ||
257 | { | ||
258 | fn.path_to_textures = argv[1]; | ||
259 | } | ||
260 | // create world | ||
261 | |||
262 | world = dWorldCreate(); | ||
263 | space = dHashSpaceCreate (0); | ||
264 | contactgroup = dJointGroupCreate (0); | ||
265 | dWorldSetGravity (world,0,0,-0.5); | ||
266 | ground = dCreatePlane (space,0,0,1,0); | ||
267 | |||
268 | // chassis body | ||
269 | body[0] = dBodyCreate (world); | ||
270 | dBodySetPosition (body[0],0,0,STARTZ); | ||
271 | dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT); | ||
272 | dMassAdjust (&m,CMASS); | ||
273 | dBodySetMass (body[0],&m); | ||
274 | box[0] = dCreateBox (0,LENGTH,WIDTH,HEIGHT); | ||
275 | dGeomSetBody (box[0],body[0]); | ||
276 | |||
277 | // a chain | ||
278 | for (i=0; i<chain_num; i++) { | ||
279 | chain_body[i] = dBodyCreate (world); | ||
280 | dBodySetPosition (chain_body[i],-LENGTH-(i*2*chain_radius),0,STARTZ-HEIGHT*0.5); | ||
281 | dMassSetSphere (&m,1,chain_radius); | ||
282 | dMassAdjust (&m,chain_mass); | ||
283 | dBodySetMass (chain_body[i],&m); | ||
284 | chain_geom[i] = dCreateSphere (space,chain_radius); | ||
285 | dGeomSetBody (chain_geom[i],chain_body[i]); | ||
286 | } | ||
287 | |||
288 | // wheel bodies | ||
289 | for (i=1; i<=4; i++) { | ||
290 | body[i] = dBodyCreate (world); | ||
291 | dQuaternion q; | ||
292 | dQFromAxisAndAngle (q,1,0,0,M_PI*0.5); | ||
293 | dBodySetQuaternion (body[i],q); | ||
294 | dMassSetSphere (&m,1,RADIUS); | ||
295 | dMassAdjust (&m,WMASS); | ||
296 | dBodySetMass (body[i],&m); | ||
297 | sphere[i-1] = dCreateSphere (0,RADIUS); | ||
298 | dGeomSetBody (sphere[i-1],body[i]); | ||
299 | } | ||
300 | dBodySetPosition (body[1], 0.5*LENGTH, WIDTH*1.0, STARTZ-HEIGHT*0.5); | ||
301 | dBodySetPosition (body[2], 0.5*LENGTH, -WIDTH*1.0, STARTZ-HEIGHT*0.5); | ||
302 | dBodySetPosition (body[3], -0.5*LENGTH, WIDTH*1.0, STARTZ-HEIGHT*0.5); | ||
303 | dBodySetPosition (body[4], -0.5*LENGTH, -WIDTH*1.0, STARTZ-HEIGHT*0.5); | ||
304 | |||
305 | // front wheel hinge | ||
306 | /* | ||
307 | joint[0] = dJointCreateHinge2 (world,0); | ||
308 | dJointAttach (joint[0],body[0],body[1]); | ||
309 | const dReal *a = dBodyGetPosition (body[1]); | ||
310 | dJointSetHinge2Anchor (joint[0],a[0],a[1],a[2]); | ||
311 | dJointSetHinge2Axis1 (joint[0],0,0,1); | ||
312 | dJointSetHinge2Axis2 (joint[0],0,1,0); | ||
313 | */ | ||
314 | |||
315 | // front and back wheel hinges | ||
316 | for (i=0; i<4; i++) { | ||
317 | joint[i] = dJointCreateHinge2 (world,0); | ||
318 | joint_exists[i] = 1; | ||
319 | dJointAttach (joint[i],body[0],body[i+1]); | ||
320 | const dReal *a = dBodyGetPosition (body[i+1]); | ||
321 | dJointSetHinge2Anchor (joint[i],a[0],a[1],a[2]); | ||
322 | dJointSetHinge2Axis1 (joint[i],0,0,1); | ||
323 | dJointSetHinge2Axis2 (joint[i],0,1,0); | ||
324 | |||
325 | // the wheels can break | ||
326 | dJointSetBreakable (joint[i], 1); | ||
327 | // the wheels wil break at a specific force | ||
328 | dJointSetBreakMode (joint[i], | ||
329 | dJOINT_BREAK_AT_B1_FORCE | | ||
330 | dJOINT_BREAK_AT_B2_FORCE | | ||
331 | dJOINT_DELETE_ON_BREAK); | ||
332 | // specify the force for the first body connected to the joint ... | ||
333 | dJointSetBreakForce (joint[i], 0, 2.5, 2.5, 2.5); | ||
334 | // and for the second body | ||
335 | dJointSetBreakForce (joint[i], 1, 2.5, 2.5, 2.5); | ||
336 | // set the callback function | ||
337 | dJointSetBreakCallback (joint[i], &jointBreakCallback); | ||
338 | } | ||
339 | |||
340 | // joints for the chain | ||
341 | for (i=0; i<chain_num-1; i++) { | ||
342 | chain_joint[i] = dJointCreateFixed (world,0); | ||
343 | dJointAttach (chain_joint[i],chain_body[i+1],chain_body[i]); | ||
344 | dJointSetFixed (chain_joint[i]); | ||
345 | // the chain can break | ||
346 | dJointSetBreakable (chain_joint[i], 1); | ||
347 | // the chain wil break at a specific force | ||
348 | dJointSetBreakMode (chain_joint[i], | ||
349 | dJOINT_BREAK_AT_B1_FORCE | | ||
350 | dJOINT_BREAK_AT_B2_FORCE | | ||
351 | dJOINT_DELETE_ON_BREAK); | ||
352 | // specify the force for the first body connected to the joint ... | ||
353 | dJointSetBreakForce (chain_joint[i], 0, 0.5, 0.5, 0.5); | ||
354 | // and for the second body | ||
355 | dJointSetBreakForce (chain_joint[i], 1, 0.5, 0.5, 0.5); | ||
356 | // set the callback function | ||
357 | dJointSetBreakCallback (chain_joint[i], &jointBreakCallback); | ||
358 | } | ||
359 | |||
360 | // set joint suspension | ||
361 | for (i=0; i<4; i++) { | ||
362 | dJointSetHinge2Param (joint[i],dParamSuspensionERP,0.4); | ||
363 | dJointSetHinge2Param (joint[i],dParamSuspensionCFM,0.1); | ||
364 | } | ||
365 | |||
366 | // lock back wheels along the steering axis | ||
367 | for (i=1; i<4; i++) { | ||
368 | // set stops to make sure wheels always stay in alignment | ||
369 | dJointSetHinge2Param (joint[i],dParamLoStop,0); | ||
370 | dJointSetHinge2Param (joint[i],dParamHiStop,0); | ||
371 | // the following alternative method is no good as the wheels may get out | ||
372 | // of alignment: | ||
373 | // dJointSetHinge2Param (joint[i],dParamVel,0); | ||
374 | // dJointSetHinge2Param (joint[i],dParamFMax,dInfinity); | ||
375 | } | ||
376 | |||
377 | // create car space and add it to the top level space | ||
378 | car_space = dSimpleSpaceCreate (space); | ||
379 | dSpaceSetCleanup (car_space,0); | ||
380 | dSpaceAdd (car_space,box[0]); | ||
381 | dSpaceAdd (car_space,sphere[0]); | ||
382 | dSpaceAdd (car_space,sphere[1]); | ||
383 | dSpaceAdd (car_space,sphere[2]); | ||
384 | |||
385 | // environment | ||
386 | ground_box = dCreateBox (space,2,1.5,1); | ||
387 | dMatrix3 R; | ||
388 | dRFromAxisAndAngle (R,0,1,0,-0.15); | ||
389 | dGeomSetPosition (ground_box,2,0,-0.34); | ||
390 | dGeomSetRotation (ground_box,R); | ||
391 | |||
392 | // obstacles | ||
393 | for (i=0; i<obstacle_num; i++) { | ||
394 | dReal height = 0.1+(dReal(rand()%10)/10.0); | ||
395 | obstacle[i] = dCreateBox (space,0.2,0.2,height); | ||
396 | dGeomSetPosition ( | ||
397 | obstacle[i], | ||
398 | (rand()%20)-10, | ||
399 | (rand()%20)-10, | ||
400 | height/2.0); | ||
401 | } | ||
402 | |||
403 | // run simulation | ||
404 | dsSimulationLoop (argc,argv,352,288,&fn); | ||
405 | |||
406 | dJointGroupDestroy (contactgroup); | ||
407 | dSpaceDestroy (space); | ||
408 | dWorldDestroy (world); | ||
409 | dGeomDestroy (box[0]); | ||
410 | for (i=0; i<4; i++) | ||
411 | dGeomDestroy (sphere[i]); | ||
412 | |||
413 | dCloseODE (); | ||
414 | |||
415 | return 0; | ||
416 | } | ||
diff --git a/libraries/ode-0.9/contrib/BreakableJoints/test_buggy.cpp b/libraries/ode-0.9/contrib/BreakableJoints/test_buggy.cpp new file mode 100644 index 0000000..1dc0ab3 --- /dev/null +++ b/libraries/ode-0.9/contrib/BreakableJoints/test_buggy.cpp | |||
@@ -0,0 +1,327 @@ | |||
1 | /************************************************************************* | ||
2 | * * | ||
3 | * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * | ||
4 | * All rights reserved. Email: russ@q12.org Web: www.q12.org * | ||
5 | * * | ||
6 | * This library is free software; you can redistribute it and/or * | ||
7 | * modify it under the terms of EITHER: * | ||
8 | * (1) The GNU Lesser General Public License as published by the Free * | ||
9 | * Software Foundation; either version 2.1 of the License, or (at * | ||
10 | * your option) any later version. The text of the GNU Lesser * | ||
11 | * General Public License is included with this library in the * | ||
12 | * file LICENSE.TXT. * | ||
13 | * (2) The BSD-style license that is included with this library in * | ||
14 | * the file LICENSE-BSD.TXT. * | ||
15 | * * | ||
16 | * This library is distributed in the hope that it will be useful, * | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * | ||
19 | * LICENSE.TXT and LICENSE-BSD.TXT for more details. * | ||
20 | * * | ||
21 | *************************************************************************/ | ||
22 | |||
23 | /* | ||
24 | |||
25 | buggy with suspension. | ||
26 | this also shows you how to use geom groups. | ||
27 | |||
28 | */ | ||
29 | |||
30 | |||
31 | #include <ode/ode.h> | ||
32 | #include <drawstuff/drawstuff.h> | ||
33 | |||
34 | #ifdef _MSC_VER | ||
35 | #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints | ||
36 | #endif | ||
37 | |||
38 | // select correct drawing functions | ||
39 | |||
40 | #ifdef dDOUBLE | ||
41 | #define dsDrawBox dsDrawBoxD | ||
42 | #define dsDrawSphere dsDrawSphereD | ||
43 | #define dsDrawCylinder dsDrawCylinderD | ||
44 | #define dsDrawCappedCylinder dsDrawCappedCylinderD | ||
45 | #endif | ||
46 | |||
47 | |||
48 | // some constants | ||
49 | |||
50 | #define LENGTH 0.7 // chassis length | ||
51 | #define WIDTH 0.5 // chassis width | ||
52 | #define HEIGHT 0.2 // chassis height | ||
53 | #define RADIUS 0.18 // wheel radius | ||
54 | #define STARTZ 0.5 // starting height of chassis | ||
55 | #define CMASS 1 // chassis mass | ||
56 | #define WMASS 0.2 // wheel mass | ||
57 | |||
58 | |||
59 | // dynamics and collision objects (chassis, 3 wheels, environment) | ||
60 | |||
61 | static dWorldID world; | ||
62 | static dSpaceID space; | ||
63 | static dBodyID body[4]; | ||
64 | static dJointID joint[3]; // joint[0] is the front wheel | ||
65 | static dJointGroupID contactgroup; | ||
66 | static dGeomID ground; | ||
67 | static dSpaceID car_space; | ||
68 | static dGeomID box[1]; | ||
69 | static dGeomID sphere[3]; | ||
70 | static dGeomID ground_box; | ||
71 | |||
72 | |||
73 | // things that the user controls | ||
74 | |||
75 | static dReal speed=0,steer=0; // user commands | ||
76 | |||
77 | |||
78 | |||
79 | // this is called by dSpaceCollide when two objects in space are | ||
80 | // potentially colliding. | ||
81 | |||
82 | static void nearCallback (void *data, dGeomID o1, dGeomID o2) | ||
83 | { | ||
84 | int i,n; | ||
85 | |||
86 | // only collide things with the ground | ||
87 | int g1 = (o1 == ground || o1 == ground_box); | ||
88 | int g2 = (o2 == ground || o2 == ground_box); | ||
89 | if (!(g1 ^ g2)) return; | ||
90 | |||
91 | const int N = 10; | ||
92 | dContact contact[N]; | ||
93 | n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact)); | ||
94 | if (n > 0) { | ||
95 | for (i=0; i<n; i++) { | ||
96 | contact[i].surface.mode = dContactSlip1 | dContactSlip2 | | ||
97 | dContactSoftERP | dContactSoftCFM | dContactApprox1; | ||
98 | contact[i].surface.mu = dInfinity; | ||
99 | contact[i].surface.slip1 = 0.1; | ||
100 | contact[i].surface.slip2 = 0.1; | ||
101 | contact[i].surface.soft_erp = 0.5; | ||
102 | contact[i].surface.soft_cfm = 0.3; | ||
103 | dJointID c = dJointCreateContact (world,contactgroup,&contact[i]); | ||
104 | dJointAttach (c, | ||
105 | dGeomGetBody(contact[i].geom.g1), | ||
106 | dGeomGetBody(contact[i].geom.g2)); | ||
107 | } | ||
108 | } | ||
109 | } | ||
110 | |||
111 | |||
112 | // start simulation - set viewpoint | ||
113 | |||
114 | static void start() | ||
115 | { | ||
116 | static float xyz[3] = {0.8317f,-0.9817f,0.8000f}; | ||
117 | static float hpr[3] = {121.0000f,-27.5000f,0.0000f}; | ||
118 | dsSetViewpoint (xyz,hpr); | ||
119 | printf ("Press:\t'a' to increase speed.\n" | ||
120 | "\t'z' to decrease speed.\n" | ||
121 | "\t',' to steer left.\n" | ||
122 | "\t'.' to steer right.\n" | ||
123 | "\t' ' to reset speed and steering.\n"); | ||
124 | } | ||
125 | |||
126 | |||
127 | // called when a key pressed | ||
128 | |||
129 | static void command (int cmd) | ||
130 | { | ||
131 | switch (cmd) { | ||
132 | case 'a': case 'A': | ||
133 | speed += 0.3; | ||
134 | break; | ||
135 | case 'z': case 'Z': | ||
136 | speed -= 0.3; | ||
137 | break; | ||
138 | case ',': | ||
139 | steer -= 0.5; | ||
140 | break; | ||
141 | case '.': | ||
142 | steer += 0.5; | ||
143 | break; | ||
144 | case ' ': | ||
145 | speed = 0; | ||
146 | steer = 0; | ||
147 | break; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | |||
152 | // simulation loop | ||
153 | |||
154 | static void simLoop (int pause) | ||
155 | { | ||
156 | int i; | ||
157 | if (!pause) { | ||
158 | // motor | ||
159 | dJointSetHinge2Param (joint[0],dParamVel2,-speed); | ||
160 | dJointSetHinge2Param (joint[0],dParamFMax2,0.1); | ||
161 | |||
162 | // steering | ||
163 | dReal v = steer - dJointGetHinge2Angle1 (joint[0]); | ||
164 | if (v > 0.1) v = 0.1; | ||
165 | if (v < -0.1) v = -0.1; | ||
166 | v *= 10.0; | ||
167 | dJointSetHinge2Param (joint[0],dParamVel,v); | ||
168 | dJointSetHinge2Param (joint[0],dParamFMax,0.2); | ||
169 | dJointSetHinge2Param (joint[0],dParamLoStop,-0.75); | ||
170 | dJointSetHinge2Param (joint[0],dParamHiStop,0.75); | ||
171 | dJointSetHinge2Param (joint[0],dParamFudgeFactor,0.1); | ||
172 | |||
173 | dSpaceCollide (space,0,&nearCallback); | ||
174 | dWorldStep (world,0.05); | ||
175 | |||
176 | // remove all contact joints | ||
177 | dJointGroupEmpty (contactgroup); | ||
178 | } | ||
179 | |||
180 | dsSetColor (0,1,1); | ||
181 | dsSetTexture (DS_WOOD); | ||
182 | dReal sides[3] = {LENGTH,WIDTH,HEIGHT}; | ||
183 | dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides); | ||
184 | dsSetColor (1,1,1); | ||
185 | for (i=1; i<=3; i++) dsDrawCylinder (dBodyGetPosition(body[i]), | ||
186 | dBodyGetRotation(body[i]),0.02f,RADIUS); | ||
187 | |||
188 | dVector3 ss; | ||
189 | dGeomBoxGetLengths (ground_box,ss); | ||
190 | dsDrawBox (dGeomGetPosition(ground_box),dGeomGetRotation(ground_box),ss); | ||
191 | |||
192 | /* | ||
193 | printf ("%.10f %.10f %.10f %.10f\n", | ||
194 | dJointGetHingeAngle (joint[1]), | ||
195 | dJointGetHingeAngle (joint[2]), | ||
196 | dJointGetHingeAngleRate (joint[1]), | ||
197 | dJointGetHingeAngleRate (joint[2])); | ||
198 | */ | ||
199 | } | ||
200 | |||
201 | |||
202 | int main (int argc, char **argv) | ||
203 | { | ||
204 | int i; | ||
205 | dMass m; | ||
206 | |||
207 | // setup pointers to drawstuff callback functions | ||
208 | dsFunctions fn; | ||
209 | fn.version = DS_VERSION; | ||
210 | fn.start = &start; | ||
211 | fn.step = &simLoop; | ||
212 | fn.command = &command; | ||
213 | fn.stop = 0; | ||
214 | fn.path_to_textures = "../../drawstuff/textures"; | ||
215 | if(argc==2) | ||
216 | { | ||
217 | fn.path_to_textures = argv[1]; | ||
218 | } | ||
219 | |||
220 | // create world | ||
221 | |||
222 | world = dWorldCreate(); | ||
223 | space = dHashSpaceCreate (0); | ||
224 | contactgroup = dJointGroupCreate (0); | ||
225 | dWorldSetGravity (world,0,0,-0.5); | ||
226 | ground = dCreatePlane (space,0,0,1,0); | ||
227 | |||
228 | // chassis body | ||
229 | body[0] = dBodyCreate (world); | ||
230 | dBodySetPosition (body[0],0,0,STARTZ); | ||
231 | dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT); | ||
232 | dMassAdjust (&m,CMASS); | ||
233 | dBodySetMass (body[0],&m); | ||
234 | box[0] = dCreateBox (0,LENGTH,WIDTH,HEIGHT); | ||
235 | dGeomSetBody (box[0],body[0]); | ||
236 | |||
237 | // wheel bodies | ||
238 | for (i=1; i<=3; i++) { | ||
239 | body[i] = dBodyCreate (world); | ||
240 | dQuaternion q; | ||
241 | dQFromAxisAndAngle (q,1,0,0,M_PI*0.5); | ||
242 | dBodySetQuaternion (body[i],q); | ||
243 | dMassSetSphere (&m,1,RADIUS); | ||
244 | dMassAdjust (&m,WMASS); | ||
245 | dBodySetMass (body[i],&m); | ||
246 | sphere[i-1] = dCreateSphere (0,RADIUS); | ||
247 | dGeomSetBody (sphere[i-1],body[i]); | ||
248 | } | ||
249 | dBodySetPosition (body[1],0.5*LENGTH,0,STARTZ-HEIGHT*0.5); | ||
250 | dBodySetPosition (body[2],-0.5*LENGTH, WIDTH*0.5,STARTZ-HEIGHT*0.5); | ||
251 | dBodySetPosition (body[3],-0.5*LENGTH,-WIDTH*0.5,STARTZ-HEIGHT*0.5); | ||
252 | |||
253 | // front wheel hinge | ||
254 | /* | ||
255 | joint[0] = dJointCreateHinge2 (world,0); | ||
256 | dJointAttach (joint[0],body[0],body[1]); | ||
257 | const dReal *a = dBodyGetPosition (body[1]); | ||
258 | dJointSetHinge2Anchor (joint[0],a[0],a[1],a[2]); | ||
259 | dJointSetHinge2Axis1 (joint[0],0,0,1); | ||
260 | dJointSetHinge2Axis2 (joint[0],0,1,0); | ||
261 | */ | ||
262 | |||
263 | // front and back wheel hinges | ||
264 | for (i=0; i<3; i++) { | ||
265 | joint[i] = dJointCreateHinge2 (world,0); | ||
266 | dJointAttach (joint[i],body[0],body[i+1]); | ||
267 | const dReal *a = dBodyGetPosition (body[i+1]); | ||
268 | dJointSetHinge2Anchor (joint[i],a[0],a[1],a[2]); | ||
269 | dJointSetHinge2Axis1 (joint[i],0,0,1); | ||
270 | dJointSetHinge2Axis2 (joint[i],0,1,0); | ||
271 | |||
272 | // breakable joints contribution | ||
273 | // the wheels can break | ||
274 | dJointSetBreakable (joint[i], 1); | ||
275 | // the wheels wil break at a specific force | ||
276 | dJointSetBreakMode (joint[i], dJOINT_BREAK_AT_B1_FORCE|dJOINT_BREAK_AT_B2_FORCE); | ||
277 | // specify the force for the first body connected to the joint ... | ||
278 | dJointSetBreakForce (joint[i], 0, 1.5, 1.5, 1.5); | ||
279 | // and for the second body | ||
280 | dJointSetBreakForce (joint[i], 1, 1.5, 1.5, 1.5); | ||
281 | } | ||
282 | |||
283 | // set joint suspension | ||
284 | for (i=0; i<3; i++) { | ||
285 | dJointSetHinge2Param (joint[i],dParamSuspensionERP,0.4); | ||
286 | dJointSetHinge2Param (joint[i],dParamSuspensionCFM,0.8); | ||
287 | } | ||
288 | |||
289 | // lock back wheels along the steering axis | ||
290 | for (i=1; i<3; i++) { | ||
291 | // set stops to make sure wheels always stay in alignment | ||
292 | dJointSetHinge2Param (joint[i],dParamLoStop,0); | ||
293 | dJointSetHinge2Param (joint[i],dParamHiStop,0); | ||
294 | // the following alternative method is no good as the wheels may get out | ||
295 | // of alignment: | ||
296 | // dJointSetHinge2Param (joint[i],dParamVel,0); | ||
297 | // dJointSetHinge2Param (joint[i],dParamFMax,dInfinity); | ||
298 | } | ||
299 | |||
300 | // create car space and add it to the top level space | ||
301 | car_space = dSimpleSpaceCreate (space); | ||
302 | dSpaceSetCleanup (car_space,0); | ||
303 | dSpaceAdd (car_space,box[0]); | ||
304 | dSpaceAdd (car_space,sphere[0]); | ||
305 | dSpaceAdd (car_space,sphere[1]); | ||
306 | dSpaceAdd (car_space,sphere[2]); | ||
307 | |||
308 | // environment | ||
309 | ground_box = dCreateBox (space,2,1.5,1); | ||
310 | dMatrix3 R; | ||
311 | dRFromAxisAndAngle (R,0,1,0,-0.15); | ||
312 | dGeomSetPosition (ground_box,2,0,-0.34); | ||
313 | dGeomSetRotation (ground_box,R); | ||
314 | |||
315 | // run simulation | ||
316 | dsSimulationLoop (argc,argv,352,288,&fn); | ||
317 | |||
318 | dJointGroupDestroy (contactgroup); | ||
319 | dSpaceDestroy (space); | ||
320 | dWorldDestroy (world); | ||
321 | dGeomDestroy (box[0]); | ||
322 | dGeomDestroy (sphere[0]); | ||
323 | dGeomDestroy (sphere[1]); | ||
324 | dGeomDestroy (sphere[2]); | ||
325 | |||
326 | return 0; | ||
327 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/AssemblyInfo.cpp b/libraries/ode-0.9/contrib/DotNetManaged/AssemblyInfo.cpp new file mode 100644 index 0000000..e550a32 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/AssemblyInfo.cpp | |||
@@ -0,0 +1,58 @@ | |||
1 | #include "stdafx.h" | ||
2 | |||
3 | using namespace System::Reflection; | ||
4 | using namespace System::Runtime::CompilerServices; | ||
5 | |||
6 | // | ||
7 | // General Information about an assembly is controlled through the following | ||
8 | // set of attributes. Change these attribute values to modify the information | ||
9 | // associated with an assembly. | ||
10 | // | ||
11 | [assembly:AssemblyTitleAttribute("")]; | ||
12 | [assembly:AssemblyDescriptionAttribute("")]; | ||
13 | [assembly:AssemblyConfigurationAttribute("")]; | ||
14 | [assembly:AssemblyCompanyAttribute("")]; | ||
15 | [assembly:AssemblyProductAttribute("")]; | ||
16 | [assembly:AssemblyCopyrightAttribute("")]; | ||
17 | [assembly:AssemblyTrademarkAttribute("")]; | ||
18 | [assembly:AssemblyCultureAttribute("")]; | ||
19 | |||
20 | // | ||
21 | // Version information for an assembly consists of the following four values: | ||
22 | // | ||
23 | // Major Version | ||
24 | // Minor Version | ||
25 | // Build Number | ||
26 | // Revision | ||
27 | // | ||
28 | // You can specify all the value or you can default the Revision and Build Numbers | ||
29 | // by using the '*' as shown below: | ||
30 | |||
31 | [assembly:AssemblyVersionAttribute("1.0.*")]; | ||
32 | |||
33 | // | ||
34 | // In order to sign your assembly you must specify a key to use. Refer to the | ||
35 | // Microsoft .NET Framework documentation for more information on assembly signing. | ||
36 | // | ||
37 | // Use the attributes below to control which key is used for signing. | ||
38 | // | ||
39 | // Notes: | ||
40 | // (*) If no key is specified, the assembly is not signed. | ||
41 | // (*) KeyName refers to a key that has been installed in the Crypto Service | ||
42 | // Provider (CSP) on your machine. KeyFile refers to a file which contains | ||
43 | // a key. | ||
44 | // (*) If the KeyFile and the KeyName values are both specified, the | ||
45 | // following processing occurs: | ||
46 | // (1) If the KeyName can be found in the CSP, that key is used. | ||
47 | // (2) If the KeyName does not exist and the KeyFile does exist, the key | ||
48 | // in the KeyFile is installed into the CSP and used. | ||
49 | // (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. | ||
50 | // When specifying the KeyFile, the location of the KeyFile should be | ||
51 | // relative to the project directory. | ||
52 | // (*) Delay Signing is an advanced option - see the Microsoft .NET Framework | ||
53 | // documentation for more information on this. | ||
54 | // | ||
55 | [assembly:AssemblyDelaySignAttribute(false)]; | ||
56 | [assembly:AssemblyKeyFileAttribute("")]; | ||
57 | [assembly:AssemblyKeyNameAttribute("")]; | ||
58 | |||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/Body.cpp b/libraries/ode-0.9/contrib/DotNetManaged/Body.cpp new file mode 100644 index 0000000..c95ae57 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/Body.cpp | |||
@@ -0,0 +1,322 @@ | |||
1 | #include "StdAfx.h" | ||
2 | |||
3 | #include <ode/ode.h> | ||
4 | #include "Body.h" | ||
5 | |||
6 | namespace ODEManaged | ||
7 | { | ||
8 | |||
9 | //Constructors | ||
10 | |||
11 | Body::Body(void) | ||
12 | { | ||
13 | _id = 0; | ||
14 | } | ||
15 | |||
16 | Body::Body(World &world) | ||
17 | { | ||
18 | _id = dBodyCreate(world.Id()); | ||
19 | } | ||
20 | |||
21 | |||
22 | //Destructor | ||
23 | |||
24 | Body::~Body(void) | ||
25 | { | ||
26 | dBodyDestroy(this->_id); | ||
27 | } | ||
28 | |||
29 | |||
30 | //Methods | ||
31 | |||
32 | //Id | ||
33 | dBodyID Body::Id() | ||
34 | { | ||
35 | return _id; | ||
36 | } | ||
37 | |||
38 | |||
39 | //SetData | ||
40 | void Body::SetData(void *data) | ||
41 | { | ||
42 | dBodySetData(this->_id, data); | ||
43 | } | ||
44 | |||
45 | //GetData | ||
46 | void *Body::GetData(void) | ||
47 | { | ||
48 | return dBodyGetData(this->_id); | ||
49 | } | ||
50 | |||
51 | |||
52 | //SetPosition | ||
53 | void Body::SetPosition (double x, double y, double z) | ||
54 | { | ||
55 | dBodySetPosition(this->_id, x, y, z); | ||
56 | } | ||
57 | |||
58 | |||
59 | //Overloaded GetPosition | ||
60 | Vector3 Body::GetPosition(void) | ||
61 | { | ||
62 | Vector3 retVal; | ||
63 | const dReal *temp; | ||
64 | temp = dBodyGetPosition(this->_id); | ||
65 | retVal.x = temp[0]; | ||
66 | retVal.y = temp[1]; | ||
67 | retVal.z = temp[2]; | ||
68 | return retVal; | ||
69 | }; | ||
70 | |||
71 | void Body::GetPosition(double position __gc[]) | ||
72 | { | ||
73 | const dReal *temp; | ||
74 | temp = dBodyGetPosition(this->_id); | ||
75 | position[0] = temp[0]; | ||
76 | position[1] = temp[1]; | ||
77 | position[2] = temp[2]; | ||
78 | } | ||
79 | |||
80 | |||
81 | //SetRotationIdentity | ||
82 | void Body::SetRotationIdentity(void) | ||
83 | { | ||
84 | dMatrix3 temp; | ||
85 | dRSetIdentity(temp); | ||
86 | dBodySetRotation(this->_id, temp); | ||
87 | } | ||
88 | |||
89 | |||
90 | //SetRotation (left handed system=>transpose) | ||
91 | void Body::SetRotation(Matrix3 rotation) | ||
92 | { | ||
93 | dMatrix3 temp; | ||
94 | temp[0] = rotation.m11; | ||
95 | temp[4] = rotation.m12; | ||
96 | temp[8] = rotation.m13; | ||
97 | temp[1] = rotation.m21; | ||
98 | temp[5] = rotation.m22; | ||
99 | temp[9] = rotation.m23; | ||
100 | temp[2] = rotation.m31; | ||
101 | temp[6] = rotation.m32; | ||
102 | temp[10] = rotation.m33; | ||
103 | dBodySetRotation(this->_id, temp); | ||
104 | } | ||
105 | |||
106 | //GetRotation (left handed system=>transpose) | ||
107 | Matrix3 Body::GetRotation(void) | ||
108 | { | ||
109 | Matrix3 retVal; | ||
110 | //const dMatrix3 *m; | ||
111 | const dReal *temp; | ||
112 | temp = dBodyGetRotation(this->_id); | ||
113 | retVal.m11 = temp[0]; | ||
114 | retVal.m12 = temp[4]; | ||
115 | retVal.m13 = temp[8]; | ||
116 | retVal.m21 = temp[1]; | ||
117 | retVal.m22 = temp[5]; | ||
118 | retVal.m23 = temp[9]; | ||
119 | retVal.m31 = temp[2]; | ||
120 | retVal.m32 = temp[6]; | ||
121 | retVal.m33 = temp[10]; | ||
122 | return retVal; | ||
123 | } | ||
124 | |||
125 | |||
126 | //Overloaded SetMass | ||
127 | void Body::SetMass(double mass, Vector3 centerOfGravity, Matrix3 inertia) | ||
128 | { | ||
129 | dMass *temp = new dMass(); | ||
130 | dMassSetParameters(temp, mass, | ||
131 | centerOfGravity.x, | ||
132 | centerOfGravity.y, | ||
133 | centerOfGravity.z, | ||
134 | inertia.m11, inertia.m22, | ||
135 | inertia.m33, inertia.m12, | ||
136 | inertia.m13, inertia.m23); | ||
137 | |||
138 | dBodySetMass(this->_id, temp); | ||
139 | } | ||
140 | |||
141 | |||
142 | //SetMassSphere | ||
143 | void Body::SetMassSphere(double density, double radius) | ||
144 | { | ||
145 | dMass *temp = new dMass(); | ||
146 | dMassSetSphere(temp, density, radius); | ||
147 | dBodySetMass(this->_id, temp); | ||
148 | } | ||
149 | |||
150 | |||
151 | //SetMassBox | ||
152 | void Body::SetMassBox(double density, double sideX, double sideY, double sideZ) | ||
153 | { | ||
154 | dMass *temp = new dMass(); | ||
155 | dMassSetBox(temp, density, sideX, sideY, sideZ); | ||
156 | dBodySetMass(this->_id, temp); | ||
157 | } | ||
158 | |||
159 | |||
160 | //SetMassCappedCylinder | ||
161 | void Body::SetMassCappedCylinder(double density, int axis, double cylinderRadius, double cylinderLength) | ||
162 | { | ||
163 | dMass *temp = new dMass(); | ||
164 | dMassSetCappedCylinder(temp, density, axis, | ||
165 | cylinderRadius, | ||
166 | cylinderLength); | ||
167 | |||
168 | dBodySetMass(this->_id, temp); | ||
169 | } | ||
170 | |||
171 | |||
172 | //AddForce | ||
173 | void Body::AddForce(double fX, double fY, double fZ) | ||
174 | { | ||
175 | dBodyAddForce(this->_id, fX, fY, fZ); | ||
176 | } | ||
177 | |||
178 | |||
179 | //AddRelForce | ||
180 | void Body::AddRelForce(double fX, double fY, double fZ) | ||
181 | { | ||
182 | dBodyAddRelForce(this->_id, fX,fY,fZ); | ||
183 | } | ||
184 | |||
185 | |||
186 | //AddForceAtPos | ||
187 | void Body::AddForceAtPos(double fX, double fY, double fZ, double pX, double pY, double pZ) | ||
188 | { | ||
189 | dBodyAddForceAtPos(this->_id, fX, fY, fZ, pX, pY, pZ); | ||
190 | } | ||
191 | |||
192 | |||
193 | //AddRelForceAtPos | ||
194 | void Body::AddRelForceAtPos(double fX, double fY, double fZ, double pX, double pY, double pZ) | ||
195 | { | ||
196 | dBodyAddRelForceAtPos(this->_id, fX, fY, fZ, pX, pY, pZ); | ||
197 | } | ||
198 | |||
199 | |||
200 | //AddRelForceAtRelPos | ||
201 | void Body::AddRelForceAtRelPos(double fX, double fY, double fZ, double pX, double pY, double pZ) | ||
202 | { | ||
203 | dBodyAddRelForceAtRelPos(this->_id, fX, fY, fZ, pX, pY, pZ); | ||
204 | } | ||
205 | |||
206 | |||
207 | //ApplyLinearVelocityDrag | ||
208 | void Body::ApplyLinearVelocityDrag(double dragCoef) | ||
209 | { | ||
210 | const dReal *temp; | ||
211 | double fX; | ||
212 | double fY; | ||
213 | double fZ; | ||
214 | temp = dBodyGetLinearVel(this->_id); | ||
215 | fX = temp[0]*dragCoef*-1; | ||
216 | fY = temp[1]*dragCoef*-1; | ||
217 | fZ = temp[2]*dragCoef*-1; | ||
218 | dBodyAddForce(this->_id, fX, fY, fZ); | ||
219 | } | ||
220 | |||
221 | |||
222 | //ApplyAngularVelocityDrag | ||
223 | void Body::ApplyAngularVelocityDrag(double dragCoef) | ||
224 | { | ||
225 | const dReal *temp; | ||
226 | double fX; | ||
227 | double fY; | ||
228 | double fZ; | ||
229 | temp = dBodyGetAngularVel(this->_id); | ||
230 | fX = temp[0]*dragCoef*-1; | ||
231 | fY = temp[1]*dragCoef*-1; | ||
232 | fZ = temp[2]*dragCoef*-1; | ||
233 | dBodyAddTorque(this->_id, fX, fY, fZ); | ||
234 | } | ||
235 | |||
236 | |||
237 | //AddTorque | ||
238 | void Body::AddTorque(double fX, double fY, double fZ) | ||
239 | { | ||
240 | dBodyAddTorque(this->_id, fX, fY, fZ); | ||
241 | } | ||
242 | |||
243 | |||
244 | //AddRelTorque | ||
245 | void Body::AddRelTorque(double fX, double fY, double fZ) | ||
246 | { | ||
247 | dBodyAddRelTorque(this->_id, fX,fY,fZ); | ||
248 | } | ||
249 | |||
250 | |||
251 | //SetLinearVelocity | ||
252 | void Body::SetLinearVelocity(double x, double y, double z) | ||
253 | { | ||
254 | dBodySetLinearVel(this->_id, x, y, z); | ||
255 | } | ||
256 | |||
257 | |||
258 | //GetLinearVelocity | ||
259 | Vector3 Body::GetLinearVelocity(void) | ||
260 | { | ||
261 | Vector3 retVal; | ||
262 | const dReal *temp; | ||
263 | temp = dBodyGetLinearVel(this->_id); | ||
264 | retVal.x = temp[0]; | ||
265 | retVal.y = temp[1]; | ||
266 | retVal.z = temp[2]; | ||
267 | return retVal; | ||
268 | } | ||
269 | |||
270 | |||
271 | //SetAngularVelocity | ||
272 | void Body::SetAngularVelocity(double x, double y, double z) | ||
273 | { | ||
274 | dBodySetAngularVel(this->_id, x, y, z); | ||
275 | } | ||
276 | |||
277 | //GetAngularVelocity | ||
278 | Vector3 Body::GetAngularVelocity(void) | ||
279 | { | ||
280 | Vector3 retVal; | ||
281 | const dReal *temp; | ||
282 | temp = dBodyGetAngularVel(this->_id); | ||
283 | retVal.x = temp[0]; | ||
284 | retVal.y = temp[1]; | ||
285 | retVal.z = temp[2]; | ||
286 | return retVal; | ||
287 | } | ||
288 | |||
289 | |||
290 | //GetRelPointPos | ||
291 | Vector3 Body::GetRelPointPos(double pX, double pY, double pZ) | ||
292 | { | ||
293 | Vector3 retVal; | ||
294 | dVector3 temp; | ||
295 | dBodyGetRelPointPos(this->_id, pX, pY, pZ, temp); | ||
296 | retVal.x = temp[0]; | ||
297 | retVal.y = temp[1]; | ||
298 | retVal.z = temp[2]; | ||
299 | return retVal; | ||
300 | } | ||
301 | |||
302 | |||
303 | //GetRelPointVel | ||
304 | Vector3 Body::GetRelPointVel(double pX, double pY, double pZ) | ||
305 | { | ||
306 | Vector3 retVal; | ||
307 | dVector3 temp; | ||
308 | dBodyGetRelPointVel(this->_id, pX, pY, pZ, temp); | ||
309 | retVal.x = temp[0]; | ||
310 | retVal.y = temp[1]; | ||
311 | retVal.z = temp[2]; | ||
312 | return retVal; | ||
313 | } | ||
314 | |||
315 | |||
316 | //ConnectedTo | ||
317 | int Body::ConnectedTo(const Body &b) | ||
318 | { | ||
319 | return dAreConnected(this->_id, b._id); | ||
320 | } | ||
321 | |||
322 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/Body.h b/libraries/ode-0.9/contrib/DotNetManaged/Body.h new file mode 100644 index 0000000..9347c17 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/Body.h | |||
@@ -0,0 +1,76 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include "World.h" | ||
4 | #include "CommonMgd.h" | ||
5 | |||
6 | namespace ODEManaged | ||
7 | { | ||
8 | __gc public class Body | ||
9 | { | ||
10 | public: | ||
11 | |||
12 | //Constructors and Destructors | ||
13 | |||
14 | Body(void); | ||
15 | Body(World &world); | ||
16 | |||
17 | ~Body(void); | ||
18 | |||
19 | |||
20 | //Public Methods | ||
21 | |||
22 | dBodyID Id(); | ||
23 | void SetData (void *data); | ||
24 | void *GetData (void); | ||
25 | |||
26 | //POSITION | ||
27 | void SetPosition(double x, double y, double z); | ||
28 | Vector3 GetPosition(void); | ||
29 | void GetPosition(double position __gc[]); | ||
30 | |||
31 | //ROTATION | ||
32 | void SetRotationIdentity(void); | ||
33 | void SetRotation(Matrix3 rotation); | ||
34 | Matrix3 GetRotation(void); | ||
35 | |||
36 | //MASS | ||
37 | void SetMass(double mass, Vector3 centerOfGravity, Matrix3 inertia); | ||
38 | void SetMassSphere(double density, double radius); | ||
39 | void SetMassBox(double density, double sideX, double sideY, double sideZ); | ||
40 | void SetMassCappedCylinder(double density, int axis, double cylinderRadius, double cylinderLength); | ||
41 | |||
42 | //FORCE AND TORQUE | ||
43 | void AddForce(double fX, double fY, double fZ); | ||
44 | void AddRelForce(double fX, double fY, double fZ); | ||
45 | void AddForceAtPos(double fX, double fY, double fZ,double pX, double pY, double pZ); | ||
46 | void AddRelForceAtPos(double fX, double fY, double fZ,double pX, double pY, double pZ); | ||
47 | void AddRelForceAtRelPos(double fX, double fY, double fZ,double pX, double pY, double pZ); | ||
48 | void ApplyLinearVelocityDrag(double dragCoef); | ||
49 | void ApplyAngularVelocityDrag(double dragCoef); | ||
50 | |||
51 | |||
52 | void AddTorque(double fX, double fY, double fZ); | ||
53 | void AddRelTorque(double fX, double fY, double fZ); | ||
54 | |||
55 | //LINEAR VELOCITY | ||
56 | void SetLinearVelocity (double x, double y, double z); | ||
57 | Vector3 GetLinearVelocity(void); | ||
58 | |||
59 | //ANGULAR VELOCITY | ||
60 | void SetAngularVelocity (double x, double y, double z); | ||
61 | Vector3 GetAngularVelocity(void); | ||
62 | |||
63 | //POINT | ||
64 | Vector3 GetRelPointPos(double pX, double pY, double pZ); | ||
65 | Vector3 GetRelPointVel(double pX, double pY, double pZ); | ||
66 | |||
67 | //CONNECTED TO | ||
68 | int ConnectedTo (const Body &b); | ||
69 | |||
70 | private: | ||
71 | |||
72 | dBodyID _id; | ||
73 | |||
74 | }; | ||
75 | } | ||
76 | |||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/CommonMgd.h b/libraries/ode-0.9/contrib/DotNetManaged/CommonMgd.h new file mode 100644 index 0000000..143397d --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/CommonMgd.h | |||
@@ -0,0 +1,43 @@ | |||
1 | #pragma once | ||
2 | |||
3 | namespace ODEManaged | ||
4 | { | ||
5 | |||
6 | __value public struct Vector3 | ||
7 | { | ||
8 | double x; | ||
9 | double y; | ||
10 | double z; | ||
11 | }; | ||
12 | |||
13 | |||
14 | __value public struct Vector4 | ||
15 | { | ||
16 | double W; | ||
17 | double x; | ||
18 | double y; | ||
19 | double z; | ||
20 | }; | ||
21 | |||
22 | |||
23 | __value public struct Matrix3 | ||
24 | { | ||
25 | double m11; | ||
26 | double m12; | ||
27 | double m13; | ||
28 | double m21; | ||
29 | double m22; | ||
30 | double m23; | ||
31 | double m31; | ||
32 | double m32; | ||
33 | double m33; | ||
34 | }; | ||
35 | |||
36 | //__value public struct NearCallback | ||
37 | //{ | ||
38 | // void *data; | ||
39 | // dGeomID o1; | ||
40 | // dGeomID o2; | ||
41 | //}; | ||
42 | |||
43 | } \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/DotNetManaged.sln b/libraries/ode-0.9/contrib/DotNetManaged/DotNetManaged.sln new file mode 100644 index 0000000..2694a26 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/DotNetManaged.sln | |||
@@ -0,0 +1,21 @@ | |||
1 | Microsoft Visual Studio Solution File, Format Version 7.00 | ||
2 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DotNetManaged", "DotNetManaged.vcproj", "{4B75AC19-971A-4CC6-A4F5-0695C9F8562F}" | ||
3 | EndProject | ||
4 | Global | ||
5 | GlobalSection(SolutionConfiguration) = preSolution | ||
6 | ConfigName.0 = Debug | ||
7 | ConfigName.1 = Release | ||
8 | EndGlobalSection | ||
9 | GlobalSection(ProjectDependencies) = postSolution | ||
10 | EndGlobalSection | ||
11 | GlobalSection(ProjectConfiguration) = postSolution | ||
12 | {4B75AC19-971A-4CC6-A4F5-0695C9F8562F}.Debug.ActiveCfg = Debug|Win32 | ||
13 | {4B75AC19-971A-4CC6-A4F5-0695C9F8562F}.Debug.Build.0 = Debug|Win32 | ||
14 | {4B75AC19-971A-4CC6-A4F5-0695C9F8562F}.Release.ActiveCfg = Release|Win32 | ||
15 | {4B75AC19-971A-4CC6-A4F5-0695C9F8562F}.Release.Build.0 = Release|Win32 | ||
16 | EndGlobalSection | ||
17 | GlobalSection(ExtensibilityGlobals) = postSolution | ||
18 | EndGlobalSection | ||
19 | GlobalSection(ExtensibilityAddIns) = postSolution | ||
20 | EndGlobalSection | ||
21 | EndGlobal | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/DotNetManaged.vcproj b/libraries/ode-0.9/contrib/DotNetManaged/DotNetManaged.vcproj new file mode 100644 index 0000000..2f5bb6c --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/DotNetManaged.vcproj | |||
@@ -0,0 +1,379 @@ | |||
1 | <?xml version="1.0" encoding = "Windows-1252"?> | ||
2 | <VisualStudioProject | ||
3 | ProjectType="Visual C++" | ||
4 | Version="7.00" | ||
5 | Name="DotNetManaged" | ||
6 | ProjectGUID="{4B75AC19-971A-4CC6-A4F5-0695C9F8562F}" | ||
7 | Keyword="ManagedCProj"> | ||
8 | <Platforms> | ||
9 | <Platform | ||
10 | Name="Win32"/> | ||
11 | </Platforms> | ||
12 | <Configurations> | ||
13 | <Configuration | ||
14 | Name="Debug|Win32" | ||
15 | OutputDirectory="Debug" | ||
16 | IntermediateDirectory="Debug" | ||
17 | ConfigurationType="2" | ||
18 | CharacterSet="2" | ||
19 | ManagedExtensions="TRUE"> | ||
20 | <Tool | ||
21 | Name="VCCLCompilerTool" | ||
22 | Optimization="2" | ||
23 | AdditionalIncludeDirectories=""F:\Documents and Settings\Visual Studio Projects\ODE\Contrib\tri-collider";"F:\Documents and Settings\Visual Studio Projects\ODE\ODE\Src";"F:\Documents and Settings\Visual Studio Projects\ODE\ODE";"F:\Documents and Settings\Visual Studio Projects\ODE\Include"" | ||
24 | PreprocessorDefinitions="WIN32;_DEBUG" | ||
25 | MinimalRebuild="FALSE" | ||
26 | BasicRuntimeChecks="0" | ||
27 | RuntimeLibrary="1" | ||
28 | WarningLevel="3" | ||
29 | DebugInformationFormat="3"/> | ||
30 | <Tool | ||
31 | Name="VCCustomBuildTool"/> | ||
32 | <Tool | ||
33 | Name="VCLinkerTool" | ||
34 | OutputFile="$(OutDir)/DotNetManaged.exe" | ||
35 | LinkIncremental="2" | ||
36 | GenerateDebugInformation="TRUE"/> | ||
37 | <Tool | ||
38 | Name="VCMIDLTool"/> | ||
39 | <Tool | ||
40 | Name="VCPostBuildEventTool"/> | ||
41 | <Tool | ||
42 | Name="VCPreBuildEventTool"/> | ||
43 | <Tool | ||
44 | Name="VCPreLinkEventTool"/> | ||
45 | <Tool | ||
46 | Name="VCResourceCompilerTool"/> | ||
47 | <Tool | ||
48 | Name="VCWebServiceProxyGeneratorTool"/> | ||
49 | <Tool | ||
50 | Name="VCWebDeploymentTool"/> | ||
51 | </Configuration> | ||
52 | <Configuration | ||
53 | Name="Release|Win32" | ||
54 | OutputDirectory="Release" | ||
55 | IntermediateDirectory="Release" | ||
56 | ConfigurationType="2" | ||
57 | CharacterSet="2" | ||
58 | ManagedExtensions="TRUE" | ||
59 | WholeProgramOptimization="FALSE"> | ||
60 | <Tool | ||
61 | Name="VCCLCompilerTool" | ||
62 | Optimization="2" | ||
63 | InlineFunctionExpansion="0" | ||
64 | OmitFramePointers="TRUE" | ||
65 | AdditionalIncludeDirectories=""F:\Documents and Settings\Visual Studio Projects\ODE";"F:\Documents and Settings\Visual Studio Projects\ODE\Contrib\DotNetManaged\odeOLd";"F:\Documents and Settings\Visual Studio Projects\ODE\Include";"F:\Documents and Settings\Visual Studio Projects\ODE\Include\ODE";"F:\Documents and Settings\Visual Studio Projects\ODE\ODE\Src";"F:\Documents and Settings\Visual Studio Projects\ODE\Contrib\tri-collider"" | ||
66 | PreprocessorDefinitions="WIN32;NDEBUG" | ||
67 | MinimalRebuild="FALSE" | ||
68 | WarningLevel="3" | ||
69 | DebugInformationFormat="3"/> | ||
70 | <Tool | ||
71 | Name="VCCustomBuildTool"/> | ||
72 | <Tool | ||
73 | Name="VCLinkerTool" | ||
74 | OutputFile="$(OutDir)/ode.dll" | ||
75 | SuppressStartupBanner="TRUE" | ||
76 | GenerateDebugInformation="FALSE"/> | ||
77 | <Tool | ||
78 | Name="VCMIDLTool"/> | ||
79 | <Tool | ||
80 | Name="VCPostBuildEventTool"/> | ||
81 | <Tool | ||
82 | Name="VCPreBuildEventTool"/> | ||
83 | <Tool | ||
84 | Name="VCPreLinkEventTool"/> | ||
85 | <Tool | ||
86 | Name="VCResourceCompilerTool"/> | ||
87 | <Tool | ||
88 | Name="VCWebServiceProxyGeneratorTool"/> | ||
89 | <Tool | ||
90 | Name="VCWebDeploymentTool"/> | ||
91 | </Configuration> | ||
92 | </Configurations> | ||
93 | <Files> | ||
94 | <Filter | ||
95 | Name="Source Files" | ||
96 | Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"> | ||
97 | <File | ||
98 | RelativePath="..\..\ODE\Src\array.cpp"> | ||
99 | </File> | ||
100 | <File | ||
101 | RelativePath="..\..\ODE\Src\error.cpp"> | ||
102 | </File> | ||
103 | <File | ||
104 | RelativePath="..\..\ODE\Src\fastdot.c"> | ||
105 | </File> | ||
106 | <File | ||
107 | RelativePath="..\..\ODE\Src\fastldlt.c"> | ||
108 | </File> | ||
109 | <File | ||
110 | RelativePath="..\..\ODE\Src\fastlsolve.c"> | ||
111 | </File> | ||
112 | <File | ||
113 | RelativePath="..\..\ODE\Src\fastltsolve.c"> | ||
114 | </File> | ||
115 | <File | ||
116 | RelativePath="..\..\ODE\Src\geom.cpp"> | ||
117 | </File> | ||
118 | <File | ||
119 | RelativePath="..\..\ODE\Src\joint.cpp"> | ||
120 | </File> | ||
121 | <File | ||
122 | RelativePath="..\..\ODE\Src\lcp.cpp"> | ||
123 | </File> | ||
124 | <File | ||
125 | RelativePath="..\..\ODE\Src\mass.cpp"> | ||
126 | </File> | ||
127 | <File | ||
128 | RelativePath="..\..\ODE\Src\mat.cpp"> | ||
129 | </File> | ||
130 | <File | ||
131 | RelativePath="..\..\ODE\Src\matrix.cpp"> | ||
132 | </File> | ||
133 | <File | ||
134 | RelativePath="..\..\ODE\Src\memory.cpp"> | ||
135 | </File> | ||
136 | <File | ||
137 | RelativePath="..\..\ODE\Src\misc.cpp"> | ||
138 | </File> | ||
139 | <File | ||
140 | RelativePath="..\..\ODE\Src\objects.h"> | ||
141 | </File> | ||
142 | <File | ||
143 | RelativePath="..\..\ODE\Src\obstack.cpp"> | ||
144 | </File> | ||
145 | <File | ||
146 | RelativePath="..\..\ODE\Src\ode.cpp"> | ||
147 | </File> | ||
148 | <File | ||
149 | RelativePath="..\..\ODE\Src\odemath.cpp"> | ||
150 | </File> | ||
151 | <File | ||
152 | RelativePath="..\..\ODE\Src\rotation.cpp"> | ||
153 | </File> | ||
154 | <File | ||
155 | RelativePath="..\..\ODE\Src\space.cpp"> | ||
156 | </File> | ||
157 | <File | ||
158 | RelativePath="..\..\ODE\Src\step.cpp"> | ||
159 | </File> | ||
160 | <File | ||
161 | RelativePath="..\..\ODE\Src\testing.cpp"> | ||
162 | </File> | ||
163 | <File | ||
164 | RelativePath="..\..\ODE\Src\timer.cpp"> | ||
165 | </File> | ||
166 | </Filter> | ||
167 | <Filter | ||
168 | Name="Header Files" | ||
169 | Filter="h;hpp;hxx;hm;inl;inc"> | ||
170 | <File | ||
171 | RelativePath="..\..\ODE\Src\array.h"> | ||
172 | </File> | ||
173 | <File | ||
174 | RelativePath="..\..\Include\ODE\common.h"> | ||
175 | </File> | ||
176 | <File | ||
177 | RelativePath="..\..\Include\ODE\config.h"> | ||
178 | </File> | ||
179 | <File | ||
180 | RelativePath="..\..\Include\ODE\contact.h"> | ||
181 | </File> | ||
182 | <File | ||
183 | RelativePath="..\..\Include\ODE\error.h"> | ||
184 | </File> | ||
185 | <File | ||
186 | RelativePath="..\..\Include\ODE\geom.h"> | ||
187 | </File> | ||
188 | <File | ||
189 | RelativePath="..\..\ODE\Src\geom_internal.h"> | ||
190 | </File> | ||
191 | <File | ||
192 | RelativePath="..\..\ODE\Src\joint.h"> | ||
193 | </File> | ||
194 | <File | ||
195 | RelativePath="..\..\ODE\Src\lcp.h"> | ||
196 | </File> | ||
197 | <File | ||
198 | RelativePath="..\..\Include\ODE\mass.h"> | ||
199 | </File> | ||
200 | <File | ||
201 | RelativePath="..\..\ODE\Src\mat.h"> | ||
202 | </File> | ||
203 | <File | ||
204 | RelativePath="..\..\Include\ODE\matrix.h"> | ||
205 | </File> | ||
206 | <File | ||
207 | RelativePath="..\..\Include\ODE\memory.h"> | ||
208 | </File> | ||
209 | <File | ||
210 | RelativePath="..\..\Include\ODE\misc.h"> | ||
211 | </File> | ||
212 | <File | ||
213 | RelativePath="..\..\Include\ODE\objects.h"> | ||
214 | </File> | ||
215 | <File | ||
216 | RelativePath="..\..\ODE\Src\obstack.h"> | ||
217 | </File> | ||
218 | <File | ||
219 | RelativePath="..\..\Include\ODE\ode.h"> | ||
220 | </File> | ||
221 | <File | ||
222 | RelativePath="..\..\Include\ODE\odecpp.h"> | ||
223 | </File> | ||
224 | <File | ||
225 | RelativePath="..\..\Include\ODE\odemath.h"> | ||
226 | </File> | ||
227 | <File | ||
228 | RelativePath="..\..\Include\ODE\rotation.h"> | ||
229 | </File> | ||
230 | <File | ||
231 | RelativePath="..\..\Include\ODE\space.h"> | ||
232 | </File> | ||
233 | <File | ||
234 | RelativePath="..\..\ODE\Src\step.h"> | ||
235 | </File> | ||
236 | <File | ||
237 | RelativePath="..\..\ODE\Src\testing.h"> | ||
238 | </File> | ||
239 | <File | ||
240 | RelativePath="..\..\Include\ODE\timer.h"> | ||
241 | </File> | ||
242 | </Filter> | ||
243 | <Filter | ||
244 | Name="Resource Files" | ||
245 | Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;r"> | ||
246 | </Filter> | ||
247 | <Filter | ||
248 | Name="Wrapper" | ||
249 | Filter=""> | ||
250 | <Filter | ||
251 | Name="Header Files" | ||
252 | Filter=""> | ||
253 | <File | ||
254 | RelativePath="Body.h"> | ||
255 | </File> | ||
256 | <File | ||
257 | RelativePath="CommonMgd.h"> | ||
258 | </File> | ||
259 | <File | ||
260 | RelativePath="Geom.h"> | ||
261 | </File> | ||
262 | <File | ||
263 | RelativePath="Joint.h"> | ||
264 | </File> | ||
265 | <File | ||
266 | RelativePath="JointAMotor.h"> | ||
267 | </File> | ||
268 | <File | ||
269 | RelativePath="JointBall.h"> | ||
270 | </File> | ||
271 | <File | ||
272 | RelativePath="JointFixed.h"> | ||
273 | </File> | ||
274 | <File | ||
275 | RelativePath="JointGroup.h"> | ||
276 | </File> | ||
277 | <File | ||
278 | RelativePath="JointHinge.h"> | ||
279 | </File> | ||
280 | <File | ||
281 | RelativePath="JointHinge2.h"> | ||
282 | </File> | ||
283 | <File | ||
284 | RelativePath="JointSlider.h"> | ||
285 | </File> | ||
286 | <File | ||
287 | RelativePath="Space.h"> | ||
288 | </File> | ||
289 | <File | ||
290 | RelativePath="Stdafx.h"> | ||
291 | </File> | ||
292 | <File | ||
293 | RelativePath="World.h"> | ||
294 | </File> | ||
295 | </Filter> | ||
296 | <Filter | ||
297 | Name="Source Files" | ||
298 | Filter=""> | ||
299 | <File | ||
300 | RelativePath="Body.cpp"> | ||
301 | </File> | ||
302 | <File | ||
303 | RelativePath="Geom.cpp"> | ||
304 | <FileConfiguration | ||
305 | Name="Debug|Win32"> | ||
306 | <Tool | ||
307 | Name="VCCLCompilerTool" | ||
308 | ObjectFile="$(IntDir)/$(InputName)1.obj"/> | ||
309 | </FileConfiguration> | ||
310 | <FileConfiguration | ||
311 | Name="Release|Win32"> | ||
312 | <Tool | ||
313 | Name="VCCLCompilerTool" | ||
314 | ObjectFile="$(IntDir)/$(InputName)1.obj"/> | ||
315 | </FileConfiguration> | ||
316 | </File> | ||
317 | <File | ||
318 | RelativePath="Joint.cpp"> | ||
319 | <FileConfiguration | ||
320 | Name="Debug|Win32"> | ||
321 | <Tool | ||
322 | Name="VCCLCompilerTool" | ||
323 | ObjectFile="$(IntDir)/$(InputName)1.obj"/> | ||
324 | </FileConfiguration> | ||
325 | <FileConfiguration | ||
326 | Name="Release|Win32"> | ||
327 | <Tool | ||
328 | Name="VCCLCompilerTool" | ||
329 | ObjectFile="$(IntDir)/$(InputName)1.obj"/> | ||
330 | </FileConfiguration> | ||
331 | </File> | ||
332 | <File | ||
333 | RelativePath="JointAMotor.cpp"> | ||
334 | </File> | ||
335 | <File | ||
336 | RelativePath="JointBall.cpp"> | ||
337 | </File> | ||
338 | <File | ||
339 | RelativePath="JointFixed.cpp"> | ||
340 | </File> | ||
341 | <File | ||
342 | RelativePath="JointGroup.cpp"> | ||
343 | </File> | ||
344 | <File | ||
345 | RelativePath="JointHinge.cpp"> | ||
346 | </File> | ||
347 | <File | ||
348 | RelativePath="JointHinge2.cpp"> | ||
349 | </File> | ||
350 | <File | ||
351 | RelativePath="JointSlider.cpp"> | ||
352 | </File> | ||
353 | <File | ||
354 | RelativePath="Space.cpp"> | ||
355 | <FileConfiguration | ||
356 | Name="Debug|Win32"> | ||
357 | <Tool | ||
358 | Name="VCCLCompilerTool" | ||
359 | ObjectFile="$(IntDir)/$(InputName)1.obj"/> | ||
360 | </FileConfiguration> | ||
361 | <FileConfiguration | ||
362 | Name="Release|Win32"> | ||
363 | <Tool | ||
364 | Name="VCCLCompilerTool" | ||
365 | ObjectFile="$(IntDir)/$(InputName)1.obj"/> | ||
366 | </FileConfiguration> | ||
367 | </File> | ||
368 | <File | ||
369 | RelativePath="Stdafx.cpp"> | ||
370 | </File> | ||
371 | <File | ||
372 | RelativePath="World.cpp"> | ||
373 | </File> | ||
374 | </Filter> | ||
375 | </Filter> | ||
376 | </Files> | ||
377 | <Globals> | ||
378 | </Globals> | ||
379 | </VisualStudioProject> | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/Geom.cpp b/libraries/ode-0.9/contrib/DotNetManaged/Geom.cpp new file mode 100644 index 0000000..3655466 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/Geom.cpp | |||
@@ -0,0 +1,219 @@ | |||
1 | |||
2 | #include "StdAfx.h" | ||
3 | |||
4 | #include <ode/ode.h> | ||
5 | #include "Geom.h" | ||
6 | |||
7 | |||
8 | namespace ODEManaged | ||
9 | { | ||
10 | |||
11 | //Constructors | ||
12 | |||
13 | Geom::Geom(void) | ||
14 | { | ||
15 | _id = 0; | ||
16 | } | ||
17 | |||
18 | |||
19 | //Destructor | ||
20 | |||
21 | Geom::~Geom(void) | ||
22 | { | ||
23 | dGeomDestroy(this->_id); | ||
24 | } | ||
25 | |||
26 | |||
27 | //Methods | ||
28 | |||
29 | //Id | ||
30 | dGeomID Geom::Id(void) | ||
31 | { | ||
32 | return _id; | ||
33 | } | ||
34 | |||
35 | |||
36 | //GetBody | ||
37 | dBodyID Geom::GetBody(void) | ||
38 | { | ||
39 | return dGeomGetBody(this->_id); | ||
40 | } | ||
41 | |||
42 | |||
43 | //Overloaded SetBody | ||
44 | void Geom::SetBody(Body &body) | ||
45 | { | ||
46 | dGeomSetBody(this->_id, body.Id()); | ||
47 | } | ||
48 | |||
49 | //void Geom::SetBody(dBodyID b) | ||
50 | //{ | ||
51 | // dGeomSetBody(this->_id, b); | ||
52 | //} | ||
53 | |||
54 | |||
55 | //SetPosition | ||
56 | void Geom::SetPosition(double x, double y, double z) | ||
57 | { | ||
58 | dGeomSetPosition(this->_id, x, y, z); | ||
59 | } | ||
60 | |||
61 | |||
62 | //SetRotation | ||
63 | void Geom::SetRotation(Matrix3 rotation) | ||
64 | { | ||
65 | dMatrix3 temp; | ||
66 | temp[0] = rotation.m11; | ||
67 | temp[4] = rotation.m12; | ||
68 | temp[8] = rotation.m13; | ||
69 | temp[1] = rotation.m21; | ||
70 | temp[5] = rotation.m22; | ||
71 | temp[9] = rotation.m23; | ||
72 | temp[2] = rotation.m31; | ||
73 | temp[6] = rotation.m32; | ||
74 | temp[10] = rotation.m33; | ||
75 | dGeomSetRotation(_id, temp); | ||
76 | } | ||
77 | |||
78 | |||
79 | //Destroy | ||
80 | void Geom::Destroy() | ||
81 | { | ||
82 | if(this->_id) dGeomDestroy(this->_id); | ||
83 | _id = 0; | ||
84 | } | ||
85 | |||
86 | |||
87 | //SetData | ||
88 | void Geom::SetData(void *data) | ||
89 | { | ||
90 | dGeomSetData(this->_id, data); | ||
91 | } | ||
92 | |||
93 | |||
94 | //GetData | ||
95 | void *Geom::GetData(void) | ||
96 | { | ||
97 | return dGeomGetData(this->_id); | ||
98 | } | ||
99 | |||
100 | |||
101 | //GetPosition | ||
102 | Vector3 Geom::GetPosition(void) | ||
103 | { | ||
104 | Vector3 retVal; | ||
105 | const dReal *temp; | ||
106 | temp = dGeomGetPosition(this->_id); | ||
107 | retVal.x = temp[0]; | ||
108 | retVal.y = temp[1]; | ||
109 | retVal.z = temp[2]; | ||
110 | return retVal; | ||
111 | } | ||
112 | |||
113 | |||
114 | //GetRotation (left handed system=>transpose) | ||
115 | Matrix3 Geom::GetRotation(void) | ||
116 | { | ||
117 | Matrix3 retVal; | ||
118 | const dReal *temp; | ||
119 | temp = dGeomGetRotation(this->_id); | ||
120 | retVal.m11 = temp[0]; | ||
121 | retVal.m12 = temp[4]; | ||
122 | retVal.m13 = temp[8]; | ||
123 | retVal.m21 = temp[1]; | ||
124 | retVal.m22 = temp[5]; | ||
125 | retVal.m23 = temp[9]; | ||
126 | retVal.m31 = temp[2]; | ||
127 | retVal.m32 = temp[6]; | ||
128 | retVal.m33 = temp[10]; | ||
129 | return retVal; | ||
130 | } | ||
131 | |||
132 | |||
133 | //CreateSphere | ||
134 | void Geom::CreateSphere(Space &space, double radius) | ||
135 | { | ||
136 | if(this->_id) dGeomDestroy(this->_id); | ||
137 | _id = dCreateSphere(space.Id(), radius); | ||
138 | } | ||
139 | |||
140 | |||
141 | //CreateBox | ||
142 | void Geom::CreateBox(Space &space, double lx, double ly, double lz) | ||
143 | { | ||
144 | if(this->_id) dGeomDestroy(this->_id); | ||
145 | _id = dCreateBox(space.Id(), lx, ly, lz); | ||
146 | } | ||
147 | |||
148 | |||
149 | //CreatePlane | ||
150 | void Geom::CreatePlane(Space &space, double a, double b, double c, double d) | ||
151 | { | ||
152 | if(this->_id) dGeomDestroy(this->_id); | ||
153 | _id = dCreatePlane(space.Id(), a, b, c, d); | ||
154 | } | ||
155 | |||
156 | |||
157 | //CreateCCylinder | ||
158 | void Geom::CreateCCylinder(Space &space, double radius, double length) | ||
159 | { | ||
160 | if(this->_id) dGeomDestroy(this->_id); | ||
161 | _id = dCreateCCylinder(space.Id(), radius, length); | ||
162 | } | ||
163 | |||
164 | |||
165 | //SphereGetRadius | ||
166 | double Geom::SphereGetRadius(void) | ||
167 | { | ||
168 | return dGeomSphereGetRadius(this->_id); | ||
169 | } | ||
170 | |||
171 | |||
172 | //BoxGetLengths | ||
173 | Vector3 Geom::BoxGetLengths(void) | ||
174 | { | ||
175 | Vector3 retVal; | ||
176 | dVector3 temp; | ||
177 | dGeomBoxGetLengths(this->_id, temp); | ||
178 | retVal.x = temp[0]; | ||
179 | retVal.y = temp[1]; | ||
180 | retVal.z = temp[2]; | ||
181 | return retVal; | ||
182 | } | ||
183 | |||
184 | |||
185 | //PlaneGetParams | ||
186 | Vector4 Geom::PlaneGetParams(void) | ||
187 | { | ||
188 | Vector4 retVal; | ||
189 | dVector4 temp; | ||
190 | dGeomPlaneGetParams(this->_id, temp); | ||
191 | retVal.W = temp[0]; | ||
192 | retVal.x = temp[1]; | ||
193 | retVal.y = temp[2]; | ||
194 | retVal.z = temp[3]; | ||
195 | return retVal; | ||
196 | } | ||
197 | |||
198 | |||
199 | //CCylinderGetParams | ||
200 | void Geom::CCylinderGetParams(double *radius, double *length) | ||
201 | { | ||
202 | dGeomCCylinderGetParams(this->_id, radius, length); | ||
203 | } | ||
204 | |||
205 | |||
206 | //GetClass | ||
207 | int Geom::GetClass(void) | ||
208 | { | ||
209 | return dGeomGetClass(this->_id); | ||
210 | } | ||
211 | |||
212 | } | ||
213 | |||
214 | |||
215 | |||
216 | |||
217 | |||
218 | |||
219 | |||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/Geom.h b/libraries/ode-0.9/contrib/DotNetManaged/Geom.h new file mode 100644 index 0000000..83a6faf --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/Geom.h | |||
@@ -0,0 +1,75 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include "Body.h" | ||
4 | #include "Space.h" | ||
5 | #include "CommonMgd.h" | ||
6 | |||
7 | namespace ODEManaged | ||
8 | { | ||
9 | __gc public class Geom | ||
10 | { | ||
11 | public: | ||
12 | |||
13 | |||
14 | //Constructor | ||
15 | |||
16 | Geom (void); | ||
17 | |||
18 | |||
19 | //Destructor | ||
20 | |||
21 | ~Geom (void); | ||
22 | |||
23 | |||
24 | //Methods | ||
25 | |||
26 | //Basic Stuff | ||
27 | |||
28 | dGeomID Id (void); | ||
29 | dBodyID GetBody (void); | ||
30 | |||
31 | //Overloaded SetBody | ||
32 | void SetBody (Body &body); | ||
33 | /*void SetBody (dBodyID b);*/ | ||
34 | |||
35 | Vector3 GetPosition (void); | ||
36 | void SetPosition (double x, double y, double z); | ||
37 | |||
38 | Matrix3 GetRotation (void); | ||
39 | void SetRotation (Matrix3 rotation); | ||
40 | |||
41 | void SetData (void *data); | ||
42 | void *GetData (void); | ||
43 | |||
44 | |||
45 | //Create Objects | ||
46 | |||
47 | void CreateSphere (Space &space, double radius); | ||
48 | void CreateBox (Space &space, double lx, double ly, double lz); | ||
49 | void CreatePlane (Space &space, double a, double b, double c, double d); | ||
50 | void CreateCCylinder (Space &space, double radius, double length); | ||
51 | |||
52 | |||
53 | //Destroy Objects | ||
54 | |||
55 | void Destroy (void); | ||
56 | |||
57 | |||
58 | //Get Object's Parameters | ||
59 | |||
60 | double SphereGetRadius (void); | ||
61 | Vector3 BoxGetLengths (void); | ||
62 | Vector4 PlaneGetParams (void); | ||
63 | void CCylinderGetParams (double *radius, double *length); | ||
64 | int GetClass (void); | ||
65 | |||
66 | |||
67 | //Properties | ||
68 | |||
69 | private: | ||
70 | |||
71 | dGeomID _id; | ||
72 | |||
73 | }; | ||
74 | |||
75 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/Joint.cpp b/libraries/ode-0.9/contrib/DotNetManaged/Joint.cpp new file mode 100644 index 0000000..e2d8de6 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/Joint.cpp | |||
@@ -0,0 +1,35 @@ | |||
1 | #include "StdAfx.h" | ||
2 | |||
3 | #include <ode/ode.h> | ||
4 | #include "joint.h" | ||
5 | #include "CommonMgd.h" | ||
6 | #include "world.h" | ||
7 | |||
8 | namespace ODEManaged | ||
9 | { | ||
10 | |||
11 | //Constructor | ||
12 | |||
13 | Joint::Joint(void) | ||
14 | { | ||
15 | _id=0; | ||
16 | } | ||
17 | |||
18 | |||
19 | //Destructor | ||
20 | |||
21 | Joint::~Joint(void) | ||
22 | { | ||
23 | dJointDestroy(this->_id); | ||
24 | } | ||
25 | |||
26 | |||
27 | //Methods | ||
28 | |||
29 | //Id | ||
30 | dJointID Joint::Id(void) | ||
31 | { | ||
32 | return _id; | ||
33 | } | ||
34 | |||
35 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/Joint.h b/libraries/ode-0.9/contrib/DotNetManaged/Joint.h new file mode 100644 index 0000000..d9ab254 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/Joint.h | |||
@@ -0,0 +1,21 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include "JointGroup.h" | ||
4 | #include "World.h" | ||
5 | #include "Body.h" | ||
6 | |||
7 | namespace ODEManaged | ||
8 | { | ||
9 | __gc public class Joint | ||
10 | { | ||
11 | protected: | ||
12 | //Constructor and Destructor Defenition | ||
13 | Joint(void); | ||
14 | ~Joint(void); | ||
15 | |||
16 | //Public Methods | ||
17 | dJointID Id(void); | ||
18 | |||
19 | dJointID _id; | ||
20 | }; | ||
21 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/JointAMotor.cpp b/libraries/ode-0.9/contrib/DotNetManaged/JointAMotor.cpp new file mode 100644 index 0000000..c5a4543 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/JointAMotor.cpp | |||
@@ -0,0 +1,162 @@ | |||
1 | #include "StdAfx.h" | ||
2 | |||
3 | #include <ode/ode.h> | ||
4 | #include "JointAMotor.h" | ||
5 | |||
6 | namespace ODEManaged | ||
7 | { | ||
8 | |||
9 | //Constructors | ||
10 | |||
11 | JointAMotor::JointAMotor(void) : Joint(){} | ||
12 | |||
13 | |||
14 | JointAMotor::JointAMotor(World &world) | ||
15 | { | ||
16 | if(this->_id) dJointDestroy(this->_id); | ||
17 | _id = dJointCreateAMotor(world.Id(), 0); | ||
18 | } | ||
19 | |||
20 | |||
21 | JointAMotor::JointAMotor(World &world, JointGroup &jointGroup) | ||
22 | { | ||
23 | if(this->_id) dJointDestroy(this->_id); | ||
24 | _id = dJointCreateAMotor(world.Id(), jointGroup.Id()); | ||
25 | } | ||
26 | |||
27 | |||
28 | //Destructor | ||
29 | |||
30 | JointAMotor::~JointAMotor(void){} | ||
31 | |||
32 | |||
33 | //Methods | ||
34 | |||
35 | //Overloaded Create | ||
36 | void JointAMotor::Create(World &world, JointGroup &jointGroup) | ||
37 | { | ||
38 | if(this->_id) dJointDestroy(this->_id); | ||
39 | _id = dJointCreateAMotor(world.Id(), jointGroup.Id()); | ||
40 | } | ||
41 | |||
42 | void JointAMotor::Create(World &world) | ||
43 | { | ||
44 | if(this->_id) dJointDestroy(this->_id); | ||
45 | _id = dJointCreateAMotor(world.Id(), 0); | ||
46 | } | ||
47 | |||
48 | |||
49 | //Overloaded Attach | ||
50 | void JointAMotor::Attach(Body &body1, Body &body2) | ||
51 | { | ||
52 | dJointAttach(this->_id, body1.Id(), body2.Id()); | ||
53 | } | ||
54 | |||
55 | void JointAMotor::Attach(Body &body1) | ||
56 | { | ||
57 | dJointAttach(this->_id, body1.Id(), 0); | ||
58 | } | ||
59 | |||
60 | |||
61 | //SetNumAxes | ||
62 | |||
63 | void JointAMotor::SetNumAxes(int num) | ||
64 | { | ||
65 | dJointSetAMotorNumAxes(this->_id, num); | ||
66 | } | ||
67 | |||
68 | |||
69 | //GetNumAxes | ||
70 | |||
71 | int JointAMotor::GetNumAxes(void) | ||
72 | { | ||
73 | return dJointGetAMotorNumAxes(this->_id); | ||
74 | } | ||
75 | |||
76 | |||
77 | //SetAxis | ||
78 | |||
79 | void JointAMotor::SetAxis(int anum, int rel, double x, double y ,double z) | ||
80 | { | ||
81 | dJointSetAMotorAxis(this->_id, anum, rel, x, y, z); | ||
82 | } | ||
83 | |||
84 | |||
85 | //GetAxis | ||
86 | |||
87 | Vector3 JointAMotor::GetAxis(int anum) | ||
88 | { | ||
89 | Vector3 retVal; | ||
90 | dVector3 temp; | ||
91 | dJointGetAMotorAxis(this->_id, anum, temp); | ||
92 | retVal.x = temp[0]; | ||
93 | retVal.y = temp[1]; | ||
94 | retVal.z = temp[2]; | ||
95 | return retVal; | ||
96 | } | ||
97 | |||
98 | |||
99 | //SetAngle | ||
100 | |||
101 | void JointAMotor::SetAngle(int anum, double angle) | ||
102 | { | ||
103 | dJointSetAMotorAngle(this->_id, anum, angle); | ||
104 | } | ||
105 | |||
106 | |||
107 | //GetAngle | ||
108 | |||
109 | double JointAMotor::GetAngle(int anum) | ||
110 | { | ||
111 | return dJointGetAMotorAngle(this->_id, anum); | ||
112 | } | ||
113 | |||
114 | |||
115 | //SetParam | ||
116 | |||
117 | void JointAMotor::SetParam(int parameter, double value) | ||
118 | { | ||
119 | dJointSetAMotorParam(this->_id, parameter, value); | ||
120 | } | ||
121 | |||
122 | |||
123 | //GetParam | ||
124 | |||
125 | double JointAMotor::GetParam(int parameter) | ||
126 | { | ||
127 | return dJointGetAMotorParam(this->_id, parameter); | ||
128 | } | ||
129 | |||
130 | |||
131 | //SetMode | ||
132 | |||
133 | void JointAMotor::SetMode(int mode) | ||
134 | { | ||
135 | dJointSetAMotorMode(this->_id, mode); | ||
136 | } | ||
137 | |||
138 | |||
139 | //GetMode | ||
140 | |||
141 | int JointAMotor::GetMode(void) | ||
142 | { | ||
143 | return dJointGetAMotorMode(this->_id); | ||
144 | } | ||
145 | |||
146 | |||
147 | //GetAxisRel | ||
148 | |||
149 | int JointAMotor::GetAxisRel(int anum) | ||
150 | { | ||
151 | return dJointGetAMotorAxisRel(this->_id, anum); | ||
152 | } | ||
153 | |||
154 | |||
155 | //GetAngleRate | ||
156 | |||
157 | double JointAMotor::GetAngleRate(int anum) | ||
158 | { | ||
159 | return dJointGetAMotorAngleRate(this->_id, anum); | ||
160 | } | ||
161 | |||
162 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/JointAMotor.h b/libraries/ode-0.9/contrib/DotNetManaged/JointAMotor.h new file mode 100644 index 0000000..aa3ca4b --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/JointAMotor.h | |||
@@ -0,0 +1,62 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include "Joint.h" | ||
4 | |||
5 | namespace ODEManaged | ||
6 | { | ||
7 | __gc public class JointAMotor : public Joint | ||
8 | { | ||
9 | public: | ||
10 | |||
11 | |||
12 | //Constructors | ||
13 | |||
14 | JointAMotor (void); | ||
15 | JointAMotor (World &world); | ||
16 | JointAMotor (World &world, JointGroup &jointGroup); | ||
17 | |||
18 | |||
19 | //Destructor | ||
20 | |||
21 | virtual ~JointAMotor (void); | ||
22 | |||
23 | |||
24 | //Methods | ||
25 | |||
26 | //Basic Stuff | ||
27 | |||
28 | //Overloaded Create | ||
29 | void Create (World &world, JointGroup &jointGroup); | ||
30 | void Create (World &world); | ||
31 | |||
32 | void SetNumAxes (int num); | ||
33 | int GetNumAxes (void); | ||
34 | |||
35 | void SetAxis (int anum, int rel, double x, double y, double z); | ||
36 | Vector3 GetAxis (int anum); | ||
37 | |||
38 | void SetAngle (int anum, double angle); | ||
39 | double GetAngle (int anum); | ||
40 | |||
41 | void SetMode (int mode); | ||
42 | int GetMode (void); | ||
43 | |||
44 | int GetAxisRel (int anum); | ||
45 | double GetAngleRate (int anum); | ||
46 | |||
47 | //Overloaded Attach | ||
48 | void Attach (Body &body1, Body &body2); | ||
49 | void Attach (Body &body1); | ||
50 | |||
51 | |||
52 | //Movement Parameters | ||
53 | |||
54 | void SetParam (int parameter, double value); | ||
55 | double GetParam (int parameter); | ||
56 | |||
57 | |||
58 | |||
59 | |||
60 | |||
61 | }; | ||
62 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/JointBall.cpp b/libraries/ode-0.9/contrib/DotNetManaged/JointBall.cpp new file mode 100644 index 0000000..d9336c9 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/JointBall.cpp | |||
@@ -0,0 +1,79 @@ | |||
1 | #include "StdAfx.h" | ||
2 | |||
3 | #include <ode/ode.h> | ||
4 | #include "jointball.h" | ||
5 | |||
6 | namespace ODEManaged | ||
7 | { | ||
8 | |||
9 | //Constructors | ||
10 | |||
11 | JointBall::JointBall(void) : Joint(){} | ||
12 | |||
13 | |||
14 | JointBall::JointBall(World &world) | ||
15 | { | ||
16 | if(this->_id) dJointDestroy(this->_id); | ||
17 | _id = dJointCreateBall(world.Id(), 0); | ||
18 | } | ||
19 | |||
20 | |||
21 | JointBall::JointBall(World &world, JointGroup &jointGroup) | ||
22 | { | ||
23 | if(this->_id) dJointDestroy(this->_id); | ||
24 | _id = dJointCreateBall(world.Id(), jointGroup.Id()); | ||
25 | } | ||
26 | |||
27 | |||
28 | //Destructor | ||
29 | |||
30 | JointBall::~JointBall(void){} | ||
31 | |||
32 | |||
33 | //Methods | ||
34 | |||
35 | //Overloaded Create | ||
36 | void JointBall::Create(World &world, JointGroup &jointGroup) | ||
37 | { | ||
38 | if(this->_id) dJointDestroy(this->_id); | ||
39 | _id = dJointCreateBall(world.Id(), jointGroup.Id()); | ||
40 | } | ||
41 | |||
42 | void JointBall::Create(World &world) | ||
43 | { | ||
44 | if(this->_id) dJointDestroy(this->_id); | ||
45 | _id = dJointCreateBall(world.Id(), 0); | ||
46 | } | ||
47 | |||
48 | |||
49 | //Overloaded Attach | ||
50 | void JointBall::Attach(Body &body1, Body &body2) | ||
51 | { | ||
52 | dJointAttach(this->_id, body1.Id(), body2.Id()); | ||
53 | } | ||
54 | |||
55 | void JointBall::Attach(Body &body1) | ||
56 | { | ||
57 | dJointAttach(this->_id, body1.Id(), 0); | ||
58 | } | ||
59 | |||
60 | |||
61 | //SetAnchor | ||
62 | void JointBall::SetAnchor(double x, double y ,double z) | ||
63 | { | ||
64 | dJointSetBallAnchor(this->_id, x, y, z); | ||
65 | } | ||
66 | |||
67 | //GetAnchor | ||
68 | Vector3 JointBall::GetAnchor(void) | ||
69 | { | ||
70 | Vector3 retVal; | ||
71 | dVector3 temp; | ||
72 | dJointGetBallAnchor(this->_id,temp); | ||
73 | retVal.x = temp[0]; | ||
74 | retVal.y = temp[1]; | ||
75 | retVal.z = temp[2]; | ||
76 | return retVal; | ||
77 | } | ||
78 | |||
79 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/JointBall.h b/libraries/ode-0.9/contrib/DotNetManaged/JointBall.h new file mode 100644 index 0000000..2355bdd --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/JointBall.h | |||
@@ -0,0 +1,38 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include "Joint.h" | ||
4 | |||
5 | namespace ODEManaged | ||
6 | { | ||
7 | __gc public class JointBall : public Joint | ||
8 | { | ||
9 | public: | ||
10 | |||
11 | //Constructors | ||
12 | |||
13 | JointBall(void); | ||
14 | JointBall(World &world); | ||
15 | JointBall(World &world, JointGroup &jointGroup); | ||
16 | |||
17 | |||
18 | //Destructors | ||
19 | |||
20 | virtual ~JointBall(void); | ||
21 | |||
22 | |||
23 | //Methods | ||
24 | |||
25 | //Overloaded Create | ||
26 | void Create(World &world, JointGroup &jointGroup); | ||
27 | void Create(World &world); | ||
28 | |||
29 | //Overloaded Attach | ||
30 | void Attach(Body &body1, Body &body2); | ||
31 | void Attach(Body &body1); | ||
32 | |||
33 | void SetAnchor(double x, double y, double z); | ||
34 | Vector3 GetAnchor(void); | ||
35 | |||
36 | }; | ||
37 | |||
38 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/JointFixed.cpp b/libraries/ode-0.9/contrib/DotNetManaged/JointFixed.cpp new file mode 100644 index 0000000..afe9222 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/JointFixed.cpp | |||
@@ -0,0 +1,67 @@ | |||
1 | #include "StdAfx.h" | ||
2 | |||
3 | #include <ode/ode.h> | ||
4 | #include "jointfixed.h" | ||
5 | |||
6 | namespace ODEManaged | ||
7 | { | ||
8 | |||
9 | //Constructors | ||
10 | |||
11 | JointFixed::JointFixed(void) : Joint(){} | ||
12 | |||
13 | |||
14 | JointFixed::JointFixed(World &world) | ||
15 | { | ||
16 | if(this->_id) dJointDestroy(this->_id); | ||
17 | _id = dJointCreateFixed(world.Id(),0); | ||
18 | } | ||
19 | |||
20 | |||
21 | JointFixed::JointFixed(World &world, JointGroup &jointGroup) | ||
22 | { | ||
23 | if(this->_id) dJointDestroy(this->_id); | ||
24 | _id = dJointCreateFixed(world.Id(), jointGroup.Id()); | ||
25 | } | ||
26 | |||
27 | |||
28 | //Destructor | ||
29 | |||
30 | JointFixed::~JointFixed(void){} | ||
31 | |||
32 | |||
33 | //Methods | ||
34 | |||
35 | //Overloaded Create | ||
36 | void JointFixed::Create(World &world, JointGroup &jointGroup) | ||
37 | { | ||
38 | if(this->_id) dJointDestroy(this->_id); | ||
39 | _id = dJointCreateFixed(world.Id(), jointGroup.Id()); | ||
40 | } | ||
41 | |||
42 | void JointFixed::Create(World &world) | ||
43 | { | ||
44 | if(this->_id) dJointDestroy(this->_id); | ||
45 | _id = dJointCreateFixed(world.Id(), 0); | ||
46 | } | ||
47 | |||
48 | |||
49 | //Overloaded Attach | ||
50 | void JointFixed::Attach(Body &body1, Body &body2) | ||
51 | { | ||
52 | dJointAttach(this->_id, body1.Id(), body2.Id()); | ||
53 | } | ||
54 | |||
55 | void JointFixed::Attach(Body &body1) | ||
56 | { | ||
57 | dJointAttach(this->_id, body1.Id(), 0); | ||
58 | } | ||
59 | |||
60 | |||
61 | //Fixed | ||
62 | void JointFixed::SetFixed(void) | ||
63 | { | ||
64 | dJointSetFixed(this->_id); | ||
65 | } | ||
66 | |||
67 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/JointFixed.h b/libraries/ode-0.9/contrib/DotNetManaged/JointFixed.h new file mode 100644 index 0000000..5ca50dc --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/JointFixed.h | |||
@@ -0,0 +1,37 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include "Joint.h" | ||
4 | |||
5 | namespace ODEManaged | ||
6 | { | ||
7 | __gc public class JointFixed : public Joint | ||
8 | { | ||
9 | public: | ||
10 | |||
11 | //Constructors | ||
12 | |||
13 | JointFixed(void); | ||
14 | JointFixed(World &world); | ||
15 | JointFixed(World &world, JointGroup &jointGroup); | ||
16 | |||
17 | |||
18 | //Destructor | ||
19 | |||
20 | virtual ~JointFixed(void); | ||
21 | |||
22 | |||
23 | //Methods | ||
24 | |||
25 | //Overloaded Create | ||
26 | void Create(World &world, JointGroup &jointGroup); | ||
27 | void Create(World &world); | ||
28 | |||
29 | //Overloaded Attach | ||
30 | void Attach(Body &body1, Body &body2); | ||
31 | void Attach(Body &body1); | ||
32 | |||
33 | void SetFixed(void); | ||
34 | |||
35 | }; | ||
36 | |||
37 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/JointGroup.cpp b/libraries/ode-0.9/contrib/DotNetManaged/JointGroup.cpp new file mode 100644 index 0000000..925751f --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/JointGroup.cpp | |||
@@ -0,0 +1,53 @@ | |||
1 | #include "StdAfx.h" | ||
2 | |||
3 | #include <ode/ode.h> | ||
4 | #include "jointgroup.h" | ||
5 | |||
6 | namespace ODEManaged | ||
7 | { | ||
8 | |||
9 | //Constructors | ||
10 | |||
11 | JointGroup::JointGroup(void) | ||
12 | { | ||
13 | _id=0; | ||
14 | } | ||
15 | |||
16 | JointGroup::JointGroup (int maxSize) | ||
17 | { | ||
18 | _id = dJointGroupCreate(maxSize); | ||
19 | } | ||
20 | |||
21 | |||
22 | //Destructor | ||
23 | |||
24 | JointGroup::~JointGroup(void) | ||
25 | { | ||
26 | dJointGroupDestroy(this->_id); | ||
27 | } | ||
28 | |||
29 | |||
30 | //Methods | ||
31 | |||
32 | //ID | ||
33 | dJointGroupID JointGroup::Id() | ||
34 | { | ||
35 | return _id; | ||
36 | } | ||
37 | |||
38 | |||
39 | //Create | ||
40 | void JointGroup::Create (int maxSize) | ||
41 | { | ||
42 | if(_id) dJointGroupDestroy(_id); | ||
43 | _id = dJointGroupCreate(maxSize); | ||
44 | } | ||
45 | |||
46 | |||
47 | //Empty | ||
48 | void JointGroup::Empty (void) | ||
49 | { | ||
50 | dJointGroupEmpty(this->_id); | ||
51 | } | ||
52 | |||
53 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/JointGroup.h b/libraries/ode-0.9/contrib/DotNetManaged/JointGroup.h new file mode 100644 index 0000000..b62ced0 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/JointGroup.h | |||
@@ -0,0 +1,33 @@ | |||
1 | #pragma once | ||
2 | |||
3 | namespace ODEManaged | ||
4 | { | ||
5 | __gc public class JointGroup | ||
6 | { | ||
7 | public: | ||
8 | |||
9 | //Constructors | ||
10 | |||
11 | JointGroup(void); | ||
12 | JointGroup(int maxSize); | ||
13 | |||
14 | |||
15 | //Destructor | ||
16 | |||
17 | ~JointGroup(void); | ||
18 | |||
19 | |||
20 | //Methods | ||
21 | |||
22 | dJointGroupID Id(void); | ||
23 | void Create(int maxSize); | ||
24 | void Empty(void); | ||
25 | |||
26 | |||
27 | private: | ||
28 | |||
29 | dJointGroupID _id; | ||
30 | |||
31 | }; | ||
32 | |||
33 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/JointHinge.cpp b/libraries/ode-0.9/contrib/DotNetManaged/JointHinge.cpp new file mode 100644 index 0000000..85d420b --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/JointHinge.cpp | |||
@@ -0,0 +1,121 @@ | |||
1 | #include "stdafx.h" | ||
2 | |||
3 | #include <ode/ode.h> | ||
4 | #include "jointhinge.h" | ||
5 | |||
6 | namespace ODEManaged | ||
7 | { | ||
8 | |||
9 | //Constructors | ||
10 | |||
11 | JointHinge::JointHinge(void) : Joint(){} | ||
12 | |||
13 | |||
14 | JointHinge::JointHinge(World &world) | ||
15 | { | ||
16 | if(this->_id) dJointDestroy(this->_id); | ||
17 | _id = dJointCreateHinge(world.Id(), 0); | ||
18 | } | ||
19 | |||
20 | |||
21 | JointHinge::JointHinge(World &world, JointGroup &jointGroup) | ||
22 | { | ||
23 | if(this->_id) dJointDestroy(this->_id); | ||
24 | _id = dJointCreateHinge(world.Id(), jointGroup.Id()); | ||
25 | } | ||
26 | |||
27 | |||
28 | //Destructor | ||
29 | |||
30 | JointHinge::~JointHinge(void){} | ||
31 | |||
32 | |||
33 | //Methods | ||
34 | |||
35 | //Overloaded Create | ||
36 | void JointHinge::Create(World &world, JointGroup &jointGroup) | ||
37 | { | ||
38 | if(this->_id) dJointDestroy(this->_id); | ||
39 | _id = dJointCreateHinge(world.Id(), jointGroup.Id()); | ||
40 | } | ||
41 | |||
42 | void JointHinge::Create(World &world) | ||
43 | { | ||
44 | if(this->_id) dJointDestroy(this->_id); | ||
45 | _id = dJointCreateHinge(world.Id(), 0); | ||
46 | } | ||
47 | |||
48 | |||
49 | //Overloaded Attach | ||
50 | void JointHinge::Attach(Body &body1, Body &body2) | ||
51 | { | ||
52 | dJointAttach(this->_id, body1.Id(), body2.Id()); | ||
53 | } | ||
54 | |||
55 | void JointHinge::Attach(Body &body1) | ||
56 | { | ||
57 | dJointAttach(this->_id, body1.Id(), 0); | ||
58 | } | ||
59 | |||
60 | |||
61 | //SetAxis | ||
62 | void JointHinge::SetAxis(double x, double y, double z) | ||
63 | { | ||
64 | dJointSetHingeAxis(this->_id, x, y, z); | ||
65 | } | ||
66 | |||
67 | //GetAxis | ||
68 | Vector3 JointHinge::GetAxis(void) | ||
69 | { | ||
70 | Vector3 retVal; | ||
71 | dVector3 temp; | ||
72 | dJointGetHingeAxis(this->_id, temp); | ||
73 | retVal.x = temp[0]; | ||
74 | retVal.y = temp[1]; | ||
75 | retVal.z = temp[2]; | ||
76 | return retVal; | ||
77 | } | ||
78 | |||
79 | |||
80 | //SetAnchor | ||
81 | void JointHinge::SetAnchor(double x, double y, double z) | ||
82 | { | ||
83 | dJointSetHingeAnchor(this->_id, x, y, z); | ||
84 | } | ||
85 | |||
86 | //GetAnchor | ||
87 | Vector3 JointHinge::GetAnchor(void) | ||
88 | { | ||
89 | Vector3 retVal; | ||
90 | dVector3 temp; | ||
91 | dJointGetHingeAnchor(this->_id, temp); | ||
92 | retVal.x = temp[0]; | ||
93 | retVal.y = temp[1]; | ||
94 | retVal.z = temp[2]; | ||
95 | return retVal; | ||
96 | } | ||
97 | |||
98 | |||
99 | //Movement Parameters | ||
100 | |||
101 | //SetAllMovParams | ||
102 | void JointHinge::SetAllMovParams(double LoStop, double HiStop, | ||
103 | double Velocity, double MaxForce, | ||
104 | double FudgeFactor, double Bounce, | ||
105 | double StopERP, double StopCFM) | ||
106 | { | ||
107 | if (LoStop > -3.141592653 && LoStop <= 0) | ||
108 | dJointSetHingeParam(this->_id, dParamLoStop, LoStop); | ||
109 | |||
110 | if (HiStop < 3.141592653 && HiStop >= 0) | ||
111 | dJointSetHingeParam(this->_id, dParamHiStop, HiStop); | ||
112 | |||
113 | dJointSetHingeParam(this->_id, dParamVel, Velocity); | ||
114 | dJointSetHingeParam(this->_id, dParamFMax, MaxForce); | ||
115 | dJointSetHingeParam(this->_id, dParamFudgeFactor, FudgeFactor); | ||
116 | dJointSetHingeParam(this->_id, dParamBounce, Bounce); | ||
117 | dJointSetHingeParam(this->_id, dParamStopERP, StopERP); | ||
118 | dJointSetHingeParam(this->_id, dParamStopCFM, StopCFM); | ||
119 | } | ||
120 | |||
121 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/JointHinge.h b/libraries/ode-0.9/contrib/DotNetManaged/JointHinge.h new file mode 100644 index 0000000..3115845 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/JointHinge.h | |||
@@ -0,0 +1,195 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include "Joint.h" | ||
4 | #include "CommonMgd.h" | ||
5 | |||
6 | namespace ODEManaged | ||
7 | { | ||
8 | __gc public class JointHinge : public Joint | ||
9 | { | ||
10 | public: | ||
11 | |||
12 | //Constructors | ||
13 | |||
14 | JointHinge(void); | ||
15 | JointHinge(World &world); | ||
16 | JointHinge(World &world, JointGroup &jointGroup); | ||
17 | |||
18 | |||
19 | //Destructor | ||
20 | |||
21 | virtual~JointHinge(void); | ||
22 | |||
23 | |||
24 | //Methods | ||
25 | |||
26 | //Overloaded Create | ||
27 | void Create(World &world, JointGroup &jointGroup); | ||
28 | void Create(World &world); | ||
29 | |||
30 | //Overloaded Attach | ||
31 | void Attach(Body &body1, Body &body2); | ||
32 | void Attach(Body &body1); | ||
33 | |||
34 | void SetAnchor(double x, double y, double z); | ||
35 | Vector3 GetAnchor(void); | ||
36 | |||
37 | void SetAxis(double x, double y, double z); | ||
38 | Vector3 GetAxis(void); | ||
39 | |||
40 | void SetAllMovParams(double LoStop, double HiStop, | ||
41 | double Velocity, double MaxForce, | ||
42 | double FudgeFactor, double Bounce, | ||
43 | double StopERP, double StopCFM); | ||
44 | |||
45 | |||
46 | //Properties | ||
47 | |||
48 | //LoStop | ||
49 | __property double get_LoStop(void) | ||
50 | { | ||
51 | return dJointGetHingeParam(this->_id, dParamLoStop); | ||
52 | } | ||
53 | |||
54 | __property void set_LoStop(double value) | ||
55 | { | ||
56 | if (value > -3.141592653 && value <= 0) | ||
57 | dJointSetHingeParam(this->_id, dParamLoStop, value); | ||
58 | } | ||
59 | |||
60 | |||
61 | //HiStop | ||
62 | __property double get_HiStop(void) | ||
63 | { | ||
64 | return dJointGetHingeParam(this->_id, dParamHiStop); | ||
65 | } | ||
66 | |||
67 | __property void set_HiStop(double value) | ||
68 | { | ||
69 | if (value < 3.141592653 && value >= 0) | ||
70 | dJointSetHingeParam(this->_id, dParamHiStop, value); | ||
71 | } | ||
72 | |||
73 | |||
74 | //Velocity | ||
75 | __property double get_Velocity(void) | ||
76 | { | ||
77 | return dJointGetHingeParam(this->_id, dParamVel); | ||
78 | } | ||
79 | |||
80 | __property void set_Velocity(double value) | ||
81 | { | ||
82 | dJointSetHingeParam(this->_id, dParamVel, value); | ||
83 | } | ||
84 | |||
85 | |||
86 | //MaxForce | ||
87 | __property double get_MaxForce(void) | ||
88 | { | ||
89 | return dJointGetHingeParam(this->_id, dParamFMax); | ||
90 | } | ||
91 | |||
92 | __property void set_MaxForce(double value) | ||
93 | { | ||
94 | dJointSetHingeParam(this->_id, dParamFMax, value); | ||
95 | } | ||
96 | |||
97 | |||
98 | //FudgeFactor | ||
99 | __property double get_FudgeFactor(void) | ||
100 | { | ||
101 | return dJointGetHingeParam(this->_id, dParamFudgeFactor); | ||
102 | } | ||
103 | |||
104 | __property void set_FudgeFactor(double value) | ||
105 | { | ||
106 | dJointSetHingeParam(this->_id, dParamFudgeFactor, value); | ||
107 | } | ||
108 | |||
109 | |||
110 | //Bounce | ||
111 | __property double get_Bounce(void) | ||
112 | { | ||
113 | return dJointGetHingeParam(this->_id, dParamBounce); | ||
114 | } | ||
115 | |||
116 | __property void set_Bounce(double value) | ||
117 | { | ||
118 | dJointSetHingeParam(this->_id, dParamBounce, value); | ||
119 | } | ||
120 | |||
121 | |||
122 | //StopERP | ||
123 | __property double get_StopERP(void) | ||
124 | { | ||
125 | return dJointGetHingeParam(this->_id, dParamStopERP); | ||
126 | } | ||
127 | |||
128 | __property void set_StopERP(double value) | ||
129 | { | ||
130 | dJointSetHingeParam(this->_id, dParamStopERP, value); | ||
131 | } | ||
132 | |||
133 | |||
134 | //StopCFM | ||
135 | __property double get_StopCFM(void) | ||
136 | { | ||
137 | return dJointGetHingeParam(this->_id, dParamStopCFM); | ||
138 | } | ||
139 | |||
140 | __property void set_StopCFM(double value) | ||
141 | { | ||
142 | dJointSetHingeParam(this->_id, dParamStopCFM, value); | ||
143 | } | ||
144 | |||
145 | |||
146 | //GetAngle | ||
147 | __property double get_Angle(void) | ||
148 | { | ||
149 | return dJointGetHingeAngle(this->_id); | ||
150 | } | ||
151 | |||
152 | |||
153 | //GetAngleRate | ||
154 | __property double get_AngleRate(void) | ||
155 | { | ||
156 | return dJointGetHingeAngleRate(this->_id); | ||
157 | } | ||
158 | |||
159 | }; | ||
160 | |||
161 | } | ||
162 | |||
163 | // void SetSuspensionERP(double value); | ||
164 | // double GetSuspensionERP(void); | ||
165 | |||
166 | // void SetSuspensionCFM(double value); | ||
167 | // double GetSuspensionCFM(void); | ||
168 | |||
169 | /* | ||
170 | //SetSuspensionERP | ||
171 | void JointHinge::SetSuspensionERP(double value) | ||
172 | { | ||
173 | dJointSetHingeParam(this->_id, dParamSuspensionERP, value); | ||
174 | } | ||
175 | |||
176 | //GetSuspensionERP | ||
177 | double JointHinge::GetSuspensionERP(void) | ||
178 | { | ||
179 | return dJointGetHingeParam(this->_id, dParamSuspensionERP); | ||
180 | } | ||
181 | |||
182 | |||
183 | //SetSuspensionCFM | ||
184 | void JointHinge::SetSuspensionCFM(double value) | ||
185 | { | ||
186 | dJointSetHingeParam(this->_id, dParamSuspensionCFM, value); | ||
187 | } | ||
188 | |||
189 | //GetSuspensionCFM | ||
190 | double JointHinge::GetSuspensionCFM(void) | ||
191 | { | ||
192 | return dJointGetHingeParam(this->_id, dParamSuspensionCFM); | ||
193 | } | ||
194 | |||
195 | */ | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/JointHinge2.cpp b/libraries/ode-0.9/contrib/DotNetManaged/JointHinge2.cpp new file mode 100644 index 0000000..94fd7a7 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/JointHinge2.cpp | |||
@@ -0,0 +1,133 @@ | |||
1 | #include "StdAfx.h" | ||
2 | |||
3 | #include <ode/ode.h> | ||
4 | #include "jointhinge2.h" | ||
5 | |||
6 | namespace ODEManaged | ||
7 | { | ||
8 | //Constructors | ||
9 | JointHinge2::JointHinge2(void) : Joint(){} | ||
10 | |||
11 | JointHinge2::JointHinge2(World &world) | ||
12 | { | ||
13 | if(this->_id) dJointDestroy(this->_id); | ||
14 | _id = dJointCreateHinge2(world.Id(),0); | ||
15 | } | ||
16 | |||
17 | JointHinge2::JointHinge2(World &world, JointGroup &jointGroup) | ||
18 | { | ||
19 | if(this->_id) dJointDestroy(this->_id); | ||
20 | _id = dJointCreateHinge2(world.Id(), jointGroup.Id()); | ||
21 | } | ||
22 | |||
23 | //Destructor | ||
24 | JointHinge2::~JointHinge2(void){} | ||
25 | |||
26 | //CreateHinge2 (overload 1) | ||
27 | void JointHinge2::Create(World &world, JointGroup &jointGroup) | ||
28 | { | ||
29 | if(this->_id) dJointDestroy(this->_id); | ||
30 | _id = dJointCreateHinge2(world.Id(), jointGroup.Id()); | ||
31 | } | ||
32 | |||
33 | //CreateHinge2 (overload 2) | ||
34 | void JointHinge2::Create(World &world) | ||
35 | { | ||
36 | if(this->_id) dJointDestroy(this->_id); | ||
37 | _id = dJointCreateHinge2(world.Id(),0); | ||
38 | } | ||
39 | |||
40 | //SetAnchor1 | ||
41 | void JointHinge2::SetAnchor (double x, double y ,double z) | ||
42 | { | ||
43 | dJointSetHinge2Anchor(_id, x,y,z); | ||
44 | } | ||
45 | |||
46 | //GetAnchor1 | ||
47 | Vector3 JointHinge2::GetAnchor() | ||
48 | { | ||
49 | Vector3 retVal; | ||
50 | dVector3 temp; | ||
51 | dJointGetHinge2Anchor(_id,temp); | ||
52 | retVal.x = temp[0]; | ||
53 | retVal.y = temp[1]; | ||
54 | retVal.z = temp[2]; | ||
55 | return retVal; | ||
56 | } | ||
57 | |||
58 | //SetAxis1 | ||
59 | void JointHinge2::SetAxis1 (double x, double y ,double z) | ||
60 | { | ||
61 | dJointSetHinge2Axis1(_id, x,y,z); | ||
62 | } | ||
63 | |||
64 | //GetAxis1 | ||
65 | Vector3 JointHinge2::GetAxis1() | ||
66 | { | ||
67 | Vector3 retVal; | ||
68 | dVector3 temp; | ||
69 | dJointGetHinge2Axis1(_id,temp); | ||
70 | retVal.x = temp[0]; | ||
71 | retVal.y = temp[1]; | ||
72 | retVal.z = temp[2]; | ||
73 | return retVal; | ||
74 | } | ||
75 | |||
76 | //SetAxis2 | ||
77 | void JointHinge2::SetAxis2 (double x, double y ,double z) | ||
78 | { | ||
79 | dJointSetHinge2Axis2(_id, x,y,z); | ||
80 | } | ||
81 | |||
82 | //GetAxis2 | ||
83 | Vector3 JointHinge2::GetAxis2() | ||
84 | { | ||
85 | Vector3 retVal; | ||
86 | dVector3 temp; | ||
87 | dJointGetHinge2Axis2(_id,temp); | ||
88 | retVal.x = temp[0]; | ||
89 | retVal.y = temp[1]; | ||
90 | retVal.z = temp[2]; | ||
91 | return retVal; | ||
92 | } | ||
93 | |||
94 | //GetAngle1 | ||
95 | double JointHinge2::GetAngle1 () | ||
96 | { | ||
97 | return dJointGetHinge2Angle1(this->_id); | ||
98 | } | ||
99 | |||
100 | //GetAngle1Rate | ||
101 | double JointHinge2::GetAngle1Rate () | ||
102 | { | ||
103 | return dJointGetHinge2Angle1Rate(this->_id); | ||
104 | } | ||
105 | |||
106 | ////GetAngle hmm, this doesn't exist | ||
107 | //double JointHinge2::GetAngle2 () | ||
108 | //{ | ||
109 | // return dJointGetHinge2Angle2(this->_id); | ||
110 | //} | ||
111 | |||
112 | //GetAngle2Rate | ||
113 | double JointHinge2::GetAngle2Rate () | ||
114 | { | ||
115 | return dJointGetHinge2Angle2Rate(this->_id); | ||
116 | } | ||
117 | |||
118 | |||
119 | //Attach (overload 1) | ||
120 | void JointHinge2::Attach (Body &body1, Body &body2) | ||
121 | { | ||
122 | dJointAttach(_id, body1.Id(),body2.Id()); | ||
123 | } | ||
124 | |||
125 | //Attach (overload 2) | ||
126 | //TODO: possibly add an overload that takes anchor as a param also. | ||
127 | void JointHinge2::Attach (Body &body1) | ||
128 | { | ||
129 | dJointAttach(_id, body1.Id(),0); | ||
130 | } | ||
131 | |||
132 | |||
133 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/JointHinge2.h b/libraries/ode-0.9/contrib/DotNetManaged/JointHinge2.h new file mode 100644 index 0000000..e883ea8 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/JointHinge2.h | |||
@@ -0,0 +1,48 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include "Joint.h" | ||
4 | #include "CommonMgd.h" | ||
5 | |||
6 | namespace ODEManaged | ||
7 | { | ||
8 | __gc public class JointHinge2 : public Joint | ||
9 | { | ||
10 | public: | ||
11 | |||
12 | |||
13 | //Constructors | ||
14 | |||
15 | JointHinge2 (void); | ||
16 | JointHinge2 (World &world); | ||
17 | JointHinge2 (World &world, JointGroup &jointGroup); | ||
18 | |||
19 | //Destructors | ||
20 | |||
21 | virtual ~JointHinge2 (void); | ||
22 | |||
23 | |||
24 | //Methods | ||
25 | |||
26 | //Overloaded Hinge.Create | ||
27 | void Create (World &world, JointGroup &jointGroup); | ||
28 | void Create (World &world); | ||
29 | |||
30 | void SetAnchor (double x, double y, double z); | ||
31 | Vector3 GetAnchor (void); | ||
32 | |||
33 | void SetAxis1 (double x, double y, double z); | ||
34 | Vector3 GetAxis1 (void); | ||
35 | |||
36 | void SetAxis2 (double x, double y, double z); | ||
37 | Vector3 GetAxis2 (void); | ||
38 | |||
39 | double GetAngle1 (void); | ||
40 | double GetAngle1Rate (void); | ||
41 | |||
42 | //double GetAngle2 (void); | ||
43 | double GetAngle2Rate (void); | ||
44 | |||
45 | void Attach (Body &body1, Body &body2); | ||
46 | void Attach( Body &body1); | ||
47 | }; | ||
48 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/JointSlider.cpp b/libraries/ode-0.9/contrib/DotNetManaged/JointSlider.cpp new file mode 100644 index 0000000..ab7ebd6 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/JointSlider.cpp | |||
@@ -0,0 +1,102 @@ | |||
1 | #include "StdAfx.h" | ||
2 | |||
3 | #include <ode/ode.h> | ||
4 | #include "jointslider.h" | ||
5 | |||
6 | namespace ODEManaged | ||
7 | { | ||
8 | |||
9 | //Constructors | ||
10 | |||
11 | JointSlider::JointSlider(void) : Joint(){} | ||
12 | |||
13 | |||
14 | JointSlider::JointSlider(World &world) | ||
15 | { | ||
16 | if(this->_id) dJointDestroy(this->_id); | ||
17 | _id = dJointCreateSlider(world.Id(), 0); | ||
18 | } | ||
19 | |||
20 | |||
21 | JointSlider::JointSlider(World &world, JointGroup &jointGroup) | ||
22 | { | ||
23 | if(this->_id) dJointDestroy(this->_id); | ||
24 | _id = dJointCreateSlider(world.Id(), jointGroup.Id()); | ||
25 | } | ||
26 | |||
27 | |||
28 | //Destructor | ||
29 | |||
30 | JointSlider::~JointSlider(void){} | ||
31 | |||
32 | |||
33 | //Methods | ||
34 | |||
35 | //Overloaded Create | ||
36 | void JointSlider::Create(World &world, JointGroup &jointGroup) | ||
37 | { | ||
38 | if(this->_id) dJointDestroy(this->_id); | ||
39 | _id = dJointCreateSlider(world.Id(), jointGroup.Id()); | ||
40 | } | ||
41 | |||
42 | void JointSlider::Create(World &world) | ||
43 | { | ||
44 | if(this->_id) dJointDestroy(this->_id); | ||
45 | _id = dJointCreateSlider(world.Id(), 0); | ||
46 | } | ||
47 | |||
48 | |||
49 | //Overloaded Attach | ||
50 | void JointSlider::Attach(Body &body1, Body &body2) | ||
51 | { | ||
52 | dJointAttach(this->_id, body1.Id(), body2.Id()); | ||
53 | } | ||
54 | |||
55 | void JointSlider::Attach(Body &body1) | ||
56 | { | ||
57 | dJointAttach(this->_id, body1.Id(), 0); | ||
58 | } | ||
59 | |||
60 | |||
61 | //SetAxis | ||
62 | void JointSlider::SetAxis(double x, double y, double z) | ||
63 | { | ||
64 | dJointSetSliderAxis(this->_id, x, y, z); | ||
65 | } | ||
66 | |||
67 | //GetAxis | ||
68 | Vector3 JointSlider::GetAxis(void) | ||
69 | { | ||
70 | Vector3 retVal; | ||
71 | dVector3 temp; | ||
72 | dJointGetSliderAxis(this->_id, temp); | ||
73 | retVal.x = temp[0]; | ||
74 | retVal.y = temp[1]; | ||
75 | retVal.z = temp[2]; | ||
76 | return retVal; | ||
77 | } | ||
78 | |||
79 | |||
80 | //Movement Parameters | ||
81 | |||
82 | //SetAllMovParams | ||
83 | void JointSlider::SetAllMovParams(double LoStop, double HiStop, | ||
84 | double Velocity, double MaxForce, | ||
85 | double FudgeFactor, double Bounce, | ||
86 | double StopERP, double StopCFM) | ||
87 | { | ||
88 | if (LoStop <= 0) | ||
89 | dJointSetHingeParam(this->_id, dParamLoStop, LoStop); | ||
90 | |||
91 | if (HiStop >= 0) | ||
92 | dJointSetHingeParam(this->_id, dParamHiStop, HiStop); | ||
93 | |||
94 | dJointSetSliderParam(this->_id, dParamVel, Velocity); | ||
95 | dJointSetSliderParam(this->_id, dParamFMax, MaxForce); | ||
96 | dJointSetSliderParam(this->_id, dParamFudgeFactor, FudgeFactor); | ||
97 | dJointSetSliderParam(this->_id, dParamBounce, Bounce); | ||
98 | dJointSetSliderParam(this->_id, dParamStopERP, StopERP); | ||
99 | dJointSetSliderParam(this->_id, dParamStopCFM, StopCFM); | ||
100 | } | ||
101 | |||
102 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/JointSlider.h b/libraries/ode-0.9/contrib/DotNetManaged/JointSlider.h new file mode 100644 index 0000000..7e96e59 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/JointSlider.h | |||
@@ -0,0 +1,158 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include "Joint.h" | ||
4 | #include "CommonMgd.h" | ||
5 | |||
6 | namespace ODEManaged | ||
7 | { | ||
8 | __gc public class JointSlider : public Joint | ||
9 | { | ||
10 | public: | ||
11 | |||
12 | |||
13 | //Constructors | ||
14 | |||
15 | JointSlider(void); | ||
16 | JointSlider(World &world); | ||
17 | JointSlider(World &world, JointGroup &jointGroup); | ||
18 | |||
19 | |||
20 | //Destructors | ||
21 | |||
22 | virtual ~JointSlider(void); | ||
23 | |||
24 | |||
25 | //Methods | ||
26 | |||
27 | //Overloaded Create | ||
28 | void Create(World &world, JointGroup &jointGroup); | ||
29 | void Create(World &world); | ||
30 | |||
31 | //Overloaded Attach | ||
32 | void Attach(Body &body1, Body &body2); | ||
33 | void Attach(Body &body1); | ||
34 | |||
35 | void SetAxis(double x, double y, double z); | ||
36 | Vector3 GetAxis(void); | ||
37 | |||
38 | void SetAllMovParams(double LoStop, double HiStop, | ||
39 | double Velocity, double MaxForce, | ||
40 | double FudgeFactor, double Bounce, | ||
41 | double StopERP, double StopCFM); | ||
42 | |||
43 | |||
44 | //Properties | ||
45 | |||
46 | //LoStop | ||
47 | __property double get_LoStop(void) | ||
48 | { | ||
49 | return dJointGetSliderParam(this->_id, dParamLoStop); | ||
50 | } | ||
51 | |||
52 | __property void set_LoStop(double value) | ||
53 | { | ||
54 | if (value <=0) | ||
55 | dJointSetSliderParam(this->_id, dParamLoStop, value); | ||
56 | } | ||
57 | |||
58 | |||
59 | //HiStop | ||
60 | __property double get_HiStop(void) | ||
61 | { | ||
62 | return dJointGetSliderParam(this->_id, dParamHiStop); | ||
63 | } | ||
64 | |||
65 | __property void set_HiStop(double value) | ||
66 | { | ||
67 | if (value >= 0) | ||
68 | dJointSetSliderParam(this->_id, dParamHiStop, value); | ||
69 | } | ||
70 | |||
71 | |||
72 | //Velocity | ||
73 | __property double get_Velocity(void) | ||
74 | { | ||
75 | return dJointGetSliderParam(this->_id, dParamVel); | ||
76 | } | ||
77 | |||
78 | __property void set_Velocity(double value) | ||
79 | { | ||
80 | dJointSetSliderParam(this->_id, dParamVel, value); | ||
81 | } | ||
82 | |||
83 | |||
84 | //MaxForce | ||
85 | __property double get_MaxForce(void) | ||
86 | { | ||
87 | return dJointGetSliderParam(this->_id, dParamFMax); | ||
88 | } | ||
89 | |||
90 | __property void set_MaxForce(double value) | ||
91 | { | ||
92 | dJointSetSliderParam(this->_id, dParamFMax, value); | ||
93 | } | ||
94 | |||
95 | |||
96 | //FudgeFactor | ||
97 | __property double get_FudgeFactor(void) | ||
98 | { | ||
99 | return dJointGetSliderParam(this->_id, dParamFudgeFactor); | ||
100 | } | ||
101 | |||
102 | __property void set_FudgeFactor(double value) | ||
103 | { | ||
104 | dJointSetSliderParam(this->_id, dParamFudgeFactor, value); | ||
105 | } | ||
106 | |||
107 | |||
108 | //Bounce | ||
109 | __property double get_Bounce(void) | ||
110 | { | ||
111 | return dJointGetSliderParam(this->_id, dParamBounce); | ||
112 | } | ||
113 | |||
114 | __property void set_Bounce(double value) | ||
115 | { | ||
116 | dJointSetSliderParam(this->_id, dParamBounce, value); | ||
117 | } | ||
118 | |||
119 | |||
120 | //StopERP | ||
121 | __property double get_StopERP(void) | ||
122 | { | ||
123 | return dJointGetSliderParam(this->_id, dParamStopERP); | ||
124 | } | ||
125 | |||
126 | __property void set_StopERP(double value) | ||
127 | { | ||
128 | dJointSetSliderParam(this->_id, dParamStopERP, value); | ||
129 | } | ||
130 | |||
131 | |||
132 | //StopCFM | ||
133 | __property double get_StopCFM(void) | ||
134 | { | ||
135 | return dJointGetSliderParam(this->_id, dParamStopCFM); | ||
136 | } | ||
137 | |||
138 | __property void set_StopCFM(double value) | ||
139 | { | ||
140 | dJointSetSliderParam(this->_id, dParamStopCFM, value); | ||
141 | } | ||
142 | |||
143 | |||
144 | //GetAngle | ||
145 | __property double get_Position(void) | ||
146 | { | ||
147 | return dJointGetSliderPosition(this->_id); | ||
148 | } | ||
149 | |||
150 | |||
151 | //GetAngleRate | ||
152 | __property double get_PositionRate(void) | ||
153 | { | ||
154 | return dJointGetSliderPositionRate(this->_id); | ||
155 | } | ||
156 | |||
157 | }; | ||
158 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/Release/ode.dll b/libraries/ode-0.9/contrib/DotNetManaged/Release/ode.dll new file mode 100755 index 0000000..ccf2a41 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/Release/ode.dll | |||
Binary files differ | |||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/Space.cpp b/libraries/ode-0.9/contrib/DotNetManaged/Space.cpp new file mode 100644 index 0000000..c9a7e19 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/Space.cpp | |||
@@ -0,0 +1,53 @@ | |||
1 | #include "StdAfx.h" | ||
2 | |||
3 | #include <ode/ode.h> | ||
4 | #include "Space.h" | ||
5 | #include "TEST.h" | ||
6 | |||
7 | namespace ODEManaged | ||
8 | { | ||
9 | |||
10 | //Constructor | ||
11 | |||
12 | Space::Space(void) | ||
13 | { | ||
14 | _id = dSimpleSpaceCreate(); | ||
15 | } | ||
16 | |||
17 | Space::Space(int minlevel, int maxlevel) | ||
18 | { | ||
19 | _id = dHashSpaceCreate(); | ||
20 | dHashSpaceSetLevels(this->_id, minlevel, maxlevel); | ||
21 | } | ||
22 | |||
23 | |||
24 | //Destructor | ||
25 | |||
26 | Space::~Space(void) | ||
27 | { | ||
28 | dSpaceDestroy(this->_id); | ||
29 | } | ||
30 | |||
31 | |||
32 | //Methods | ||
33 | |||
34 | //Id | ||
35 | dSpaceID Space::Id() | ||
36 | { | ||
37 | return _id; | ||
38 | } | ||
39 | |||
40 | |||
41 | //Collide | ||
42 | void Space::Collide(void *data, dNearCallback *callback) | ||
43 | { | ||
44 | dSpaceCollide(this->_id, data, callback); | ||
45 | } | ||
46 | |||
47 | |||
48 | |||
49 | |||
50 | |||
51 | |||
52 | |||
53 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/Space.h b/libraries/ode-0.9/contrib/DotNetManaged/Space.h new file mode 100644 index 0000000..78e81ad --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/Space.h | |||
@@ -0,0 +1,33 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include "CommonMgd.h" | ||
4 | |||
5 | namespace ODEManaged | ||
6 | { | ||
7 | __gc public class Space | ||
8 | { | ||
9 | public: | ||
10 | |||
11 | //Constructor | ||
12 | |||
13 | Space(void); | ||
14 | Space(int minlevel, int maxlevel); | ||
15 | |||
16 | //Destructor | ||
17 | |||
18 | ~Space(void); | ||
19 | |||
20 | |||
21 | //Methods | ||
22 | |||
23 | dSpaceID Id(void); | ||
24 | void Collide(void *data, dNearCallback *callback); | ||
25 | |||
26 | |||
27 | private: | ||
28 | |||
29 | dSpaceID _id; | ||
30 | |||
31 | }; | ||
32 | |||
33 | } | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/Stdafx.cpp b/libraries/ode-0.9/contrib/DotNetManaged/Stdafx.cpp new file mode 100644 index 0000000..b6c9d98 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/Stdafx.cpp | |||
@@ -0,0 +1,5 @@ | |||
1 | // stdafx.cpp : source file that includes just the standard includes | ||
2 | // ODEManaged.pch will be the pre-compiled header | ||
3 | // stdafx.obj will contain the pre-compiled type information | ||
4 | |||
5 | #include "stdafx.h" | ||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/Stdafx.h b/libraries/ode-0.9/contrib/DotNetManaged/Stdafx.h new file mode 100644 index 0000000..2222759 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/Stdafx.h | |||
@@ -0,0 +1,12 @@ | |||
1 | // stdafx.h : include file for standard system include files, | ||
2 | // or project specific include files that are used frequently, | ||
3 | // but are changed infrequently | ||
4 | |||
5 | #pragma once | ||
6 | |||
7 | #using <mscorlib.dll> | ||
8 | |||
9 | |||
10 | |||
11 | |||
12 | |||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/TEST.h b/libraries/ode-0.9/contrib/DotNetManaged/TEST.h new file mode 100644 index 0000000..e2cdbc3 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/TEST.h | |||
@@ -0,0 +1,17 @@ | |||
1 | |||
2 | #pragma once | ||
3 | |||
4 | #include "CommonMgd.h" | ||
5 | |||
6 | namespace ODEManaged | ||
7 | { | ||
8 | |||
9 | void RnearCallback(void *data, dGeomID o1, dGeomID o2) | ||
10 | { | ||
11 | } | ||
12 | |||
13 | } | ||
14 | |||
15 | |||
16 | |||
17 | |||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/World.cpp b/libraries/ode-0.9/contrib/DotNetManaged/World.cpp new file mode 100644 index 0000000..beab21a --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/World.cpp | |||
@@ -0,0 +1,74 @@ | |||
1 | #include "StdAfx.h" | ||
2 | |||
3 | #include <ode/ode.h> | ||
4 | #include "World.h" | ||
5 | |||
6 | namespace ODEManaged | ||
7 | { | ||
8 | |||
9 | //Constructor | ||
10 | |||
11 | World::World(void) | ||
12 | { | ||
13 | /*dWorldID _temp = dWorldCreate(); | ||
14 | _id = _temp;*/ | ||
15 | _id = dWorldCreate(); | ||
16 | } | ||
17 | |||
18 | |||
19 | //Destructor | ||
20 | |||
21 | World::~World(void) | ||
22 | { | ||
23 | dWorldDestroy(this->_id); | ||
24 | } | ||
25 | |||
26 | |||
27 | //Methods | ||
28 | |||
29 | //Id | ||
30 | dWorldID World::Id() | ||
31 | { | ||
32 | return _id; | ||
33 | } | ||
34 | |||
35 | |||
36 | //SetGravity | ||
37 | void World::SetGravity(double x, double y, double z) | ||
38 | { | ||
39 | dWorldSetGravity(this->_id, x, y, z); | ||
40 | } | ||
41 | |||
42 | |||
43 | //Overloaded GetGravity | ||
44 | Vector3 World::GetGravity(void) | ||
45 | { | ||
46 | Vector3 retVal; | ||
47 | dVector3 temp; | ||
48 | dWorldGetGravity(this->_id, temp); | ||
49 | retVal.x = temp[0]; | ||
50 | retVal.y = temp[1]; | ||
51 | retVal.z = temp[2]; | ||
52 | return retVal; | ||
53 | } | ||
54 | |||
55 | void World::GetGravity(double gravity __gc[]) | ||
56 | { | ||
57 | dVector3 temp; | ||
58 | dWorldGetGravity(this->_id, temp); | ||
59 | gravity[0] = temp[0]; | ||
60 | gravity[1] = temp[1]; | ||
61 | gravity[2] = temp[2]; | ||
62 | } | ||
63 | |||
64 | |||
65 | //Step | ||
66 | void World::Step(double stepSize) | ||
67 | { | ||
68 | dWorldStep(this->_id, stepSize); | ||
69 | } | ||
70 | |||
71 | } | ||
72 | |||
73 | |||
74 | |||
diff --git a/libraries/ode-0.9/contrib/DotNetManaged/World.h b/libraries/ode-0.9/contrib/DotNetManaged/World.h new file mode 100644 index 0000000..c4c60e5 --- /dev/null +++ b/libraries/ode-0.9/contrib/DotNetManaged/World.h | |||
@@ -0,0 +1,67 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include "CommonMgd.h" | ||
4 | |||
5 | namespace ODEManaged | ||
6 | { | ||
7 | __gc public class World | ||
8 | { | ||
9 | public: | ||
10 | |||
11 | //Constructor | ||
12 | |||
13 | World(void); | ||
14 | |||
15 | |||
16 | //Destructor | ||
17 | |||
18 | ~World(void); | ||
19 | |||
20 | |||
21 | // Methods | ||
22 | |||
23 | dWorldID Id(void); | ||
24 | |||
25 | void SetGravity(double x, double y, double z); | ||
26 | |||
27 | //Overloaded GetGravity | ||
28 | Vector3 GetGravity(void); | ||
29 | void GetGravity(double gravity __gc[]); | ||
30 | |||
31 | void Step(double stepSize); | ||
32 | |||
33 | |||
34 | //Properties | ||
35 | |||
36 | //Constraint Force Mixing | ||
37 | __property void set_CFM(double cfm) | ||
38 | { | ||
39 | dWorldSetCFM(this->_id,cfm); | ||
40 | } | ||
41 | |||
42 | __property double get_CFM(void) | ||
43 | { | ||
44 | return dWorldGetCFM(this->_id); | ||
45 | } | ||
46 | |||
47 | |||
48 | //Error Reduction Parameter | ||
49 | __property void set_ERP(double erp) | ||
50 | { | ||
51 | dWorldSetERP(this->_id,erp); | ||
52 | } | ||
53 | |||
54 | __property double get_ERP(void) | ||
55 | { | ||
56 | return dWorldGetERP(this->_id); | ||
57 | } | ||
58 | |||
59 | |||
60 | private: | ||
61 | |||
62 | dWorldID _id; | ||
63 | |||
64 | }; | ||
65 | |||
66 | } | ||
67 | |||
diff --git a/libraries/ode-0.9/contrib/GeomTransformGroup/GeomTransformGroup.cpp b/libraries/ode-0.9/contrib/GeomTransformGroup/GeomTransformGroup.cpp new file mode 100644 index 0000000..26b77b0 --- /dev/null +++ b/libraries/ode-0.9/contrib/GeomTransformGroup/GeomTransformGroup.cpp | |||
@@ -0,0 +1,218 @@ | |||
1 | |||
2 | /* ************************************************************************ */ | ||
3 | /* | ||
4 | grouped and transformed geometry functions | ||
5 | author: Tim Schmidt tisch@uni-paderborn.de | ||
6 | */ | ||
7 | |||
8 | |||
9 | #include <ode/common.h> | ||
10 | #include <ode/geom.h> | ||
11 | #include <ode/rotation.h> | ||
12 | #include <ode/odemath.h> | ||
13 | #include <ode/memory.h> | ||
14 | #include <ode/misc.h> | ||
15 | #include <ode/objects.h> | ||
16 | #include <ode/matrix.h> | ||
17 | #include <ode/GeomTransformGroup.h> | ||
18 | #include "objects.h" | ||
19 | #include "array.h" | ||
20 | #include "geom_internal.h" | ||
21 | |||
22 | // given a pointer `p' to a dContactGeom, return the dContactGeom at | ||
23 | // p + skip bytes. | ||
24 | |||
25 | #define CONTACT(p,skip) ((dContactGeom*) (((char*)p) + (skip))) | ||
26 | |||
27 | |||
28 | // ############################################################################ | ||
29 | |||
30 | int dGeomTransformGroupClass = -1; | ||
31 | // ############################################################################ | ||
32 | |||
33 | struct dxGeomTransformGroup { | ||
34 | dArray<dxGeom*> parts; // all the geoms that make up the group | ||
35 | dVector3 relativePosition; | ||
36 | dMatrix3 relativeRotation; | ||
37 | }; | ||
38 | // ############################################################################ | ||
39 | |||
40 | void dGeomTransformGroupSetRelativePosition (dxGeom *g, dReal x, dReal y, dReal z) | ||
41 | { | ||
42 | dAASSERT (g); | ||
43 | dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(g); | ||
44 | transformGroup->relativePosition[0] = x; | ||
45 | transformGroup->relativePosition[1] = y; | ||
46 | transformGroup->relativePosition[2] = z; | ||
47 | } | ||
48 | // ############################################################################ | ||
49 | |||
50 | void dGeomTransformGroupSetRelativeRotation (dxGeom *g, const dMatrix3 R) | ||
51 | { | ||
52 | dAASSERT (g); | ||
53 | dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(g); | ||
54 | memcpy (transformGroup->relativeRotation,R,sizeof(dMatrix3)); | ||
55 | } | ||
56 | // ############################################################################ | ||
57 | |||
58 | const dReal * dGeomTransformGroupGetRelativePosition (dxGeom *g) | ||
59 | { | ||
60 | dAASSERT (g); | ||
61 | dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(g); | ||
62 | return transformGroup->relativePosition; | ||
63 | } | ||
64 | // ############################################################################ | ||
65 | |||
66 | const dReal * dGeomTransformGroupGetRelativeRotation (dxGeom *g) | ||
67 | { | ||
68 | dAASSERT (g); | ||
69 | dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(g); | ||
70 | return transformGroup->relativeRotation; | ||
71 | } | ||
72 | // ############################################################################ | ||
73 | |||
74 | static void computeFinalTransformation (const dxGeom *tg, const dxGeom *part) | ||
75 | { | ||
76 | dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(tg); | ||
77 | dMULTIPLY0_331 (part->pos,tg->R,transformGroup->relativePosition); | ||
78 | part->pos[0] += tg->pos[0]; | ||
79 | part->pos[1] += tg->pos[1]; | ||
80 | part->pos[2] += tg->pos[2]; | ||
81 | dMULTIPLY0_333 (part->R,tg->R,transformGroup->relativeRotation); | ||
82 | } | ||
83 | // ############################################################################ | ||
84 | |||
85 | int dCollideTransformGroup (const dxGeom *o1, const dxGeom *o2, int flags, | ||
86 | dContactGeom *contact, int skip) | ||
87 | { | ||
88 | dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(o1); | ||
89 | if (transformGroup->parts.size() == 0) | ||
90 | { | ||
91 | return 0; | ||
92 | } | ||
93 | int numleft = flags & NUMC_MASK; | ||
94 | if (numleft == 0) numleft = 1; | ||
95 | flags &= ~NUMC_MASK; | ||
96 | int num=0, i=0; | ||
97 | while (i < transformGroup->parts.size() && numleft > 0) | ||
98 | { | ||
99 | dUASSERT (transformGroup->parts[i]->spaceid==0, | ||
100 | "GeomTransformGroup encapsulated object must not be in a space"); | ||
101 | dUASSERT (transformGroup->parts[i]->body==0, | ||
102 | "GeomTransformGroup encapsulated object must not be attached to a body"); | ||
103 | if (!o1->space_aabb) | ||
104 | { | ||
105 | computeFinalTransformation (o1, transformGroup->parts[i]); | ||
106 | } | ||
107 | dxBody *bodyBackup = transformGroup->parts[i]->body; | ||
108 | transformGroup->parts[i]->body = o1->body; | ||
109 | int n = dCollide (transformGroup->parts[i],const_cast<dxGeom*>(o2), | ||
110 | flags | numleft,contact,skip); | ||
111 | transformGroup->parts[i]->body = bodyBackup; | ||
112 | contact = CONTACT (contact,skip*n); | ||
113 | numleft -= n; | ||
114 | num += n; | ||
115 | i++; | ||
116 | } | ||
117 | return num; | ||
118 | } | ||
119 | // ############################################################################ | ||
120 | |||
121 | static dColliderFn * dGeomTransformGroupColliderFn (int num) | ||
122 | { | ||
123 | return (dColliderFn *) &dCollideTransformGroup; | ||
124 | } | ||
125 | // ############################################################################ | ||
126 | |||
127 | static void dGeomTransformGroupAABB (dxGeom *geom, dReal aabb[6]) | ||
128 | { | ||
129 | dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(geom); | ||
130 | aabb[0] = dInfinity; | ||
131 | aabb[1] = -dInfinity; | ||
132 | aabb[2] = dInfinity; | ||
133 | aabb[3] = -dInfinity; | ||
134 | aabb[4] = dInfinity; | ||
135 | aabb[5] = -dInfinity; | ||
136 | int i,j; | ||
137 | for (i=0; i < transformGroup->parts.size(); i++) | ||
138 | { | ||
139 | computeFinalTransformation (geom, transformGroup->parts[i]); | ||
140 | dReal aabb2[6]; | ||
141 | transformGroup->parts[i]->_class->aabb (transformGroup->parts[i],aabb2); | ||
142 | for (j=0; j<6; j += 2) if (aabb2[j] < aabb[j]) aabb[j] = aabb2[j]; | ||
143 | for (j=1; j<6; j += 2) if (aabb2[j] > aabb[j]) aabb[j] = aabb2[j]; | ||
144 | } | ||
145 | } | ||
146 | // ############################################################################ | ||
147 | |||
148 | static void dGeomTransformGroupDtor (dxGeom *geom) | ||
149 | { | ||
150 | dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(geom); | ||
151 | transformGroup->parts.~dArray(); | ||
152 | } | ||
153 | // ############################################################################ | ||
154 | |||
155 | dxGeom *dCreateGeomTransformGroup (dSpaceID space) | ||
156 | { | ||
157 | if (dGeomTransformGroupClass == -1) { | ||
158 | dGeomClass c; | ||
159 | c.bytes = sizeof (dxGeomTransformGroup); | ||
160 | c.collider = &dGeomTransformGroupColliderFn; | ||
161 | c.aabb = &dGeomTransformGroupAABB; | ||
162 | c.aabb_test = 0; | ||
163 | c.dtor = dGeomTransformGroupDtor; | ||
164 | dGeomTransformGroupClass = dCreateGeomClass (&c); | ||
165 | } | ||
166 | dxGeom *g = dCreateGeom (dGeomTransformGroupClass); | ||
167 | if (space) | ||
168 | { | ||
169 | dSpaceAdd (space,g); | ||
170 | } | ||
171 | dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(g); | ||
172 | transformGroup->parts.constructor(); | ||
173 | dSetZero (transformGroup->relativePosition,4); | ||
174 | dRSetIdentity (transformGroup->relativeRotation); | ||
175 | return g; | ||
176 | } | ||
177 | // ############################################################################ | ||
178 | |||
179 | void dGeomTransformGroupAddGeom (dxGeom *g, dxGeom *obj) | ||
180 | { | ||
181 | dUASSERT (g && g->_class->num == dGeomTransformGroupClass, | ||
182 | "argument not a geom TransformGroup"); | ||
183 | dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(g); | ||
184 | transformGroup->parts.push (obj); | ||
185 | } | ||
186 | // ############################################################################ | ||
187 | |||
188 | void dGeomTransformGroupRemoveGeom (dxGeom *g, dxGeom *obj) | ||
189 | { | ||
190 | dUASSERT (g && g->_class->num == dGeomTransformGroupClass, | ||
191 | "argument not a geom TransformGroup"); | ||
192 | dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(g); | ||
193 | for (int i=0; i < transformGroup->parts.size(); i++) { | ||
194 | if (transformGroup->parts[i] == obj) { | ||
195 | transformGroup->parts.remove (i); | ||
196 | return; | ||
197 | } | ||
198 | } | ||
199 | } | ||
200 | // ############################################################################ | ||
201 | |||
202 | dxGeom * dGeomTransformGroupGetGeom (dxGeom *g, int i) | ||
203 | { | ||
204 | dUASSERT (g && g->_class->num == dGeomTransformGroupClass, | ||
205 | "argument not a geom TransformGroup"); | ||
206 | dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(g); | ||
207 | dAASSERT (i >= 0 && i < transformGroup->parts.size()); | ||
208 | return transformGroup->parts[i]; | ||
209 | } | ||
210 | // ############################################################################ | ||
211 | |||
212 | int dGeomTransformGroupGetNumGeoms (dxGeom *g) | ||
213 | { | ||
214 | dUASSERT (g && g->_class->num == dGeomTransformGroupClass, | ||
215 | "argument not a geom TransformGroup"); | ||
216 | dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(g); | ||
217 | return transformGroup->parts.size(); | ||
218 | } | ||
diff --git a/libraries/ode-0.9/contrib/GeomTransformGroup/GeomTransformGroup.h b/libraries/ode-0.9/contrib/GeomTransformGroup/GeomTransformGroup.h new file mode 100644 index 0000000..705fdb9 --- /dev/null +++ b/libraries/ode-0.9/contrib/GeomTransformGroup/GeomTransformGroup.h | |||
@@ -0,0 +1,29 @@ | |||
1 | |||
2 | /* ************************************************************************ */ | ||
3 | /* | ||
4 | grouped and transformed geometry functions | ||
5 | author: Tim Schmidt tisch@uni-paderborn.de | ||
6 | */ | ||
7 | |||
8 | |||
9 | #ifdef __cplusplus | ||
10 | extern "C" { | ||
11 | #endif | ||
12 | |||
13 | |||
14 | extern int dGeomTransformGroupClass; | ||
15 | |||
16 | void dGeomTransformGroupSetRelativePosition (dGeomID g, dReal x, dReal y, dReal z); | ||
17 | void dGeomTransformGroupSetRelativeRotation (dGeomID g, const dMatrix3 R); | ||
18 | const dReal * dGeomTransformGroupGetRelativePosition (dxGeom *g); | ||
19 | const dReal * dGeomTransformGroupGetRelativeRotation (dxGeom *g); | ||
20 | dGeomID dCreateGeomTransformGroup (dSpaceID space); | ||
21 | void dGeomTransformGroupAddGeom (dGeomID tg, dGeomID obj); | ||
22 | void dGeomTransformGroupRemoveGeom (dGeomID tg, dGeomID obj); | ||
23 | dGeomID dGeomTransformGroupGetGeom (dGeomID tg, int i); | ||
24 | int dGeomTransformGroupGetNumGeoms (dGeomID tg); | ||
25 | |||
26 | |||
27 | #ifdef __cplusplus | ||
28 | } | ||
29 | #endif | ||
diff --git a/libraries/ode-0.9/contrib/GeomTransformGroup/README.txt b/libraries/ode-0.9/contrib/GeomTransformGroup/README.txt new file mode 100644 index 0000000..bca0e66 --- /dev/null +++ b/libraries/ode-0.9/contrib/GeomTransformGroup/README.txt | |||
@@ -0,0 +1,148 @@ | |||
1 | README for GeomTransformGroup by Tim Schmidt. | ||
2 | --------------------------------------------- | ||
3 | |||
4 | This is a patch to add the dGeomTransformGroup object to the list of geometry | ||
5 | objects. | ||
6 | |||
7 | It should work with the cvs version of the ode library from 07/24/2002. | ||
8 | |||
9 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | ||
10 | |||
11 | comment by russ smith: this code is easy to use with the rest of ODE. | ||
12 | simply copy GeomTransformGroup.cpp to ode/src and copy GeomTransformGroup.h | ||
13 | to include/ode. then add GeomTransformGroup.cpp to the ODE_SRC variable | ||
14 | in the makefile. rebuild, and you're done! of course i could have done all | ||
15 | this for you, but i prefer to keep GeomTransformGroup separated from the | ||
16 | rest of ODE for now while other issues with the collision system are | ||
17 | resolved. | ||
18 | |||
19 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | ||
20 | |||
21 | |||
22 | Description: | ||
23 | |||
24 | The dGeomTransformGroup is an adaption of the TransformGroup known from | ||
25 | Java3D (and maybe other libraries with a similar scene graph representation). | ||
26 | It can be used to build an arbitrarily structured tree of objects that are | ||
27 | each positioned relative to the particular parent node. | ||
28 | |||
29 | If you have a plane for example, there is one root node associated with the | ||
30 | plane's body and another three transformgroups placed 'under' this node. One | ||
31 | with the fuselage (cappedcylinder) under it and two with the underlying wings | ||
32 | (flat boxes). And if you want to add engines, simply put them 'next to' the | ||
33 | wings under another two transformgroups. | ||
34 | |||
35 | bodyTG ---> associated with dBody | ||
36 | | | ||
37 | +--fuselageTG | ||
38 | | | | ||
39 | | +--fuselageCylinder | ||
40 | | | ||
41 | +--leftwingTG | ||
42 | | | | ||
43 | | +--wingBox | ||
44 | | | | ||
45 | | +--leftengineTG | ||
46 | | | | ||
47 | | +--leftengineCylinder | ||
48 | | | ||
49 | +--rightwingTG | ||
50 | | | ||
51 | +--wingBox | ||
52 | | | ||
53 | +--rightengineTG | ||
54 | | | ||
55 | +--rightengineCylinder | ||
56 | |||
57 | This is a method to easily compose objects without the necessity of always | ||
58 | calculating global coordinates. But apart from this there is something else | ||
59 | that makes dGeomTransformGroups very valuable. | ||
60 | |||
61 | Maybe you remember that some users reported the problem of acquiring the | ||
62 | correct bodies to be attached by a contactjoint in the nearCallback when | ||
63 | using dGeomGroups and dGeomTransforms at the same time. This results from the | ||
64 | fact that dGeomGroups are not associated with bodies while all other | ||
65 | geometries are. | ||
66 | |||
67 | So, as you can see in the nearCallback of the the test_buggy demo you have to | ||
68 | attach the contactjoint with the bodies that you get from the geometries that | ||
69 | are stored in the contact struct (-> dGeomGetBody(contacts[i].geom.g1)). | ||
70 | Normally you would do this by asking o1 and o2 directly with dGeomGetBody(o1) | ||
71 | and dGeomGetBody(o2) respectively. | ||
72 | |||
73 | As a first approach you can overcome that problem by testing o1 and o2 if | ||
74 | they are groups or not to find out how to get the corresponding bodies. | ||
75 | |||
76 | However this will fail if you want grouped transforms that are constructed | ||
77 | out of dGeomTransforms encapsulated in a dGeomGroup. According to the test | ||
78 | you use contacts[i].geom.g1 to get the right body. Unfortunately g1 is | ||
79 | encapsulated in a transform and therefore not attached to any body. In this | ||
80 | case the dGeomTransform 'in the middle' would have been the right object to | ||
81 | be asked for the body. | ||
82 | |||
83 | You may now conclude that it is a good idea to unwrap the group encapsulated | ||
84 | geoms at the beginning of the nearcallback and use dGeomGetBody(o1) | ||
85 | consistently. But keep in mind that this also means not to invoke | ||
86 | dCollide(..) on groups at all and therefore not to expoit the capability of | ||
87 | dGeomGroups to speed up collision detection by the creation of bounding boxes | ||
88 | around the encapsulated geometry. | ||
89 | |||
90 | Everything becomes even worse if you create a dGeomTransform that contains a | ||
91 | dGeomGroup of geoms. The function that cares about the collision of | ||
92 | transforms with other objects uses the position and rotation of the | ||
93 | respective encapsulated object to compute its final position and orientation. | ||
94 | Unfortunately dGeomGroups do not have a position and rotation, so the result | ||
95 | will not be what you have expected. | ||
96 | |||
97 | Here the dGeomTransformGroups comes into operation, because it combines the | ||
98 | advantages and capabilities of the dGeomGroup and the dGeomTransform. | ||
99 | And as an effect of synergy it is now even possible to set the position of a | ||
100 | group of geoms with one single command. | ||
101 | Even nested encapsulations of dGeomTransformGroups in dGeomTransformGroups | ||
102 | should be possible (to be honest, I have not tried that so far ;-) ). | ||
103 | |||
104 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | ||
105 | |||
106 | API: | ||
107 | |||
108 | dGeomID dCreateGeomTransformGroup (dSpaceID space); | ||
109 | - create a GeomTransformGroup | ||
110 | |||
111 | void dGeomTransformGroupAddGeom (dGeomID tg, dGeomID obj); | ||
112 | - Comparable to dGeomTransformSetGeom or dGeomGroupAdd | ||
113 | - add objects to this group | ||
114 | |||
115 | void dGeomTransformGroupRemoveGeom (dGeomID tg, dGeomID obj); | ||
116 | - remove objects from this group | ||
117 | |||
118 | void dGeomTransformGroupSetRelativePosition | ||
119 | (dGeomID g, dReal x, dReal y, dReal z); | ||
120 | void dGeomTransformGroupSetRelativeRotation | ||
121 | (dGeomID g, const dMatrix3 R); | ||
122 | - Comparable to setting the position and rotation of all the | ||
123 | dGeomTransform encapsulated geometry. The difference | ||
124 | is that it is global with respect to this group and therefore | ||
125 | affects all geoms in this group. | ||
126 | - The relative position and rotation are attributes of the | ||
127 | transformgroup, so the position and rotation of the individual | ||
128 | geoms are not changed | ||
129 | |||
130 | const dReal * dGeomTransformGroupGetRelativePosition (dGeomID g); | ||
131 | const dReal * dGeomTransformGroupGetRelativeRotation (dGeomID g); | ||
132 | - get the relative position and rotation | ||
133 | |||
134 | dGeomID dGeomTransformGroupGetGeom (dGeomID tg, int i); | ||
135 | - Comparable to dGeomGroupGetGeom | ||
136 | - get a specific geom of the group | ||
137 | |||
138 | int dGeomTransformGroupGetNumGeoms (dGeomID tg); | ||
139 | - Comparable to dGeomGroupGetNumGeoms | ||
140 | - get the number of geoms in the group | ||
141 | |||
142 | |||
143 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | ||
144 | |||
145 | Tim Schmidt | ||
146 | student of computer science | ||
147 | University of Paderborn, Germany | ||
148 | tisch@uni-paderborn.de | ||
diff --git a/libraries/ode-0.9/contrib/Mac_CFMCarbon/CW7_projects.sit.bin b/libraries/ode-0.9/contrib/Mac_CFMCarbon/CW7_projects.sit.bin new file mode 100644 index 0000000..c06768c --- /dev/null +++ b/libraries/ode-0.9/contrib/Mac_CFMCarbon/CW7_projects.sit.bin | |||
Binary files differ | |||
diff --git a/libraries/ode-0.9/contrib/Mac_CFMCarbon/README.txt b/libraries/ode-0.9/contrib/Mac_CFMCarbon/README.txt new file mode 100644 index 0000000..7c1f8a4 --- /dev/null +++ b/libraries/ode-0.9/contrib/Mac_CFMCarbon/README.txt | |||
@@ -0,0 +1,95 @@ | |||
1 | ----------------------------- | ||
2 | ODE - Mac CFM Carbon Port | ||
3 | (contact Frank Condello <pox@planetquake.com> with questions regarding this port) | ||
4 | |||
5 | Although ODE contains a MacOSX makefile, and some individuals have implemented ODE in | ||
6 | Cocoa, I opted to use (and prefer) CodeWarrior. This also opens up ODE to MacOS8 & 9 | ||
7 | users, without scarfing functionality in MacOSX (same binaries run on both platforms). | ||
8 | |||
9 | The 'ode_CW7.mcp' project contains release and debug targets to create static ODE and | ||
10 | DrawStuff libraries. | ||
11 | |||
12 | 'examples_CW7.mcp' contains targets for the entire ODE test suite, plus a couple other | ||
13 | test programs which were posted to the ODE mailing list. | ||
14 | |||
15 | |||
16 | ----------------------------- | ||
17 | Compiling Notes: | ||
18 | |||
19 | You'll need to extract the CodeWarrior projects from the 'CW7_projects.sit.bin' archive | ||
20 | (They're nearly a meg uncompressed so this was done to be bandwith friendly on the CVS). | ||
21 | |||
22 | Projects require CodeWarrior 7 or above (recreating them with earlier versions shouldn't | ||
23 | be too difficult). The projects use relative paths and are meant to be compiled from | ||
24 | 'contrib/Mac_CFMCarbon/'. Don't move them! | ||
25 | |||
26 | All the libraries build into the 'lib/' directory, all test applications build into | ||
27 | 'contrib/Mac_CFMCarbon/mac_testbin/' (and must be run from that directory since the | ||
28 | texture path is hard-coded). | ||
29 | |||
30 | You'll need to compile the release ODE library, and the DrawStuff library before | ||
31 | compiling the examples. | ||
32 | |||
33 | The ODE 'configurator' has not been ported, but a Mac-friendly 'config.h' header has been | ||
34 | manually hacked together (all PPC Macs should be fine with this header). Single or double | ||
35 | precision can be defined in the 'CommonPrefix.h' header found in | ||
36 | 'contrib/Mac_CFMCarbon/mac_source/'. | ||
37 | |||
38 | 'contrib/Mac_CFMCarbon/mac_source/' also contains any mac specific additions to the main source. | ||
39 | The directory structure here matches the main source tree, and I would recommend that this | ||
40 | format is maintained when making additions, since the access paths are touchy (more below...) | ||
41 | |||
42 | Some issues were encountered with duplicate header names. CodeWarrior tends to be | ||
43 | unforgiving about this sort of thing but fudging with the access paths eventually | ||
44 | cleared up the problem. If ODE fails to compile, make sure the <ode/objects.h> and | ||
45 | "objects.h" or <timer.h> and <Timer.h> are actually pointing to the correct header. | ||
46 | |||
47 | You'll need Apple's OpenGL SDK (with GLUT) in your compiler path to build DrawStuff. I've | ||
48 | added redirection headers in 'contrib/Mac_CFMCarbon/mac_source/include/GL/' to properly | ||
49 | link with the Apple headers (since the projects are set to follow DOS paths). | ||
50 | |||
51 | The examples link against a crapload of static libraries, but my initial builds using | ||
52 | ODE, MSL, GLUT, and DrawStuff shared/merged DLL's proved unstable (mostly problems with | ||
53 | SIOUX spawning multiple sessions, and crashes in Classic). Static libs just worked better | ||
54 | in the end, but the test apps are a little bloated as a result, and need to be re-linked | ||
55 | whenever a change to a library is made. | ||
56 | |||
57 | IMPORTANT: You must use the same 'CommonPrefix.h' settings for libraries, and test apps | ||
58 | (i.e. double or single precision). | ||
59 | |||
60 | |||
61 | ----------------------------- | ||
62 | Running the test apps: | ||
63 | |||
64 | The test apps will show the SIOUX CLI prompt when run. Just hit OK to ignore it, or add any | ||
65 | DrawStuff arguments. You'll want to log output to a file for 'test_ode'. | ||
66 | |||
67 | There are two extra test programs in the 'mac_source' directory. Both were posted to the ODE | ||
68 | mailing list by OSX users. 'test_stability1' visualizes some internal issues with ODE, and | ||
69 | 'test_stacktest' is a standalone GLUT program (doesn't use DrawStuff) that can be useful | ||
70 | to stress test the library, and give you an idea of just how much stack memory you're | ||
71 | going to need for large systems. | ||
72 | |||
73 | ISSUES: | ||
74 | |||
75 | The carbon DrawStuff lib uses GLUT to make life easy, but GLUT isn't exactly bug-free | ||
76 | or stable on the Mac... Try moving the mouse around if a simulation is running slowly | ||
77 | on OS9 (it's not ODE's fault, but rather a poor carbon GLUT implementation - seems GLUT stalls | ||
78 | when it's not getting system events - I haven't seen this problem on OSX). | ||
79 | |||
80 | The 3D view may not update if typing in the SIOUX console window. | ||
81 | |||
82 | You cannot pass startup args to GLUT due to the way the DrawStuff library initializes. | ||
83 | |||
84 | 'Write Frames' doesn't actually do anything at the moment. | ||
85 | |||
86 | The 'test_joints' app seems broken (though I don't know what the intended effect should be) | ||
87 | |||
88 | |||
89 | ----------------------------- | ||
90 | TODO: | ||
91 | |||
92 | - Re-add shared library targets (if stability issues are resolved). | ||
93 | - Implement 'Write Frames' in DrawStuff. | ||
94 | - Write a Carbon compatible configurator | ||
95 | - Create CodeWarrior 8 projects (once I scrounge up enough dough for the update). \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/CommonPrefix.h b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/CommonPrefix.h new file mode 100644 index 0000000..5948b3e --- /dev/null +++ b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/CommonPrefix.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #define TARGET_API_MAC_CARBON 1 | ||
2 | #define finite isfinite | ||
3 | #define dNODEBUG 1 | ||
4 | |||
5 | // Comment out for single precision | ||
6 | #define PRECISION_DOUBLE 1 \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/DSPrefix.h b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/DSPrefix.h new file mode 100644 index 0000000..6122528 --- /dev/null +++ b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/DSPrefix.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef prefix_h | ||
2 | #define prefix_h | ||
3 | |||
4 | #include "CommonPrefix.h" | ||
5 | |||
6 | #endif // prefix_h \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/DebugPrefix.h b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/DebugPrefix.h new file mode 100644 index 0000000..0e328a9 --- /dev/null +++ b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/DebugPrefix.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef prefix_h | ||
2 | #define prefix_h | ||
3 | |||
4 | #include "CommonPrefix.h" | ||
5 | |||
6 | #ifdef dNODEBUG | ||
7 | #undef dNODEBUG | ||
8 | #endif | ||
9 | |||
10 | #endif // prefix_h \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ExamplesPrefix.h b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ExamplesPrefix.h new file mode 100644 index 0000000..1dedfc9 --- /dev/null +++ b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ExamplesPrefix.h | |||
@@ -0,0 +1,13 @@ | |||
1 | #ifndef prefix_h | ||
2 | #define prefix_h | ||
3 | |||
4 | #include "CommonPrefix.h" | ||
5 | |||
6 | // Hack to automatically call SIOUX's CLI interface for the test apps | ||
7 | #include <console.h> | ||
8 | #include <SIOUX.h> | ||
9 | int fmain (int argc, char **argv); | ||
10 | int main (int argc, char **argv) { argc = ccommand(&argv); return fmain(argc, argv); } | ||
11 | #define main(argc, argv) fmain(argc, argv) | ||
12 | |||
13 | #endif // prefix_h \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ODETestPrefix.h b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ODETestPrefix.h new file mode 100644 index 0000000..f8f5022 --- /dev/null +++ b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ODETestPrefix.h | |||
@@ -0,0 +1,13 @@ | |||
1 | #ifndef prefix_h | ||
2 | #define prefix_h | ||
3 | |||
4 | #include "CommonPrefix.h" | ||
5 | |||
6 | // Hack to automatically call SIOUX's CLI interface for the test apps | ||
7 | #include <console.h> | ||
8 | #include <SIOUX.h> | ||
9 | int fmain (); | ||
10 | int main (int argc, char **argv) { argc = ccommand(&argv); return fmain(); } | ||
11 | #define main() fmain() | ||
12 | |||
13 | #endif // prefix_h \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ReleasePrefix.h b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ReleasePrefix.h new file mode 100644 index 0000000..6122528 --- /dev/null +++ b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ReleasePrefix.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef prefix_h | ||
2 | #define prefix_h | ||
3 | |||
4 | #include "CommonPrefix.h" | ||
5 | |||
6 | #endif // prefix_h \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/drawstuff/src/mac_glut_carbon.cpp b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/drawstuff/src/mac_glut_carbon.cpp new file mode 100644 index 0000000..eb0b144 --- /dev/null +++ b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/drawstuff/src/mac_glut_carbon.cpp | |||
@@ -0,0 +1,281 @@ | |||
1 | /************************************************************************* | ||
2 | * * | ||
3 | * DrawStuff Library, Copyright (C) 2001 Russell L. Smith. * | ||
4 | * Email: russ@q12.org Web: www.q12.org * | ||
5 | * * | ||
6 | * This library is free software; you can redistribute it and/or * | ||
7 | * modify it under the terms of the GNU Lesser General Public * | ||
8 | * License as published by the Free Software Foundation; either * | ||
9 | * version 2.1 of the License, or (at your option) any later version. * | ||
10 | * * | ||
11 | * This library is distributed in the hope that it will be useful, * | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * | ||
14 | * Lesser General Public License for more details. * | ||
15 | * * | ||
16 | * You should have received a copy of the GNU Lesser General Public * | ||
17 | * License along with this library (see the file LICENSE.TXT); if not, * | ||
18 | * write to the Free Software Foundation, Inc., 59 Temple Place, * | ||
19 | * Suite 330, Boston, MA 02111-1307 USA. * | ||
20 | * * | ||
21 | *************************************************************************/ | ||
22 | |||
23 | // main window and event handling for Mac CFM Carbon | ||
24 | |||
25 | #include <ode/config.h> | ||
26 | #include <stdlib.h> | ||
27 | #include <string.h> | ||
28 | #include <stdarg.h> | ||
29 | #include <stdio.h> | ||
30 | #include <glut.h> | ||
31 | #include <SIOUX.h> | ||
32 | |||
33 | #include <MacTypes.h> | ||
34 | #include <Timer.h> | ||
35 | |||
36 | #include <drawstuff/drawstuff.h> | ||
37 | #include <drawstuff/version.h> | ||
38 | #include "internal.h" | ||
39 | |||
40 | |||
41 | //*************************************************************************** | ||
42 | // error handling for unix (works just fine with SIOUX) | ||
43 | |||
44 | static void printMessage (char *msg1, char *msg2, va_list ap) | ||
45 | { | ||
46 | fflush (stderr); | ||
47 | fflush (stdout); | ||
48 | fprintf (stderr,"\n%s: ",msg1); | ||
49 | vfprintf (stderr,msg2,ap); | ||
50 | fprintf (stderr,"\n"); | ||
51 | fflush (stderr); | ||
52 | } | ||
53 | |||
54 | extern "C" void dsError (char *msg, ...) | ||
55 | { | ||
56 | va_list ap; | ||
57 | va_start (ap,msg); | ||
58 | printMessage ("Error",msg,ap); | ||
59 | exit (1); | ||
60 | } | ||
61 | |||
62 | |||
63 | extern "C" void dsDebug (char *msg, ...) | ||
64 | { | ||
65 | va_list ap; | ||
66 | va_start (ap,msg); | ||
67 | printMessage ("INTERNAL ERROR",msg,ap); | ||
68 | // *((char *)0) = 0; ... commit SEGVicide ? | ||
69 | abort(); | ||
70 | } | ||
71 | |||
72 | extern "C" void dsPrint (char *msg, ...) | ||
73 | { | ||
74 | va_list ap; | ||
75 | va_start (ap,msg); | ||
76 | vprintf (msg,ap); | ||
77 | } | ||
78 | |||
79 | //*************************************************************************** | ||
80 | // openGL window | ||
81 | |||
82 | // window and openGL | ||
83 | static int width=0,height=0; // window size | ||
84 | static int last_key_pressed=0; // last key pressed in the window | ||
85 | static int pause=0; // 1 if in `pause' mode | ||
86 | static int singlestep=0; // 1 if single step key pressed | ||
87 | static int writeframes=0; // 1 if frame files to be written | ||
88 | static dsFunctions *gfn; | ||
89 | static int frame = 1; | ||
90 | |||
91 | float getTime (void) | ||
92 | { | ||
93 | UnsignedWide ms; | ||
94 | |||
95 | Microseconds(&ms); | ||
96 | return ms.lo / 1000000.0; | ||
97 | } | ||
98 | |||
99 | |||
100 | static void captureFrame (int num) | ||
101 | { | ||
102 | // TODO | ||
103 | } | ||
104 | |||
105 | static void reshape(int w, int h) | ||
106 | { | ||
107 | width = w; | ||
108 | height = h; | ||
109 | } | ||
110 | |||
111 | static void draw(void) | ||
112 | { | ||
113 | dsDrawFrame (width,height,gfn,pause && !singlestep); | ||
114 | singlestep = 0; | ||
115 | glutSwapBuffers(); | ||
116 | |||
117 | if (pause==0 && writeframes) { | ||
118 | captureFrame (frame); | ||
119 | frame++; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | static void idle(void) | ||
124 | { | ||
125 | static float lasttime=0; | ||
126 | float t; | ||
127 | |||
128 | // Try to maintain a reasonable rate (good enough for testing anyway) | ||
129 | t = getTime(); | ||
130 | if (lasttime < t) { | ||
131 | lasttime = t+0.005; | ||
132 | draw(); | ||
133 | } | ||
134 | } | ||
135 | |||
136 | static void key(unsigned char key, int x, int y) | ||
137 | { | ||
138 | if (!glutGetModifiers()) { | ||
139 | |||
140 | if (key >= ' ' && key <= 126 && gfn->command) gfn->command (key); | ||
141 | |||
142 | // GLUT_ACTIVE_CTRL doesn't seem to be working, so we use Alt | ||
143 | } else if (glutGetModifiers()&GLUT_ACTIVE_ALT) { | ||
144 | |||
145 | switch (key) { | ||
146 | case 't': case 'T': | ||
147 | dsSetTextures (dsGetTextures() ^ 1); | ||
148 | break; | ||
149 | case 's': case 'S': | ||
150 | dsSetShadows (dsGetShadows() ^ 1); | ||
151 | break; | ||
152 | case 'p': case 'P': | ||
153 | pause ^= 1; | ||
154 | singlestep = 0; | ||
155 | break; | ||
156 | case 'o': case 'O': | ||
157 | if (pause) singlestep = 1; | ||
158 | break; | ||
159 | case 'v': case 'V': { | ||
160 | float xyz[3],hpr[3]; | ||
161 | dsGetViewpoint (xyz,hpr); | ||
162 | printf ("Viewpoint = (%.4f,%.4f,%.4f,%.4f,%.4f,%.4f)\n", | ||
163 | xyz[0],xyz[1],xyz[2],hpr[0],hpr[1],hpr[2]); | ||
164 | break; | ||
165 | } | ||
166 | // No case 'X' - Quit works through the Mac system menu, or cmd-q | ||
167 | case 'w': case 'W': | ||
168 | writeframes ^= 1; | ||
169 | if (writeframes) printf ("Write frames not done yet!\n");// TODO | ||
170 | break; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | last_key_pressed = key; | ||
175 | } | ||
176 | |||
177 | static int mx=0,my=0; // mouse position | ||
178 | static int mode = 0; // mouse button bits | ||
179 | |||
180 | static void MouseDown(int button, int state, int x, int y) | ||
181 | { | ||
182 | if(button == GLUT_LEFT_BUTTON) | ||
183 | { | ||
184 | if(state == GLUT_DOWN) | ||
185 | mode |= 1; | ||
186 | else if(state == GLUT_UP) | ||
187 | mode &= (~1); | ||
188 | } | ||
189 | else if (button == GLUT_MIDDLE_BUTTON) | ||
190 | { | ||
191 | if(state == GLUT_DOWN) | ||
192 | mode |= 3; | ||
193 | else if(state == GLUT_UP) | ||
194 | mode &= (~3); | ||
195 | } | ||
196 | else if (button == GLUT_RIGHT_BUTTON) | ||
197 | { | ||
198 | if(state == GLUT_DOWN) | ||
199 | mode |= 2; | ||
200 | else if(state == GLUT_UP) | ||
201 | mode &= (~2); | ||
202 | } | ||
203 | |||
204 | mx = x; | ||
205 | my = y; | ||
206 | } | ||
207 | |||
208 | static void MouseMove(int x, int y) | ||
209 | { | ||
210 | dsMotion (mode, x - mx, y - my); | ||
211 | mx = x; | ||
212 | my = y; | ||
213 | } | ||
214 | |||
215 | static void createMainWindow (int _width, int _height) | ||
216 | { | ||
217 | // So GLUT doesn't complain | ||
218 | int argc = 0; | ||
219 | char **argv = NULL; | ||
220 | |||
221 | // initialize variables | ||
222 | width = _width; | ||
223 | height = _height; | ||
224 | last_key_pressed = 0; | ||
225 | |||
226 | if (width < 1 || height < 1) dsDebug (0,"bad window width or height"); | ||
227 | |||
228 | glutInit(&argc, argv); | ||
229 | glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); | ||
230 | glutInitWindowSize(_width, _height); | ||
231 | glutInitWindowPosition(100, 100); | ||
232 | glutCreateWindow("ODE Simulation"); | ||
233 | |||
234 | glutKeyboardFunc(key); | ||
235 | glutMotionFunc(MouseMove); | ||
236 | glutMouseFunc(MouseDown); | ||
237 | glutReshapeFunc(reshape); | ||
238 | glutDisplayFunc(idle); | ||
239 | glutIdleFunc(idle); | ||
240 | } | ||
241 | |||
242 | void dsPlatformSimLoop (int window_width, int window_height, dsFunctions *fn, | ||
243 | int initial_pause) | ||
244 | { | ||
245 | SIOUXSettings.initializeTB = false; | ||
246 | SIOUXSettings.standalone = false; | ||
247 | SIOUXSettings.setupmenus = false; | ||
248 | SIOUXSettings.autocloseonquit = true; | ||
249 | SIOUXSettings.asktosaveonclose = false; | ||
250 | |||
251 | gfn = fn; | ||
252 | pause = initial_pause; | ||
253 | |||
254 | printf ( | ||
255 | "\n" | ||
256 | "Simulation test environment v%d.%02d\n" | ||
257 | " Option-P : pause / unpause (or say `-pause' on command line).\n" | ||
258 | " Option-O : single step when paused.\n" | ||
259 | " Option-T : toggle textures (or say `-notex' on command line).\n" | ||
260 | " Option-S : toggle shadows (or say `-noshadow' on command line).\n" | ||
261 | " Option-V : print current viewpoint coordinates (x,y,z,h,p,r).\n" | ||
262 | " Option-W : write frames to ppm files: frame/frameNNN.ppm\n" | ||
263 | "\n" | ||
264 | "Change the camera position by clicking + dragging in the window.\n" | ||
265 | " Left button - pan and tilt.\n" | ||
266 | " Right button - forward and sideways.\n" | ||
267 | " Left + Right button (or middle button) - sideways and up.\n" | ||
268 | "\n",DS_VERSION >> 8,DS_VERSION & 0xff); | ||
269 | |||
270 | createMainWindow (window_width, window_height); | ||
271 | dsStartGraphics (window_width,window_height,fn); | ||
272 | |||
273 | if (fn->start) fn->start(); | ||
274 | |||
275 | glutMainLoop(); | ||
276 | |||
277 | if (fn->stop) fn->stop(); | ||
278 | dsStopGraphics(); | ||
279 | } | ||
280 | |||
281 | extern "C" void dsStop(){ }// GLUT/MSL hooks into the system to exit | ||
diff --git a/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/include/GL/gl.h b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/include/GL/gl.h new file mode 100644 index 0000000..4acaeed --- /dev/null +++ b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/include/GL/gl.h | |||
@@ -0,0 +1,2 @@ | |||
1 | // A little hackaround (Apple use / in the FILENAME, which doesn't work when following DOS paths) | ||
2 | #include <gl.h> \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/include/GL/glu.h b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/include/GL/glu.h new file mode 100644 index 0000000..5b4a791 --- /dev/null +++ b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/include/GL/glu.h | |||
@@ -0,0 +1,2 @@ | |||
1 | // A little hackaround (Apple use / in the FILENAME, which doesn't work when following DOS paths) | ||
2 | #include <glu.h> \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/include/ode/config.h b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/include/ode/config.h new file mode 100644 index 0000000..bb889f9 --- /dev/null +++ b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/include/ode/config.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* This file has been manually hacked together for the Mac CFM Carbon build - Frank. */ | ||
2 | |||
3 | #ifndef _ODE_CONFIG_H_ | ||
4 | #define _ODE_CONFIG_H_ | ||
5 | |||
6 | /* standard system headers */ | ||
7 | #include <stdio.h> | ||
8 | #include <stdlib.h> | ||
9 | #include <math.h> | ||
10 | #include <string.h> | ||
11 | #include <stdarg.h> | ||
12 | #include <malloc.h> | ||
13 | #include <alloca.h> | ||
14 | #include <float.h> | ||
15 | |||
16 | #ifdef __cplusplus | ||
17 | extern "C" { | ||
18 | #endif | ||
19 | |||
20 | /* #define PENTIUM 1 -- not a pentium */ | ||
21 | |||
22 | /* integer types (we assume int >= 32 bits) */ | ||
23 | typedef char int8; | ||
24 | typedef unsigned char uint8; | ||
25 | typedef int int32; | ||
26 | typedef unsigned int uint32; | ||
27 | |||
28 | /* an integer type that we can safely cast a pointer to and from without loss of bits. */ | ||
29 | typedef unsigned int intP; | ||
30 | |||
31 | #ifdef PRECISION_DOUBLE | ||
32 | |||
33 | /*select the base floating point type*/ | ||
34 | #define dDOUBLE 1 | ||
35 | |||
36 | /* the floating point infinity */ | ||
37 | #define dInfinity DBL_MAX | ||
38 | |||
39 | #else | ||
40 | |||
41 | /* select the base floating point type */ | ||
42 | #define dSINGLE 1 | ||
43 | |||
44 | /* the floating point infinity */ | ||
45 | #define dInfinity FLT_MAX | ||
46 | |||
47 | #endif | ||
48 | |||
49 | #ifdef __cplusplus | ||
50 | } | ||
51 | #endif | ||
52 | #endif \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ode/test/test_stability1.cpp b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ode/test/test_stability1.cpp new file mode 100644 index 0000000..79c066a --- /dev/null +++ b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ode/test/test_stability1.cpp | |||
@@ -0,0 +1,289 @@ | |||
1 | /************************************************************************* | ||
2 | * * | ||
3 | * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * | ||
4 | * All rights reserved. Email: russ@q12.org Web: www.q12.org * | ||
5 | * * | ||
6 | * This library is free software; you can redistribute it and/or * | ||
7 | * modify it under the terms of EITHER: * | ||
8 | * (1) The GNU Lesser General Public License as published by the Free * | ||
9 | * Software Foundation; either version 2.1 of the License, or (at * | ||
10 | * your option) any later version. The text of the GNU Lesser * | ||
11 | * General Public License is included with this library in the * | ||
12 | * file LICENSE.TXT. * | ||
13 | * (2) The BSD-style license that is included with this library in * | ||
14 | * the file LICENSE-BSD.TXT. * | ||
15 | * * | ||
16 | * This library is distributed in the hope that it will be useful, * | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * | ||
19 | * LICENSE.TXT and LICENSE-BSD.TXT for more details. * | ||
20 | * * | ||
21 | *************************************************************************/ | ||
22 | |||
23 | #include <ode/ode.h> | ||
24 | #include <drawstuff/drawstuff.h> | ||
25 | |||
26 | #ifdef _MSC_VER | ||
27 | #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints | ||
28 | #endif | ||
29 | |||
30 | // select correct drawing functions | ||
31 | |||
32 | #ifdef dDOUBLE | ||
33 | #define dsDrawBox dsDrawBoxD | ||
34 | #define dsDrawSphere dsDrawSphereD | ||
35 | #define dsDrawCylinder dsDrawCylinderD | ||
36 | #define dsDrawCappedCylinder dsDrawCappedCylinderD | ||
37 | #endif | ||
38 | |||
39 | |||
40 | // some constants | ||
41 | |||
42 | #define DENSITY (5.0) // density of all objects | ||
43 | |||
44 | // dynamics and collision objects | ||
45 | |||
46 | struct MyObject { | ||
47 | dBodyID body; // the body | ||
48 | dGeomID geom; // geometry representing this body | ||
49 | }; | ||
50 | |||
51 | static dWorldID world; | ||
52 | static dSpaceID space; | ||
53 | static MyObject fallingObject; | ||
54 | static dGeomID box1, box2; | ||
55 | static dJointGroupID contactgroup; | ||
56 | |||
57 | |||
58 | // this is called by dSpaceCollide when two objects in space are | ||
59 | // potentially colliding. | ||
60 | |||
61 | static void nearCallback (void *data, dGeomID o1, dGeomID o2) | ||
62 | { | ||
63 | int i; | ||
64 | // if (o1->body && o2->body) return; | ||
65 | |||
66 | // exit without doing anything if the two bodies are connected by a joint | ||
67 | dBodyID b1 = dGeomGetBody(o1); | ||
68 | dBodyID b2 = dGeomGetBody(o2); | ||
69 | if (b1 && b2 && dAreConnected (b1,b2)) return; | ||
70 | |||
71 | dContact contact[4]; // up to 3 contacts per box | ||
72 | for (i=0; i<4; i++) { | ||
73 | contact[i].surface.mode = dContactBounce; //dContactMu2; | ||
74 | contact[i].surface.mu = dInfinity; | ||
75 | contact[i].surface.mu2 = 0; | ||
76 | contact[i].surface.bounce = 0.5; | ||
77 | contact[i].surface.bounce_vel = 0.1; | ||
78 | } | ||
79 | if (int numc = dCollide (o1,o2,4,&contact[0].geom,sizeof(dContact))) { | ||
80 | // dMatrix3 RI; | ||
81 | // dRSetIdentity (RI); | ||
82 | // const dReal ss[3] = {0.02,0.02,0.02}; | ||
83 | for (i=0; i<numc; i++) { | ||
84 | dJointID c = dJointCreateContact (world,contactgroup,contact+i); | ||
85 | dJointAttach (c,b1,b2); | ||
86 | // dsDrawBox (contact[i].geom.pos,RI,ss); | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | |||
91 | |||
92 | // start simulation - set viewpoint | ||
93 | |||
94 | static void start() | ||
95 | { | ||
96 | static float xyz[3] = {-4.0f, 0.0f, 3.0f}; | ||
97 | static float hpr[3] = {0.0f,-15.0f,0.0f}; | ||
98 | dsSetViewpoint (xyz,hpr); | ||
99 | printf ("To drop another object, press:\n"); | ||
100 | printf (" b for box.\n"); | ||
101 | printf (" s for sphere.\n"); | ||
102 | printf (" c for cylinder.\n"); | ||
103 | printf ("To select an object, press space.\n"); | ||
104 | } | ||
105 | |||
106 | |||
107 | char locase (char c) | ||
108 | { | ||
109 | if (c >= 'A' && c <= 'Z') return c - ('a'-'A'); | ||
110 | else return c; | ||
111 | } | ||
112 | |||
113 | |||
114 | // called when a key pressed | ||
115 | |||
116 | static void command (int cmd) | ||
117 | { | ||
118 | int i,k; | ||
119 | dReal sides[3]; | ||
120 | dMass m; | ||
121 | |||
122 | cmd = locase (cmd); | ||
123 | if (cmd == 'b' || cmd == 's' || cmd == 'c') { | ||
124 | // Destroy the currently falling object and replace it by an instance of the requested type | ||
125 | if (fallingObject.body) { | ||
126 | dBodyDestroy (fallingObject.body); | ||
127 | dGeomDestroy (fallingObject.geom); | ||
128 | memset (&fallingObject, 0, sizeof(fallingObject)); | ||
129 | } | ||
130 | |||
131 | fallingObject.body = dBodyCreate (world); | ||
132 | for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1; | ||
133 | |||
134 | // Start out centered above the V-gap | ||
135 | dBodySetPosition (fallingObject.body, 0,0,5); | ||
136 | |||
137 | #if 0 | ||
138 | dMatrix3 R; | ||
139 | dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0, | ||
140 | dRandReal()*2.0-1.0,dRandReal()*10.0-5.0); | ||
141 | dBodySetRotation (fallingObject.body,R); | ||
142 | dBodySetData (fallingObject.body,(void*) i); | ||
143 | #endif | ||
144 | |||
145 | if (cmd == 'b') { | ||
146 | dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]); | ||
147 | fallingObject.geom = dCreateBox (space,sides[0],sides[1],sides[2]); | ||
148 | } | ||
149 | else if (cmd == 'c') { | ||
150 | sides[0] *= 0.5; | ||
151 | dMassSetCappedCylinder (&m,DENSITY,3,sides[0],sides[1]); | ||
152 | fallingObject.geom = dCreateCCylinder (space,sides[0],sides[1]); | ||
153 | } | ||
154 | else if (cmd == 's') { | ||
155 | sides[0] *= 0.5; | ||
156 | dMassSetSphere (&m,DENSITY,sides[0]); | ||
157 | fallingObject.geom = dCreateSphere (space,sides[0]); | ||
158 | } | ||
159 | |||
160 | dGeomSetBody (fallingObject.geom,fallingObject.body); | ||
161 | |||
162 | dBodySetMass (fallingObject.body,&m); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | |||
167 | // draw a geom | ||
168 | |||
169 | void drawGeom (dGeomID g, const dReal *pos, const dReal *R) | ||
170 | { | ||
171 | if (!g) return; | ||
172 | if (!pos) pos = dGeomGetPosition (g); | ||
173 | if (!R) R = dGeomGetRotation (g); | ||
174 | |||
175 | int type = dGeomGetClass (g); | ||
176 | if (type == dBoxClass) { | ||
177 | dVector3 sides; | ||
178 | dGeomBoxGetLengths (g,sides); | ||
179 | dsDrawBox (pos,R,sides); | ||
180 | } | ||
181 | else if (type == dSphereClass) { | ||
182 | dsDrawSphere (pos,R,dGeomSphereGetRadius (g)); | ||
183 | } | ||
184 | else if (type == dCCylinderClass) { | ||
185 | dReal radius,length; | ||
186 | dGeomCCylinderGetParams (g,&radius,&length); | ||
187 | dsDrawCappedCylinder (pos,R,length,radius); | ||
188 | } | ||
189 | /* | ||
190 | else if (type == dGeomTransformClass) { | ||
191 | dGeomID g2 = dGeomTransformGetGeom (g); | ||
192 | const dReal *pos2 = dGeomGetPosition (g2); | ||
193 | const dReal *R2 = dGeomGetRotation (g2); | ||
194 | dVector3 actual_pos; | ||
195 | dMatrix3 actual_R; | ||
196 | dMULTIPLY0_331 (actual_pos,R,pos2); | ||
197 | actual_pos[0] += pos[0]; | ||
198 | actual_pos[1] += pos[1]; | ||
199 | actual_pos[2] += pos[2]; | ||
200 | dMULTIPLY0_333 (actual_R,R,R2); | ||
201 | drawGeom (g2,actual_pos,actual_R); | ||
202 | } | ||
203 | */ | ||
204 | } | ||
205 | |||
206 | |||
207 | // simulation loop | ||
208 | |||
209 | static void simLoop (int pause) | ||
210 | { | ||
211 | dsSetColor (0,0,2); | ||
212 | dSpaceCollide (space,0,&nearCallback); | ||
213 | if (!pause) dWorldStep (world,0.0005); | ||
214 | |||
215 | // remove all contact joints | ||
216 | dJointGroupEmpty (contactgroup); | ||
217 | |||
218 | dsSetColor (1,1,0); | ||
219 | dsSetTexture (DS_WOOD); | ||
220 | |||
221 | // draw the falling object | ||
222 | dsSetColor (1,0,0); | ||
223 | drawGeom (fallingObject.geom,0,0); | ||
224 | |||
225 | // draw the constraining boxes | ||
226 | dsSetColor(0.8, 1, 0.8); | ||
227 | drawGeom (box1,0,0); | ||
228 | drawGeom (box2,0,0); | ||
229 | } | ||
230 | |||
231 | |||
232 | int main (int argc, char **argv) | ||
233 | { | ||
234 | // setup pointers to drawstuff callback functions | ||
235 | dsFunctions fn; | ||
236 | fn.version = DS_VERSION; | ||
237 | fn.start = &start; | ||
238 | fn.step = &simLoop; | ||
239 | fn.command = &command; | ||
240 | fn.stop = 0; | ||
241 | fn.path_to_textures = "../../drawstuff/textures"; | ||
242 | if(argc==2) | ||
243 | { | ||
244 | fn.path_to_textures = argv[1]; | ||
245 | } | ||
246 | |||
247 | // create world | ||
248 | |||
249 | world = dWorldCreate(); | ||
250 | space = dHashSpaceCreate(); | ||
251 | contactgroup = dJointGroupCreate (0); | ||
252 | dWorldSetGravity (world,0,0,-0.5); | ||
253 | dWorldSetCFM (world,1e-5); | ||
254 | dCreatePlane (space,0,0,1,0); | ||
255 | memset (&fallingObject,0,sizeof(fallingObject)); | ||
256 | |||
257 | // Create two flat boxes, just slightly off vertical and a bit apart for stuff to fall in between. | ||
258 | // Don't create bodies for these boxes -- they'll be immovable instead. | ||
259 | { | ||
260 | dReal sides[3]; | ||
261 | dMatrix3 R; | ||
262 | |||
263 | sides[0] = 4; | ||
264 | sides[1] = 0.2; | ||
265 | sides[2] = 3; | ||
266 | |||
267 | box1 = dCreateBox (space,sides[0],sides[1],sides[2]); | ||
268 | dGeomSetPosition (box1, 0, sides[1], sides[2]/2); | ||
269 | dRFromAxisAndAngle (R, 1, 0, 0, -0.1); | ||
270 | dGeomSetRotation (box1, R); | ||
271 | |||
272 | box2 = dCreateBox (space,sides[0],sides[1],sides[2]); | ||
273 | dGeomSetPosition (box2, 0, -sides[1], sides[2]/2); | ||
274 | dRFromAxisAndAngle (R, 1, 0, 0, 0.1); | ||
275 | dGeomSetRotation (box2, R); | ||
276 | } | ||
277 | |||
278 | // Pretend to drop a box to start | ||
279 | command('b'); | ||
280 | |||
281 | // run simulation | ||
282 | dsSimulationLoop (argc,argv,640,480,&fn); | ||
283 | |||
284 | dJointGroupDestroy (contactgroup); | ||
285 | dSpaceDestroy (space); | ||
286 | dWorldDestroy (world); | ||
287 | |||
288 | return 0; | ||
289 | } | ||
diff --git a/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ode/test/test_stacktest.c b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ode/test/test_stacktest.c new file mode 100644 index 0000000..e49fd73 --- /dev/null +++ b/libraries/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ode/test/test_stacktest.c | |||
@@ -0,0 +1,197 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <glut.h> | ||
3 | #include "ode.h" | ||
4 | |||
5 | #define NUMBODIES 80 | ||
6 | |||
7 | #define USE_SPHERE 0 | ||
8 | #define USE_HELIX 1 | ||
9 | #define USE_TORQUE 1 | ||
10 | #define USE_WEIRD_MATRIX_OPS 0 | ||
11 | |||
12 | #define CONTACTS 1 | ||
13 | |||
14 | dWorldID aWorld; | ||
15 | dSpaceID aSpace; | ||
16 | float cycle = 0, fade; | ||
17 | dJointGroupID aContactGroup; | ||
18 | dBodyID bodies[NUMBODIES]; | ||
19 | dGeomID geoms[NUMBODIES]; | ||
20 | GLfloat colors[NUMBODIES][4]; | ||
21 | unsigned int contactsThisFrame; | ||
22 | |||
23 | void kglTransformByODEGeom(dGeomID geom) { | ||
24 | const dReal *p = dGeomGetPosition(geom); | ||
25 | const dReal *R = dGeomGetRotation(geom); | ||
26 | GLdouble glm[16]; | ||
27 | |||
28 | glm[0] = R[0]; glm[1] = R[4]; glm[2] = R[8]; glm[3] = 0; | ||
29 | glm[4] = R[1]; glm[5] = R[5]; glm[6] = R[9]; glm[7] = 0; | ||
30 | glm[8] = R[2]; glm[9] = R[6]; glm[10] = R[10];glm[11] = 0; | ||
31 | glm[12] = p[0]; glm[13] = p[1]; glm[14] = p[2]; glm[15] = 1; | ||
32 | |||
33 | glMultMatrixd(glm); | ||
34 | } | ||
35 | |||
36 | static void odeNearCallback(void *data, dGeomID g1, dGeomID g2) { | ||
37 | dBodyID b1 = dGeomGetBody(g1), | ||
38 | b2 = dGeomGetBody(g2); | ||
39 | dContact contact[CONTACTS]; | ||
40 | int contactsUsed, i; | ||
41 | |||
42 | if (b1 && b2 && dAreConnected(b1, b2)) return; | ||
43 | |||
44 | contactsUsed = dCollide(g1, g2, CONTACTS, &contact[0].geom, | ||
45 | sizeof(dContact)); | ||
46 | if (contactsUsed > CONTACTS) contactsUsed = CONTACTS; | ||
47 | |||
48 | for (i = 0; i < contactsUsed; i++) { | ||
49 | contact[i].surface.mode = 0; | ||
50 | contact[i].surface.mu = 20.0; | ||
51 | |||
52 | dJointAttach(dJointCreateContact(aWorld, aContactGroup, | ||
53 | &(contact[i])), b1, b2); | ||
54 | contactsThisFrame++; | ||
55 | } | ||
56 | } | ||
57 | |||
58 | void myGlutResize(int w, int h) { | ||
59 | glViewport(0, 0, w, h); | ||
60 | glMatrixMode(GL_PROJECTION); | ||
61 | glLoadIdentity(); | ||
62 | gluPerspective(45.0, (GLfloat)w / h, 1.0, 120.0); | ||
63 | glMatrixMode(GL_MODELVIEW); | ||
64 | glLoadIdentity(); | ||
65 | glTranslatef(0, -6, -20); | ||
66 | } | ||
67 | |||
68 | void myGlutIdle(void) { | ||
69 | const float step = 1.0/120; | ||
70 | int i; | ||
71 | |||
72 | cycle = fmod(cycle + step / 4, 1); | ||
73 | fade = fabs(cycle * 2 - 1); | ||
74 | |||
75 | contactsThisFrame = 0; | ||
76 | dSpaceCollide(aSpace, NULL, &odeNearCallback); | ||
77 | //printf("%u\n", contactsThisFrame); | ||
78 | dWorldStep(aWorld, step); | ||
79 | dJointGroupEmpty(aContactGroup); | ||
80 | |||
81 | for (i = 0; i < NUMBODIES; i++) { | ||
82 | const dReal *cvel = dBodyGetLinearVel(bodies[i]); | ||
83 | dBodyAddForce(bodies[i], | ||
84 | -cvel[0] * 0.5, | ||
85 | -cvel[1] * 0.5, | ||
86 | -cvel[2] * 0.5 | ||
87 | ); | ||
88 | } | ||
89 | |||
90 | glutPostRedisplay(); | ||
91 | } | ||
92 | |||
93 | void myGlutDisplay(void) { | ||
94 | int i; | ||
95 | |||
96 | glClearColor(fade * 0.15, 0, 0, 1); | ||
97 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | ||
98 | |||
99 | if (USE_WEIRD_MATRIX_OPS) glPushMatrix(); | ||
100 | for (i = 0; i < NUMBODIES; i++) { | ||
101 | if (!USE_WEIRD_MATRIX_OPS) glPushMatrix(); | ||
102 | kglTransformByODEGeom(geoms[i]); | ||
103 | glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, colors[i]); | ||
104 | glColor3f(fade * 1.5, 0, 0); | ||
105 | #if USE_SPHERE | ||
106 | glRotatef(90, 1, 0, 0); | ||
107 | glutSolidSphere(0.5, 9, 6); | ||
108 | glDisable(GL_LIGHTING); | ||
109 | glutWireSphere(0.5, 9, 6); | ||
110 | #else | ||
111 | glutSolidCube(1); | ||
112 | glDisable(GL_LIGHTING); | ||
113 | glutWireCube(1); | ||
114 | #endif | ||
115 | glEnable(GL_LIGHTING); | ||
116 | if (!USE_WEIRD_MATRIX_OPS) glPopMatrix(); | ||
117 | } | ||
118 | if (USE_WEIRD_MATRIX_OPS) glPopMatrix(); | ||
119 | |||
120 | glutSwapBuffers(); | ||
121 | } | ||
122 | |||
123 | int main(int argc, char **argv) { | ||
124 | printf("Initializing GLUT\n"); | ||
125 | |||
126 | glutInit(&argc, argv); | ||
127 | glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); | ||
128 | glutInitWindowSize(400, 300); | ||
129 | glutInitWindowPosition(100, 100); | ||
130 | glutCreateWindow("ODE Crash Test"); | ||
131 | |||
132 | glutDisplayFunc(myGlutDisplay); | ||
133 | glutReshapeFunc(myGlutResize); | ||
134 | glutIdleFunc(myGlutIdle); | ||
135 | |||
136 | glPolygonOffset(1, 1); | ||
137 | glDepthFunc(GL_LEQUAL); | ||
138 | glEnable(GL_POLYGON_OFFSET_FILL); | ||
139 | glEnable(GL_DEPTH_TEST); | ||
140 | glEnable(GL_CULL_FACE); | ||
141 | glEnable(GL_LIGHTING); | ||
142 | glEnable(GL_LIGHT0); | ||
143 | myGlutResize(400, 300); | ||
144 | |||
145 | printf("Creating ODE world\n"); | ||
146 | aWorld = dWorldCreate(); | ||
147 | aSpace = dHashSpaceCreate(); | ||
148 | aContactGroup = dJointGroupCreate(0); | ||
149 | dCreatePlane(aSpace, 0, 1, 0, 0); | ||
150 | dWorldSetGravity(aWorld, 0, -9.81, 0); | ||
151 | dWorldSetERP(aWorld, 0.4); | ||
152 | dWorldSetCFM(aWorld, 1e-10); | ||
153 | |||
154 | printf("Creating objects\n"); | ||
155 | { | ||
156 | int i; | ||
157 | dMass mass; | ||
158 | |||
159 | dMassSetBox(&mass, 1.0, 1, 1, 1); | ||
160 | |||
161 | for (i = 0; i < NUMBODIES; i++) { | ||
162 | float fraction = (float)i / NUMBODIES; | ||
163 | |||
164 | bodies[i] = dBodyCreate(aWorld); | ||
165 | dBodySetMass(bodies[i], &mass); | ||
166 | #if USE_SPHERE | ||
167 | geoms[i] = dCreateSphere(aSpace, 0.5); | ||
168 | #else | ||
169 | geoms[i] = dCreateBox(aSpace, 1, 1, 1); | ||
170 | #endif | ||
171 | dGeomSetBody(geoms[i], bodies[i]); | ||
172 | |||
173 | if (USE_HELIX) { | ||
174 | float r = (i % 3 - 1) * (1.5+4*(1 - fraction)), | ||
175 | theta = (float)i / 4; | ||
176 | dBodySetPosition(bodies[i], | ||
177 | sin(theta) * r, | ||
178 | (float)i + 1, | ||
179 | cos(theta) * r | ||
180 | ); | ||
181 | } else { | ||
182 | dBodySetPosition(bodies[i], 0, (float)i * 2 + 1, 0); | ||
183 | } | ||
184 | if (USE_TORQUE) dBodyAddTorque(bodies[i], fraction*10, fraction*20, fraction*30); | ||
185 | |||
186 | colors[i][0] = fraction; | ||
187 | colors[i][1] = 1 - fraction; | ||
188 | colors[i][2] = 1 - fabs(fraction * 2 - 1); | ||
189 | colors[i][3] = 1; | ||
190 | } | ||
191 | } | ||
192 | |||
193 | printf("Starting simulation\n"); | ||
194 | glutMainLoop(); | ||
195 | |||
196 | return 0; | ||
197 | } \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/Ode.NET/Drawstuff/AssemblyInfo.cs b/libraries/ode-0.9/contrib/Ode.NET/Drawstuff/AssemblyInfo.cs new file mode 100644 index 0000000..8d2b86a --- /dev/null +++ b/libraries/ode-0.9/contrib/Ode.NET/Drawstuff/AssemblyInfo.cs | |||
@@ -0,0 +1,18 @@ | |||
1 | using System; | ||
2 | using System.Reflection; | ||
3 | using System.Runtime.CompilerServices; | ||
4 | using System.Runtime.InteropServices; | ||
5 | |||
6 | [assembly: AssemblyTitle("Drawstuff.NET")] | ||
7 | [assembly: AssemblyDescription("")] | ||
8 | [assembly: AssemblyConfiguration("")] | ||
9 | [assembly: AssemblyCompany("")] | ||
10 | [assembly: AssemblyProduct("Ode.NET")] | ||
11 | [assembly: AssemblyCopyright("")] | ||
12 | [assembly: AssemblyTrademark("")] | ||
13 | [assembly: AssemblyCulture("")] | ||
14 | [assembly: ComVisible(false)] | ||
15 | [assembly: Guid("b2a39dd4-dd67-4e8a-af70-d3b412da8850")] | ||
16 | [assembly: AssemblyVersion("0.7.0.0")] | ||
17 | [assembly: AssemblyFileVersion("0.7.0.0")] | ||
18 | [assembly: CLSCompliantAttribute(true)] | ||
diff --git a/libraries/ode-0.9/contrib/Ode.NET/Drawstuff/Drawstuff.cs b/libraries/ode-0.9/contrib/Ode.NET/Drawstuff/Drawstuff.cs new file mode 100644 index 0000000..aa84966 --- /dev/null +++ b/libraries/ode-0.9/contrib/Ode.NET/Drawstuff/Drawstuff.cs | |||
@@ -0,0 +1,58 @@ | |||
1 | using System; | ||
2 | using System.Runtime.InteropServices; | ||
3 | using Ode.NET; | ||
4 | |||
5 | namespace Drawstuff.NET | ||
6 | { | ||
7 | #if dDOUBLE | ||
8 | using dReal = System.Double; | ||
9 | #else | ||
10 | using dReal = System.Single; | ||
11 | #endif | ||
12 | |||
13 | public static class ds | ||
14 | { | ||
15 | public const int VERSION = 2; | ||
16 | |||
17 | public enum Texture | ||
18 | { | ||
19 | None, | ||
20 | Wood | ||
21 | } | ||
22 | |||
23 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | ||
24 | public delegate void CallbackFunction(int arg); | ||
25 | |||
26 | [StructLayout(LayoutKind.Sequential)] | ||
27 | public struct Functions | ||
28 | { | ||
29 | public int version; | ||
30 | public CallbackFunction start; | ||
31 | public CallbackFunction step; | ||
32 | public CallbackFunction command; | ||
33 | public CallbackFunction stop; | ||
34 | public string path_to_textures; | ||
35 | } | ||
36 | |||
37 | [DllImport("drawstuff", EntryPoint="dsDrawBox")] | ||
38 | public static extern void DrawBox(ref d.Vector3 pos, ref d.Matrix3 R, ref d.Vector3 sides); | ||
39 | |||
40 | [DllImport("drawstuff", EntryPoint = "dsDrawCapsule")] | ||
41 | public static extern void DrawCapsule(ref d.Vector3 pos, ref d.Matrix3 R, dReal length, dReal radius); | ||
42 | |||
43 | [DllImport("drawstuff", EntryPoint = "dsDrawConvex")] | ||
44 | public static extern void DrawConvex(ref d.Vector3 pos, ref d.Matrix3 R, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons); | ||
45 | |||
46 | [DllImport("drawstuff", EntryPoint="dsSetColor")] | ||
47 | public static extern void SetColor(float red, float green, float blue); | ||
48 | |||
49 | [DllImport("drawstuff", EntryPoint="dsSetTexture")] | ||
50 | public static extern void SetTexture(Texture texture); | ||
51 | |||
52 | [DllImport("drawstuff", EntryPoint="dsSetViewpoint")] | ||
53 | public static extern void SetViewpoint(ref d.Vector3 xyz, ref d.Vector3 hpr); | ||
54 | |||
55 | [DllImport("drawstuff", EntryPoint="dsSimulationLoop")] | ||
56 | public static extern void SimulationLoop(int argc, string[] argv, int window_width, int window_height, ref Functions fn); | ||
57 | } | ||
58 | } | ||
diff --git a/libraries/ode-0.9/contrib/Ode.NET/Drawstuff/premake.lua b/libraries/ode-0.9/contrib/Ode.NET/Drawstuff/premake.lua new file mode 100644 index 0000000..d777ffb --- /dev/null +++ b/libraries/ode-0.9/contrib/Ode.NET/Drawstuff/premake.lua | |||
@@ -0,0 +1,19 @@ | |||
1 | package.name = "Drawstuff.NET" | ||
2 | package.kind = "dll" | ||
3 | package.language = "c#" | ||
4 | |||
5 | if (options["with-doubles"]) then | ||
6 | package.defines = { "dDOUBLE" } | ||
7 | else | ||
8 | package.defines = { "dSINGLE " } | ||
9 | end | ||
10 | |||
11 | package.links = { | ||
12 | "System", | ||
13 | "Ode.NET" | ||
14 | } | ||
15 | |||
16 | package.files = { | ||
17 | "AssemblyInfo.cs", | ||
18 | "Drawstuff.cs" | ||
19 | } | ||
diff --git a/libraries/ode-0.9/contrib/Ode.NET/Ode/AssemblyInfo.cs b/libraries/ode-0.9/contrib/Ode.NET/Ode/AssemblyInfo.cs new file mode 100644 index 0000000..6a8c2b6 --- /dev/null +++ b/libraries/ode-0.9/contrib/Ode.NET/Ode/AssemblyInfo.cs | |||
@@ -0,0 +1,18 @@ | |||
1 | using System; | ||
2 | using System.Reflection; | ||
3 | using System.Runtime.CompilerServices; | ||
4 | using System.Runtime.InteropServices; | ||
5 | |||
6 | [assembly: AssemblyTitle("Ode.NET")] | ||
7 | [assembly: AssemblyDescription("")] | ||
8 | [assembly: AssemblyConfiguration("")] | ||
9 | [assembly: AssemblyCompany("")] | ||
10 | [assembly: AssemblyProduct("Ode.NET")] | ||
11 | [assembly: AssemblyCopyright("")] | ||
12 | [assembly: AssemblyTrademark("")] | ||
13 | [assembly: AssemblyCulture("")] | ||
14 | [assembly: ComVisible(false)] | ||
15 | [assembly: Guid("1347a35e-c32b-4ff6-8064-7d10b2cc113b")] | ||
16 | [assembly: AssemblyVersion("0.7.0.0")] | ||
17 | [assembly: AssemblyFileVersion("0.7.0.0")] | ||
18 | [assembly: CLSCompliantAttribute(true)] | ||
diff --git a/libraries/ode-0.9/contrib/Ode.NET/Ode/Ode.cs b/libraries/ode-0.9/contrib/Ode.NET/Ode/Ode.cs new file mode 100644 index 0000000..0603810 --- /dev/null +++ b/libraries/ode-0.9/contrib/Ode.NET/Ode/Ode.cs | |||
@@ -0,0 +1,1732 @@ | |||
1 | using System; | ||
2 | using System.Runtime.InteropServices; | ||
3 | using System.Security; | ||
4 | |||
5 | namespace Ode.NET | ||
6 | { | ||
7 | #if dDOUBLE | ||
8 | using dReal = System.Double; | ||
9 | #else | ||
10 | using dReal = System.Single; | ||
11 | #endif | ||
12 | |||
13 | public static class d | ||
14 | { | ||
15 | public static dReal Infinity = dReal.MaxValue; | ||
16 | |||
17 | #region Flags and Enumerations | ||
18 | |||
19 | [Flags] | ||
20 | public enum ContactFlags : int | ||
21 | { | ||
22 | Mu2 = 0x001, | ||
23 | FDir1 = 0x002, | ||
24 | Bounce = 0x004, | ||
25 | SoftERP = 0x008, | ||
26 | SoftCFM = 0x010, | ||
27 | Motion1 = 0x020, | ||
28 | Motion2 = 0x040, | ||
29 | Slip1 = 0x080, | ||
30 | Slip2 = 0x100, | ||
31 | Approx0 = 0x0000, | ||
32 | Approx1_1 = 0x1000, | ||
33 | Approx1_2 = 0x2000, | ||
34 | Approx1 = 0x3000 | ||
35 | } | ||
36 | |||
37 | public enum GeomClassID : int | ||
38 | { | ||
39 | SphereClass, | ||
40 | BoxClass, | ||
41 | CapsuleClass, | ||
42 | CylinderClass, | ||
43 | PlaneClass, | ||
44 | RayClass, | ||
45 | ConvexClass, | ||
46 | GeomTransformClass, | ||
47 | TriMeshClass, | ||
48 | HeightfieldClass, | ||
49 | FirstSpaceClass, | ||
50 | SimpleSpaceClass = FirstSpaceClass, | ||
51 | HashSpaceClass, | ||
52 | QuadTreeSpaceClass, | ||
53 | LastSpaceClass = QuadTreeSpaceClass, | ||
54 | FirstUserClass, | ||
55 | LastUserClass = FirstUserClass + MaxUserClasses - 1, | ||
56 | NumClasses, | ||
57 | MaxUserClasses = 4 | ||
58 | } | ||
59 | |||
60 | public enum JointType : int | ||
61 | { | ||
62 | None, | ||
63 | Ball, | ||
64 | Hinge, | ||
65 | Slider, | ||
66 | Contact, | ||
67 | Universal, | ||
68 | Hinge2, | ||
69 | Fixed, | ||
70 | Null, | ||
71 | AMotor, | ||
72 | LMotor, | ||
73 | Plane2D | ||
74 | } | ||
75 | |||
76 | public enum JointParam : int | ||
77 | { | ||
78 | LoStop, | ||
79 | HiStop, | ||
80 | Vel, | ||
81 | FMax, | ||
82 | FudgeFactor, | ||
83 | Bounce, | ||
84 | CFM, | ||
85 | StopERP, | ||
86 | StopCFM, | ||
87 | SuspensionERP, | ||
88 | SuspensionCFM, | ||
89 | LoStop2 = 256, | ||
90 | HiStop2, | ||
91 | Vel2, | ||
92 | FMax2, | ||
93 | FudgeFactor2, | ||
94 | Bounce2, | ||
95 | CFM2, | ||
96 | StopERP2, | ||
97 | StopCFM2, | ||
98 | SuspensionERP2, | ||
99 | SuspensionCFM2, | ||
100 | LoStop3 = 512, | ||
101 | HiStop3, | ||
102 | Vel3, | ||
103 | FMax3, | ||
104 | FudgeFactor3, | ||
105 | Bounce3, | ||
106 | CFM3, | ||
107 | StopERP3, | ||
108 | StopCFM3, | ||
109 | SuspensionERP3, | ||
110 | SuspensionCFM3 | ||
111 | } | ||
112 | |||
113 | #endregion | ||
114 | |||
115 | #region Callbacks | ||
116 | |||
117 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | ||
118 | public delegate int AABBTestFn(IntPtr o1, IntPtr o2, ref AABB aabb); | ||
119 | |||
120 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | ||
121 | public delegate int ColliderFn(IntPtr o1, IntPtr o2, int flags, out ContactGeom contact, int skip); | ||
122 | |||
123 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | ||
124 | public delegate void GetAABBFn(IntPtr geom, out AABB aabb); | ||
125 | |||
126 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | ||
127 | public delegate ColliderFn GetColliderFnFn(int num); | ||
128 | |||
129 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | ||
130 | public delegate void GeomDtorFn(IntPtr o); | ||
131 | |||
132 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | ||
133 | public delegate dReal HeightfieldGetHeight(IntPtr p_user_data, int x, int z); | ||
134 | |||
135 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | ||
136 | public delegate void NearCallback(IntPtr data, IntPtr geom1, IntPtr geom2); | ||
137 | |||
138 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | ||
139 | public delegate int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex); | ||
140 | |||
141 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | ||
142 | public delegate int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount); | ||
143 | |||
144 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | ||
145 | public delegate int TriRayCallback(IntPtr trimesh, IntPtr ray, int triangleIndex, dReal u, dReal v); | ||
146 | |||
147 | #endregion | ||
148 | |||
149 | #region Structs | ||
150 | |||
151 | [StructLayout(LayoutKind.Sequential)] | ||
152 | public struct AABB | ||
153 | { | ||
154 | public dReal MinX, MaxX; | ||
155 | public dReal MinY, MaxY; | ||
156 | public dReal MinZ, MaxZ; | ||
157 | } | ||
158 | |||
159 | |||
160 | [StructLayout(LayoutKind.Sequential)] | ||
161 | public struct Contact | ||
162 | { | ||
163 | public SurfaceParameters surface; | ||
164 | public ContactGeom geom; | ||
165 | public Vector3 fdir1; | ||
166 | } | ||
167 | |||
168 | |||
169 | [StructLayout(LayoutKind.Sequential)] | ||
170 | public struct ContactGeom | ||
171 | { | ||
172 | public static readonly int SizeOf = Marshal.SizeOf(typeof(ContactGeom)); | ||
173 | |||
174 | public Vector3 pos; | ||
175 | public Vector3 normal; | ||
176 | public dReal depth; | ||
177 | public IntPtr g1; | ||
178 | public IntPtr g2; | ||
179 | public int side1; | ||
180 | public int side2; | ||
181 | } | ||
182 | |||
183 | [StructLayout(LayoutKind.Sequential)] | ||
184 | public struct GeomClass | ||
185 | { | ||
186 | public int bytes; | ||
187 | public GetColliderFnFn collider; | ||
188 | public GetAABBFn aabb; | ||
189 | public AABBTestFn aabb_test; | ||
190 | public GeomDtorFn dtor; | ||
191 | } | ||
192 | |||
193 | |||
194 | [StructLayout(LayoutKind.Sequential)] | ||
195 | public struct JointFeedback | ||
196 | { | ||
197 | public Vector3 f1; | ||
198 | public Vector3 t1; | ||
199 | public Vector3 f2; | ||
200 | public Vector3 t2; | ||
201 | } | ||
202 | |||
203 | |||
204 | [StructLayout(LayoutKind.Sequential)] | ||
205 | public struct Mass | ||
206 | { | ||
207 | public dReal mass; | ||
208 | public Vector4 c; | ||
209 | public Matrix3 I; | ||
210 | } | ||
211 | |||
212 | |||
213 | [StructLayout(LayoutKind.Sequential)] | ||
214 | public struct Matrix3 | ||
215 | { | ||
216 | public Matrix3(dReal m00, dReal m10, dReal m20, dReal m01, dReal m11, dReal m21, dReal m02, dReal m12, dReal m22) | ||
217 | { | ||
218 | M00 = m00; M10 = m10; M20 = m20; _m30 = 0.0f; | ||
219 | M01 = m01; M11 = m11; M21 = m21; _m31 = 0.0f; | ||
220 | M02 = m02; M12 = m12; M22 = m22; _m32 = 0.0f; | ||
221 | } | ||
222 | public dReal M00, M10, M20; | ||
223 | private dReal _m30; | ||
224 | public dReal M01, M11, M21; | ||
225 | private dReal _m31; | ||
226 | public dReal M02, M12, M22; | ||
227 | private dReal _m32; | ||
228 | } | ||
229 | |||
230 | [StructLayout(LayoutKind.Sequential)] | ||
231 | public struct Matrix4 | ||
232 | { | ||
233 | public Matrix4(dReal m00, dReal m10, dReal m20, dReal m30, | ||
234 | dReal m01, dReal m11, dReal m21, dReal m31, | ||
235 | dReal m02, dReal m12, dReal m22, dReal m32, | ||
236 | dReal m03, dReal m13, dReal m23, dReal m33) | ||
237 | { | ||
238 | M00 = m00; M10 = m10; M20 = m20; M30 = m30; | ||
239 | M01 = m01; M11 = m11; M21 = m21; M31 = m31; | ||
240 | M02 = m02; M12 = m12; M22 = m22; M32 = m32; | ||
241 | M03 = m03; M13 = m13; M23 = m23; M33 = m33; | ||
242 | } | ||
243 | public dReal M00, M10, M20, M30; | ||
244 | public dReal M01, M11, M21, M31; | ||
245 | public dReal M02, M12, M22, M32; | ||
246 | public dReal M03, M13, M23, M33; | ||
247 | } | ||
248 | |||
249 | [StructLayout(LayoutKind.Sequential)] | ||
250 | public struct Quaternion | ||
251 | { | ||
252 | public dReal W, X, Y, Z; | ||
253 | } | ||
254 | |||
255 | |||
256 | [StructLayout(LayoutKind.Sequential)] | ||
257 | public struct SurfaceParameters | ||
258 | { | ||
259 | public ContactFlags mode; | ||
260 | public dReal mu; | ||
261 | public dReal mu2; | ||
262 | public dReal bounce; | ||
263 | public dReal bounce_vel; | ||
264 | public dReal soft_erp; | ||
265 | public dReal soft_cfm; | ||
266 | public dReal motion1; | ||
267 | public dReal motion2; | ||
268 | public dReal slip1; | ||
269 | public dReal slip2; | ||
270 | } | ||
271 | |||
272 | |||
273 | [StructLayout(LayoutKind.Sequential)] | ||
274 | public struct Vector3 | ||
275 | { | ||
276 | public Vector3(dReal x, dReal y, dReal z) | ||
277 | { | ||
278 | X = x; Y = y; Z = z; _w = 0.0f; | ||
279 | } | ||
280 | public dReal X, Y, Z; | ||
281 | private dReal _w; | ||
282 | } | ||
283 | |||
284 | |||
285 | [StructLayout(LayoutKind.Sequential)] | ||
286 | public struct Vector4 | ||
287 | { | ||
288 | public Vector4(dReal x, dReal y, dReal z, dReal w) | ||
289 | { | ||
290 | X = x; Y = y; Z = z; W = w; | ||
291 | } | ||
292 | public dReal X, Y, Z, W; | ||
293 | } | ||
294 | |||
295 | #endregion | ||
296 | |||
297 | [DllImport("ode", EntryPoint = "dAreConnected"), SuppressUnmanagedCodeSecurity] | ||
298 | public static extern bool AreConnected(IntPtr b1, IntPtr b2); | ||
299 | |||
300 | [DllImport("ode", EntryPoint = "dAreConnectedExcluding"), SuppressUnmanagedCodeSecurity] | ||
301 | public static extern bool AreConnectedExcluding(IntPtr b1, IntPtr b2, JointType joint_type); | ||
302 | |||
303 | [DllImport("ode", EntryPoint = "dBodyAddForce"), SuppressUnmanagedCodeSecurity] | ||
304 | public static extern void BodyAddForce(IntPtr body, dReal fx, dReal fy, dReal fz); | ||
305 | |||
306 | [DllImport("ode", EntryPoint = "dBodyAddForceAtPos"), SuppressUnmanagedCodeSecurity] | ||
307 | public static extern void BodyAddForceAtPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz); | ||
308 | |||
309 | [DllImport("ode", EntryPoint = "dBodyAddForceAtRelPos"), SuppressUnmanagedCodeSecurity] | ||
310 | public static extern void BodyAddForceAtRelPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz); | ||
311 | |||
312 | [DllImport("ode", EntryPoint = "dBodyAddRelForce"), SuppressUnmanagedCodeSecurity] | ||
313 | public static extern void BodyAddRelForce(IntPtr body, dReal fx, dReal fy, dReal fz); | ||
314 | |||
315 | [DllImport("ode", EntryPoint = "dBodyAddRelForceAtPos"), SuppressUnmanagedCodeSecurity] | ||
316 | public static extern void BodyAddRelForceAtPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz); | ||
317 | |||
318 | [DllImport("ode", EntryPoint = "dBodyAddRelForceAtRelPos"), SuppressUnmanagedCodeSecurity] | ||
319 | public static extern void BodyAddRelForceAtRelPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz); | ||
320 | |||
321 | [DllImport("ode", EntryPoint = "dBodyAddRelTorque"), SuppressUnmanagedCodeSecurity] | ||
322 | public static extern void BodyAddRelTorque(IntPtr body, dReal fx, dReal fy, dReal fz); | ||
323 | |||
324 | [DllImport("ode", EntryPoint = "dBodyAddTorque"), SuppressUnmanagedCodeSecurity] | ||
325 | public static extern void BodyAddTorque(IntPtr body, dReal fx, dReal fy, dReal fz); | ||
326 | |||
327 | [DllImport("ode", EntryPoint = "dBodyCopyPosition"), SuppressUnmanagedCodeSecurity] | ||
328 | public static extern void BodyCopyPosition(IntPtr body, out Vector3 pos); | ||
329 | |||
330 | [DllImport("ode", EntryPoint = "dBodyCopyPosition"), SuppressUnmanagedCodeSecurity] | ||
331 | public static extern void BodyCopyPosition(IntPtr body, out dReal X); | ||
332 | |||
333 | [DllImport("ode", EntryPoint = "dBodyCopyQuaternion"), SuppressUnmanagedCodeSecurity] | ||
334 | public static extern void BodyCopyQuaternion(IntPtr body, out Quaternion quat); | ||
335 | |||
336 | [DllImport("ode", EntryPoint = "dBodyCopyQuaternion"), SuppressUnmanagedCodeSecurity] | ||
337 | public static extern void BodyCopyQuaternion(IntPtr body, out dReal X); | ||
338 | |||
339 | [DllImport("ode", EntryPoint = "dBodyCopyRotation"), SuppressUnmanagedCodeSecurity] | ||
340 | public static extern void BodyCopyRotation(IntPtr body, out Matrix3 R); | ||
341 | |||
342 | [DllImport("ode", EntryPoint = "dBodyCopyRotation"), SuppressUnmanagedCodeSecurity] | ||
343 | public static extern void BodyCopyRotation(IntPtr body, out dReal M00); | ||
344 | |||
345 | [DllImport("ode", EntryPoint = "dBodyCreate"), SuppressUnmanagedCodeSecurity] | ||
346 | public static extern IntPtr BodyCreate(IntPtr world); | ||
347 | |||
348 | [DllImport("ode", EntryPoint = "dBodyDestroy"), SuppressUnmanagedCodeSecurity] | ||
349 | public static extern void BodyDestroy(IntPtr body); | ||
350 | |||
351 | [DllImport("ode", EntryPoint = "dBodyDisable"), SuppressUnmanagedCodeSecurity] | ||
352 | public static extern void BodyDisable(IntPtr body); | ||
353 | |||
354 | [DllImport("ode", EntryPoint = "dBodyEnable"), SuppressUnmanagedCodeSecurity] | ||
355 | public static extern void BodyEnable(IntPtr body); | ||
356 | |||
357 | [DllImport("ode", EntryPoint = "dBodyGetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity] | ||
358 | public static extern dReal BodyGetAutoDisableAngularThreshold(IntPtr body); | ||
359 | |||
360 | [DllImport("ode", EntryPoint = "dBodyGetAutoDisableFlag"), SuppressUnmanagedCodeSecurity] | ||
361 | public static extern bool BodyGetAutoDisableFlag(IntPtr body); | ||
362 | |||
363 | [DllImport("ode", EntryPoint = "dBodyGetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity] | ||
364 | public static extern dReal BodyGetAutoDisableLinearThreshold(IntPtr body); | ||
365 | |||
366 | [DllImport("ode", EntryPoint = "dBodyGetAutoDisableSteps"), SuppressUnmanagedCodeSecurity] | ||
367 | public static extern int BodyGetAutoDisableSteps(IntPtr body); | ||
368 | |||
369 | [DllImport("ode", EntryPoint = "dBodyGetAutoDisableTime"), SuppressUnmanagedCodeSecurity] | ||
370 | public static extern dReal BodyGetAutoDisableTime(IntPtr body); | ||
371 | |||
372 | #if !dNO_UNSAFE_CODE | ||
373 | [CLSCompliant(false)] | ||
374 | [DllImport("ode", EntryPoint = "dBodyGetAngularVel"), SuppressUnmanagedCodeSecurity] | ||
375 | public extern unsafe static Vector3* BodyGetAngularVelUnsafe(IntPtr body); | ||
376 | public static Vector3 BodyGetAngularVel(IntPtr body) | ||
377 | { | ||
378 | unsafe { return *(BodyGetAngularVelUnsafe(body)); } | ||
379 | } | ||
380 | #endif | ||
381 | |||
382 | [DllImport("ode", EntryPoint = "dBodyGetData"), SuppressUnmanagedCodeSecurity] | ||
383 | public static extern IntPtr BodyGetData(IntPtr body); | ||
384 | |||
385 | [DllImport("ode", EntryPoint = "dBodyGetFiniteRotationMode"), SuppressUnmanagedCodeSecurity] | ||
386 | public static extern int BodyGetFiniteRotationMode(IntPtr body); | ||
387 | |||
388 | [DllImport("ode", EntryPoint = "dBodyGetFiniteRotationAxis"), SuppressUnmanagedCodeSecurity] | ||
389 | public static extern void BodyGetFiniteRotationAxis(IntPtr body, out Vector3 result); | ||
390 | |||
391 | #if !dNO_UNSAFE_CODE | ||
392 | [CLSCompliant(false)] | ||
393 | [DllImport("ode", EntryPoint = "dBodyGetForce"), SuppressUnmanagedCodeSecurity] | ||
394 | public extern unsafe static Vector3* BodyGetForceUnsafe(IntPtr body); | ||
395 | public static Vector3 BodyGetForce(IntPtr body) | ||
396 | { | ||
397 | unsafe { return *(BodyGetForceUnsafe(body)); } | ||
398 | } | ||
399 | #endif | ||
400 | |||
401 | [DllImport("ode", EntryPoint = "dBodyGetGravityMode"), SuppressUnmanagedCodeSecurity] | ||
402 | public static extern bool BodyGetGravityMode(IntPtr body); | ||
403 | |||
404 | [DllImport("ode", EntryPoint = "dBodyGetJoint"), SuppressUnmanagedCodeSecurity] | ||
405 | public static extern IntPtr BodyGetJoint(IntPtr body, int index); | ||
406 | |||
407 | #if !dNO_UNSAFE_CODE | ||
408 | [CLSCompliant(false)] | ||
409 | [DllImport("ode", EntryPoint = "dBodyGetLinearVel"), SuppressUnmanagedCodeSecurity] | ||
410 | public extern unsafe static Vector3* BodyGetLinearVelUnsafe(IntPtr body); | ||
411 | public static Vector3 BodyGetLinearVel(IntPtr body) | ||
412 | { | ||
413 | unsafe { return *(BodyGetLinearVelUnsafe(body)); } | ||
414 | } | ||
415 | #endif | ||
416 | |||
417 | [DllImport("ode", EntryPoint = "dBodyGetMass"), SuppressUnmanagedCodeSecurity] | ||
418 | public static extern void BodyGetMass(IntPtr body, out Mass mass); | ||
419 | |||
420 | [DllImport("ode", EntryPoint = "dBodyGetNumJoints"), SuppressUnmanagedCodeSecurity] | ||
421 | public static extern int BodyGetNumJoints(IntPtr body); | ||
422 | |||
423 | [DllImport("ode", EntryPoint = "dBodyGetPointVel"), SuppressUnmanagedCodeSecurity] | ||
424 | public static extern void BodyGetPointVel(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result); | ||
425 | |||
426 | #if !dNO_UNSAFE_CODE | ||
427 | [CLSCompliant(false)] | ||
428 | [DllImport("ode", EntryPoint = "dBodyGetPosition"), SuppressUnmanagedCodeSecurity] | ||
429 | public extern unsafe static Vector3* BodyGetPositionUnsafe(IntPtr body); | ||
430 | public static Vector3 BodyGetPosition(IntPtr body) | ||
431 | { | ||
432 | unsafe { return *(BodyGetPositionUnsafe(body)); } | ||
433 | } | ||
434 | #endif | ||
435 | |||
436 | [DllImport("ode", EntryPoint = "dBodyGetPosRelPoint"), SuppressUnmanagedCodeSecurity] | ||
437 | public static extern void BodyGetPosRelPoint(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result); | ||
438 | |||
439 | #if !dNO_UNSAFE_CODE | ||
440 | [CLSCompliant(false)] | ||
441 | [DllImport("ode", EntryPoint = "dBodyGetQuaternion"), SuppressUnmanagedCodeSecurity] | ||
442 | public extern unsafe static Quaternion* BodyGetQuaternionUnsafe(IntPtr body); | ||
443 | public static Quaternion BodyGetQuaternion(IntPtr body) | ||
444 | { | ||
445 | unsafe { return *(BodyGetQuaternionUnsafe(body)); } | ||
446 | } | ||
447 | #endif | ||
448 | |||
449 | [DllImport("ode", EntryPoint = "dBodyGetRelPointPos"), SuppressUnmanagedCodeSecurity] | ||
450 | public static extern void BodyGetRelPointPos(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result); | ||
451 | |||
452 | [DllImport("ode", EntryPoint = "dBodyGetRelPointVel"), SuppressUnmanagedCodeSecurity] | ||
453 | public static extern void BodyGetRelPointVel(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result); | ||
454 | |||
455 | #if !dNO_UNSAFE_CODE | ||
456 | [CLSCompliant(false)] | ||
457 | [DllImport("ode", EntryPoint = "dBodyGetRotation"), SuppressUnmanagedCodeSecurity] | ||
458 | public extern unsafe static Matrix3* BodyGetRotationUnsafe(IntPtr body); | ||
459 | public static Matrix3 BodyGetRotation(IntPtr body) | ||
460 | { | ||
461 | unsafe { return *(BodyGetRotationUnsafe(body)); } | ||
462 | } | ||
463 | #endif | ||
464 | |||
465 | #if !dNO_UNSAFE_CODE | ||
466 | [CLSCompliant(false)] | ||
467 | [DllImport("ode", EntryPoint = "dBodyGetTorque"), SuppressUnmanagedCodeSecurity] | ||
468 | public extern unsafe static Vector3* BodyGetTorqueUnsafe(IntPtr body); | ||
469 | public static Vector3 BodyGetTorque(IntPtr body) | ||
470 | { | ||
471 | unsafe { return *(BodyGetTorqueUnsafe(body)); } | ||
472 | } | ||
473 | #endif | ||
474 | |||
475 | [DllImport("ode", EntryPoint = "dBodyIsEnabled"), SuppressUnmanagedCodeSecurity] | ||
476 | public static extern bool BodyIsEnabled(IntPtr body); | ||
477 | |||
478 | [DllImport("ode", EntryPoint = "dBodySetAngularVel"), SuppressUnmanagedCodeSecurity] | ||
479 | public static extern void BodySetAngularVel(IntPtr body, dReal x, dReal y, dReal z); | ||
480 | |||
481 | [DllImport("ode", EntryPoint = "dBodySetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity] | ||
482 | public static extern void BodySetAutoDisableAngularThreshold(IntPtr body, dReal angular_threshold); | ||
483 | |||
484 | [DllImport("ode", EntryPoint = "dBodySetAutoDisableDefaults"), SuppressUnmanagedCodeSecurity] | ||
485 | public static extern void BodySetAutoDisableDefaults(IntPtr body); | ||
486 | |||
487 | [DllImport("ode", EntryPoint = "dBodySetAutoDisableFlag"), SuppressUnmanagedCodeSecurity] | ||
488 | public static extern void BodySetAutoDisableFlag(IntPtr body, bool do_auto_disable); | ||
489 | |||
490 | [DllImport("ode", EntryPoint = "dBodySetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity] | ||
491 | public static extern void BodySetAutoDisableLinearThreshold(IntPtr body, dReal linear_threshold); | ||
492 | |||
493 | [DllImport("ode", EntryPoint = "dBodySetAutoDisableSteps"), SuppressUnmanagedCodeSecurity] | ||
494 | public static extern void BodySetAutoDisableSteps(IntPtr body, int steps); | ||
495 | |||
496 | [DllImport("ode", EntryPoint = "dBodySetAutoDisableTime"), SuppressUnmanagedCodeSecurity] | ||
497 | public static extern void BodySetAutoDisableTime(IntPtr body, dReal time); | ||
498 | |||
499 | [DllImport("ode", EntryPoint = "dBodySetData"), SuppressUnmanagedCodeSecurity] | ||
500 | public static extern void BodySetData(IntPtr body, IntPtr data); | ||
501 | |||
502 | [DllImport("ode", EntryPoint = "dBodySetFiniteRotationMode"), SuppressUnmanagedCodeSecurity] | ||
503 | public static extern void BodySetFiniteRotationMode(IntPtr body, int mode); | ||
504 | |||
505 | [DllImport("ode", EntryPoint = "dBodySetFiniteRotationModeAxis"), SuppressUnmanagedCodeSecurity] | ||
506 | public static extern void BodySetFiniteRotationModeAxis(IntPtr body, dReal x, dReal y, dReal z); | ||
507 | |||
508 | [DllImport("ode", EntryPoint = "dBodySetForce"), SuppressUnmanagedCodeSecurity] | ||
509 | public static extern void BodySetForce(IntPtr body, dReal x, dReal y, dReal z); | ||
510 | |||
511 | [DllImport("ode", EntryPoint = "dBodySetGravityMode"), SuppressUnmanagedCodeSecurity] | ||
512 | public static extern void BodySetGravityMode(IntPtr body, bool mode); | ||
513 | |||
514 | [DllImport("ode", EntryPoint = "dBodySetLinearVel"), SuppressUnmanagedCodeSecurity] | ||
515 | public static extern void BodySetLinearVel(IntPtr body, dReal x, dReal y, dReal z); | ||
516 | |||
517 | [DllImport("ode", EntryPoint = "dBodySetMass"), SuppressUnmanagedCodeSecurity] | ||
518 | public static extern void BodySetMass(IntPtr body, ref Mass mass); | ||
519 | |||
520 | [DllImport("ode", EntryPoint = "dBodySetPosition"), SuppressUnmanagedCodeSecurity] | ||
521 | public static extern void BodySetPosition(IntPtr body, dReal x, dReal y, dReal z); | ||
522 | |||
523 | [DllImport("ode", EntryPoint = "dBodySetQuaternion"), SuppressUnmanagedCodeSecurity] | ||
524 | public static extern void BodySetQuaternion(IntPtr body, ref Quaternion q); | ||
525 | |||
526 | [DllImport("ode", EntryPoint = "dBodySetQuaternion"), SuppressUnmanagedCodeSecurity] | ||
527 | public static extern void BodySetQuaternion(IntPtr body, ref dReal w); | ||
528 | |||
529 | [DllImport("ode", EntryPoint = "dBodySetRotation"), SuppressUnmanagedCodeSecurity] | ||
530 | public static extern void BodySetRotation(IntPtr body, ref Matrix3 R); | ||
531 | |||
532 | [DllImport("ode", EntryPoint = "dBodySetRotation"), SuppressUnmanagedCodeSecurity] | ||
533 | public static extern void BodySetRotation(IntPtr body, ref dReal M00); | ||
534 | |||
535 | [DllImport("ode", EntryPoint = "dBodySetTorque"), SuppressUnmanagedCodeSecurity] | ||
536 | public static extern void BodySetTorque(IntPtr body, dReal x, dReal y, dReal z); | ||
537 | |||
538 | [DllImport("ode", EntryPoint = "dBodyVectorFromWorld"), SuppressUnmanagedCodeSecurity] | ||
539 | public static extern void BodyVectorFromWorld(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result); | ||
540 | |||
541 | [DllImport("ode", EntryPoint = "dBodyVectorToWorld"), SuppressUnmanagedCodeSecurity] | ||
542 | public static extern void BodyVectorToWorld(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result); | ||
543 | |||
544 | [DllImport("ode", EntryPoint = "dBoxBox"), SuppressUnmanagedCodeSecurity] | ||
545 | public static extern void BoxBox(ref Vector3 p1, ref Matrix3 R1, | ||
546 | ref Vector3 side1, ref Vector3 p2, | ||
547 | ref Matrix3 R2, ref Vector3 side2, | ||
548 | ref Vector3 normal, out dReal depth, out int return_code, | ||
549 | int maxc, out ContactGeom contact, int skip); | ||
550 | |||
551 | [DllImport("ode", EntryPoint = "dBoxTouchesBox"), SuppressUnmanagedCodeSecurity] | ||
552 | public static extern void BoxTouchesBox(ref Vector3 _p1, ref Matrix3 R1, | ||
553 | ref Vector3 side1, ref Vector3 _p2, | ||
554 | ref Matrix3 R2, ref Vector3 side2); | ||
555 | |||
556 | [DllImport("ode", EntryPoint = "dClosestLineSegmentPoints"), SuppressUnmanagedCodeSecurity] | ||
557 | public static extern void ClosestLineSegmentPoints(ref Vector3 a1, ref Vector3 a2, | ||
558 | ref Vector3 b1, ref Vector3 b2, | ||
559 | ref Vector3 cp1, ref Vector3 cp2); | ||
560 | |||
561 | [DllImport("ode", EntryPoint = "dCloseODE"), SuppressUnmanagedCodeSecurity] | ||
562 | public static extern void CloseODE(); | ||
563 | |||
564 | [DllImport("ode", EntryPoint = "dCollide"), SuppressUnmanagedCodeSecurity] | ||
565 | public static extern int Collide(IntPtr o1, IntPtr o2, int flags, [In, Out] ContactGeom[] contact, int skip); | ||
566 | |||
567 | [DllImport("ode", EntryPoint = "dConnectingJoint"), SuppressUnmanagedCodeSecurity] | ||
568 | public static extern IntPtr ConnectingJoint(IntPtr j1, IntPtr j2); | ||
569 | |||
570 | [DllImport("ode", EntryPoint = "dCreateBox"), SuppressUnmanagedCodeSecurity] | ||
571 | public static extern IntPtr CreateBox(IntPtr space, dReal lx, dReal ly, dReal lz); | ||
572 | |||
573 | [DllImport("ode", EntryPoint = "dCreateCapsule"), SuppressUnmanagedCodeSecurity] | ||
574 | public static extern IntPtr CreateCapsule(IntPtr space, dReal radius, dReal length); | ||
575 | |||
576 | [DllImport("ode", EntryPoint = "dCreateConvex"), SuppressUnmanagedCodeSecurity] | ||
577 | public static extern IntPtr CreateConvex(IntPtr space, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons); | ||
578 | |||
579 | [DllImport("ode", EntryPoint = "dCreateCylinder"), SuppressUnmanagedCodeSecurity] | ||
580 | public static extern IntPtr CreateCylinder(IntPtr space, dReal radius, dReal length); | ||
581 | |||
582 | [DllImport("ode", EntryPoint = "dCreateHeightfield"), SuppressUnmanagedCodeSecurity] | ||
583 | public static extern IntPtr CreateHeightfield(IntPtr space, IntPtr data, int bPlaceable); | ||
584 | |||
585 | [DllImport("ode", EntryPoint = "dCreateGeom"), SuppressUnmanagedCodeSecurity] | ||
586 | public static extern IntPtr CreateGeom(int classnum); | ||
587 | |||
588 | [DllImport("ode", EntryPoint = "dCreateGeomClass"), SuppressUnmanagedCodeSecurity] | ||
589 | public static extern int CreateGeomClass(ref GeomClass classptr); | ||
590 | |||
591 | [DllImport("ode", EntryPoint = "dCreateGeomTransform"), SuppressUnmanagedCodeSecurity] | ||
592 | public static extern IntPtr CreateGeomTransform(IntPtr space); | ||
593 | |||
594 | [DllImport("ode", EntryPoint = "dCreatePlane"), SuppressUnmanagedCodeSecurity] | ||
595 | public static extern IntPtr CreatePlane(IntPtr space, dReal a, dReal b, dReal c, dReal d); | ||
596 | |||
597 | [DllImport("ode", EntryPoint = "dCreateRay"), SuppressUnmanagedCodeSecurity] | ||
598 | public static extern IntPtr CreateRay(IntPtr space, dReal length); | ||
599 | |||
600 | [DllImport("ode", EntryPoint = "dCreateSphere"), SuppressUnmanagedCodeSecurity] | ||
601 | public static extern IntPtr CreateSphere(IntPtr space, dReal radius); | ||
602 | |||
603 | [DllImport("ode", EntryPoint = "dCreateTriMesh"), SuppressUnmanagedCodeSecurity] | ||
604 | public static extern IntPtr CreateTriMesh(IntPtr space, IntPtr data, | ||
605 | TriCallback callback, TriArrayCallback arrayCallback, TriRayCallback rayCallback); | ||
606 | |||
607 | [DllImport("ode", EntryPoint = "dDot"), SuppressUnmanagedCodeSecurity] | ||
608 | public static extern dReal Dot(ref dReal X0, ref dReal X1, int n); | ||
609 | |||
610 | [DllImport("ode", EntryPoint = "dDQfromW"), SuppressUnmanagedCodeSecurity] | ||
611 | public static extern void DQfromW(dReal[] dq, ref Vector3 w, ref Quaternion q); | ||
612 | |||
613 | [DllImport("ode", EntryPoint = "dFactorCholesky"), SuppressUnmanagedCodeSecurity] | ||
614 | public static extern int FactorCholesky(ref dReal A00, int n); | ||
615 | |||
616 | [DllImport("ode", EntryPoint = "dFactorLDLT"), SuppressUnmanagedCodeSecurity] | ||
617 | public static extern void FactorLDLT(ref dReal A, out dReal d, int n, int nskip); | ||
618 | |||
619 | [DllImport("ode", EntryPoint = "dGeomBoxGetLengths"), SuppressUnmanagedCodeSecurity] | ||
620 | public static extern void GeomBoxGetLengths(IntPtr geom, out Vector3 len); | ||
621 | |||
622 | [DllImport("ode", EntryPoint = "dGeomBoxGetLengths"), SuppressUnmanagedCodeSecurity] | ||
623 | public static extern void GeomBoxGetLengths(IntPtr geom, out dReal x); | ||
624 | |||
625 | [DllImport("ode", EntryPoint = "dGeomBoxPointDepth"), SuppressUnmanagedCodeSecurity] | ||
626 | public static extern dReal GeomBoxPointDepth(IntPtr geom, dReal x, dReal y, dReal z); | ||
627 | |||
628 | [DllImport("ode", EntryPoint = "dGeomBoxSetLengths"), SuppressUnmanagedCodeSecurity] | ||
629 | public static extern void GeomBoxSetLengths(IntPtr geom, dReal x, dReal y, dReal z); | ||
630 | |||
631 | [DllImport("ode", EntryPoint = "dGeomCapsuleGetParams"), SuppressUnmanagedCodeSecurity] | ||
632 | public static extern void GeomCapsuleGetParams(IntPtr geom, out dReal radius, out dReal length); | ||
633 | |||
634 | [DllImport("ode", EntryPoint = "dGeomCapsulePointDepth"), SuppressUnmanagedCodeSecurity] | ||
635 | public static extern dReal GeomCapsulePointDepth(IntPtr geom, dReal x, dReal y, dReal z); | ||
636 | |||
637 | [DllImport("ode", EntryPoint = "dGeomCapsuleSetParams"), SuppressUnmanagedCodeSecurity] | ||
638 | public static extern void GeomCapsuleSetParams(IntPtr geom, dReal radius, dReal length); | ||
639 | |||
640 | [DllImport("ode", EntryPoint = "dGeomClearOffset"), SuppressUnmanagedCodeSecurity] | ||
641 | public static extern void GeomClearOffset(IntPtr geom); | ||
642 | |||
643 | [DllImport("ode", EntryPoint = "dGeomCopyOffsetPosition"), SuppressUnmanagedCodeSecurity] | ||
644 | public static extern IntPtr GeomCopyOffsetPosition(IntPtr geom, ref Vector3 pos); | ||
645 | |||
646 | [DllImport("ode", EntryPoint = "dGeomCopyOffsetPosition"), SuppressUnmanagedCodeSecurity] | ||
647 | public static extern IntPtr GeomCopyOffsetPosition(IntPtr geom, ref dReal X); | ||
648 | |||
649 | [DllImport("ode", EntryPoint = "dGeomGetOffsetQuaternion"), SuppressUnmanagedCodeSecurity] | ||
650 | public static extern void GeomCopyOffsetQuaternion(IntPtr geom, ref Quaternion Q); | ||
651 | |||
652 | [DllImport("ode", EntryPoint = "dGeomGetOffsetQuaternion"), SuppressUnmanagedCodeSecurity] | ||
653 | public static extern void GeomCopyOffsetQuaternion(IntPtr geom, ref dReal X); | ||
654 | |||
655 | [DllImport("ode", EntryPoint = "dGeomCopyOffsetRotation"), SuppressUnmanagedCodeSecurity] | ||
656 | public static extern IntPtr GeomCopyOffsetRotation(IntPtr geom, ref Matrix3 R); | ||
657 | |||
658 | [DllImport("ode", EntryPoint = "dGeomCopyOffsetRotation"), SuppressUnmanagedCodeSecurity] | ||
659 | public static extern IntPtr GeomCopyOffsetRotation(IntPtr geom, ref dReal M00); | ||
660 | |||
661 | [DllImport("ode", EntryPoint = "dGeomCopyPosition"), SuppressUnmanagedCodeSecurity] | ||
662 | public static extern void GeomCopyPosition(IntPtr geom, out Vector3 pos); | ||
663 | |||
664 | [DllImport("ode", EntryPoint = "dGeomCopyPosition"), SuppressUnmanagedCodeSecurity] | ||
665 | public static extern void GeomCopyPosition(IntPtr geom, out dReal X); | ||
666 | |||
667 | [DllImport("ode", EntryPoint = "dGeomCopyRotation"), SuppressUnmanagedCodeSecurity] | ||
668 | public static extern void GeomCopyRotation(IntPtr geom, out Matrix3 R); | ||
669 | |||
670 | [DllImport("ode", EntryPoint = "dGeomCopyRotation"), SuppressUnmanagedCodeSecurity] | ||
671 | public static extern void GeomCopyRotation(IntPtr geom, out dReal M00); | ||
672 | |||
673 | [DllImport("ode", EntryPoint = "dGeomCylinderGetParams"), SuppressUnmanagedCodeSecurity] | ||
674 | public static extern void GeomCylinderGetParams(IntPtr geom, out dReal radius, out dReal length); | ||
675 | |||
676 | [DllImport("ode", EntryPoint = "dGeomCylinderSetParams"), SuppressUnmanagedCodeSecurity] | ||
677 | public static extern void GeomCylinderSetParams(IntPtr geom, dReal radius, dReal length); | ||
678 | |||
679 | [DllImport("ode", EntryPoint = "dGeomDestroy"), SuppressUnmanagedCodeSecurity] | ||
680 | public static extern void GeomDestroy(IntPtr geom); | ||
681 | |||
682 | [DllImport("ode", EntryPoint = "dGeomDisable"), SuppressUnmanagedCodeSecurity] | ||
683 | public static extern void GeomDisable(IntPtr geom); | ||
684 | |||
685 | [DllImport("ode", EntryPoint = "dGeomEnable"), SuppressUnmanagedCodeSecurity] | ||
686 | public static extern void GeomEnable(IntPtr geom); | ||
687 | |||
688 | [DllImport("ode", EntryPoint = "dGeomGetAABB"), SuppressUnmanagedCodeSecurity] | ||
689 | public static extern void GeomGetAABB(IntPtr geom, out AABB aabb); | ||
690 | |||
691 | [DllImport("ode", EntryPoint = "dGeomGetAABB"), SuppressUnmanagedCodeSecurity] | ||
692 | public static extern void GeomGetAABB(IntPtr geom, out dReal minX); | ||
693 | |||
694 | [DllImport("ode", EntryPoint = "dGeomGetBody"), SuppressUnmanagedCodeSecurity] | ||
695 | public static extern IntPtr GeomGetBody(IntPtr geom); | ||
696 | |||
697 | [DllImport("ode", EntryPoint = "dGeomGetCategoryBits"), SuppressUnmanagedCodeSecurity] | ||
698 | public static extern int GeomGetCategoryBits(IntPtr geom); | ||
699 | |||
700 | [DllImport("ode", EntryPoint = "dGeomGetClassData"), SuppressUnmanagedCodeSecurity] | ||
701 | public static extern IntPtr GeomGetClassData(IntPtr geom); | ||
702 | |||
703 | [DllImport("ode", EntryPoint = "dGeomGetCollideBits"), SuppressUnmanagedCodeSecurity] | ||
704 | public static extern int GeomGetCollideBits(IntPtr geom); | ||
705 | |||
706 | [DllImport("ode", EntryPoint = "dGeomGetClass"), SuppressUnmanagedCodeSecurity] | ||
707 | public static extern GeomClassID GeomGetClass(IntPtr geom); | ||
708 | |||
709 | [DllImport("ode", EntryPoint = "dGeomGetData"), SuppressUnmanagedCodeSecurity] | ||
710 | public static extern IntPtr GeomGetData(IntPtr geom); | ||
711 | |||
712 | #if !dNO_UNSAFE_CODE | ||
713 | [CLSCompliant(false)] | ||
714 | [DllImport("ode", EntryPoint = "dGeomGetOffsetPosition"), SuppressUnmanagedCodeSecurity] | ||
715 | public extern unsafe static Vector3* GeomGetOffsetPositionUnsafe(IntPtr geom); | ||
716 | public static Vector3 GeomGetOffsetPosition(IntPtr geom) | ||
717 | { | ||
718 | unsafe { return *(GeomGetOffsetPositionUnsafe(geom)); } | ||
719 | } | ||
720 | #endif | ||
721 | |||
722 | #if !dNO_UNSAFE_CODE | ||
723 | [CLSCompliant(false)] | ||
724 | [DllImport("ode", EntryPoint = "dGeomGetOffsetRotation"), SuppressUnmanagedCodeSecurity] | ||
725 | public extern unsafe static Matrix3* GeomGetOffsetRotationUnsafe(IntPtr geom); | ||
726 | public static Matrix3 GeomGetOffsetRotation(IntPtr geom) | ||
727 | { | ||
728 | unsafe { return *(GeomGetOffsetRotationUnsafe(geom)); } | ||
729 | } | ||
730 | #endif | ||
731 | |||
732 | #if !dNO_UNSAFE_CODE | ||
733 | [CLSCompliant(false)] | ||
734 | [DllImport("ode", EntryPoint = "dGeomGetPosition"), SuppressUnmanagedCodeSecurity] | ||
735 | public extern unsafe static Vector3* GeomGetPositionUnsafe(IntPtr geom); | ||
736 | public static Vector3 GeomGetPosition(IntPtr geom) | ||
737 | { | ||
738 | unsafe { return *(GeomGetPositionUnsafe(geom)); } | ||
739 | } | ||
740 | #endif | ||
741 | |||
742 | [DllImport("ode", EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity] | ||
743 | public static extern void GeomCopyQuaternion(IntPtr geom, out Quaternion q); | ||
744 | |||
745 | [DllImport("ode", EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity] | ||
746 | public static extern void GeomCopyQuaternion(IntPtr geom, out dReal X); | ||
747 | |||
748 | #if !dNO_UNSAFE_CODE | ||
749 | [CLSCompliant(false)] | ||
750 | [DllImport("ode", EntryPoint = "dGeomGetRotation"), SuppressUnmanagedCodeSecurity] | ||
751 | public extern unsafe static Matrix3* GeomGetRotationUnsafe(IntPtr geom); | ||
752 | public static Matrix3 GeomGetRotation(IntPtr geom) | ||
753 | { | ||
754 | unsafe { return *(GeomGetRotationUnsafe(geom)); } | ||
755 | } | ||
756 | #endif | ||
757 | |||
758 | [DllImport("ode", EntryPoint = "dGeomGetSpace"), SuppressUnmanagedCodeSecurity] | ||
759 | public static extern IntPtr GeomGetSpace(IntPtr geom); | ||
760 | |||
761 | [DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildByte"), SuppressUnmanagedCodeSecurity] | ||
762 | public static extern void GeomHeightfieldDataBuildByte(IntPtr d, byte[] pHeightData, int bCopyHeightData, | ||
763 | dReal width, dReal depth, int widthSamples, int depthSamples, | ||
764 | dReal scale, dReal offset, dReal thickness, int bWrap); | ||
765 | |||
766 | [DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildByte"), SuppressUnmanagedCodeSecurity] | ||
767 | public static extern void GeomHeightfieldDataBuildByte(IntPtr d, IntPtr pHeightData, int bCopyHeightData, | ||
768 | dReal width, dReal depth, int widthSamples, int depthSamples, | ||
769 | dReal scale, dReal offset, dReal thickness, int bWrap); | ||
770 | |||
771 | [DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildCallback"), SuppressUnmanagedCodeSecurity] | ||
772 | public static extern void GeomHeightfieldDataBuildCallback(IntPtr d, IntPtr pUserData, HeightfieldGetHeight pCallback, | ||
773 | dReal width, dReal depth, int widthSamples, int depthSamples, | ||
774 | dReal scale, dReal offset, dReal thickness, int bWrap); | ||
775 | |||
776 | [CLSCompliant(false)] | ||
777 | [DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildShort"), SuppressUnmanagedCodeSecurity] | ||
778 | public static extern void GeomHeightfieldDataBuildShort(IntPtr d, ushort[] pHeightData, int bCopyHeightData, | ||
779 | dReal width, dReal depth, int widthSamples, int depthSamples, | ||
780 | dReal scale, dReal offset, dReal thickness, int bWrap); | ||
781 | |||
782 | [DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildShort"), SuppressUnmanagedCodeSecurity] | ||
783 | public static extern void GeomHeightfieldDataBuildShort(IntPtr d, short[] pHeightData, int bCopyHeightData, | ||
784 | dReal width, dReal depth, int widthSamples, int depthSamples, | ||
785 | dReal scale, dReal offset, dReal thickness, int bWrap); | ||
786 | |||
787 | [DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildShort"), SuppressUnmanagedCodeSecurity] | ||
788 | public static extern void GeomHeightfieldDataBuildShort(IntPtr d, IntPtr pHeightData, int bCopyHeightData, | ||
789 | dReal width, dReal depth, int widthSamples, int depthSamples, | ||
790 | dReal scale, dReal offset, dReal thickness, int bWrap); | ||
791 | |||
792 | [DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildSingle"), SuppressUnmanagedCodeSecurity] | ||
793 | public static extern void GeomHeightfieldDataBuildSingle(IntPtr d, float[] pHeightData, int bCopyHeightData, | ||
794 | dReal width, dReal depth, int widthSamples, int depthSamples, | ||
795 | dReal scale, dReal offset, dReal thickness, int bWrap); | ||
796 | |||
797 | [DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildSingle"), SuppressUnmanagedCodeSecurity] | ||
798 | public static extern void GeomHeightfieldDataBuildSingle(IntPtr d, IntPtr pHeightData, int bCopyHeightData, | ||
799 | dReal width, dReal depth, int widthSamples, int depthSamples, | ||
800 | dReal scale, dReal offset, dReal thickness, int bWrap); | ||
801 | |||
802 | [DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildDouble"), SuppressUnmanagedCodeSecurity] | ||
803 | public static extern void GeomHeightfieldDataBuildDouble(IntPtr d, double[] pHeightData, int bCopyHeightData, | ||
804 | dReal width, dReal depth, int widthSamples, int depthSamples, | ||
805 | dReal scale, dReal offset, dReal thickness, int bWrap); | ||
806 | |||
807 | [DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildDouble"), SuppressUnmanagedCodeSecurity] | ||
808 | public static extern void GeomHeightfieldDataBuildDouble(IntPtr d, IntPtr pHeightData, int bCopyHeightData, | ||
809 | dReal width, dReal depth, int widthSamples, int depthSamples, | ||
810 | dReal scale, dReal offset, dReal thickness, int bWrap); | ||
811 | |||
812 | [DllImport("ode", EntryPoint = "dGeomHeightfieldDataCreate"), SuppressUnmanagedCodeSecurity] | ||
813 | public static extern IntPtr GeomHeightfieldDataCreate(); | ||
814 | |||
815 | [DllImport("ode", EntryPoint = "dGeomHeightfieldDataDestroy"), SuppressUnmanagedCodeSecurity] | ||
816 | public static extern void GeomHeightfieldDataDestroy(IntPtr d); | ||
817 | |||
818 | [DllImport("ode", EntryPoint = "dGeomHeightfieldDataSetBounds"), SuppressUnmanagedCodeSecurity] | ||
819 | public static extern void GeomHeightfieldDataSetBounds(IntPtr d, dReal minHeight, dReal maxHeight); | ||
820 | |||
821 | [DllImport("ode", EntryPoint = "dGeomHeightfieldGetHeightfieldData"), SuppressUnmanagedCodeSecurity] | ||
822 | public static extern IntPtr GeomHeightfieldGetHeightfieldData(IntPtr g); | ||
823 | |||
824 | [DllImport("ode", EntryPoint = "dGeomHeightfieldSetHeightfieldData"), SuppressUnmanagedCodeSecurity] | ||
825 | public static extern void GeomHeightfieldSetHeightfieldData(IntPtr g, IntPtr d); | ||
826 | |||
827 | [DllImport("ode", EntryPoint = "dGeomIsEnabled"), SuppressUnmanagedCodeSecurity] | ||
828 | public static extern bool GeomIsEnabled(IntPtr geom); | ||
829 | |||
830 | [DllImport("ode", EntryPoint = "dGeomIsOffset"), SuppressUnmanagedCodeSecurity] | ||
831 | public static extern bool GeomIsOffset(IntPtr geom); | ||
832 | |||
833 | [DllImport("ode", EntryPoint = "dGeomIsSpace"), SuppressUnmanagedCodeSecurity] | ||
834 | public static extern bool GeomIsSpace(IntPtr geom); | ||
835 | |||
836 | [DllImport("ode", EntryPoint = "dGeomPlaneGetParams"), SuppressUnmanagedCodeSecurity] | ||
837 | public static extern void GeomPlaneGetParams(IntPtr geom, ref Vector4 result); | ||
838 | |||
839 | [DllImport("ode", EntryPoint = "dGeomPlaneGetParams"), SuppressUnmanagedCodeSecurity] | ||
840 | public static extern void GeomPlaneGetParams(IntPtr geom, ref dReal A); | ||
841 | |||
842 | [DllImport("ode", EntryPoint = "dGeomPlanePointDepth"), SuppressUnmanagedCodeSecurity] | ||
843 | public static extern dReal GeomPlanePointDepth(IntPtr geom, dReal x, dReal y, dReal z); | ||
844 | |||
845 | [DllImport("ode", EntryPoint = "dGeomPlaneSetParams"), SuppressUnmanagedCodeSecurity] | ||
846 | public static extern void GeomPlaneSetParams(IntPtr plane, dReal a, dReal b, dReal c, dReal d); | ||
847 | |||
848 | [DllImport("ode", EntryPoint = "dGeomRayGet"), SuppressUnmanagedCodeSecurity] | ||
849 | public static extern void GeomRayGet(IntPtr ray, ref Vector3 start, ref Vector3 dir); | ||
850 | |||
851 | [DllImport("ode", EntryPoint = "dGeomRayGet"), SuppressUnmanagedCodeSecurity] | ||
852 | public static extern void GeomRayGet(IntPtr ray, ref dReal startX, ref dReal dirX); | ||
853 | |||
854 | [DllImport("ode", EntryPoint = "dGeomRayGetClosestHit"), SuppressUnmanagedCodeSecurity] | ||
855 | public static extern int GeomRayGetClosestHit(IntPtr ray); | ||
856 | |||
857 | [DllImport("ode", EntryPoint = "dGeomRayGetLength"), SuppressUnmanagedCodeSecurity] | ||
858 | public static extern dReal GeomRayGetLength(IntPtr ray); | ||
859 | |||
860 | [DllImport("ode", EntryPoint = "dGeomRayGetParams"), SuppressUnmanagedCodeSecurity] | ||
861 | public static extern dReal GeomRayGetParams(IntPtr g, out int firstContact, out int backfaceCull); | ||
862 | |||
863 | [DllImport("ode", EntryPoint = "dGeomRaySet"), SuppressUnmanagedCodeSecurity] | ||
864 | public static extern void GeomRaySet(IntPtr ray, dReal px, dReal py, dReal pz, dReal dx, dReal dy, dReal dz); | ||
865 | |||
866 | [DllImport("ode", EntryPoint = "dGeomRaySetClosestHit"), SuppressUnmanagedCodeSecurity] | ||
867 | public static extern void GeomRaySetClosestHit(IntPtr ray, int closestHit); | ||
868 | |||
869 | [DllImport("ode", EntryPoint = "dGeomRaySetLength"), SuppressUnmanagedCodeSecurity] | ||
870 | public static extern void GeomRaySetLength(IntPtr ray, dReal length); | ||
871 | |||
872 | [DllImport("ode", EntryPoint = "dGeomRaySetParams"), SuppressUnmanagedCodeSecurity] | ||
873 | public static extern void GeomRaySetParams(IntPtr ray, int firstContact, int backfaceCull); | ||
874 | |||
875 | [DllImport("ode", EntryPoint = "dGeomSetBody"), SuppressUnmanagedCodeSecurity] | ||
876 | public static extern void GeomSetBody(IntPtr geom, IntPtr body); | ||
877 | |||
878 | [DllImport("ode", EntryPoint = "dGeomSetCategoryBits"), SuppressUnmanagedCodeSecurity] | ||
879 | public static extern void GeomSetCategoryBits(IntPtr geom, int bits); | ||
880 | |||
881 | [DllImport("ode", EntryPoint = "dGeomSetCollideBits"), SuppressUnmanagedCodeSecurity] | ||
882 | public static extern void GeomSetCollideBits(IntPtr geom, int bits); | ||
883 | |||
884 | [DllImport("ode", EntryPoint = "dGeomSetConvex"), SuppressUnmanagedCodeSecurity] | ||
885 | public static extern IntPtr GeomSetConvex(IntPtr geom, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons); | ||
886 | |||
887 | [DllImport("ode", EntryPoint = "dGeomSetData"), SuppressUnmanagedCodeSecurity] | ||
888 | public static extern void GeomSetData(IntPtr geom, IntPtr data); | ||
889 | |||
890 | [DllImport("ode", EntryPoint = "dGeomSetOffsetPosition"), SuppressUnmanagedCodeSecurity] | ||
891 | public static extern void GeomSetOffsetPosition(IntPtr geom, dReal x, dReal y, dReal z); | ||
892 | |||
893 | [DllImport("ode", EntryPoint = "dGeomSetOffsetQuaternion"), SuppressUnmanagedCodeSecurity] | ||
894 | public static extern void GeomSetOffsetQuaternion(IntPtr geom, ref Quaternion Q); | ||
895 | |||
896 | [DllImport("ode", EntryPoint = "dGeomSetOffsetQuaternion"), SuppressUnmanagedCodeSecurity] | ||
897 | public static extern void GeomSetOffsetQuaternion(IntPtr geom, ref dReal X); | ||
898 | |||
899 | [DllImport("ode", EntryPoint = "dGeomSetOffsetRotation"), SuppressUnmanagedCodeSecurity] | ||
900 | public static extern void GeomSetOffsetRotation(IntPtr geom, ref Matrix3 R); | ||
901 | |||
902 | [DllImport("ode", EntryPoint = "dGeomSetOffsetRotation"), SuppressUnmanagedCodeSecurity] | ||
903 | public static extern void GeomSetOffsetRotation(IntPtr geom, ref dReal M00); | ||
904 | |||
905 | [DllImport("ode", EntryPoint = "dGeomSetOffsetWorldPosition"), SuppressUnmanagedCodeSecurity] | ||
906 | public static extern void GeomSetOffsetWorldPosition(IntPtr geom, dReal x, dReal y, dReal z); | ||
907 | |||
908 | [DllImport("ode", EntryPoint = "dGeomSetOffsetWorldQuaternion"), SuppressUnmanagedCodeSecurity] | ||
909 | public static extern void GeomSetOffsetWorldQuaternion(IntPtr geom, ref Quaternion Q); | ||
910 | |||
911 | [DllImport("ode", EntryPoint = "dGeomSetOffsetWorldQuaternion"), SuppressUnmanagedCodeSecurity] | ||
912 | public static extern void GeomSetOffsetWorldQuaternion(IntPtr geom, ref dReal X); | ||
913 | |||
914 | [DllImport("ode", EntryPoint = "dGeomSetOffsetWorldRotation"), SuppressUnmanagedCodeSecurity] | ||
915 | public static extern void GeomSetOffsetWorldRotation(IntPtr geom, ref Matrix3 R); | ||
916 | |||
917 | [DllImport("ode", EntryPoint = "dGeomSetOffsetWorldRotation"), SuppressUnmanagedCodeSecurity] | ||
918 | public static extern void GeomSetOffsetWorldRotation(IntPtr geom, ref dReal M00); | ||
919 | |||
920 | [DllImport("ode", EntryPoint = "dGeomSetPosition"), SuppressUnmanagedCodeSecurity] | ||
921 | public static extern void GeomSetPosition(IntPtr geom, dReal x, dReal y, dReal z); | ||
922 | |||
923 | [DllImport("ode", EntryPoint = "dGeomSetQuaternion"), SuppressUnmanagedCodeSecurity] | ||
924 | public static extern void GeomSetQuaternion(IntPtr geom, ref Quaternion quat); | ||
925 | |||
926 | [DllImport("ode", EntryPoint = "dGeomSetQuaternion"), SuppressUnmanagedCodeSecurity] | ||
927 | public static extern void GeomSetQuaternion(IntPtr geom, ref dReal w); | ||
928 | |||
929 | [DllImport("ode", EntryPoint = "dGeomSetRotation"), SuppressUnmanagedCodeSecurity] | ||
930 | public static extern void GeomSetRotation(IntPtr geom, ref Matrix3 R); | ||
931 | |||
932 | [DllImport("ode", EntryPoint = "dGeomSetRotation"), SuppressUnmanagedCodeSecurity] | ||
933 | public static extern void GeomSetRotation(IntPtr geom, ref dReal M00); | ||
934 | |||
935 | [DllImport("ode", EntryPoint = "dGeomSphereGetRadius"), SuppressUnmanagedCodeSecurity] | ||
936 | public static extern dReal GeomSphereGetRadius(IntPtr geom); | ||
937 | |||
938 | [DllImport("ode", EntryPoint = "dGeomSpherePointDepth"), SuppressUnmanagedCodeSecurity] | ||
939 | public static extern dReal GeomSpherePointDepth(IntPtr geom, dReal x, dReal y, dReal z); | ||
940 | |||
941 | [DllImport("ode", EntryPoint = "dGeomSphereSetRadius"), SuppressUnmanagedCodeSecurity] | ||
942 | public static extern void GeomSphereSetRadius(IntPtr geom, dReal radius); | ||
943 | |||
944 | [DllImport("ode", EntryPoint = "dGeomTransformGetCleanup"), SuppressUnmanagedCodeSecurity] | ||
945 | public static extern int GeomTransformGetCleanup(IntPtr geom); | ||
946 | |||
947 | [DllImport("ode", EntryPoint = "dGeomTransformGetGeom"), SuppressUnmanagedCodeSecurity] | ||
948 | public static extern IntPtr GeomTransformGetGeom(IntPtr geom); | ||
949 | |||
950 | [DllImport("ode", EntryPoint = "dGeomTransformGetInfo"), SuppressUnmanagedCodeSecurity] | ||
951 | public static extern int GeomTransformGetInfo(IntPtr geom); | ||
952 | |||
953 | [DllImport("ode", EntryPoint = "dGeomTransformSetCleanup"), SuppressUnmanagedCodeSecurity] | ||
954 | public static extern void GeomTransformSetCleanup(IntPtr geom, int mode); | ||
955 | |||
956 | [DllImport("ode", EntryPoint = "dGeomTransformSetGeom"), SuppressUnmanagedCodeSecurity] | ||
957 | public static extern void GeomTransformSetGeom(IntPtr geom, IntPtr obj); | ||
958 | |||
959 | [DllImport("ode", EntryPoint = "dGeomTransformSetInfo"), SuppressUnmanagedCodeSecurity] | ||
960 | public static extern void GeomTransformSetInfo(IntPtr geom, int info); | ||
961 | |||
962 | [DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildDouble"), SuppressUnmanagedCodeSecurity] | ||
963 | public static extern void GeomTriMeshDataBuildDouble(IntPtr d, | ||
964 | double[] vertices, int vertexStride, int vertexCount, | ||
965 | int[] indices, int indexCount, int triStride); | ||
966 | |||
967 | [DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildDouble"), SuppressUnmanagedCodeSecurity] | ||
968 | public static extern void GeomTriMeshDataBuildDouble(IntPtr d, | ||
969 | IntPtr vertices, int vertexStride, int vertexCount, | ||
970 | IntPtr indices, int indexCount, int triStride); | ||
971 | |||
972 | [DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildDouble1"), SuppressUnmanagedCodeSecurity] | ||
973 | public static extern void GeomTriMeshDataBuildDouble1(IntPtr d, | ||
974 | double[] vertices, int vertexStride, int vertexCount, | ||
975 | int[] indices, int indexCount, int triStride, | ||
976 | double[] normals); | ||
977 | |||
978 | [DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildDouble1"), SuppressUnmanagedCodeSecurity] | ||
979 | public static extern void GeomTriMeshDataBuildDouble(IntPtr d, | ||
980 | IntPtr vertices, int vertexStride, int vertexCount, | ||
981 | IntPtr indices, int indexCount, int triStride, | ||
982 | IntPtr normals); | ||
983 | |||
984 | [DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildSimple"), SuppressUnmanagedCodeSecurity] | ||
985 | public static extern void GeomTriMeshDataBuildSingle(IntPtr d, | ||
986 | dReal[] vertices, int vertexStride, int vertexCount, | ||
987 | int[] indices, int indexCount, int triStride); | ||
988 | |||
989 | [DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildSimple"), SuppressUnmanagedCodeSecurity] | ||
990 | public static extern void GeomTriMeshDataBuildSingle(IntPtr d, | ||
991 | IntPtr vertices, int vertexStride, int vertexCount, | ||
992 | IntPtr indices, int indexCount, int triStride); | ||
993 | |||
994 | [DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildSimple1"), SuppressUnmanagedCodeSecurity] | ||
995 | public static extern void GeomTriMeshDataBuildSingle1(IntPtr d, | ||
996 | dReal[] vertices, int vertexStride, int vertexCount, | ||
997 | int[] indices, int indexCount, int triStride, | ||
998 | dReal[] normals); | ||
999 | |||
1000 | [DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildSimple1"), SuppressUnmanagedCodeSecurity] | ||
1001 | public static extern void GeomTriMeshDataBuildSingle1(IntPtr d, | ||
1002 | IntPtr vertices, int vertexStride, int vertexCount, | ||
1003 | IntPtr indices, int indexCount, int triStride, | ||
1004 | IntPtr normals); | ||
1005 | |||
1006 | [DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildSingle"), SuppressUnmanagedCodeSecurity] | ||
1007 | public static extern void GeomTriMeshDataBuildSimple(IntPtr d, | ||
1008 | float[] vertices, int vertexStride, int vertexCount, | ||
1009 | int[] indices, int indexCount, int triStride); | ||
1010 | |||
1011 | [DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildSingle"), SuppressUnmanagedCodeSecurity] | ||
1012 | public static extern void GeomTriMeshDataBuildSimple(IntPtr d, | ||
1013 | IntPtr vertices, int vertexStride, int vertexCount, | ||
1014 | IntPtr indices, int indexCount, int triStride); | ||
1015 | |||
1016 | [DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildSingle1"), SuppressUnmanagedCodeSecurity] | ||
1017 | public static extern void GeomTriMeshDataBuildSimple1(IntPtr d, | ||
1018 | float[] vertices, int vertexStride, int vertexCount, | ||
1019 | int[] indices, int indexCount, int triStride, | ||
1020 | float[] normals); | ||
1021 | |||
1022 | [DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildSingle1"), SuppressUnmanagedCodeSecurity] | ||
1023 | public static extern void GeomTriMeshDataBuildSimple1(IntPtr d, | ||
1024 | IntPtr vertices, int vertexStride, int vertexCount, | ||
1025 | IntPtr indices, int indexCount, int triStride, | ||
1026 | IntPtr normals); | ||
1027 | |||
1028 | [DllImport("ode", EntryPoint = "dGeomTriMeshClearTCCache"), SuppressUnmanagedCodeSecurity] | ||
1029 | public static extern void GeomTriMeshClearTCCache(IntPtr g); | ||
1030 | |||
1031 | [DllImport("ode", EntryPoint = "dGeomTriMeshDataCreate"), SuppressUnmanagedCodeSecurity] | ||
1032 | public static extern IntPtr GeomTriMeshDataCreate(); | ||
1033 | |||
1034 | [DllImport("ode", EntryPoint = "dGeomTriMeshDataDestroy"), SuppressUnmanagedCodeSecurity] | ||
1035 | public static extern void GeomTriMeshDataDestroy(IntPtr d); | ||
1036 | |||
1037 | [DllImport("ode", EntryPoint = "dGeomTriMeshDataGet"), SuppressUnmanagedCodeSecurity] | ||
1038 | public static extern IntPtr GeomTriMeshDataGet(IntPtr d, int data_id); | ||
1039 | |||
1040 | [DllImport("ode", EntryPoint = "dGeomTriMeshDataPreprocess"), SuppressUnmanagedCodeSecurity] | ||
1041 | public static extern void GeomTriMeshDataPreprocess(IntPtr d); | ||
1042 | |||
1043 | [DllImport("ode", EntryPoint = "dGeomTriMeshDataSet"), SuppressUnmanagedCodeSecurity] | ||
1044 | public static extern void GeomTriMeshDataSet(IntPtr d, int data_id, IntPtr in_data); | ||
1045 | |||
1046 | [DllImport("ode", EntryPoint = "dGeomTriMeshDataUpdate"), SuppressUnmanagedCodeSecurity] | ||
1047 | public static extern void GeomTriMeshDataUpdate(IntPtr d); | ||
1048 | |||
1049 | [DllImport("ode", EntryPoint = "dGeomTriMeshEnableTC"), SuppressUnmanagedCodeSecurity] | ||
1050 | public static extern void GeomTriMeshEnableTC(IntPtr g, int geomClass, bool enable); | ||
1051 | |||
1052 | [DllImport("ode", EntryPoint = "dGeomTriMeshGetArrayCallback"), SuppressUnmanagedCodeSecurity] | ||
1053 | public static extern TriArrayCallback GeomTriMeshGetArrayCallback(IntPtr g); | ||
1054 | |||
1055 | [DllImport("ode", EntryPoint = "dGeomTriMeshGetCallback"), SuppressUnmanagedCodeSecurity] | ||
1056 | public static extern TriCallback GeomTriMeshGetCallback(IntPtr g); | ||
1057 | |||
1058 | [DllImport("ode", EntryPoint = "dGeomTriMeshGetData"), SuppressUnmanagedCodeSecurity] | ||
1059 | public static extern IntPtr GeomTriMeshGetData(IntPtr g); | ||
1060 | |||
1061 | #if !dNO_UNSAFE_CODE | ||
1062 | [CLSCompliant(false)] | ||
1063 | [DllImport("ode", EntryPoint = "dGeomTriMeshGetLastTransform"), SuppressUnmanagedCodeSecurity] | ||
1064 | public extern unsafe static Matrix4* GeomTriMeshGetLastTransformUnsafe(IntPtr geom); | ||
1065 | public static Matrix4 GeomTriMeshGetLastTransform(IntPtr geom) | ||
1066 | { | ||
1067 | unsafe { return *(GeomTriMeshGetLastTransformUnsafe(geom)); } | ||
1068 | } | ||
1069 | #endif | ||
1070 | |||
1071 | [DllImport("ode", EntryPoint = "dGeomTriMeshGetPoint"), SuppressUnmanagedCodeSecurity] | ||
1072 | public extern static void GeomTriMeshGetPoint(IntPtr g, int index, dReal u, dReal v, ref Vector3 outVec); | ||
1073 | |||
1074 | [DllImport("ode", EntryPoint = "dGeomTriMeshGetRayCallback"), SuppressUnmanagedCodeSecurity] | ||
1075 | public static extern TriRayCallback GeomTriMeshGetRayCallback(IntPtr g); | ||
1076 | |||
1077 | [DllImport("ode", EntryPoint = "dGeomTriMeshGetTriangle"), SuppressUnmanagedCodeSecurity] | ||
1078 | public extern static void GeomTriMeshGetTriangle(IntPtr g, int index, ref Vector3 v0, ref Vector3 v1, ref Vector3 v2); | ||
1079 | |||
1080 | [DllImport("ode", EntryPoint = "dGeomTriMeshGetTriangleCount"), SuppressUnmanagedCodeSecurity] | ||
1081 | public extern static int GeomTriMeshGetTriangleCount(IntPtr g); | ||
1082 | |||
1083 | [DllImport("ode", EntryPoint = "dGeomTriMeshGetTriMeshDataID"), SuppressUnmanagedCodeSecurity] | ||
1084 | public static extern IntPtr GeomTriMeshGetTriMeshDataID(IntPtr g); | ||
1085 | |||
1086 | [DllImport("ode", EntryPoint = "dGeomTriMeshIsTCEnabled"), SuppressUnmanagedCodeSecurity] | ||
1087 | public static extern bool GeomTriMeshIsTCEnabled(IntPtr g, int geomClass); | ||
1088 | |||
1089 | [DllImport("ode", EntryPoint = "dGeomTriMeshSetArrayCallback"), SuppressUnmanagedCodeSecurity] | ||
1090 | public static extern void GeomTriMeshSetArrayCallback(IntPtr g, TriArrayCallback arrayCallback); | ||
1091 | |||
1092 | [DllImport("ode", EntryPoint = "dGeomTriMeshSetCallback"), SuppressUnmanagedCodeSecurity] | ||
1093 | public static extern void GeomTriMeshSetCallback(IntPtr g, TriCallback callback); | ||
1094 | |||
1095 | [DllImport("ode", EntryPoint = "dGeomTriMeshSetData"), SuppressUnmanagedCodeSecurity] | ||
1096 | public static extern void GeomTriMeshSetData(IntPtr g, IntPtr data); | ||
1097 | |||
1098 | [DllImport("ode", EntryPoint = "dGeomTriMeshSetLastTransform"), SuppressUnmanagedCodeSecurity] | ||
1099 | public static extern void GeomTriMeshSetLastTransform(IntPtr g, ref Matrix4 last_trans); | ||
1100 | |||
1101 | [DllImport("ode", EntryPoint = "dGeomTriMeshSetLastTransform"), SuppressUnmanagedCodeSecurity] | ||
1102 | public static extern void GeomTriMeshSetLastTransform(IntPtr g, ref dReal M00); | ||
1103 | |||
1104 | [DllImport("ode", EntryPoint = "dGeomTriMeshSetRayCallback"), SuppressUnmanagedCodeSecurity] | ||
1105 | public static extern void GeomTriMeshSetRayCallback(IntPtr g, TriRayCallback callback); | ||
1106 | |||
1107 | [DllImport("ode", EntryPoint = "dHashSpaceCreate"), SuppressUnmanagedCodeSecurity] | ||
1108 | public static extern IntPtr HashSpaceCreate(IntPtr space); | ||
1109 | |||
1110 | [DllImport("ode", EntryPoint = "dHashSpaceGetLevels"), SuppressUnmanagedCodeSecurity] | ||
1111 | public static extern void HashSpaceGetLevels(IntPtr space, out int minlevel, out int maxlevel); | ||
1112 | |||
1113 | [DllImport("ode", EntryPoint = "dHashSpaceSetLevels"), SuppressUnmanagedCodeSecurity] | ||
1114 | public static extern void HashSpaceSetLevels(IntPtr space, int minlevel, int maxlevel); | ||
1115 | |||
1116 | [DllImport("ode", EntryPoint = "dInfiniteAABB"), SuppressUnmanagedCodeSecurity] | ||
1117 | public static extern void InfiniteAABB(IntPtr geom, out AABB aabb); | ||
1118 | |||
1119 | [DllImport("ode", EntryPoint = "dInitODE"), SuppressUnmanagedCodeSecurity] | ||
1120 | public static extern void InitODE(); | ||
1121 | |||
1122 | [DllImport("ode", EntryPoint = "dIsPositiveDefinite"), SuppressUnmanagedCodeSecurity] | ||
1123 | public static extern int IsPositiveDefinite(ref dReal A, int n); | ||
1124 | |||
1125 | [DllImport("ode", EntryPoint = "dInvertPDMatrix"), SuppressUnmanagedCodeSecurity] | ||
1126 | public static extern int InvertPDMatrix(ref dReal A, out dReal Ainv, int n); | ||
1127 | |||
1128 | [DllImport("ode", EntryPoint = "dJointAddAMotorTorques"), SuppressUnmanagedCodeSecurity] | ||
1129 | public static extern void JointAddAMotorTorques(IntPtr joint, dReal torque1, dReal torque2, dReal torque3); | ||
1130 | |||
1131 | [DllImport("ode", EntryPoint = "dJointAddHingeTorque"), SuppressUnmanagedCodeSecurity] | ||
1132 | public static extern void JointAddHingeTorque(IntPtr joint, dReal torque); | ||
1133 | |||
1134 | [DllImport("ode", EntryPoint = "dJointAddHinge2Torque"), SuppressUnmanagedCodeSecurity] | ||
1135 | public static extern void JointAddHinge2Torques(IntPtr joint, dReal torque1, dReal torque2); | ||
1136 | |||
1137 | [DllImport("ode", EntryPoint = "dJointAddPRTorque"), SuppressUnmanagedCodeSecurity] | ||
1138 | public static extern void JointAddPRTorque(IntPtr joint, dReal torque); | ||
1139 | |||
1140 | [DllImport("ode", EntryPoint = "dJointAddUniversalTorque"), SuppressUnmanagedCodeSecurity] | ||
1141 | public static extern void JointAddUniversalTorques(IntPtr joint, dReal torque1, dReal torque2); | ||
1142 | |||
1143 | [DllImport("ode", EntryPoint = "dJointAddSliderForce"), SuppressUnmanagedCodeSecurity] | ||
1144 | public static extern void JointAddSliderForce(IntPtr joint, dReal force); | ||
1145 | |||
1146 | [DllImport("ode", EntryPoint = "dJointAttach"), SuppressUnmanagedCodeSecurity] | ||
1147 | public static extern void JointAttach(IntPtr joint, IntPtr body1, IntPtr body2); | ||
1148 | |||
1149 | [DllImport("ode", EntryPoint = "dJointCreateAMotor"), SuppressUnmanagedCodeSecurity] | ||
1150 | public static extern IntPtr JointCreateAMotor(IntPtr world, IntPtr group); | ||
1151 | |||
1152 | [DllImport("ode", EntryPoint = "dJointCreateBall"), SuppressUnmanagedCodeSecurity] | ||
1153 | public static extern IntPtr JointCreateBall(IntPtr world, IntPtr group); | ||
1154 | |||
1155 | [DllImport("ode", EntryPoint = "dJointCreateContact"), SuppressUnmanagedCodeSecurity] | ||
1156 | public static extern IntPtr JointCreateContact(IntPtr world, IntPtr group, ref Contact contact); | ||
1157 | |||
1158 | [DllImport("ode", EntryPoint = "dJointCreateFixed"), SuppressUnmanagedCodeSecurity] | ||
1159 | public static extern IntPtr JointCreateFixed(IntPtr world, IntPtr group); | ||
1160 | |||
1161 | [DllImport("ode", EntryPoint = "dJointCreateHinge"), SuppressUnmanagedCodeSecurity] | ||
1162 | public static extern IntPtr JointCreateHinge(IntPtr world, IntPtr group); | ||
1163 | |||
1164 | [DllImport("ode", EntryPoint = "dJointCreateHinge2"), SuppressUnmanagedCodeSecurity] | ||
1165 | public static extern IntPtr JointCreateHinge2(IntPtr world, IntPtr group); | ||
1166 | |||
1167 | [DllImport("ode", EntryPoint = "dJointCreateLMotor"), SuppressUnmanagedCodeSecurity] | ||
1168 | public static extern IntPtr JointCreateLMotor(IntPtr world, IntPtr group); | ||
1169 | |||
1170 | [DllImport("ode", EntryPoint = "dJointCreateNull"), SuppressUnmanagedCodeSecurity] | ||
1171 | public static extern IntPtr JointCreateNull(IntPtr world, IntPtr group); | ||
1172 | |||
1173 | [DllImport("ode", EntryPoint = "dJointCreatePR"), SuppressUnmanagedCodeSecurity] | ||
1174 | public static extern IntPtr JointCreatePR(IntPtr world, IntPtr group); | ||
1175 | |||
1176 | [DllImport("ode", EntryPoint = "dJointCreatePlane2D"), SuppressUnmanagedCodeSecurity] | ||
1177 | public static extern IntPtr JointCreatePlane2D(IntPtr world, IntPtr group); | ||
1178 | |||
1179 | [DllImport("ode", EntryPoint = "dJointCreateSlider"), SuppressUnmanagedCodeSecurity] | ||
1180 | public static extern IntPtr JointCreateSlider(IntPtr world, IntPtr group); | ||
1181 | |||
1182 | [DllImport("ode", EntryPoint = "dJointCreateUniversal"), SuppressUnmanagedCodeSecurity] | ||
1183 | public static extern IntPtr JointCreateUniversal(IntPtr world, IntPtr group); | ||
1184 | |||
1185 | [DllImport("ode", EntryPoint = "dJointDestroy"), SuppressUnmanagedCodeSecurity] | ||
1186 | public static extern void JointDestroy(IntPtr j); | ||
1187 | |||
1188 | [DllImport("ode", EntryPoint = "dJointGetAMotorAngle"), SuppressUnmanagedCodeSecurity] | ||
1189 | public static extern dReal JointGetAMotorAngle(IntPtr j, int anum); | ||
1190 | |||
1191 | [DllImport("ode", EntryPoint = "dJointGetAMotorAngleRate"), SuppressUnmanagedCodeSecurity] | ||
1192 | public static extern dReal JointGetAMotorAngleRate(IntPtr j, int anum); | ||
1193 | |||
1194 | [DllImport("ode", EntryPoint = "dJointGetAMotorAxis"), SuppressUnmanagedCodeSecurity] | ||
1195 | public static extern void JointGetAMotorAxis(IntPtr j, int anum, out Vector3 result); | ||
1196 | |||
1197 | [DllImport("ode", EntryPoint = "dJointGetAMotorAxisRel"), SuppressUnmanagedCodeSecurity] | ||
1198 | public static extern int JointGetAMotorAxisRel(IntPtr j, int anum); | ||
1199 | |||
1200 | [DllImport("ode", EntryPoint = "dJointGetAMotorMode"), SuppressUnmanagedCodeSecurity] | ||
1201 | public static extern int JointGetAMotorMode(IntPtr j); | ||
1202 | |||
1203 | [DllImport("ode", EntryPoint = "dJointGetAMotorNumAxes"), SuppressUnmanagedCodeSecurity] | ||
1204 | public static extern int JointGetAMotorNumAxes(IntPtr j); | ||
1205 | |||
1206 | [DllImport("ode", EntryPoint = "dJointGetAMotorParam"), SuppressUnmanagedCodeSecurity] | ||
1207 | public static extern dReal JointGetAMotorParam(IntPtr j, int parameter); | ||
1208 | |||
1209 | [DllImport("ode", EntryPoint = "dJointGetBallAnchor"), SuppressUnmanagedCodeSecurity] | ||
1210 | public static extern void JointGetBallAnchor(IntPtr j, out Vector3 result); | ||
1211 | |||
1212 | [DllImport("ode", EntryPoint = "dJointGetBallAnchor2"), SuppressUnmanagedCodeSecurity] | ||
1213 | public static extern void JointGetBallAnchor2(IntPtr j, out Vector3 result); | ||
1214 | |||
1215 | [DllImport("ode", EntryPoint = "dJointGetBody"), SuppressUnmanagedCodeSecurity] | ||
1216 | public static extern IntPtr JointGetBody(IntPtr j); | ||
1217 | |||
1218 | [DllImport("ode", EntryPoint = "dJointGetData"), SuppressUnmanagedCodeSecurity] | ||
1219 | public static extern IntPtr JointGetData(IntPtr j); | ||
1220 | |||
1221 | #if !dNO_UNSAFE_CODE | ||
1222 | [CLSCompliant(false)] | ||
1223 | [DllImport("ode", EntryPoint = "dJointGetFeedback"), SuppressUnmanagedCodeSecurity] | ||
1224 | public extern unsafe static JointFeedback* JointGetFeedbackUnsafe(IntPtr j); | ||
1225 | public static JointFeedback JointGetFeedback(IntPtr j) | ||
1226 | { | ||
1227 | unsafe { return *(JointGetFeedbackUnsafe(j)); } | ||
1228 | } | ||
1229 | #endif | ||
1230 | |||
1231 | [DllImport("ode", EntryPoint = "dJointGetHingeAnchor"), SuppressUnmanagedCodeSecurity] | ||
1232 | public static extern void JointGetHingeAnchor(IntPtr j, out Vector3 result); | ||
1233 | |||
1234 | [DllImport("ode", EntryPoint = "dJointGetHingeAngle"), SuppressUnmanagedCodeSecurity] | ||
1235 | public static extern dReal JointGetHingeAngle(IntPtr j); | ||
1236 | |||
1237 | [DllImport("ode", EntryPoint = "dJointGetHingeAngleRate"), SuppressUnmanagedCodeSecurity] | ||
1238 | public static extern dReal JointGetHingeAngleRate(IntPtr j); | ||
1239 | |||
1240 | [DllImport("ode", EntryPoint = "dJointGetHingeAxis"), SuppressUnmanagedCodeSecurity] | ||
1241 | public static extern void JointGetHingeAxis(IntPtr j, out Vector3 result); | ||
1242 | |||
1243 | [DllImport("ode", EntryPoint = "dJointGetHingeParam"), SuppressUnmanagedCodeSecurity] | ||
1244 | public static extern dReal JointGetHingeParam(IntPtr j, int parameter); | ||
1245 | |||
1246 | [DllImport("ode", EntryPoint = "dJointGetHinge2Angle1"), SuppressUnmanagedCodeSecurity] | ||
1247 | public static extern dReal JointGetHinge2Angle1(IntPtr j); | ||
1248 | |||
1249 | [DllImport("ode", EntryPoint = "dJointGetHinge2Angle1Rate"), SuppressUnmanagedCodeSecurity] | ||
1250 | public static extern dReal JointGetHinge2Angle1Rate(IntPtr j); | ||
1251 | |||
1252 | [DllImport("ode", EntryPoint = "dJointGetHinge2Angle2Rate"), SuppressUnmanagedCodeSecurity] | ||
1253 | public static extern dReal JointGetHinge2Angle2Rate(IntPtr j); | ||
1254 | |||
1255 | [DllImport("ode", EntryPoint = "dJointGetHingeAnchor2"), SuppressUnmanagedCodeSecurity] | ||
1256 | public static extern void JointGetHingeAnchor2(IntPtr j, out Vector3 result); | ||
1257 | |||
1258 | [DllImport("ode", EntryPoint = "dJointGetHinge2Anchor"), SuppressUnmanagedCodeSecurity] | ||
1259 | public static extern void JointGetHinge2Anchor(IntPtr j, out Vector3 result); | ||
1260 | |||
1261 | [DllImport("ode", EntryPoint = "dJointGetHinge2Anchor2"), SuppressUnmanagedCodeSecurity] | ||
1262 | public static extern void JointGetHinge2Anchor2(IntPtr j, out Vector3 result); | ||
1263 | |||
1264 | [DllImport("ode", EntryPoint = "dJointGetHinge2Axis1"), SuppressUnmanagedCodeSecurity] | ||
1265 | public static extern void JointGetHinge2Axis1(IntPtr j, out Vector3 result); | ||
1266 | |||
1267 | [DllImport("ode", EntryPoint = "dJointGetHinge2Axis2"), SuppressUnmanagedCodeSecurity] | ||
1268 | public static extern void JointGetHinge2Axis2(IntPtr j, out Vector3 result); | ||
1269 | |||
1270 | [DllImport("ode", EntryPoint = "dJointGetHinge2Param"), SuppressUnmanagedCodeSecurity] | ||
1271 | public static extern dReal JointGetHinge2Param(IntPtr j, int parameter); | ||
1272 | |||
1273 | [DllImport("ode", EntryPoint = "dJointGetLMotorAxis"), SuppressUnmanagedCodeSecurity] | ||
1274 | public static extern void JointGetLMotorAxis(IntPtr j, int anum, out Vector3 result); | ||
1275 | |||
1276 | [DllImport("ode", EntryPoint = "dJointGetLMotorNumAxes"), SuppressUnmanagedCodeSecurity] | ||
1277 | public static extern int JointGetLMotorNumAxes(IntPtr j); | ||
1278 | |||
1279 | [DllImport("ode", EntryPoint = "dJointGetLMotorParam"), SuppressUnmanagedCodeSecurity] | ||
1280 | public static extern dReal JointGetLMotorParam(IntPtr j, int parameter); | ||
1281 | |||
1282 | [DllImport("ode", EntryPoint = "dJointGetPRAnchor"), SuppressUnmanagedCodeSecurity] | ||
1283 | public static extern void JointGetPRAnchor(IntPtr j, out Vector3 result); | ||
1284 | |||
1285 | [DllImport("ode", EntryPoint = "dJointGetPRAxis1"), SuppressUnmanagedCodeSecurity] | ||
1286 | public static extern void JointGetPRAxis1(IntPtr j, out Vector3 result); | ||
1287 | |||
1288 | [DllImport("ode", EntryPoint = "dJointGetPRAxis2"), SuppressUnmanagedCodeSecurity] | ||
1289 | public static extern void JointGetPRAxis2(IntPtr j, out Vector3 result); | ||
1290 | |||
1291 | [DllImport("ode", EntryPoint = "dJointGetPRParam"), SuppressUnmanagedCodeSecurity] | ||
1292 | public static extern dReal JointGetPRParam(IntPtr j, int parameter); | ||
1293 | |||
1294 | [DllImport("ode", EntryPoint = "dJointGetPRPosition"), SuppressUnmanagedCodeSecurity] | ||
1295 | public static extern dReal JointGetPRPosition(IntPtr j); | ||
1296 | |||
1297 | [DllImport("ode", EntryPoint = "dJointGetPRPositionRate"), SuppressUnmanagedCodeSecurity] | ||
1298 | public static extern dReal JointGetPRPositionRate(IntPtr j); | ||
1299 | |||
1300 | [DllImport("ode", EntryPoint = "dJointGetSliderAxis"), SuppressUnmanagedCodeSecurity] | ||
1301 | public static extern void JointGetSliderAxis(IntPtr j, out Vector3 result); | ||
1302 | |||
1303 | [DllImport("ode", EntryPoint = "dJointGetSliderParam"), SuppressUnmanagedCodeSecurity] | ||
1304 | public static extern dReal JointGetSliderParam(IntPtr j, int parameter); | ||
1305 | |||
1306 | [DllImport("ode", EntryPoint = "dJointGetSliderPosition"), SuppressUnmanagedCodeSecurity] | ||
1307 | public static extern dReal JointGetSliderPosition(IntPtr j); | ||
1308 | |||
1309 | [DllImport("ode", EntryPoint = "dJointGetSliderPositionRate"), SuppressUnmanagedCodeSecurity] | ||
1310 | public static extern dReal JointGetSliderPositionRate(IntPtr j); | ||
1311 | |||
1312 | [DllImport("ode", EntryPoint = "dJointGetType"), SuppressUnmanagedCodeSecurity] | ||
1313 | public static extern JointType JointGetType(IntPtr j); | ||
1314 | |||
1315 | [DllImport("ode", EntryPoint = "dJointGetUniversalAnchor"), SuppressUnmanagedCodeSecurity] | ||
1316 | public static extern void JointGetUniversalAnchor(IntPtr j, out Vector3 result); | ||
1317 | |||
1318 | [DllImport("ode", EntryPoint = "dJointGetUniversalAnchor2"), SuppressUnmanagedCodeSecurity] | ||
1319 | public static extern void JointGetUniversalAnchor2(IntPtr j, out Vector3 result); | ||
1320 | |||
1321 | [DllImport("ode", EntryPoint = "dJointGetUniversalAngle1"), SuppressUnmanagedCodeSecurity] | ||
1322 | public static extern dReal JointGetUniversalAngle1(IntPtr j); | ||
1323 | |||
1324 | [DllImport("ode", EntryPoint = "dJointGetUniversalAngle1Rate"), SuppressUnmanagedCodeSecurity] | ||
1325 | public static extern dReal JointGetUniversalAngle1Rate(IntPtr j); | ||
1326 | |||
1327 | [DllImport("ode", EntryPoint = "dJointGetUniversalAngle2"), SuppressUnmanagedCodeSecurity] | ||
1328 | public static extern dReal JointGetUniversalAngle2(IntPtr j); | ||
1329 | |||
1330 | [DllImport("ode", EntryPoint = "dJointGetUniversalAngle2Rate"), SuppressUnmanagedCodeSecurity] | ||
1331 | public static extern dReal JointGetUniversalAngle2Rate(IntPtr j); | ||
1332 | |||
1333 | [DllImport("ode", EntryPoint = "dJointGetUniversalAngles"), SuppressUnmanagedCodeSecurity] | ||
1334 | public static extern void JointGetUniversalAngles(IntPtr j, out dReal angle1, out dReal angle2); | ||
1335 | |||
1336 | [DllImport("ode", EntryPoint = "dJointGetUniversalAxis1"), SuppressUnmanagedCodeSecurity] | ||
1337 | public static extern void JointGetUniversalAxis1(IntPtr j, out Vector3 result); | ||
1338 | |||
1339 | [DllImport("ode", EntryPoint = "dJointGetUniversalAxis2"), SuppressUnmanagedCodeSecurity] | ||
1340 | public static extern void JointGetUniversalAxis2(IntPtr j, out Vector3 result); | ||
1341 | |||
1342 | [DllImport("ode", EntryPoint = "dJointGetUniversalParam"), SuppressUnmanagedCodeSecurity] | ||
1343 | public static extern dReal JointGetUniversalParam(IntPtr j, int parameter); | ||
1344 | |||
1345 | [DllImport("ode", EntryPoint = "dJointGroupCreate"), SuppressUnmanagedCodeSecurity] | ||
1346 | public static extern IntPtr JointGroupCreate(int max_size); | ||
1347 | |||
1348 | [DllImport("ode", EntryPoint = "dJointGroupDestroy"), SuppressUnmanagedCodeSecurity] | ||
1349 | public static extern void JointGroupDestroy(IntPtr group); | ||
1350 | |||
1351 | [DllImport("ode", EntryPoint = "dJointGroupEmpty"), SuppressUnmanagedCodeSecurity] | ||
1352 | public static extern void JointGroupEmpty(IntPtr group); | ||
1353 | |||
1354 | [DllImport("ode", EntryPoint = "dJointSetAMotorAngle"), SuppressUnmanagedCodeSecurity] | ||
1355 | public static extern void JointSetAMotorAngle(IntPtr j, int anum, dReal angle); | ||
1356 | |||
1357 | [DllImport("ode", EntryPoint = "dJointSetAMotorAxis"), SuppressUnmanagedCodeSecurity] | ||
1358 | public static extern void JointSetAMotorAxis(IntPtr j, int anum, int rel, dReal x, dReal y, dReal z); | ||
1359 | |||
1360 | [DllImport("ode", EntryPoint = "dJointSetAMotorMode"), SuppressUnmanagedCodeSecurity] | ||
1361 | public static extern void JointSetAMotorMode(IntPtr j, int mode); | ||
1362 | |||
1363 | [DllImport("ode", EntryPoint = "dJointSetAMotorNumAxes"), SuppressUnmanagedCodeSecurity] | ||
1364 | public static extern void JointSetAMotorNumAxes(IntPtr group, int num); | ||
1365 | |||
1366 | [DllImport("ode", EntryPoint = "dJointSetAMotorParam"), SuppressUnmanagedCodeSecurity] | ||
1367 | public static extern void JointSetAMotorParam(IntPtr group, int parameter, dReal value); | ||
1368 | |||
1369 | [DllImport("ode", EntryPoint = "dJointSetBallAnchor"), SuppressUnmanagedCodeSecurity] | ||
1370 | public static extern void JointSetBallAnchor(IntPtr j, dReal x, dReal y, dReal z); | ||
1371 | |||
1372 | [DllImport("ode", EntryPoint = "dJointSetBallAnchor2"), SuppressUnmanagedCodeSecurity] | ||
1373 | public static extern void JointSetBallAnchor2(IntPtr j, dReal x, dReal y, dReal z); | ||
1374 | |||
1375 | [DllImport("ode", EntryPoint = "dJointSetData"), SuppressUnmanagedCodeSecurity] | ||
1376 | public static extern void JointSetData(IntPtr j, IntPtr data); | ||
1377 | |||
1378 | [DllImport("ode", EntryPoint = "dJointSetFeedback"), SuppressUnmanagedCodeSecurity] | ||
1379 | public static extern void JointSetFeedback(IntPtr j, out JointFeedback feedback); | ||
1380 | |||
1381 | [DllImport("ode", EntryPoint = "dJointSetFixed"), SuppressUnmanagedCodeSecurity] | ||
1382 | public static extern void JointSetFixed(IntPtr j); | ||
1383 | |||
1384 | [DllImport("ode", EntryPoint = "dJointSetHingeAnchor"), SuppressUnmanagedCodeSecurity] | ||
1385 | public static extern void JointSetHingeAnchor(IntPtr j, dReal x, dReal y, dReal z); | ||
1386 | |||
1387 | [DllImport("ode", EntryPoint = "dJointSetHingeAnchorDelta"), SuppressUnmanagedCodeSecurity] | ||
1388 | public static extern void JointSetHingeAnchorDelta(IntPtr j, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az); | ||
1389 | |||
1390 | [DllImport("ode", EntryPoint = "dJointSetHingeAxis"), SuppressUnmanagedCodeSecurity] | ||
1391 | public static extern void JointSetHingeAxis(IntPtr j, dReal x, dReal y, dReal z); | ||
1392 | |||
1393 | [DllImport("ode", EntryPoint = "dJointSetHingeParam"), SuppressUnmanagedCodeSecurity] | ||
1394 | public static extern void JointSetHingeParam(IntPtr j, int parameter, dReal value); | ||
1395 | |||
1396 | [DllImport("ode", EntryPoint = "dJointSetHinge2Anchor"), SuppressUnmanagedCodeSecurity] | ||
1397 | public static extern void JointSetHinge2Anchor(IntPtr j, dReal x, dReal y, dReal z); | ||
1398 | |||
1399 | [DllImport("ode", EntryPoint = "dJointSetHinge2Axis1"), SuppressUnmanagedCodeSecurity] | ||
1400 | public static extern void JointSetHinge2Axis1(IntPtr j, dReal x, dReal y, dReal z); | ||
1401 | |||
1402 | [DllImport("ode", EntryPoint = "dJointSetHinge2Axis2"), SuppressUnmanagedCodeSecurity] | ||
1403 | public static extern void JointSetHinge2Axis2(IntPtr j, dReal x, dReal y, dReal z); | ||
1404 | |||
1405 | [DllImport("ode", EntryPoint = "dJointSetHinge2Param"), SuppressUnmanagedCodeSecurity] | ||
1406 | public static extern void JointSetHinge2Param(IntPtr j, int parameter, dReal value); | ||
1407 | |||
1408 | [DllImport("ode", EntryPoint = "dJointSetLMotorAxis"), SuppressUnmanagedCodeSecurity] | ||
1409 | public static extern void JointSetLMotorAxis(IntPtr j, int anum, int rel, dReal x, dReal y, dReal z); | ||
1410 | |||
1411 | [DllImport("ode", EntryPoint = "dJointSetLMotorNumAxes"), SuppressUnmanagedCodeSecurity] | ||
1412 | public static extern void JointSetLMotorNumAxes(IntPtr j, int num); | ||
1413 | |||
1414 | [DllImport("ode", EntryPoint = "dJointSetLMotorParam"), SuppressUnmanagedCodeSecurity] | ||
1415 | public static extern void JointSetLMotorParam(IntPtr j, int parameter, dReal value); | ||
1416 | |||
1417 | [DllImport("ode", EntryPoint = "dJointSetPlane2DAngleParam"), SuppressUnmanagedCodeSecurity] | ||
1418 | public static extern void JointSetPlane2DAngleParam(IntPtr j, int parameter, dReal value); | ||
1419 | |||
1420 | [DllImport("ode", EntryPoint = "dJointSetPlane2DXParam"), SuppressUnmanagedCodeSecurity] | ||
1421 | public static extern void JointSetPlane2DXParam(IntPtr j, int parameter, dReal value); | ||
1422 | |||
1423 | [DllImport("ode", EntryPoint = "dJointSetPlane2DYParam"), SuppressUnmanagedCodeSecurity] | ||
1424 | public static extern void JointSetPlane2DYParam(IntPtr j, int parameter, dReal value); | ||
1425 | |||
1426 | [DllImport("ode", EntryPoint = "dJointSetPRAnchor"), SuppressUnmanagedCodeSecurity] | ||
1427 | public static extern void JointSetPRAnchor(IntPtr j, dReal x, dReal y, dReal z); | ||
1428 | |||
1429 | [DllImport("ode", EntryPoint = "dJointSetPRAxis1"), SuppressUnmanagedCodeSecurity] | ||
1430 | public static extern void JointSetPRAxis1(IntPtr j, dReal x, dReal y, dReal z); | ||
1431 | |||
1432 | [DllImport("ode", EntryPoint = "dJointSetPRAxis2"), SuppressUnmanagedCodeSecurity] | ||
1433 | public static extern void JointSetPRAxis2(IntPtr j, dReal x, dReal y, dReal z); | ||
1434 | |||
1435 | [DllImport("ode", EntryPoint = "dJointSetPRParam"), SuppressUnmanagedCodeSecurity] | ||
1436 | public static extern void JointSetPRParam(IntPtr j, int parameter, dReal value); | ||
1437 | |||
1438 | [DllImport("ode", EntryPoint = "dJointSetSliderAxis"), SuppressUnmanagedCodeSecurity] | ||
1439 | public static extern void JointSetSliderAxis(IntPtr j, dReal x, dReal y, dReal z); | ||
1440 | |||
1441 | [DllImport("ode", EntryPoint = "dJointSetSliderAxisDelta"), SuppressUnmanagedCodeSecurity] | ||
1442 | public static extern void JointSetSliderAxisDelta(IntPtr j, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az); | ||
1443 | |||
1444 | [DllImport("ode", EntryPoint = "dJointSetSliderParam"), SuppressUnmanagedCodeSecurity] | ||
1445 | public static extern void JointSetSliderParam(IntPtr j, int parameter, dReal value); | ||
1446 | |||
1447 | [DllImport("ode", EntryPoint = "dJointSetUniversalAnchor"), SuppressUnmanagedCodeSecurity] | ||
1448 | public static extern void JointSetUniversalAnchor(IntPtr j, dReal x, dReal y, dReal z); | ||
1449 | |||
1450 | [DllImport("ode", EntryPoint = "dJointSetUniversalAxis1"), SuppressUnmanagedCodeSecurity] | ||
1451 | public static extern void JointSetUniversalAxis1(IntPtr j, dReal x, dReal y, dReal z); | ||
1452 | |||
1453 | [DllImport("ode", EntryPoint = "dJointSetUniversalAxis2"), SuppressUnmanagedCodeSecurity] | ||
1454 | public static extern void JointSetUniversalAxis2(IntPtr j, dReal x, dReal y, dReal z); | ||
1455 | |||
1456 | [DllImport("ode", EntryPoint = "dJointSetUniversalParam"), SuppressUnmanagedCodeSecurity] | ||
1457 | public static extern void JointSetUniversalParam(IntPtr j, int parameter, dReal value); | ||
1458 | |||
1459 | [DllImport("ode", EntryPoint = "dLDLTAddTL"), SuppressUnmanagedCodeSecurity] | ||
1460 | public static extern void LDLTAddTL(ref dReal L, ref dReal d, ref dReal a, int n, int nskip); | ||
1461 | |||
1462 | [DllImport("ode", EntryPoint = "dMassAdd"), SuppressUnmanagedCodeSecurity] | ||
1463 | public static extern void MassAdd(ref Mass a, ref Mass b); | ||
1464 | |||
1465 | [DllImport("ode", EntryPoint = "dMassAdjust"), SuppressUnmanagedCodeSecurity] | ||
1466 | public static extern void MassAdjust(ref Mass m, dReal newmass); | ||
1467 | |||
1468 | [DllImport("ode", EntryPoint = "dMassCheck"), SuppressUnmanagedCodeSecurity] | ||
1469 | public static extern bool MassCheck(ref Mass m); | ||
1470 | |||
1471 | [DllImport("ode", EntryPoint = "dMassRotate"), SuppressUnmanagedCodeSecurity] | ||
1472 | public static extern void MassRotate(out Mass mass, ref Matrix3 R); | ||
1473 | |||
1474 | [DllImport("ode", EntryPoint = "dMassRotate"), SuppressUnmanagedCodeSecurity] | ||
1475 | public static extern void MassRotate(out Mass mass, ref dReal M00); | ||
1476 | |||
1477 | [DllImport("ode", EntryPoint = "dMassSetBox"), SuppressUnmanagedCodeSecurity] | ||
1478 | public static extern void MassSetBox(out Mass mass, dReal density, dReal lx, dReal ly, dReal lz); | ||
1479 | |||
1480 | [DllImport("ode", EntryPoint = "dMassSetBoxTotal"), SuppressUnmanagedCodeSecurity] | ||
1481 | public static extern void MassSetBoxTotal(out Mass mass, dReal total_mass, dReal lx, dReal ly, dReal lz); | ||
1482 | |||
1483 | [DllImport("ode", EntryPoint = "dMassSetCapsule"), SuppressUnmanagedCodeSecurity] | ||
1484 | public static extern void MassSetCapsule(out Mass mass, dReal density, int direction, dReal radius, dReal length); | ||
1485 | |||
1486 | [DllImport("ode", EntryPoint = "dMassSetCapsuleTotal"), SuppressUnmanagedCodeSecurity] | ||
1487 | public static extern void MassSetCapsuleTotal(out Mass mass, dReal total_mass, int direction, dReal radius, dReal length); | ||
1488 | |||
1489 | [DllImport("ode", EntryPoint = "dMassSetCylinder"), SuppressUnmanagedCodeSecurity] | ||
1490 | public static extern void MassSetCylinder(out Mass mass, dReal density, int direction, dReal radius, dReal length); | ||
1491 | |||
1492 | [DllImport("ode", EntryPoint = "dMassSetCylinderTotal"), SuppressUnmanagedCodeSecurity] | ||
1493 | public static extern void MassSetCylinderTotal(out Mass mass, dReal total_mass, int direction, dReal radius, dReal length); | ||
1494 | |||
1495 | [DllImport("ode", EntryPoint = "dMassSetParameters"), SuppressUnmanagedCodeSecurity] | ||
1496 | public static extern void MassSetParameters(out Mass mass, dReal themass, | ||
1497 | dReal cgx, dReal cgy, dReal cgz, | ||
1498 | dReal i11, dReal i22, dReal i33, | ||
1499 | dReal i12, dReal i13, dReal i23); | ||
1500 | |||
1501 | [DllImport("ode", EntryPoint = "dMassSetSphere"), SuppressUnmanagedCodeSecurity] | ||
1502 | public static extern void MassSetSphere(out Mass mass, dReal density, dReal radius); | ||
1503 | |||
1504 | [DllImport("ode", EntryPoint = "dMassSetSphereTotal"), SuppressUnmanagedCodeSecurity] | ||
1505 | public static extern void dMassSetSphereTotal(out Mass mass, dReal total_mass, dReal radius); | ||
1506 | |||
1507 | [DllImport("ode", EntryPoint = "dMassSetTrimesh"), SuppressUnmanagedCodeSecurity] | ||
1508 | public static extern void MassSetTrimesh(out Mass mass, dReal density, IntPtr g); | ||
1509 | |||
1510 | [DllImport("ode", EntryPoint = "dMassSetZero"), SuppressUnmanagedCodeSecurity] | ||
1511 | public static extern void MassSetZero(out Mass mass); | ||
1512 | |||
1513 | [DllImport("ode", EntryPoint = "dMassTranslate"), SuppressUnmanagedCodeSecurity] | ||
1514 | public static extern void MassTranslate(out Mass mass, dReal x, dReal y, dReal z); | ||
1515 | |||
1516 | [DllImport("ode", EntryPoint = "dMultiply0"), SuppressUnmanagedCodeSecurity] | ||
1517 | public static extern void Multiply0(out dReal A00, ref dReal B00, ref dReal C00, int p, int q, int r); | ||
1518 | |||
1519 | [DllImport("ode", EntryPoint = "dMultiply1"), SuppressUnmanagedCodeSecurity] | ||
1520 | public static extern void Multiply1(out dReal A00, ref dReal B00, ref dReal C00, int p, int q, int r); | ||
1521 | |||
1522 | [DllImport("ode", EntryPoint = "dMultiply2"), SuppressUnmanagedCodeSecurity] | ||
1523 | public static extern void Multiply2(out dReal A00, ref dReal B00, ref dReal C00, int p, int q, int r); | ||
1524 | |||
1525 | [DllImport("ode", EntryPoint = "dQFromAxisAndAngle"), SuppressUnmanagedCodeSecurity] | ||
1526 | public static extern void QFromAxisAndAngle(out Quaternion q, dReal ax, dReal ay, dReal az, dReal angle); | ||
1527 | |||
1528 | [DllImport("ode", EntryPoint = "dQfromR"), SuppressUnmanagedCodeSecurity] | ||
1529 | public static extern void QfromR(out Quaternion q, ref Matrix3 R); | ||
1530 | |||
1531 | [DllImport("ode", EntryPoint = "dQMultiply0"), SuppressUnmanagedCodeSecurity] | ||
1532 | public static extern void QMultiply0(out Quaternion qa, ref Quaternion qb, ref Quaternion qc); | ||
1533 | |||
1534 | [DllImport("ode", EntryPoint = "dQMultiply1"), SuppressUnmanagedCodeSecurity] | ||
1535 | public static extern void QMultiply1(out Quaternion qa, ref Quaternion qb, ref Quaternion qc); | ||
1536 | |||
1537 | [DllImport("ode", EntryPoint = "dQMultiply2"), SuppressUnmanagedCodeSecurity] | ||
1538 | public static extern void QMultiply2(out Quaternion qa, ref Quaternion qb, ref Quaternion qc); | ||
1539 | |||
1540 | [DllImport("ode", EntryPoint = "dQMultiply3"), SuppressUnmanagedCodeSecurity] | ||
1541 | public static extern void QMultiply3(out Quaternion qa, ref Quaternion qb, ref Quaternion qc); | ||
1542 | |||
1543 | [DllImport("ode", EntryPoint = "dQSetIdentity"), SuppressUnmanagedCodeSecurity] | ||
1544 | public static extern void QSetIdentity(out Quaternion q); | ||
1545 | |||
1546 | [DllImport("ode", EntryPoint = "dQuadTreeSpaceCreate"), SuppressUnmanagedCodeSecurity] | ||
1547 | public static extern IntPtr QuadTreeSpaceCreate(IntPtr space, ref Vector3 center, ref Vector3 extents, int depth); | ||
1548 | |||
1549 | [DllImport("ode", EntryPoint = "dQuadTreeSpaceCreate"), SuppressUnmanagedCodeSecurity] | ||
1550 | public static extern IntPtr QuadTreeSpaceCreate(IntPtr space, ref dReal centerX, ref dReal extentsX, int depth); | ||
1551 | |||
1552 | [DllImport("ode", EntryPoint = "dRandReal"), SuppressUnmanagedCodeSecurity] | ||
1553 | public static extern dReal RandReal(); | ||
1554 | |||
1555 | [DllImport("ode", EntryPoint = "dRFrom2Axes"), SuppressUnmanagedCodeSecurity] | ||
1556 | public static extern void RFrom2Axes(out Matrix3 R, dReal ax, dReal ay, dReal az, dReal bx, dReal by, dReal bz); | ||
1557 | |||
1558 | [DllImport("ode", EntryPoint = "dRFromAxisAndAngle"), SuppressUnmanagedCodeSecurity] | ||
1559 | public static extern void RFromAxisAndAngle(out Matrix3 R, dReal x, dReal y, dReal z, dReal angle); | ||
1560 | |||
1561 | [DllImport("ode", EntryPoint = "dRFromEulerAngles"), SuppressUnmanagedCodeSecurity] | ||
1562 | public static extern void RFromEulerAngles(out Matrix3 R, dReal phi, dReal theta, dReal psi); | ||
1563 | |||
1564 | [DllImport("ode", EntryPoint = "dRfromQ"), SuppressUnmanagedCodeSecurity] | ||
1565 | public static extern void RfromQ(out Matrix3 R, ref Quaternion q); | ||
1566 | |||
1567 | [DllImport("ode", EntryPoint = "dRFromZAxis"), SuppressUnmanagedCodeSecurity] | ||
1568 | public static extern void RFromZAxis(out Matrix3 R, dReal ax, dReal ay, dReal az); | ||
1569 | |||
1570 | [DllImport("ode", EntryPoint = "dRSetIdentity"), SuppressUnmanagedCodeSecurity] | ||
1571 | public static extern void RSetIdentity(out Matrix3 R); | ||
1572 | |||
1573 | [DllImport("ode", EntryPoint = "dSetValue"), SuppressUnmanagedCodeSecurity] | ||
1574 | public static extern void SetValue(out dReal a, int n); | ||
1575 | |||
1576 | [DllImport("ode", EntryPoint = "dSetZero"), SuppressUnmanagedCodeSecurity] | ||
1577 | public static extern void SetZero(out dReal a, int n); | ||
1578 | |||
1579 | [DllImport("ode", EntryPoint = "dSimpleSpaceCreate"), SuppressUnmanagedCodeSecurity] | ||
1580 | public static extern IntPtr SimpleSpaceCreate(IntPtr space); | ||
1581 | |||
1582 | [DllImport("ode", EntryPoint = "dSolveCholesky"), SuppressUnmanagedCodeSecurity] | ||
1583 | public static extern void SolveCholesky(ref dReal L, out dReal b, int n); | ||
1584 | |||
1585 | [DllImport("ode", EntryPoint = "dSolveL1"), SuppressUnmanagedCodeSecurity] | ||
1586 | public static extern void SolveL1(ref dReal L, out dReal b, int n, int nskip); | ||
1587 | |||
1588 | [DllImport("ode", EntryPoint = "dSolveL1T"), SuppressUnmanagedCodeSecurity] | ||
1589 | public static extern void SolveL1T(ref dReal L, out dReal b, int n, int nskip); | ||
1590 | |||
1591 | [DllImport("ode", EntryPoint = "dSolveLDLT"), SuppressUnmanagedCodeSecurity] | ||
1592 | public static extern void SolveLDLT(ref dReal L, ref dReal d, out dReal b, int n, int nskip); | ||
1593 | |||
1594 | [DllImport("ode", EntryPoint = "dSpaceAdd"), SuppressUnmanagedCodeSecurity] | ||
1595 | public static extern void SpaceAdd(IntPtr space, IntPtr geom); | ||
1596 | |||
1597 | [DllImport("ode", EntryPoint = "dSpaceClean"), SuppressUnmanagedCodeSecurity] | ||
1598 | public static extern void SpaceClean(IntPtr space); | ||
1599 | |||
1600 | [DllImport("ode", EntryPoint = "dSpaceCollide"), SuppressUnmanagedCodeSecurity] | ||
1601 | public static extern void SpaceCollide(IntPtr space, IntPtr data, NearCallback callback); | ||
1602 | |||
1603 | [DllImport("ode", EntryPoint = "dSpaceCollide2"), SuppressUnmanagedCodeSecurity] | ||
1604 | public static extern void SpaceCollide2(IntPtr space1, IntPtr space2, IntPtr data, NearCallback callback); | ||
1605 | |||
1606 | [DllImport("ode", EntryPoint = "dSpaceDestroy"), SuppressUnmanagedCodeSecurity] | ||
1607 | public static extern void SpaceDestroy(IntPtr space); | ||
1608 | |||
1609 | [DllImport("ode", EntryPoint = "dSpaceGetCleanup"), SuppressUnmanagedCodeSecurity] | ||
1610 | public static extern bool SpaceGetCleanup(IntPtr space); | ||
1611 | |||
1612 | [DllImport("ode", EntryPoint = "dSpaceGetNumGeoms"), SuppressUnmanagedCodeSecurity] | ||
1613 | public static extern int SpaceGetNumGeoms(IntPtr space); | ||
1614 | |||
1615 | [DllImport("ode", EntryPoint = "dSpaceGetGeom"), SuppressUnmanagedCodeSecurity] | ||
1616 | public static extern IntPtr SpaceGetGeom(IntPtr space, int i); | ||
1617 | |||
1618 | [DllImport("ode", EntryPoint = "dSpaceQuery"), SuppressUnmanagedCodeSecurity] | ||
1619 | public static extern bool SpaceQuery(IntPtr space, IntPtr geom); | ||
1620 | |||
1621 | [DllImport("ode", EntryPoint = "dSpaceRemove"), SuppressUnmanagedCodeSecurity] | ||
1622 | public static extern void SpaceRemove(IntPtr space, IntPtr geom); | ||
1623 | |||
1624 | [DllImport("ode", EntryPoint = "dSpaceSetCleanup"), SuppressUnmanagedCodeSecurity] | ||
1625 | public static extern void SpaceSetCleanup(IntPtr space, bool mode); | ||
1626 | |||
1627 | [DllImport("ode", EntryPoint = "dVectorScale"), SuppressUnmanagedCodeSecurity] | ||
1628 | public static extern void VectorScale(out dReal a, ref dReal d, int n); | ||
1629 | |||
1630 | [DllImport("ode", EntryPoint = "dWorldCreate"), SuppressUnmanagedCodeSecurity] | ||
1631 | public static extern IntPtr WorldCreate(); | ||
1632 | |||
1633 | [DllImport("ode", EntryPoint = "dWorldDestroy"), SuppressUnmanagedCodeSecurity] | ||
1634 | public static extern void WorldDestroy(IntPtr world); | ||
1635 | |||
1636 | [DllImport("ode", EntryPoint = "dWorldGetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity] | ||
1637 | public static extern dReal WorldGetAutoDisableAngularThreshold(IntPtr world); | ||
1638 | |||
1639 | [DllImport("ode", EntryPoint = "dWorldGetAutoDisableFlag"), SuppressUnmanagedCodeSecurity] | ||
1640 | public static extern bool WorldGetAutoDisableFlag(IntPtr world); | ||
1641 | |||
1642 | [DllImport("ode", EntryPoint = "dWorldGetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity] | ||
1643 | public static extern dReal WorldGetAutoDisableLinearThreshold(IntPtr world); | ||
1644 | |||
1645 | [DllImport("ode", EntryPoint = "dWorldGetAutoDisableSteps"), SuppressUnmanagedCodeSecurity] | ||
1646 | public static extern int WorldGetAutoDisableSteps(IntPtr world); | ||
1647 | |||
1648 | [DllImport("ode", EntryPoint = "dWorldGetAutoDisableTime"), SuppressUnmanagedCodeSecurity] | ||
1649 | public static extern dReal WorldGetAutoDisableTime(IntPtr world); | ||
1650 | |||
1651 | [DllImport("ode", EntryPoint = "dWorldGetAutoEnableDepthSF1"), SuppressUnmanagedCodeSecurity] | ||
1652 | public static extern int WorldGetAutoEnableDepthSF1(IntPtr world); | ||
1653 | |||
1654 | [DllImport("ode", EntryPoint = "dWorldGetCFM"), SuppressUnmanagedCodeSecurity] | ||
1655 | public static extern dReal WorldGetCFM(IntPtr world); | ||
1656 | |||
1657 | [DllImport("ode", EntryPoint = "dWorldGetERP"), SuppressUnmanagedCodeSecurity] | ||
1658 | public static extern dReal WorldGetERP(IntPtr world); | ||
1659 | |||
1660 | [DllImport("ode", EntryPoint = "dWorldGetGravity"), SuppressUnmanagedCodeSecurity] | ||
1661 | public static extern void WorldGetGravity(IntPtr world, out Vector3 gravity); | ||
1662 | |||
1663 | [DllImport("ode", EntryPoint = "dWorldGetGravity"), SuppressUnmanagedCodeSecurity] | ||
1664 | public static extern void WorldGetGravity(IntPtr world, out dReal X); | ||
1665 | |||
1666 | [DllImport("ode", EntryPoint = "dWorldGetContactMaxCorrectingVel"), SuppressUnmanagedCodeSecurity] | ||
1667 | public static extern dReal WorldGetContactMaxCorrectingVel(IntPtr world); | ||
1668 | |||
1669 | [DllImport("ode", EntryPoint = "dWorldGetContactSurfaceLayer"), SuppressUnmanagedCodeSecurity] | ||
1670 | public static extern dReal WorldGetContactSurfaceLayer(IntPtr world); | ||
1671 | |||
1672 | [DllImport("ode", EntryPoint = "dWorldGetQuickStepNumIterations"), SuppressUnmanagedCodeSecurity] | ||
1673 | public static extern int WorldGetQuickStepNumIterations(IntPtr world); | ||
1674 | |||
1675 | [DllImport("ode", EntryPoint = "dWorldGetQuickStepW"), SuppressUnmanagedCodeSecurity] | ||
1676 | public static extern dReal WorldGetQuickStepW(IntPtr world); | ||
1677 | |||
1678 | [DllImport("ode", EntryPoint = "dWorldImpulseToForce"), SuppressUnmanagedCodeSecurity] | ||
1679 | public static extern void WorldImpulseToForce(IntPtr world, dReal stepsize, dReal ix, dReal iy, dReal iz, out Vector3 force); | ||
1680 | |||
1681 | [DllImport("ode", EntryPoint = "dWorldImpulseToForce"), SuppressUnmanagedCodeSecurity] | ||
1682 | public static extern void WorldImpulseToForce(IntPtr world, dReal stepsize, dReal ix, dReal iy, dReal iz, out dReal forceX); | ||
1683 | |||
1684 | [DllImport("ode", EntryPoint = "dWorldQuickStep"), SuppressUnmanagedCodeSecurity] | ||
1685 | public static extern void WorldQuickStep(IntPtr world, dReal stepsize); | ||
1686 | |||
1687 | [DllImport("ode", EntryPoint = "dWorldSetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity] | ||
1688 | public static extern void WorldSetAutoDisableAngularThreshold(IntPtr world, dReal angular_threshold); | ||
1689 | |||
1690 | [DllImport("ode", EntryPoint = "dWorldSetAutoDisableFlag"), SuppressUnmanagedCodeSecurity] | ||
1691 | public static extern void WorldSetAutoDisableFlag(IntPtr world, bool do_auto_disable); | ||
1692 | |||
1693 | [DllImport("ode", EntryPoint = "dWorldSetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity] | ||
1694 | public static extern void WorldSetAutoDisableLinearThreshold(IntPtr world, dReal linear_threshold); | ||
1695 | |||
1696 | [DllImport("ode", EntryPoint = "dWorldSetAutoDisableSteps"), SuppressUnmanagedCodeSecurity] | ||
1697 | public static extern void WorldSetAutoDisableSteps(IntPtr world, int steps); | ||
1698 | |||
1699 | [DllImport("ode", EntryPoint = "dWorldSetAutoDisableTime"), SuppressUnmanagedCodeSecurity] | ||
1700 | public static extern void WorldSetAutoDisableTime(IntPtr world, dReal time); | ||
1701 | |||
1702 | [DllImport("ode", EntryPoint = "dWorldSetAutoEnableDepthSF1"), SuppressUnmanagedCodeSecurity] | ||
1703 | public static extern void WorldSetAutoEnableDepthSF1(IntPtr world, int autoEnableDepth); | ||
1704 | |||
1705 | [DllImport("ode", EntryPoint = "dWorldSetCFM"), SuppressUnmanagedCodeSecurity] | ||
1706 | public static extern void WorldSetCFM(IntPtr world, dReal cfm); | ||
1707 | |||
1708 | [DllImport("ode", EntryPoint = "dWorldSetContactMaxCorrectingVel"), SuppressUnmanagedCodeSecurity] | ||
1709 | public static extern void WorldSetContactMaxCorrectingVel(IntPtr world, dReal vel); | ||
1710 | |||
1711 | [DllImport("ode", EntryPoint = "dWorldSetContactSurfaceLayer"), SuppressUnmanagedCodeSecurity] | ||
1712 | public static extern void WorldSetContactSurfaceLayer(IntPtr world, dReal depth); | ||
1713 | |||
1714 | [DllImport("ode", EntryPoint = "dWorldSetERP"), SuppressUnmanagedCodeSecurity] | ||
1715 | public static extern void WorldSetERP(IntPtr world, dReal erp); | ||
1716 | |||
1717 | [DllImport("ode", EntryPoint = "dWorldSetGravity"), SuppressUnmanagedCodeSecurity] | ||
1718 | public static extern void WorldSetGravity(IntPtr world, dReal x, dReal y, dReal z); | ||
1719 | |||
1720 | [DllImport("ode", EntryPoint = "dWorldSetQuickStepNumIterations"), SuppressUnmanagedCodeSecurity] | ||
1721 | public static extern void WorldSetQuickStepNumIterations(IntPtr world, int num); | ||
1722 | |||
1723 | [DllImport("ode", EntryPoint = "dWorldSetQuickStepW"), SuppressUnmanagedCodeSecurity] | ||
1724 | public static extern void WorldSetQuickStepW(IntPtr world, dReal over_relaxation); | ||
1725 | |||
1726 | [DllImport("ode", EntryPoint = "dWorldStep"), SuppressUnmanagedCodeSecurity] | ||
1727 | public static extern void WorldStep(IntPtr world, dReal stepsize); | ||
1728 | |||
1729 | [DllImport("ode", EntryPoint = "dWorldStepFast1"), SuppressUnmanagedCodeSecurity] | ||
1730 | public static extern void WorldStepFast1(IntPtr world, dReal stepsize, int maxiterations); | ||
1731 | } | ||
1732 | } | ||
diff --git a/libraries/ode-0.9/contrib/Ode.NET/Ode/premake.lua b/libraries/ode-0.9/contrib/Ode.NET/Ode/premake.lua new file mode 100644 index 0000000..b53d54c --- /dev/null +++ b/libraries/ode-0.9/contrib/Ode.NET/Ode/premake.lua | |||
@@ -0,0 +1,31 @@ | |||
1 | package.name = "Ode.NET" | ||
2 | package.kind = "dll" | ||
3 | package.language = "c#" | ||
4 | |||
5 | -- Build options | ||
6 | |||
7 | package.defines = { } | ||
8 | |||
9 | if (options["with-doubles"]) then | ||
10 | table.insert(package.defines, "dDOUBLE") | ||
11 | else | ||
12 | table.insert(package.defines, "dSINGLE") | ||
13 | end | ||
14 | |||
15 | if (options["no-unsafe"]) then | ||
16 | table.insert(package.defines, "dNO_UNSAFE_CODE") | ||
17 | else | ||
18 | package.buildflags = { "unsafe" } | ||
19 | end | ||
20 | |||
21 | |||
22 | -- Files & Libraries | ||
23 | |||
24 | package.files = { | ||
25 | "AssemblyInfo.cs", | ||
26 | "Ode.cs" | ||
27 | } | ||
28 | |||
29 | package.links = { | ||
30 | "System" | ||
31 | } | ||
diff --git a/libraries/ode-0.9/contrib/Ode.NET/README.TXT b/libraries/ode-0.9/contrib/Ode.NET/README.TXT new file mode 100644 index 0000000..e6f1262 --- /dev/null +++ b/libraries/ode-0.9/contrib/Ode.NET/README.TXT | |||
@@ -0,0 +1,73 @@ | |||
1 | Ode.NET - .NET bindings for ODE | ||
2 | Jason Perkins (starkos@gmail.com) | ||
3 | |||
4 | THIS IS A WORK IN PROGRESS! I'm not done yet! | ||
5 | |||
6 | |||
7 | --------------------------------------------------------------------- | ||
8 | INSTALLATION | ||
9 | --------------------------------------------------------------------- | ||
10 | |||
11 | Note that this binding uses a C# 2.0 feature (the | ||
12 | UnmanagedFunctionPointer attribute). You will need to use | ||
13 | Visual Studio 2005 (C# Express is fine) or Mono's gmcs | ||
14 | compiler. | ||
15 | |||
16 | Start by getting or building ODE as a shared library (DLL). | ||
17 | |||
18 | The simplest way to build the bindings is probably to create a | ||
19 | new library assembly in your tool of choice and drop in the files | ||
20 | Ode/Ode.cs and Ode/AssemblyInfo.cs. Define the symbol`dDOUBLE` if | ||
21 | you used double-precision math in your ode.dll. Build, done. | ||
22 | |||
23 | For testing purposes, I have also created bindings for the | ||
24 | Drawstuff library and a C# version of the BoxStack demo. You can | ||
25 | throw all of these files into a console executable and run it to | ||
26 | see the demo. | ||
27 | |||
28 | If you happen to have Premake installed (http://premake.sf.net/), | ||
29 | you can generate build scripts for the library with: | ||
30 | |||
31 | premake --target (toolset) # for single precision | ||
32 | premake --with-doubles --target (toolset) # for double precision | ||
33 | |||
34 | To build the test application too, use: | ||
35 | |||
36 | premake --with-tests --target (toolset) | ||
37 | |||
38 | To build with Mono, you must add the --dotnet parameter to enable | ||
39 | support .NET 2.0: | ||
40 | |||
41 | premake --dotnet mono2 --target gnu | ||
42 | |||
43 | |||
44 | --------------------------------------------------------------------- | ||
45 | USAGE | ||
46 | --------------------------------------------------------------------- | ||
47 | |||
48 | I have tried to keep things as close to the original C API as I can, | ||
49 | rather than forcing a class structure on everyone. Everything is | ||
50 | contained within the `Ode.NET` namespace inside a static class | ||
51 | named `d`. All ODE IDs are replaced with IntPtrs. A quick example: | ||
52 | |||
53 | using Ode.NET; | ||
54 | |||
55 | IntPtr world = d.WorldCreate(); | ||
56 | IntPtr body = d.BodyCreate(world); | ||
57 | |||
58 | Take a look at Tests/BoxStack.cs for a more complete example. | ||
59 | |||
60 | |||
61 | --------------------------------------------------------------------- | ||
62 | KNOWN ISSUES | ||
63 | --------------------------------------------------------------------- | ||
64 | |||
65 | I'm not done yet, so many functions are still missing. | ||
66 | |||
67 | It is not possible to implement dBodyGetPosition(), dBodyGetRotation(), | ||
68 | etc. without resorting to unsafe code, which I was trying to avoid. | ||
69 | This binding uses the .NET friendly dBodyCopyPosition(), | ||
70 | dBodyCopyRotation(), etc. instead. | ||
71 | |||
72 | Collision response (contact joints) do not work when built under | ||
73 | Mono as double-precision. I have not tried to track down why. | ||
diff --git a/libraries/ode-0.9/contrib/Ode.NET/Tests/BoxStack.cs b/libraries/ode-0.9/contrib/Ode.NET/Tests/BoxStack.cs new file mode 100644 index 0000000..1077124 --- /dev/null +++ b/libraries/ode-0.9/contrib/Ode.NET/Tests/BoxStack.cs | |||
@@ -0,0 +1,260 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using Drawstuff.NET; | ||
4 | |||
5 | namespace Ode.NET | ||
6 | { | ||
7 | #if dDOUBLE | ||
8 | using dReal = System.Double; | ||
9 | #else | ||
10 | using dReal = System.Single; | ||
11 | #endif | ||
12 | |||
13 | public class TestBoxStack | ||
14 | { | ||
15 | #region Description of convex shape | ||
16 | |||
17 | static dReal[] planes = | ||
18 | { | ||
19 | 1.0f, 0.0f, 0.0f, 0.25f, | ||
20 | 0.0f, 1.0f, 0.0f, 0.25f, | ||
21 | 0.0f, 0.0f, 1.0f, 0.25f, | ||
22 | 0.0f, 0.0f, -1.0f, 0.25f, | ||
23 | 0.0f, -1.0f, 0.0f, 0.25f, | ||
24 | -1.0f, 0.0f , 0.0f, 0.25f | ||
25 | }; | ||
26 | |||
27 | static dReal[] points = | ||
28 | { | ||
29 | 0.25f, 0.25f, 0.25f, | ||
30 | -0.25f, 0.25f, 0.25f, | ||
31 | 0.25f, -0.25f, 0.25f, | ||
32 | -0.25f, -0.25f, 0.25f, | ||
33 | 0.25f, 0.25f, -0.25f, | ||
34 | -0.25f,0.25f,-0.25f, | ||
35 | 0.25f,-0.25f,-0.25f, | ||
36 | -0.25f,-0.25f,-0.25f, | ||
37 | }; | ||
38 | |||
39 | static int[] polygons = | ||
40 | { | ||
41 | 4, 0, 2, 6, 4, | ||
42 | 4, 1, 0, 4, 5, | ||
43 | 4, 0, 1, 3, 2, | ||
44 | 4, 3, 1, 5, 7, | ||
45 | 4, 2, 3, 7, 6, | ||
46 | 4, 5, 4, 6, 7, | ||
47 | }; | ||
48 | |||
49 | #endregion | ||
50 | |||
51 | const int NUM = 100; | ||
52 | const float DENSITY = 5.0f; | ||
53 | const int MAX_CONTACTS = 8; | ||
54 | |||
55 | static IntPtr world; | ||
56 | static IntPtr space; | ||
57 | static IntPtr contactgroup; | ||
58 | |||
59 | static Queue<IntPtr> obj = new Queue<IntPtr>(); | ||
60 | |||
61 | static d.Vector3 xyz = new d.Vector3(2.1640f, -1.3079f, 1.7600f); | ||
62 | static d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); | ||
63 | |||
64 | static d.NearCallback nearCallback = near; | ||
65 | static d.ContactGeom[] contacts = new d.ContactGeom[MAX_CONTACTS]; | ||
66 | static d.Contact contact; | ||
67 | |||
68 | |||
69 | // Called when window is opened - sets up viewpoint and prints usage | ||
70 | static void start(int unused) | ||
71 | { | ||
72 | ds.SetViewpoint(ref xyz, ref hpr); | ||
73 | Console.WriteLine("To drop another object, press:"); | ||
74 | Console.WriteLine(" b for box."); | ||
75 | Console.WriteLine(" s for sphere."); | ||
76 | Console.WriteLine(" c for capsule."); | ||
77 | Console.WriteLine(" y for cylinder."); | ||
78 | Console.WriteLine(" v for a convex object."); | ||
79 | Console.WriteLine(" x for a composite object."); | ||
80 | Console.WriteLine("To select an object, press space."); | ||
81 | Console.WriteLine("To disable the selected object, press d."); | ||
82 | Console.WriteLine("To enable the selected object, press e."); | ||
83 | Console.WriteLine("To toggle showing the geom AABBs, press a."); | ||
84 | Console.WriteLine("To toggle showing the contact points, press t."); | ||
85 | Console.WriteLine("To toggle dropping from random position/orientation, press r."); | ||
86 | Console.WriteLine("To save the current state to 'state.dif', press 1."); | ||
87 | } | ||
88 | |||
89 | |||
90 | // Near callback - creates contact joints | ||
91 | static void near(IntPtr space, IntPtr g1, IntPtr g2) | ||
92 | { | ||
93 | IntPtr b1 = d.GeomGetBody(g1); | ||
94 | IntPtr b2 = d.GeomGetBody(g2); | ||
95 | if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) | ||
96 | return; | ||
97 | |||
98 | int count = d.Collide(g1, g2, MAX_CONTACTS, contacts, d.ContactGeom.SizeOf); | ||
99 | for (int i = 0; i < count; ++i) | ||
100 | { | ||
101 | contact.geom = contacts[i]; | ||
102 | IntPtr joint = d.JointCreateContact(world, contactgroup, ref contact); | ||
103 | d.JointAttach(joint, b1, b2); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | |||
108 | // Adds a new object to the scene - attaches a body to the geom and | ||
109 | // sets the initial position and orientation | ||
110 | static void addObject(IntPtr geom, d.Mass mass) | ||
111 | { | ||
112 | // Create a body for this object | ||
113 | IntPtr body = d.BodyCreate(world); | ||
114 | d.GeomSetBody(geom, body); | ||
115 | d.BodySetMass(body, ref mass); | ||
116 | obj.Enqueue(geom); | ||
117 | |||
118 | // Set the position of the new object | ||
119 | d.Matrix3 R; | ||
120 | d.BodySetPosition(body, d.RandReal() * 2 - 1, d.RandReal() * 2 - 1, d.RandReal() + 2); | ||
121 | d.RFromAxisAndAngle(out R, d.RandReal() * 2 - 1, d.RandReal() * 2 - 1, d.RandReal() * 2 - 1, d.RandReal() * 10 - 5); | ||
122 | d.BodySetRotation(body, ref R); | ||
123 | |||
124 | // Cap the total number of objects | ||
125 | if (obj.Count > NUM) | ||
126 | { | ||
127 | geom = obj.Dequeue(); | ||
128 | body = d.GeomGetBody(geom); | ||
129 | d.BodyDestroy(body); | ||
130 | d.GeomDestroy(geom); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | |||
135 | // Keyboard callback | ||
136 | static void command(int cmd) | ||
137 | { | ||
138 | IntPtr geom; | ||
139 | d.Mass mass; | ||
140 | d.Vector3 sides = new d.Vector3(d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f); | ||
141 | |||
142 | Char ch = Char.ToLower((Char)cmd); | ||
143 | switch ((Char)ch) | ||
144 | { | ||
145 | case 'b': | ||
146 | d.MassSetBox(out mass, DENSITY, sides.X, sides.Y, sides.Z); | ||
147 | geom = d.CreateBox(space, sides.X, sides.Y, sides.Z); | ||
148 | addObject(geom, mass); | ||
149 | break; | ||
150 | |||
151 | case 'c': | ||
152 | sides.X *= 0.5f; | ||
153 | d.MassSetCapsule(out mass, DENSITY, 3, sides.X, sides.Y); | ||
154 | geom = d.CreateCapsule(space, sides.X, sides.Y); | ||
155 | addObject(geom, mass); | ||
156 | break; | ||
157 | |||
158 | case 'v': | ||
159 | d.MassSetBox(out mass, DENSITY, 0.25f, 0.25f, 0.25f); | ||
160 | geom = d.CreateConvex(space, planes, planes.Length / 4, points, points.Length / 3, polygons); | ||
161 | addObject(geom, mass); | ||
162 | break; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | |||
167 | // Draw an object in the scene | ||
168 | static void drawGeom(IntPtr geom) | ||
169 | { | ||
170 | IntPtr body = d.GeomGetBody(geom); | ||
171 | |||
172 | d.Vector3 pos; | ||
173 | d.BodyCopyPosition(body, out pos); | ||
174 | |||
175 | d.Matrix3 R; | ||
176 | d.BodyCopyRotation(body, out R); | ||
177 | |||
178 | d.GeomClassID type = d.GeomGetClass(geom); | ||
179 | switch (type) | ||
180 | { | ||
181 | case d.GeomClassID.BoxClass: | ||
182 | d.Vector3 sides; | ||
183 | d.GeomBoxGetLengths(geom, out sides); | ||
184 | ds.DrawBox(ref pos, ref R, ref sides); | ||
185 | break; | ||
186 | case d.GeomClassID.CapsuleClass: | ||
187 | dReal radius, length; | ||
188 | d.GeomCapsuleGetParams(geom, out radius, out length); | ||
189 | ds.DrawCapsule(ref pos, ref R, length, radius); | ||
190 | break; | ||
191 | case d.GeomClassID.ConvexClass: | ||
192 | ds.DrawConvex(ref pos, ref R, planes, planes.Length / 4, points, points.Length / 3, polygons); | ||
193 | break; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | |||
198 | // Called once per frame; updates the scene | ||
199 | static void step(int pause) | ||
200 | { | ||
201 | d.SpaceCollide(space, IntPtr.Zero, nearCallback); | ||
202 | if (pause == 0) | ||
203 | d.WorldQuickStep(world, 0.02f); | ||
204 | d.JointGroupEmpty(contactgroup); | ||
205 | |||
206 | ds.SetColor(1.0f, 1.0f, 0.0f); | ||
207 | ds.SetTexture(ds.Texture.Wood); | ||
208 | |||
209 | foreach (IntPtr geom in obj) | ||
210 | { | ||
211 | drawGeom(geom); | ||
212 | } | ||
213 | } | ||
214 | |||
215 | |||
216 | static void Main(string[] args) | ||
217 | { | ||
218 | // Setup pointers to drawstuff callback functions | ||
219 | ds.Functions fn; | ||
220 | fn.version = ds.VERSION; | ||
221 | fn.start = new ds.CallbackFunction(start); | ||
222 | fn.step = new ds.CallbackFunction(step); | ||
223 | fn.command = new ds.CallbackFunction(command); | ||
224 | fn.stop = null; | ||
225 | fn.path_to_textures = "../../../../drawstuff/textures"; | ||
226 | if (args.Length > 0) | ||
227 | { | ||
228 | fn.path_to_textures = args[0]; | ||
229 | } | ||
230 | |||
231 | // Set up contact response parameters | ||
232 | contact.surface.mode = d.ContactFlags.Bounce | d.ContactFlags.SoftCFM; | ||
233 | contact.surface.mu = d.Infinity; | ||
234 | contact.surface.mu2 = 0.0f; | ||
235 | contact.surface.bounce = 0.1f; | ||
236 | contact.surface.bounce_vel = 0.1f; | ||
237 | contact.surface.soft_cfm = 0.01f; | ||
238 | |||
239 | // Initialize the scene | ||
240 | world = d.WorldCreate(); | ||
241 | space = d.HashSpaceCreate(IntPtr.Zero); | ||
242 | contactgroup = d.JointGroupCreate(0); | ||
243 | d.WorldSetGravity(world, 0.0f, 0.0f, -0.5f); | ||
244 | d.WorldSetCFM(world, 1e-5f); | ||
245 | d.WorldSetAutoDisableFlag(world, true); | ||
246 | d.WorldSetContactMaxCorrectingVel(world, 0.1f); | ||
247 | d.WorldSetContactSurfaceLayer(world, 0.001f); | ||
248 | d.CreatePlane(space, 0, 0, 1, 0); | ||
249 | |||
250 | // Run the scene | ||
251 | ds.SimulationLoop(args.Length, args, 352, 288, ref fn); | ||
252 | |||
253 | // Clean up | ||
254 | d.JointGroupDestroy(contactgroup); | ||
255 | d.SpaceDestroy(space); | ||
256 | d.WorldDestroy(world); | ||
257 | d.CloseODE(); | ||
258 | } | ||
259 | } | ||
260 | } | ||
diff --git a/libraries/ode-0.9/contrib/Ode.NET/Tests/premake.lua b/libraries/ode-0.9/contrib/Ode.NET/Tests/premake.lua new file mode 100644 index 0000000..5253ae1 --- /dev/null +++ b/libraries/ode-0.9/contrib/Ode.NET/Tests/premake.lua | |||
@@ -0,0 +1,27 @@ | |||
1 | -- This function creates the test packages | ||
2 | function maketest(name) | ||
3 | |||
4 | package = newpackage() | ||
5 | package.name = name | ||
6 | package.kind = "exe" | ||
7 | package.language = "c#" | ||
8 | |||
9 | if (options["with-doubles"]) then | ||
10 | package.defines = { "dDOUBLE" } | ||
11 | else | ||
12 | package.defines = { "dSINGLE " } | ||
13 | end | ||
14 | |||
15 | package.links = { | ||
16 | "System", | ||
17 | "Ode.NET", | ||
18 | "Drawstuff.NET" | ||
19 | } | ||
20 | |||
21 | package.files = { | ||
22 | name .. ".cs" | ||
23 | } | ||
24 | |||
25 | end | ||
26 | |||
27 | maketest("BoxStack") | ||
diff --git a/libraries/ode-0.9/contrib/Ode.NET/premake.lua b/libraries/ode-0.9/contrib/Ode.NET/premake.lua new file mode 100644 index 0000000..c25a017 --- /dev/null +++ b/libraries/ode-0.9/contrib/Ode.NET/premake.lua | |||
@@ -0,0 +1,29 @@ | |||
1 | project.name = "Ode.NET" | ||
2 | |||
3 | -- Target checking | ||
4 | |||
5 | if (target and target ~= "vs2005" and target ~= "gnu") then | ||
6 | error("Ode.NET requires a .NET 2.0 compiler") | ||
7 | end | ||
8 | |||
9 | |||
10 | -- Project options | ||
11 | |||
12 | addoption("with-doubles", "Use double instead of float as base numeric type") | ||
13 | addoption("with-tests", "Builds the test applications and DrawStuff library") | ||
14 | addoption("no-unsafe", "Exclude functions using unsafe code (dBodyGetPosition, etc.)") | ||
15 | |||
16 | |||
17 | -- Build settings | ||
18 | |||
19 | project.config["Debug"].bindir = "bin/Debug" | ||
20 | project.config["Release"].bindir = "bin/Release" | ||
21 | |||
22 | |||
23 | -- Packages | ||
24 | |||
25 | if (options["with-tests"]) then | ||
26 | dopackage("Tests") | ||
27 | dopackage("Drawstuff") | ||
28 | end | ||
29 | dopackage("Ode") | ||
diff --git a/libraries/ode-0.9/contrib/OdeModelProcessor/LICENSE-BSD.TXT b/libraries/ode-0.9/contrib/OdeModelProcessor/LICENSE-BSD.TXT new file mode 100644 index 0000000..b2b1995 --- /dev/null +++ b/libraries/ode-0.9/contrib/OdeModelProcessor/LICENSE-BSD.TXT | |||
@@ -0,0 +1,37 @@ | |||
1 | |||
2 | This is the BSD-style license for The ODE Model Processor | ||
3 | ---------------------------------------------------------- | ||
4 | |||
5 | The ODE Model Processor | ||
6 | Copyright (c) 2007, Department Of Information Science, | ||
7 | University of Otago, Dunedin, New Zealand. | ||
8 | All rights reserved. | ||
9 | |||
10 | Author: Richard Barrington <barri662@student.otago.ac.nz> | ||
11 | |||
12 | Redistribution and use in source and binary forms, with or without | ||
13 | modification, are permitted provided that the following conditions | ||
14 | are met: | ||
15 | |||
16 | Redistributions of source code must retain the above copyright notice, | ||
17 | this list of conditions and the following disclaimer. | ||
18 | |||
19 | Redistributions in binary form must reproduce the above copyright notice, | ||
20 | this list of conditions and the following disclaimer in the documentation | ||
21 | and/or other materials provided with the distribution. | ||
22 | |||
23 | Neither the names of the copyright owner nor the names of its | ||
24 | contributors may be used to endorse or promote products derived from | ||
25 | this software without specific prior written permission. | ||
26 | |||
27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
28 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
29 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||
30 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
31 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
32 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||
33 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
34 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
35 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
36 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
37 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
diff --git a/libraries/ode-0.9/contrib/OdeModelProcessor/LICENSE.TXT b/libraries/ode-0.9/contrib/OdeModelProcessor/LICENSE.TXT new file mode 100644 index 0000000..cfe59bc --- /dev/null +++ b/libraries/ode-0.9/contrib/OdeModelProcessor/LICENSE.TXT | |||
@@ -0,0 +1,502 @@ | |||
1 | GNU LESSER GENERAL PUBLIC LICENSE | ||
2 | Version 2.1, February 1999 | ||
3 | |||
4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. | ||
5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
6 | Everyone is permitted to copy and distribute verbatim copies | ||
7 | of this license document, but changing it is not allowed. | ||
8 | |||
9 | [This is the first released version of the Lesser GPL. It also counts | ||
10 | as the successor of the GNU Library Public License, version 2, hence | ||
11 | the version number 2.1.] | ||
12 | |||
13 | Preamble | ||
14 | |||
15 | The licenses for most software are designed to take away your | ||
16 | freedom to share and change it. By contrast, the GNU General Public | ||
17 | Licenses are intended to guarantee your freedom to share and change | ||
18 | free software--to make sure the software is free for all its users. | ||
19 | |||
20 | This license, the Lesser General Public License, applies to some | ||
21 | specially designated software packages--typically libraries--of the | ||
22 | Free Software Foundation and other authors who decide to use it. You | ||
23 | can use it too, but we suggest you first think carefully about whether | ||
24 | this license or the ordinary General Public License is the better | ||
25 | strategy to use in any particular case, based on the explanations below. | ||
26 | |||
27 | When we speak of free software, we are referring to freedom of use, | ||
28 | not price. Our General Public Licenses are designed to make sure that | ||
29 | you have the freedom to distribute copies of free software (and charge | ||
30 | for this service if you wish); that you receive source code or can get | ||
31 | it if you want it; that you can change the software and use pieces of | ||
32 | it in new free programs; and that you are informed that you can do | ||
33 | these things. | ||
34 | |||
35 | To protect your rights, we need to make restrictions that forbid | ||
36 | distributors to deny you these rights or to ask you to surrender these | ||
37 | rights. These restrictions translate to certain responsibilities for | ||
38 | you if you distribute copies of the library or if you modify it. | ||
39 | |||
40 | For example, if you distribute copies of the library, whether gratis | ||
41 | or for a fee, you must give the recipients all the rights that we gave | ||
42 | you. You must make sure that they, too, receive or can get the source | ||
43 | code. If you link other code with the library, you must provide | ||
44 | complete object files to the recipients, so that they can relink them | ||
45 | with the library after making changes to the library and recompiling | ||
46 | it. And you must show them these terms so they know their rights. | ||
47 | |||
48 | We protect your rights with a two-step method: (1) we copyright the | ||
49 | library, and (2) we offer you this license, which gives you legal | ||
50 | permission to copy, distribute and/or modify the library. | ||
51 | |||
52 | To protect each distributor, we want to make it very clear that | ||
53 | there is no warranty for the free library. Also, if the library is | ||
54 | modified by someone else and passed on, the recipients should know | ||
55 | that what they have is not the original version, so that the original | ||
56 | author's reputation will not be affected by problems that might be | ||
57 | introduced by others. | ||
58 | |||
59 | Finally, software patents pose a constant threat to the existence of | ||
60 | any free program. We wish to make sure that a company cannot | ||
61 | effectively restrict the users of a free program by obtaining a | ||
62 | restrictive license from a patent holder. Therefore, we insist that | ||
63 | any patent license obtained for a version of the library must be | ||
64 | consistent with the full freedom of use specified in this license. | ||
65 | |||
66 | Most GNU software, including some libraries, is covered by the | ||
67 | ordinary GNU General Public License. This license, the GNU Lesser | ||
68 | General Public License, applies to certain designated libraries, and | ||
69 | is quite different from the ordinary General Public License. We use | ||
70 | this license for certain libraries in order to permit linking those | ||
71 | libraries into non-free programs. | ||
72 | |||
73 | When a program is linked with a library, whether statically or using | ||
74 | a shared library, the combination of the two is legally speaking a | ||
75 | combined work, a derivative of the original library. The ordinary | ||
76 | General Public License therefore permits such linking only if the | ||
77 | entire combination fits its criteria of freedom. The Lesser General | ||
78 | Public License permits more lax criteria for linking other code with | ||
79 | the library. | ||
80 | |||
81 | We call this license the "Lesser" General Public License because it | ||
82 | does Less to protect the user's freedom than the ordinary General | ||
83 | Public License. It also provides other free software developers Less | ||
84 | of an advantage over competing non-free programs. These disadvantages | ||
85 | are the reason we use the ordinary General Public License for many | ||
86 | libraries. However, the Lesser license provides advantages in certain | ||
87 | special circumstances. | ||
88 | |||
89 | For example, on rare occasions, there may be a special need to | ||
90 | encourage the widest possible use of a certain library, so that it becomes | ||
91 | a de-facto standard. To achieve this, non-free programs must be | ||
92 | allowed to use the library. A more frequent case is that a free | ||
93 | library does the same job as widely used non-free libraries. In this | ||
94 | case, there is little to gain by limiting the free library to free | ||
95 | software only, so we use the Lesser General Public License. | ||
96 | |||
97 | In other cases, permission to use a particular library in non-free | ||
98 | programs enables a greater number of people to use a large body of | ||
99 | free software. For example, permission to use the GNU C Library in | ||
100 | non-free programs enables many more people to use the whole GNU | ||
101 | operating system, as well as its variant, the GNU/Linux operating | ||
102 | system. | ||
103 | |||
104 | Although the Lesser General Public License is Less protective of the | ||
105 | users' freedom, it does ensure that the user of a program that is | ||
106 | linked with the Library has the freedom and the wherewithal to run | ||
107 | that program using a modified version of the Library. | ||
108 | |||
109 | The precise terms and conditions for copying, distribution and | ||
110 | modification follow. Pay close attention to the difference between a | ||
111 | "work based on the library" and a "work that uses the library". The | ||
112 | former contains code derived from the library, whereas the latter must | ||
113 | be combined with the library in order to run. | ||
114 | |||
115 | GNU LESSER GENERAL PUBLIC LICENSE | ||
116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | ||
117 | |||
118 | 0. This License Agreement applies to any software library or other | ||
119 | program which contains a notice placed by the copyright holder or | ||
120 | other authorized party saying it may be distributed under the terms of | ||
121 | this Lesser General Public License (also called "this License"). | ||
122 | Each licensee is addressed as "you". | ||
123 | |||
124 | A "library" means a collection of software functions and/or data | ||
125 | prepared so as to be conveniently linked with application programs | ||
126 | (which use some of those functions and data) to form executables. | ||
127 | |||
128 | The "Library", below, refers to any such software library or work | ||
129 | which has been distributed under these terms. A "work based on the | ||
130 | Library" means either the Library or any derivative work under | ||
131 | copyright law: that is to say, a work containing the Library or a | ||
132 | portion of it, either verbatim or with modifications and/or translated | ||
133 | straightforwardly into another language. (Hereinafter, translation is | ||
134 | included without limitation in the term "modification".) | ||
135 | |||
136 | "Source code" for a work means the preferred form of the work for | ||
137 | making modifications to it. For a library, complete source code means | ||
138 | all the source code for all modules it contains, plus any associated | ||
139 | interface definition files, plus the scripts used to control compilation | ||
140 | and installation of the library. | ||
141 | |||
142 | Activities other than copying, distribution and modification are not | ||
143 | covered by this License; they are outside its scope. The act of | ||
144 | running a program using the Library is not restricted, and output from | ||
145 | such a program is covered only if its contents constitute a work based | ||
146 | on the Library (independent of the use of the Library in a tool for | ||
147 | writing it). Whether that is true depends on what the Library does | ||
148 | and what the program that uses the Library does. | ||
149 | |||
150 | 1. You may copy and distribute verbatim copies of the Library's | ||
151 | complete source code as you receive it, in any medium, provided that | ||
152 | you conspicuously and appropriately publish on each copy an | ||
153 | appropriate copyright notice and disclaimer of warranty; keep intact | ||
154 | all the notices that refer to this License and to the absence of any | ||
155 | warranty; and distribute a copy of this License along with the | ||
156 | Library. | ||
157 | |||
158 | You may charge a fee for the physical act of transferring a copy, | ||
159 | and you may at your option offer warranty protection in exchange for a | ||
160 | fee. | ||
161 | |||
162 | 2. You may modify your copy or copies of the Library or any portion | ||
163 | of it, thus forming a work based on the Library, and copy and | ||
164 | distribute such modifications or work under the terms of Section 1 | ||
165 | above, provided that you also meet all of these conditions: | ||
166 | |||
167 | a) The modified work must itself be a software library. | ||
168 | |||
169 | b) You must cause the files modified to carry prominent notices | ||
170 | stating that you changed the files and the date of any change. | ||
171 | |||
172 | c) You must cause the whole of the work to be licensed at no | ||
173 | charge to all third parties under the terms of this License. | ||
174 | |||
175 | d) If a facility in the modified Library refers to a function or a | ||
176 | table of data to be supplied by an application program that uses | ||
177 | the facility, other than as an argument passed when the facility | ||
178 | is invoked, then you must make a good faith effort to ensure that, | ||
179 | in the event an application does not supply such function or | ||
180 | table, the facility still operates, and performs whatever part of | ||
181 | its purpose remains meaningful. | ||
182 | |||
183 | (For example, a function in a library to compute square roots has | ||
184 | a purpose that is entirely well-defined independent of the | ||
185 | application. Therefore, Subsection 2d requires that any | ||
186 | application-supplied function or table used by this function must | ||
187 | be optional: if the application does not supply it, the square | ||
188 | root function must still compute square roots.) | ||
189 | |||
190 | These requirements apply to the modified work as a whole. If | ||
191 | identifiable sections of that work are not derived from the Library, | ||
192 | and can be reasonably considered independent and separate works in | ||
193 | themselves, then this License, and its terms, do not apply to those | ||
194 | sections when you distribute them as separate works. But when you | ||
195 | distribute the same sections as part of a whole which is a work based | ||
196 | on the Library, the distribution of the whole must be on the terms of | ||
197 | this License, whose permissions for other licensees extend to the | ||
198 | entire whole, and thus to each and every part regardless of who wrote | ||
199 | it. | ||
200 | |||
201 | Thus, it is not the intent of this section to claim rights or contest | ||
202 | your rights to work written entirely by you; rather, the intent is to | ||
203 | exercise the right to control the distribution of derivative or | ||
204 | collective works based on the Library. | ||
205 | |||
206 | In addition, mere aggregation of another work not based on the Library | ||
207 | with the Library (or with a work based on the Library) on a volume of | ||
208 | a storage or distribution medium does not bring the other work under | ||
209 | the scope of this License. | ||
210 | |||
211 | 3. You may opt to apply the terms of the ordinary GNU General Public | ||
212 | License instead of this License to a given copy of the Library. To do | ||
213 | this, you must alter all the notices that refer to this License, so | ||
214 | that they refer to the ordinary GNU General Public License, version 2, | ||
215 | instead of to this License. (If a newer version than version 2 of the | ||
216 | ordinary GNU General Public License has appeared, then you can specify | ||
217 | that version instead if you wish.) Do not make any other change in | ||
218 | these notices. | ||
219 | |||
220 | Once this change is made in a given copy, it is irreversible for | ||
221 | that copy, so the ordinary GNU General Public License applies to all | ||
222 | subsequent copies and derivative works made from that copy. | ||
223 | |||
224 | This option is useful when you wish to copy part of the code of | ||
225 | the Library into a program that is not a library. | ||
226 | |||
227 | 4. You may copy and distribute the Library (or a portion or | ||
228 | derivative of it, under Section 2) in object code or executable form | ||
229 | under the terms of Sections 1 and 2 above provided that you accompany | ||
230 | it with the complete corresponding machine-readable source code, which | ||
231 | must be distributed under the terms of Sections 1 and 2 above on a | ||
232 | medium customarily used for software interchange. | ||
233 | |||
234 | If distribution of object code is made by offering access to copy | ||
235 | from a designated place, then offering equivalent access to copy the | ||
236 | source code from the same place satisfies the requirement to | ||
237 | distribute the source code, even though third parties are not | ||
238 | compelled to copy the source along with the object code. | ||
239 | |||
240 | 5. A program that contains no derivative of any portion of the | ||
241 | Library, but is designed to work with the Library by being compiled or | ||
242 | linked with it, is called a "work that uses the Library". Such a | ||
243 | work, in isolation, is not a derivative work of the Library, and | ||
244 | therefore falls outside the scope of this License. | ||
245 | |||
246 | However, linking a "work that uses the Library" with the Library | ||
247 | creates an executable that is a derivative of the Library (because it | ||
248 | contains portions of the Library), rather than a "work that uses the | ||
249 | library". The executable is therefore covered by this License. | ||
250 | Section 6 states terms for distribution of such executables. | ||
251 | |||
252 | When a "work that uses the Library" uses material from a header file | ||
253 | that is part of the Library, the object code for the work may be a | ||
254 | derivative work of the Library even though the source code is not. | ||
255 | Whether this is true is especially significant if the work can be | ||
256 | linked without the Library, or if the work is itself a library. The | ||
257 | threshold for this to be true is not precisely defined by law. | ||
258 | |||
259 | If such an object file uses only numerical parameters, data | ||
260 | structure layouts and accessors, and small macros and small inline | ||
261 | functions (ten lines or less in length), then the use of the object | ||
262 | file is unrestricted, regardless of whether it is legally a derivative | ||
263 | work. (Executables containing this object code plus portions of the | ||
264 | Library will still fall under Section 6.) | ||
265 | |||
266 | Otherwise, if the work is a derivative of the Library, you may | ||
267 | distribute the object code for the work under the terms of Section 6. | ||
268 | Any executables containing that work also fall under Section 6, | ||
269 | whether or not they are linked directly with the Library itself. | ||
270 | |||
271 | 6. As an exception to the Sections above, you may also combine or | ||
272 | link a "work that uses the Library" with the Library to produce a | ||
273 | work containing portions of the Library, and distribute that work | ||
274 | under terms of your choice, provided that the terms permit | ||
275 | modification of the work for the customer's own use and reverse | ||
276 | engineering for debugging such modifications. | ||
277 | |||
278 | You must give prominent notice with each copy of the work that the | ||
279 | Library is used in it and that the Library and its use are covered by | ||
280 | this License. You must supply a copy of this License. If the work | ||
281 | during execution displays copyright notices, you must include the | ||
282 | copyright notice for the Library among them, as well as a reference | ||
283 | directing the user to the copy of this License. Also, you must do one | ||
284 | of these things: | ||
285 | |||
286 | a) Accompany the work with the complete corresponding | ||
287 | machine-readable source code for the Library including whatever | ||
288 | changes were used in the work (which must be distributed under | ||
289 | Sections 1 and 2 above); and, if the work is an executable linked | ||
290 | with the Library, with the complete machine-readable "work that | ||
291 | uses the Library", as object code and/or source code, so that the | ||
292 | user can modify the Library and then relink to produce a modified | ||
293 | executable containing the modified Library. (It is understood | ||
294 | that the user who changes the contents of definitions files in the | ||
295 | Library will not necessarily be able to recompile the application | ||
296 | to use the modified definitions.) | ||
297 | |||
298 | b) Use a suitable shared library mechanism for linking with the | ||
299 | Library. A suitable mechanism is one that (1) uses at run time a | ||
300 | copy of the library already present on the user's computer system, | ||
301 | rather than copying library functions into the executable, and (2) | ||
302 | will operate properly with a modified version of the library, if | ||
303 | the user installs one, as long as the modified version is | ||
304 | interface-compatible with the version that the work was made with. | ||
305 | |||
306 | c) Accompany the work with a written offer, valid for at | ||
307 | least three years, to give the same user the materials | ||
308 | specified in Subsection 6a, above, for a charge no more | ||
309 | than the cost of performing this distribution. | ||
310 | |||
311 | d) If distribution of the work is made by offering access to copy | ||
312 | from a designated place, offer equivalent access to copy the above | ||
313 | specified materials from the same place. | ||
314 | |||
315 | e) Verify that the user has already received a copy of these | ||
316 | materials or that you have already sent this user a copy. | ||
317 | |||
318 | For an executable, the required form of the "work that uses the | ||
319 | Library" must include any data and utility programs needed for | ||
320 | reproducing the executable from it. However, as a special exception, | ||
321 | the materials to be distributed need not include anything that is | ||
322 | normally distributed (in either source or binary form) with the major | ||
323 | components (compiler, kernel, and so on) of the operating system on | ||
324 | which the executable runs, unless that component itself accompanies | ||
325 | the executable. | ||
326 | |||
327 | It may happen that this requirement contradicts the license | ||
328 | restrictions of other proprietary libraries that do not normally | ||
329 | accompany the operating system. Such a contradiction means you cannot | ||
330 | use both them and the Library together in an executable that you | ||
331 | distribute. | ||
332 | |||
333 | 7. You may place library facilities that are a work based on the | ||
334 | Library side-by-side in a single library together with other library | ||
335 | facilities not covered by this License, and distribute such a combined | ||
336 | library, provided that the separate distribution of the work based on | ||
337 | the Library and of the other library facilities is otherwise | ||
338 | permitted, and provided that you do these two things: | ||
339 | |||
340 | a) Accompany the combined library with a copy of the same work | ||
341 | based on the Library, uncombined with any other library | ||
342 | facilities. This must be distributed under the terms of the | ||
343 | Sections above. | ||
344 | |||
345 | b) Give prominent notice with the combined library of the fact | ||
346 | that part of it is a work based on the Library, and explaining | ||
347 | where to find the accompanying uncombined form of the same work. | ||
348 | |||
349 | 8. You may not copy, modify, sublicense, link with, or distribute | ||
350 | the Library except as expressly provided under this License. Any | ||
351 | attempt otherwise to copy, modify, sublicense, link with, or | ||
352 | distribute the Library is void, and will automatically terminate your | ||
353 | rights under this License. However, parties who have received copies, | ||
354 | or rights, from you under this License will not have their licenses | ||
355 | terminated so long as such parties remain in full compliance. | ||
356 | |||
357 | 9. You are not required to accept this License, since you have not | ||
358 | signed it. However, nothing else grants you permission to modify or | ||
359 | distribute the Library or its derivative works. These actions are | ||
360 | prohibited by law if you do not accept this License. Therefore, by | ||
361 | modifying or distributing the Library (or any work based on the | ||
362 | Library), you indicate your acceptance of this License to do so, and | ||
363 | all its terms and conditions for copying, distributing or modifying | ||
364 | the Library or works based on it. | ||
365 | |||
366 | 10. Each time you redistribute the Library (or any work based on the | ||
367 | Library), the recipient automatically receives a license from the | ||
368 | original licensor to copy, distribute, link with or modify the Library | ||
369 | subject to these terms and conditions. You may not impose any further | ||
370 | restrictions on the recipients' exercise of the rights granted herein. | ||
371 | You are not responsible for enforcing compliance by third parties with | ||
372 | this License. | ||
373 | |||
374 | 11. If, as a consequence of a court judgment or allegation of patent | ||
375 | infringement or for any other reason (not limited to patent issues), | ||
376 | conditions are imposed on you (whether by court order, agreement or | ||
377 | otherwise) that contradict the conditions of this License, they do not | ||
378 | excuse you from the conditions of this License. If you cannot | ||
379 | distribute so as to satisfy simultaneously your obligations under this | ||
380 | License and any other pertinent obligations, then as a consequence you | ||
381 | may not distribute the Library at all. For example, if a patent | ||
382 | license would not permit royalty-free redistribution of the Library by | ||
383 | all those who receive copies directly or indirectly through you, then | ||
384 | the only way you could satisfy both it and this License would be to | ||
385 | refrain entirely from distribution of the Library. | ||
386 | |||
387 | If any portion of this section is held invalid or unenforceable under any | ||
388 | particular circumstance, the balance of the section is intended to apply, | ||
389 | and the section as a whole is intended to apply in other circumstances. | ||
390 | |||
391 | It is not the purpose of this section to induce you to infringe any | ||
392 | patents or other property right claims or to contest validity of any | ||
393 | such claims; this section has the sole purpose of protecting the | ||
394 | integrity of the free software distribution system which is | ||
395 | implemented by public license practices. Many people have made | ||
396 | generous contributions to the wide range of software distributed | ||
397 | through that system in reliance on consistent application of that | ||
398 | system; it is up to the author/donor to decide if he or she is willing | ||
399 | to distribute software through any other system and a licensee cannot | ||
400 | impose that choice. | ||
401 | |||
402 | This section is intended to make thoroughly clear what is believed to | ||
403 | be a consequence of the rest of this License. | ||
404 | |||
405 | 12. If the distribution and/or use of the Library is restricted in | ||
406 | certain countries either by patents or by copyrighted interfaces, the | ||
407 | original copyright holder who places the Library under this License may add | ||
408 | an explicit geographical distribution limitation excluding those countries, | ||
409 | so that distribution is permitted only in or among countries not thus | ||
410 | excluded. In such case, this License incorporates the limitation as if | ||
411 | written in the body of this License. | ||
412 | |||
413 | 13. The Free Software Foundation may publish revised and/or new | ||
414 | versions of the Lesser General Public License from time to time. | ||
415 | Such new versions will be similar in spirit to the present version, | ||
416 | but may differ in detail to address new problems or concerns. | ||
417 | |||
418 | Each version is given a distinguishing version number. If the Library | ||
419 | specifies a version number of this License which applies to it and | ||
420 | "any later version", you have the option of following the terms and | ||
421 | conditions either of that version or of any later version published by | ||
422 | the Free Software Foundation. If the Library does not specify a | ||
423 | license version number, you may choose any version ever published by | ||
424 | the Free Software Foundation. | ||
425 | |||
426 | 14. If you wish to incorporate parts of the Library into other free | ||
427 | programs whose distribution conditions are incompatible with these, | ||
428 | write to the author to ask for permission. For software which is | ||
429 | copyrighted by the Free Software Foundation, write to the Free | ||
430 | Software Foundation; we sometimes make exceptions for this. Our | ||
431 | decision will be guided by the two goals of preserving the free status | ||
432 | of all derivatives of our free software and of promoting the sharing | ||
433 | and reuse of software generally. | ||
434 | |||
435 | NO WARRANTY | ||
436 | |||
437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO | ||
438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. | ||
439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR | ||
440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY | ||
441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE | ||
442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE | ||
444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME | ||
445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | ||
446 | |||
447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN | ||
448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY | ||
449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU | ||
450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR | ||
451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE | ||
452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING | ||
453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A | ||
454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF | ||
455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | ||
456 | DAMAGES. | ||
457 | |||
458 | END OF TERMS AND CONDITIONS | ||
459 | |||
460 | How to Apply These Terms to Your New Libraries | ||
461 | |||
462 | If you develop a new library, and you want it to be of the greatest | ||
463 | possible use to the public, we recommend making it free software that | ||
464 | everyone can redistribute and change. You can do so by permitting | ||
465 | redistribution under these terms (or, alternatively, under the terms of the | ||
466 | ordinary General Public License). | ||
467 | |||
468 | To apply these terms, attach the following notices to the library. It is | ||
469 | safest to attach them to the start of each source file to most effectively | ||
470 | convey the exclusion of warranty; and each file should have at least the | ||
471 | "copyright" line and a pointer to where the full notice is found. | ||
472 | |||
473 | <one line to give the library's name and a brief idea of what it does.> | ||
474 | Copyright (C) <year> <name of author> | ||
475 | |||
476 | This library is free software; you can redistribute it and/or | ||
477 | modify it under the terms of the GNU Lesser General Public | ||
478 | License as published by the Free Software Foundation; either | ||
479 | version 2.1 of the License, or (at your option) any later version. | ||
480 | |||
481 | This library is distributed in the hope that it will be useful, | ||
482 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
484 | Lesser General Public License for more details. | ||
485 | |||
486 | You should have received a copy of the GNU Lesser General Public | ||
487 | License along with this library; if not, write to the Free Software | ||
488 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
489 | |||
490 | Also add information on how to contact you by electronic and paper mail. | ||
491 | |||
492 | You should also get your employer (if you work as a programmer) or your | ||
493 | school, if any, to sign a "copyright disclaimer" for the library, if | ||
494 | necessary. Here is a sample; alter the names: | ||
495 | |||
496 | Yoyodyne, Inc., hereby disclaims all copyright interest in the | ||
497 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. | ||
498 | |||
499 | <signature of Ty Coon>, 1 April 1990 | ||
500 | Ty Coon, President of Vice | ||
501 | |||
502 | That's all there is to it! | ||
diff --git a/libraries/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor.sln b/libraries/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor.sln new file mode 100644 index 0000000..6a3f521 --- /dev/null +++ b/libraries/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor.sln | |||
@@ -0,0 +1,20 @@ | |||
1 |  | ||
2 | Microsoft Visual Studio Solution File, Format Version 9.00 | ||
3 | # Visual C# Express 2005 | ||
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OdeModelProcessor", "OdeModelProcessor\OdeModelProcessor.csproj", "{246F3075-FEE3-45F9-8CB6-47DADBFFD1F2}" | ||
5 | EndProject | ||
6 | Global | ||
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
8 | Debug|Any CPU = Debug|Any CPU | ||
9 | Release|Any CPU = Release|Any CPU | ||
10 | EndGlobalSection | ||
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
12 | {246F3075-FEE3-45F9-8CB6-47DADBFFD1F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
13 | {246F3075-FEE3-45F9-8CB6-47DADBFFD1F2}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
14 | {246F3075-FEE3-45F9-8CB6-47DADBFFD1F2}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
15 | {246F3075-FEE3-45F9-8CB6-47DADBFFD1F2}.Release|Any CPU.Build.0 = Release|Any CPU | ||
16 | EndGlobalSection | ||
17 | GlobalSection(SolutionProperties) = preSolution | ||
18 | HideSolutionNode = FALSE | ||
19 | EndGlobalSection | ||
20 | EndGlobal | ||
diff --git a/libraries/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/OdeModelProcessor.cs b/libraries/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/OdeModelProcessor.cs new file mode 100644 index 0000000..9c974eb --- /dev/null +++ b/libraries/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/OdeModelProcessor.cs | |||
@@ -0,0 +1,354 @@ | |||
1 | /* | ||
2 | * The ODE Model Processor | ||
3 | * ----------------------- | ||
4 | * | ||
5 | * Copyright 2007, Department of Information Science, | ||
6 | * University of Otago, Dunedin, New Zealand. | ||
7 | * | ||
8 | * Author: Richard Barrington <barri662@student.otago.ac.nz> | ||
9 | * | ||
10 | * This is a Content Processor and Tag library written for use with | ||
11 | * Microsoft Visual C# 2005 Express Edition and Microsoft XNA Game | ||
12 | * Studio Express 1.0. | ||
13 | * | ||
14 | * It can be used to read .x model vertex and index data before | ||
15 | * insertion into the content pipeline. This is used to build ODE | ||
16 | * Triangle Meshes which are then used for collision detection that | ||
17 | * is more accurate than the default XNA bounding boxes or spheres. | ||
18 | * | ||
19 | * Usage is simple: | ||
20 | * Build the library and reference the DLL in your project. | ||
21 | * Add the DLL to the Content Pipeline | ||
22 | * Set the content processor for you .x models to OdeModelProcessor. | ||
23 | * | ||
24 | * Create triangle meshes as follows: | ||
25 | * 1) Create a space, but only one for all of models. | ||
26 | * 2) Create a triangle data. | ||
27 | * 3) Load the model. | ||
28 | * 4) Retreive the tag from the model. | ||
29 | * 6) Build the triangle mesh by calling d.GeomTriMeshDataBuildSimple. | ||
30 | * | ||
31 | * Eg: | ||
32 | * IntPtr space = d.SimpleSpaceCreate(IntPtr.Zero); | ||
33 | * IntPtr triangleData = d.GeomTriMeshDataCreate(); | ||
34 | * Model obj = content.Load<Model>("Content\\mycube"); | ||
35 | * OdeTag tag = (OdeTag)obj.Tag; | ||
36 | * IntPtr vertexArray = tag.getVertices(); | ||
37 | * IntPtr indexArray = tag.getIndices(); | ||
38 | * d.GeomTriMeshDataBuildSimple | ||
39 | * ( | ||
40 | * triangleData, | ||
41 | * vertexArray, tag.getVertexStride(), tag.getVertexCount(), | ||
42 | * indexArray, tag.getIndexCount(), tag.getIndexStride() | ||
43 | * ); | ||
44 | * IntPtr triangleMesh = d.CreateTriMesh(space, triangleData, null, null, null); | ||
45 | * | ||
46 | * You can load multiple models and test for collisions with something | ||
47 | * like this in the update method: | ||
48 | * | ||
49 | * d.GeomSetPosition(odeTri1, obj1Position.X, obj1Position.Y, obj1Position.Z); | ||
50 | * d.GeomSetPosition(odeTri2, obj2Position.X, obj2Position.Y, obj2Position.Z); | ||
51 | * int numberOfContacts = d.Collide(odeTri1, odeTri2, ODE_CONTACTS, | ||
52 | * contactGeom, d.ContactGeom.SizeOf); | ||
53 | * | ||
54 | * Where odeTri1 and odeTri2 are triangle meshes you've created, obj1Position | ||
55 | * and obj2Position are the positions of your rendered models in the scene, | ||
56 | * ODE_CONTACTS is a constant defining the maximum number of contacts | ||
57 | * to test for, contactGeom is a d.ContactGeom[] of length ODE_CONTACTS. | ||
58 | * | ||
59 | * If numberOfContacts is greater than 0, you have a collision. | ||
60 | * | ||
61 | * Other ODE functions such as d.SpaceCollide() also work; see ODE.NET BoxTest.cs. | ||
62 | * | ||
63 | * This library is free software; you can redistribute it and/or | ||
64 | * modify it under the same terms as the ODE and ODE.Net libraries. | ||
65 | * Specifically, the terms are one of EITHER: | ||
66 | * | ||
67 | * (1) The GNU Lesser General Public License as published by the Free | ||
68 | * Software Foundation; either version 2.1 of the License, or (at | ||
69 | * your option) any later version. The text of the GNU Lesser | ||
70 | * General Public License is included with this library in the | ||
71 | * file LICENSE.TXT. | ||
72 | * | ||
73 | * (2) The BSD-style license that is included with this library in | ||
74 | * the file LICENSE-BSD.TXT. | ||
75 | * | ||
76 | * This library is distributed in the hope that it will be useful, | ||
77 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
78 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files | ||
79 | * LICENSE.TXT and LICENSE-BSD.TXT for more details. | ||
80 | * | ||
81 | */ | ||
82 | |||
83 | using System; | ||
84 | using System.Collections.Generic; | ||
85 | using System.Text; | ||
86 | using Microsoft.Xna.Framework; | ||
87 | using Microsoft.Xna.Framework.Content; | ||
88 | using Microsoft.Xna.Framework.Graphics; | ||
89 | using Microsoft.Xna.Framework.Design; | ||
90 | using Microsoft.Xna.Framework.Content.Pipeline; | ||
91 | using Microsoft.Xna.Framework.Content.Pipeline.Graphics; | ||
92 | using Microsoft.Xna.Framework.Content.Pipeline.Processors; | ||
93 | using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler; | ||
94 | using Ode.NET; | ||
95 | using System.Runtime.InteropServices; | ||
96 | |||
97 | namespace OdeModelProcessor | ||
98 | { | ||
99 | /* | ||
100 | * Container for vertex and index data in a format | ||
101 | * that ODE.Net can use | ||
102 | */ | ||
103 | public class OdeTag | ||
104 | { | ||
105 | |||
106 | private float[] vertexData; | ||
107 | private int[] indexData; | ||
108 | private const int indexStride = (sizeof(int)); | ||
109 | private const int vertexStride = (3 * sizeof(float)); | ||
110 | |||
111 | /* Constructors */ | ||
112 | public OdeTag() | ||
113 | { | ||
114 | vertexData = new float[0]; | ||
115 | indexData = new int[0]; | ||
116 | } | ||
117 | |||
118 | public OdeTag(float[] vertexData, int[] indexData) | ||
119 | { | ||
120 | this.vertexData = vertexData; | ||
121 | this.indexData = indexData; | ||
122 | } | ||
123 | |||
124 | /* Data setter */ | ||
125 | public void setData(float[] vertexData, int[] indexData) | ||
126 | { | ||
127 | this.vertexData = vertexData; | ||
128 | this.indexData = indexData; | ||
129 | } | ||
130 | |||
131 | /* Data appenders */ | ||
132 | public void appendVertexData(float[] vertexData) | ||
133 | { | ||
134 | int newVertexDataLength = vertexData.Length; | ||
135 | float[] tempVertexArray = new float[newVertexDataLength + this.vertexData.Length]; | ||
136 | this.vertexData.CopyTo(tempVertexArray, 0); | ||
137 | vertexData.CopyTo(tempVertexArray, this.vertexData.Length); | ||
138 | this.vertexData = tempVertexArray; | ||
139 | } | ||
140 | |||
141 | public void appendIndexData(int[] indexData) | ||
142 | { | ||
143 | int newIndexDataLength = indexData.Length; | ||
144 | int[] tempIndexArray = new int[newIndexDataLength + this.indexData.Length]; | ||
145 | this.indexData.CopyTo(tempIndexArray, 0); | ||
146 | indexData.CopyTo(tempIndexArray, this.indexData.Length); | ||
147 | this.indexData = tempIndexArray; | ||
148 | } | ||
149 | |||
150 | /* Data getters */ | ||
151 | public float[] getVertexData() | ||
152 | { | ||
153 | return this.vertexData; | ||
154 | } | ||
155 | |||
156 | public int[] getIndexData() | ||
157 | { | ||
158 | return this.indexData; | ||
159 | } | ||
160 | |||
161 | /* Native data getters */ | ||
162 | public IntPtr getVertices() | ||
163 | { | ||
164 | int count = getVertexData().Length; | ||
165 | int memsize = count * Marshal.SizeOf(getVertexData()[0].GetType()); | ||
166 | IntPtr pointer = Marshal.AllocCoTaskMem(memsize); | ||
167 | Marshal.Copy(getVertexData(), 0, pointer, count); | ||
168 | return pointer; | ||
169 | } | ||
170 | |||
171 | public IntPtr getIndices() | ||
172 | { | ||
173 | int count = getIndexData().Length; | ||
174 | int memsize = count * Marshal.SizeOf(getIndexData()[0].GetType()); | ||
175 | IntPtr pointer = Marshal.AllocCoTaskMem(memsize); | ||
176 | Marshal.Copy(getIndexData(), 0, pointer, count); | ||
177 | return pointer; | ||
178 | } | ||
179 | |||
180 | /* Count getters */ | ||
181 | public int getVertexCount() | ||
182 | { | ||
183 | return vertexData.Length/3; | ||
184 | } | ||
185 | |||
186 | public int getIndexCount() | ||
187 | { | ||
188 | return indexData.Length; | ||
189 | } | ||
190 | |||
191 | /* Stride getters */ | ||
192 | public int getVertexStride() | ||
193 | { | ||
194 | return vertexStride; | ||
195 | } | ||
196 | |||
197 | public int getIndexStride() | ||
198 | { | ||
199 | return indexStride; | ||
200 | } | ||
201 | |||
202 | /* | ||
203 | * Convienience method to build the mesh and return it. The triangleData | ||
204 | * is passed in to allow the calling application to delete it afterwards. | ||
205 | * | ||
206 | * Be sure to destroy the returned TriangleMesh in the client application. | ||
207 | * | ||
208 | * Can't destroy the index and vertex arrays here though, so best to handle | ||
209 | * this manually - only use this method if nothing else makes sense. | ||
210 | */ | ||
211 | public IntPtr getTriangleMesh(IntPtr space, IntPtr triangleData) | ||
212 | { | ||
213 | d.GeomTriMeshDataBuildSimple( | ||
214 | triangleData, | ||
215 | getVertices(), getVertexStride(), getVertexCount(), | ||
216 | getIndices(), getIndexCount(), getIndexStride() | ||
217 | ); | ||
218 | return d.CreateTriMesh(space, triangleData, null, null, null); | ||
219 | } | ||
220 | |||
221 | } | ||
222 | |||
223 | /* | ||
224 | * Subclass of the XNA .x model processor, which creates and appends a tag | ||
225 | * containing vertex and index data for ODE.Net to use. | ||
226 | */ | ||
227 | [ContentProcessor] | ||
228 | public class OdeModelProcessor : ModelProcessor | ||
229 | { | ||
230 | private OdeTag tag; | ||
231 | private int indexOffset = 0; | ||
232 | |||
233 | public override ModelContent Process(NodeContent input, ContentProcessorContext context) | ||
234 | { | ||
235 | tag = new OdeTag(); | ||
236 | GenerateVerticesRecursive( input ); | ||
237 | ModelContent model = base.Process(input, context); | ||
238 | model.Tag = tag; | ||
239 | indexOffset = 0; | ||
240 | return model; | ||
241 | } | ||
242 | |||
243 | public void GenerateVerticesRecursive(NodeContent input) | ||
244 | { | ||
245 | |||
246 | MeshContent mesh = input as MeshContent; | ||
247 | |||
248 | if (mesh != null) | ||
249 | { | ||
250 | GeometryContentCollection gc = mesh.Geometry; | ||
251 | foreach (GeometryContent g in gc) | ||
252 | { | ||
253 | VertexContent vc = g.Vertices; | ||
254 | IndirectPositionCollection ipc = vc.Positions; | ||
255 | IndexCollection ic = g.Indices; | ||
256 | |||
257 | float[] vertexData = new float[ipc.Count * 3]; | ||
258 | for (int i = 0; i < ipc.Count; i++) | ||
259 | { | ||
260 | |||
261 | Vector3 v0 = ipc[i]; | ||
262 | vertexData[(i * 3) + 0] = v0.X; | ||
263 | vertexData[(i * 3) + 1] = v0.Y; | ||
264 | vertexData[(i * 3) + 2] = v0.Z; | ||
265 | |||
266 | } | ||
267 | |||
268 | int[] indexData = new int[ic.Count]; | ||
269 | for (int j = 0; j < ic.Count; j ++) | ||
270 | { | ||
271 | |||
272 | indexData[j] = ic[j] + indexOffset; | ||
273 | |||
274 | } | ||
275 | |||
276 | tag.appendVertexData(vertexData); | ||
277 | tag.appendIndexData(indexData); | ||
278 | indexOffset += ipc.Count; | ||
279 | } | ||
280 | |||
281 | } | ||
282 | |||
283 | foreach (NodeContent child in input.Children) | ||
284 | { | ||
285 | GenerateVerticesRecursive(child); | ||
286 | } | ||
287 | |||
288 | } | ||
289 | |||
290 | } | ||
291 | |||
292 | /* Writer for the OdeTag class */ | ||
293 | [ContentTypeWriter] | ||
294 | public class OdeTagWriter : ContentTypeWriter<OdeTag> | ||
295 | { | ||
296 | |||
297 | protected override void Write(ContentWriter output, OdeTag value) | ||
298 | { | ||
299 | float[] vertexData = value.getVertexData(); | ||
300 | int[] indexData = value.getIndexData(); | ||
301 | output.Write(vertexData.Length); | ||
302 | output.Write(indexData.Length); | ||
303 | for (int j = 0; j < vertexData.Length; j++) | ||
304 | { | ||
305 | output.Write(vertexData[j]); | ||
306 | } | ||
307 | for (int i = 0; i < indexData.Length; i++) | ||
308 | { | ||
309 | output.Write(indexData[i]); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | public override string GetRuntimeType(TargetPlatform targetPlatform) | ||
314 | { | ||
315 | return typeof(OdeTag).AssemblyQualifiedName; | ||
316 | } | ||
317 | |||
318 | public override string GetRuntimeReader(TargetPlatform targetPlatform) | ||
319 | { | ||
320 | return "OdeModelProcessor.OdeTagReader, OdeModelProcessor, Version=1.0.0.0, Culture=neutral"; | ||
321 | } | ||
322 | |||
323 | } | ||
324 | |||
325 | /* Reader for the OdeTag class */ | ||
326 | public class OdeTagReader : ContentTypeReader<OdeTag> | ||
327 | { | ||
328 | protected override OdeTag Read(ContentReader input, OdeTag existingInstance) | ||
329 | { | ||
330 | float[] vertexData = new float[input.ReadInt32()]; | ||
331 | int[] indexData = new int[input.ReadInt32()]; | ||
332 | for (int j = 0; j < vertexData.Length; j++) | ||
333 | { | ||
334 | vertexData[j] = input.ReadSingle(); | ||
335 | } | ||
336 | for (int i = 0; i < indexData.Length; i++) | ||
337 | { | ||
338 | indexData[i] = input.ReadInt32(); | ||
339 | } | ||
340 | |||
341 | OdeTag tag = null; | ||
342 | if (existingInstance == null) | ||
343 | { | ||
344 | tag = new OdeTag(vertexData, indexData); | ||
345 | } | ||
346 | else | ||
347 | { | ||
348 | tag = existingInstance; | ||
349 | tag.setData(vertexData, indexData); | ||
350 | } | ||
351 | return tag; | ||
352 | } | ||
353 | } | ||
354 | } | ||
diff --git a/libraries/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/OdeModelProcessor.csproj b/libraries/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/OdeModelProcessor.csproj new file mode 100644 index 0000000..3a36a12 --- /dev/null +++ b/libraries/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/OdeModelProcessor.csproj | |||
@@ -0,0 +1,69 @@ | |||
1 | <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
2 | <PropertyGroup> | ||
3 | <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | ||
4 | <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | ||
5 | <ProductVersion>8.0.50727</ProductVersion> | ||
6 | <SchemaVersion>2.0</SchemaVersion> | ||
7 | <ProjectGuid>{246F3075-FEE3-45F9-8CB6-47DADBFFD1F2}</ProjectGuid> | ||
8 | <OutputType>Library</OutputType> | ||
9 | <AppDesignerFolder>Properties</AppDesignerFolder> | ||
10 | <RootNamespace>OdeModelProcessor</RootNamespace> | ||
11 | <AssemblyName>OdeModelProcessor</AssemblyName> | ||
12 | </PropertyGroup> | ||
13 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | ||
14 | <DebugSymbols>true</DebugSymbols> | ||
15 | <DebugType>full</DebugType> | ||
16 | <Optimize>false</Optimize> | ||
17 | <OutputPath>bin\Debug\</OutputPath> | ||
18 | <DefineConstants>DEBUG</DefineConstants> | ||
19 | <ErrorReport>prompt</ErrorReport> | ||
20 | <WarningLevel>4</WarningLevel> | ||
21 | <AllowUnsafeBlocks>false</AllowUnsafeBlocks> | ||
22 | <UseVSHostingProcess>false</UseVSHostingProcess> | ||
23 | </PropertyGroup> | ||
24 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | ||
25 | <DebugType>pdbonly</DebugType> | ||
26 | <Optimize>true</Optimize> | ||
27 | <OutputPath>bin\Release\</OutputPath> | ||
28 | <DefineConstants> | ||
29 | </DefineConstants> | ||
30 | <ErrorReport>prompt</ErrorReport> | ||
31 | <WarningLevel>4</WarningLevel> | ||
32 | <AllowUnsafeBlocks>false</AllowUnsafeBlocks> | ||
33 | <UseVSHostingProcess>false</UseVSHostingProcess> | ||
34 | </PropertyGroup> | ||
35 | <ItemGroup> | ||
36 | <Reference Include="Microsoft.Xna.Framework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=x86" /> | ||
37 | <Reference Include="Microsoft.Xna.Framework.Content.Pipeline, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=x86" /> | ||
38 | <Reference Include="Ode.NET, Version=0.7.0.0, Culture=neutral, processorArchitecture=MSIL"> | ||
39 | <SpecificVersion>False</SpecificVersion> | ||
40 | <HintPath>..\..\ODE\Ode.NET-0.8\bin\Release\Ode.NET.dll</HintPath> | ||
41 | </Reference> | ||
42 | <Reference Include="System" /> | ||
43 | <Reference Include="System.Data" /> | ||
44 | <Reference Include="System.Xml" /> | ||
45 | </ItemGroup> | ||
46 | <ItemGroup> | ||
47 | <Compile Include="OdeModelProcessor.cs" /> | ||
48 | <Compile Include="Properties\AssemblyInfo.cs" /> | ||
49 | <Compile Include="Properties\Settings.Designer.cs"> | ||
50 | <AutoGen>True</AutoGen> | ||
51 | <DesignTimeSharedInput>True</DesignTimeSharedInput> | ||
52 | <DependentUpon>Settings.settings</DependentUpon> | ||
53 | </Compile> | ||
54 | </ItemGroup> | ||
55 | <ItemGroup> | ||
56 | <None Include="Properties\Settings.settings"> | ||
57 | <Generator>SettingsSingleFileGenerator</Generator> | ||
58 | <LastGenOutput>Settings.Designer.cs</LastGenOutput> | ||
59 | </None> | ||
60 | </ItemGroup> | ||
61 | <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> | ||
62 | <!-- To modify your build process, add your task inside one of the targets below and uncomment it. | ||
63 | Other similar extension points exist, see Microsoft.Common.targets. | ||
64 | <Target Name="BeforeBuild"> | ||
65 | </Target> | ||
66 | <Target Name="AfterBuild"> | ||
67 | </Target> | ||
68 | --> | ||
69 | </Project> \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/Properties/AssemblyInfo.cs b/libraries/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..1ecad3e --- /dev/null +++ b/libraries/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/Properties/AssemblyInfo.cs | |||
@@ -0,0 +1,35 @@ | |||
1 | using System.Reflection; | ||
2 | using System.Runtime.CompilerServices; | ||
3 | using System.Runtime.InteropServices; | ||
4 | |||
5 | // General Information about an assembly is controlled through the following | ||
6 | // set of attributes. Change these attribute values to modify the information | ||
7 | // associated with an assembly. | ||
8 | [assembly: AssemblyTitle("OdeModelProcessor")] | ||
9 | [assembly: AssemblyDescription("")] | ||
10 | [assembly: AssemblyConfiguration("")] | ||
11 | [assembly: AssemblyCompany("")] | ||
12 | [assembly: AssemblyProduct("OdeModelProcessor")] | ||
13 | [assembly: AssemblyCopyright("Copyright © 2007")] | ||
14 | [assembly: AssemblyTrademark("")] | ||
15 | [assembly: AssemblyCulture("")] | ||
16 | |||
17 | // Setting ComVisible to false makes the types in this assembly not visible | ||
18 | // to COM components. If you need to access a type in this assembly from | ||
19 | // COM, set the ComVisible attribute to true on that type. | ||
20 | [assembly: ComVisible(false)] | ||
21 | |||
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM | ||
23 | [assembly: Guid("29c5609a-cd5f-480b-b4ef-5c11de022268")] | ||
24 | |||
25 | // Version information for an assembly consists of the following four values: | ||
26 | // | ||
27 | // Major Version | ||
28 | // Minor Version | ||
29 | // Build Number | ||
30 | // Revision | ||
31 | // | ||
32 | // You can specify all the values or you can default the Revision and Build Numbers | ||
33 | // by using the '*' as shown below: | ||
34 | [assembly: AssemblyVersion("1.0.0.0")] | ||
35 | [assembly: AssemblyFileVersion("1.0.0.0")] | ||
diff --git a/libraries/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/Properties/Settings.Designer.cs b/libraries/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/Properties/Settings.Designer.cs new file mode 100755 index 0000000..6ab60a8 --- /dev/null +++ b/libraries/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/Properties/Settings.Designer.cs | |||
@@ -0,0 +1,26 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // <auto-generated> | ||
3 | // This code was generated by a tool. | ||
4 | // Runtime Version:2.0.50727.832 | ||
5 | // | ||
6 | // Changes to this file may cause incorrect behavior and will be lost if | ||
7 | // the code is regenerated. | ||
8 | // </auto-generated> | ||
9 | //------------------------------------------------------------------------------ | ||
10 | |||
11 | namespace OdeModelProcessor.Properties { | ||
12 | |||
13 | |||
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] | ||
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "8.0.0.0")] | ||
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { | ||
17 | |||
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); | ||
19 | |||
20 | public static Settings Default { | ||
21 | get { | ||
22 | return defaultInstance; | ||
23 | } | ||
24 | } | ||
25 | } | ||
26 | } | ||
diff --git a/libraries/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/Properties/Settings.settings b/libraries/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/Properties/Settings.settings new file mode 100755 index 0000000..15034e7 --- /dev/null +++ b/libraries/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/Properties/Settings.settings | |||
@@ -0,0 +1,6 @@ | |||
1 | <?xml version='1.0' encoding='utf-8'?> | ||
2 | <SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)"> | ||
3 | <Profiles> | ||
4 | <Profile Name="(Default)" /> | ||
5 | </Profiles> | ||
6 | </SettingsFile> | ||
diff --git a/libraries/ode-0.9/contrib/OdeModelProcessor/README.TXT b/libraries/ode-0.9/contrib/OdeModelProcessor/README.TXT new file mode 100644 index 0000000..97683f9 --- /dev/null +++ b/libraries/ode-0.9/contrib/OdeModelProcessor/README.TXT | |||
@@ -0,0 +1,78 @@ | |||
1 | The ODE Model Processor | ||
2 | ----------------------- | ||
3 | |||
4 | Copyright 2007, Department of Information Science, | ||
5 | University of Otago, Dunedin, New Zealand. | ||
6 | |||
7 | Author: Richard Barrington <barri662@student.otago.ac.nz> | ||
8 | |||
9 | This is a Content Processor and Tag library written for use with | ||
10 | Microsoft Visual C# 2005 Express Edition and Microsoft XNA Game | ||
11 | Studio Express 1.0. | ||
12 | |||
13 | It can be used to read .x model vertex and index data before | ||
14 | insertion into the content pipeline. This is used to build ODE | ||
15 | Triangle Meshes which are then used for collision detection that | ||
16 | is more accurate than the default XNA bounding boxes or spheres. | ||
17 | |||
18 | Usage is fairly simple: | ||
19 | Build the library and reference the DLL in your project. | ||
20 | Add the DLL to the Content Pipeline | ||
21 | Set the content processor for you .x models to OdeModelProcessor. | ||
22 | |||
23 | Create triangle meshes as follows: | ||
24 | 1) Create a space, but only one for all of models. | ||
25 | 2) Create a triangle data. | ||
26 | 3) Load the model. | ||
27 | 4) Retreive the tag from the model. | ||
28 | 6) Build the triangle mesh by calling d.GeomTriMeshDataBuildSimple. | ||
29 | |||
30 | Eg: | ||
31 | IntPtr space = d.SimpleSpaceCreate(IntPtr.Zero); | ||
32 | IntPtr triangleData = d.GeomTriMeshDataCreate(); | ||
33 | Model obj = content.Load<Model>("Content\\mycube"); | ||
34 | OdeTag tag = (OdeTag)obj.Tag; | ||
35 | IntPtr vertexArray = tag.getVertices(); | ||
36 | IntPtr indexArray = tag.getIndices(); | ||
37 | d.GeomTriMeshDataBuildSimple | ||
38 | ( | ||
39 | triangleData, | ||
40 | vertexArray, tag.getVertexStride(), tag.getVertexCount(), | ||
41 | indexArray, tag.getIndexCount(), tag.getIndexStride() | ||
42 | ); | ||
43 | IntPtr triangleMesh = d.CreateTriMesh(space, triangleData, null, null, null); | ||
44 | |||
45 | You can load multiple models and test for collisions with something | ||
46 | like this in the update method: | ||
47 | |||
48 | d.GeomSetPosition(odeTri1, obj1Position.X, obj1Position.Y, obj1Position.Z); | ||
49 | d.GeomSetPosition(odeTri2, obj2Position.X, obj2Position.Y, obj2Position.Z); | ||
50 | int numberOfContacts = d.Collide(odeTri1, odeTri2, ODE_CONTACTS, | ||
51 | contactGeom, d.ContactGeom.SizeOf); | ||
52 | |||
53 | Where odeTri1 and odeTri2 are triangle meshes you've created, obj1Position | ||
54 | and obj2Position are the positions of your rendered models in the scene, | ||
55 | ODE_CONTACTS is a constant defining the maximum number of contacts | ||
56 | to test for, contactGeom is a d.ContactGeom[] of length ODE_CONTACTS. | ||
57 | |||
58 | If numberOfContacts is greater than 0, you have a collision. | ||
59 | |||
60 | Other ODE functions such as d.SpaceCollide() also work; see ODE.NET BoxTest.cs. | ||
61 | |||
62 | This library is free software; you can redistribute it and/or | ||
63 | modify it under the same terms as the ODE and ODE.Net libraries. | ||
64 | Specifically, the terms are one of EITHER: | ||
65 | |||
66 | (1) The GNU Lesser General Public License as published by the Free | ||
67 | Software Foundation; either version 2.1 of the License, or (at | ||
68 | your option) any later version. The text of the GNU Lesser | ||
69 | General Public License is included with this library in the | ||
70 | file LICENSE.TXT. | ||
71 | |||
72 | (2) The BSD-style license that is included with this library in | ||
73 | the file LICENSE-BSD.TXT. | ||
74 | |||
75 | This library is distributed in the hope that it will be useful, | ||
76 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
77 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files | ||
78 | LICENSE.TXT and LICENSE-BSD.TXT for more details. | ||
diff --git a/libraries/ode-0.9/contrib/README b/libraries/ode-0.9/contrib/README new file mode 100644 index 0000000..dbfaf7f --- /dev/null +++ b/libraries/ode-0.9/contrib/README | |||
@@ -0,0 +1,19 @@ | |||
1 | This directory contains ODE-related things that have been generously | ||
2 | contributed by ODE's users. Why is this stuff here and not integrated | ||
3 | into the main ODE source tree? There may be several reasons: | ||
4 | |||
5 | * The author(s) and ODE maintainers(s) may not have had time to do | ||
6 | the job. | ||
7 | |||
8 | * It may not be finished. | ||
9 | |||
10 | * It may contribute functionality that is useful but not considered | ||
11 | to be part of ODE's core. | ||
12 | |||
13 | No guarantees are made about the code in this directory - it may not | ||
14 | be documented, it may not have been tested, and it may not even | ||
15 | compile for you. | ||
16 | |||
17 | Each package has its own subdirectory, with a README file in that | ||
18 | directory explaining what the package is. | ||
19 | |||
diff --git a/libraries/ode-0.9/contrib/TerrainAndCone/collision_std_internal.h b/libraries/ode-0.9/contrib/TerrainAndCone/collision_std_internal.h new file mode 100644 index 0000000..b445353 --- /dev/null +++ b/libraries/ode-0.9/contrib/TerrainAndCone/collision_std_internal.h | |||
@@ -0,0 +1,100 @@ | |||
1 | //Benoit CHAPEROT 2003-2004 www.jstarlab.com | ||
2 | #ifndef _ODE_COLLISION_STD_INTERNAL_H_ | ||
3 | #define _ODE_COLLISION_STD_INTERNAL_H_ | ||
4 | |||
5 | #include <ode/common.h> | ||
6 | #include "collision_kernel.h" | ||
7 | |||
8 | struct dxSphere : public dxGeom { | ||
9 | dReal radius; // sphere radius | ||
10 | dxSphere (dSpaceID space, dReal _radius); | ||
11 | void computeAABB(); | ||
12 | }; | ||
13 | |||
14 | |||
15 | struct dxBox : public dxGeom { | ||
16 | dVector3 side; // side lengths (x,y,z) | ||
17 | dxBox (dSpaceID space, dReal lx, dReal ly, dReal lz); | ||
18 | void computeAABB(); | ||
19 | }; | ||
20 | |||
21 | |||
22 | struct dxCCylinder : public dxGeom { | ||
23 | dReal radius,lz; // radius, length along z axis | ||
24 | dxCCylinder (dSpaceID space, dReal _radius, dReal _length); | ||
25 | void computeAABB(); | ||
26 | }; | ||
27 | |||
28 | |||
29 | struct dxPlane : public dxGeom { | ||
30 | dReal p[4]; | ||
31 | dxPlane (dSpaceID space, dReal a, dReal b, dReal c, dReal d); | ||
32 | void computeAABB(); | ||
33 | }; | ||
34 | |||
35 | struct dxCylinder : public dxGeom { | ||
36 | dReal radius,lz; // radius, length along z axis | ||
37 | dxCylinder (dSpaceID space, dReal _radius, dReal _length); | ||
38 | void computeAABB(); | ||
39 | }; | ||
40 | |||
41 | struct dxCone : public dxGeom { | ||
42 | dReal radius,lz; | ||
43 | dxCone(dSpaceID space, dReal _radius,dReal _length); | ||
44 | ~dxCone(); | ||
45 | void computeAABB(); | ||
46 | }; | ||
47 | |||
48 | struct dxRay : public dxGeom { | ||
49 | dReal length; | ||
50 | dxRay (dSpaceID space, dReal _length); | ||
51 | void computeAABB(); | ||
52 | }; | ||
53 | |||
54 | struct dxTerrainY : public dxGeom { | ||
55 | dReal m_vLength; | ||
56 | dReal *m_pHeights; | ||
57 | dReal m_vMinHeight; | ||
58 | dReal m_vMaxHeight; | ||
59 | dReal m_vNodeLength; | ||
60 | int m_nNumNodesPerSide; | ||
61 | int m_nNumNodesPerSideShift; | ||
62 | int m_nNumNodesPerSideMask; | ||
63 | int m_bFinite; | ||
64 | dxTerrainY(dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable); | ||
65 | ~dxTerrainY(); | ||
66 | void computeAABB(); | ||
67 | dReal GetHeight(dReal x,dReal z); | ||
68 | dReal GetHeight(int x,int z); | ||
69 | int dCollideTerrainUnit(int x,int z,dxGeom *o2,int numMaxContacts,int flags,dContactGeom *contact, int skip); | ||
70 | bool IsOnTerrain(int nx,int nz,int w,dReal *pos); | ||
71 | }; | ||
72 | |||
73 | struct dxTerrainZ : public dxGeom { | ||
74 | dReal m_vLength; | ||
75 | dReal *m_pHeights; | ||
76 | dReal m_vMinHeight; | ||
77 | dReal m_vMaxHeight; | ||
78 | dReal m_vNodeLength; | ||
79 | int m_nNumNodesPerSide; | ||
80 | int m_nNumNodesPerSideShift; | ||
81 | int m_nNumNodesPerSideMask; | ||
82 | int m_bFinite; | ||
83 | dxTerrainZ(dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable); | ||
84 | ~dxTerrainZ(); | ||
85 | void computeAABB(); | ||
86 | dReal GetHeight(dReal x,dReal y); | ||
87 | dReal GetHeight(int x,int y); | ||
88 | int dCollideTerrainUnit(int x,int y,dxGeom *o2,int numMaxContacts,int flags,dContactGeom *contact, int skip); | ||
89 | bool IsOnTerrain(int nx,int ny,int w,dReal *pos); | ||
90 | }; | ||
91 | |||
92 | #ifndef MIN | ||
93 | #define MIN(a,b) ((a<b)?a:b) | ||
94 | #endif | ||
95 | |||
96 | #ifndef MAX | ||
97 | #define MAX(a,b) ((a>b)?a:b) | ||
98 | #endif | ||
99 | |||
100 | #endif //_ODE_COLLISION_STD_INTERNAL_H_ \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/TerrainAndCone/dCone.cpp b/libraries/ode-0.9/contrib/TerrainAndCone/dCone.cpp new file mode 100644 index 0000000..8c5c3be --- /dev/null +++ b/libraries/ode-0.9/contrib/TerrainAndCone/dCone.cpp | |||
@@ -0,0 +1,504 @@ | |||
1 | //Benoit CHAPEROT 2003-2004 www.jstarlab.com | ||
2 | //some code inspired by Magic Software | ||
3 | #include <ode/common.h> | ||
4 | #include <ode/collision.h> | ||
5 | #include <ode/matrix.h> | ||
6 | #include <ode/rotation.h> | ||
7 | #include <ode/odemath.h> | ||
8 | #include "collision_kernel.h" | ||
9 | #include "collision_std.h" | ||
10 | #include "collision_std_internal.h" | ||
11 | #include "collision_util.h" | ||
12 | #include <drawstuff/drawstuff.h> | ||
13 | #include "windows.h" | ||
14 | #include "ode\ode.h" | ||
15 | |||
16 | #define CONTACT(p,skip) ((dContactGeom*) (((char*)p) + (skip))) | ||
17 | const dReal fEPSILON = 1e-9f; | ||
18 | |||
19 | dxCone::dxCone (dSpaceID space, dReal _radius,dReal _length) : | ||
20 | dxGeom (space,1) | ||
21 | { | ||
22 | dAASSERT(_radius > 0.f); | ||
23 | dAASSERT(_length > 0.f); | ||
24 | type = dConeClass; | ||
25 | radius = _radius; | ||
26 | lz = _length; | ||
27 | } | ||
28 | |||
29 | dxCone::~dxCone() | ||
30 | { | ||
31 | } | ||
32 | |||
33 | void dxCone::computeAABB() | ||
34 | { | ||
35 | const dMatrix3& R = final_posr->R; | ||
36 | const dVector3& pos = final_posr->pos; | ||
37 | |||
38 | dReal xrange = dFabs(R[2] * lz) + radius; | ||
39 | dReal yrange = dFabs(R[6] * lz) + radius; | ||
40 | dReal zrange = dFabs(R[10] * lz) + radius; | ||
41 | aabb[0] = pos[0] - xrange; | ||
42 | aabb[1] = pos[0] + xrange; | ||
43 | aabb[2] = pos[1] - yrange; | ||
44 | aabb[3] = pos[1] + yrange; | ||
45 | aabb[4] = pos[2] - zrange; | ||
46 | aabb[5] = pos[2] + zrange; | ||
47 | } | ||
48 | |||
49 | dGeomID dCreateCone(dSpaceID space, dReal _radius,dReal _length) | ||
50 | { | ||
51 | return new dxCone(space,_radius,_length); | ||
52 | } | ||
53 | |||
54 | void dGeomConeSetParams (dGeomID g, dReal _radius, dReal _length) | ||
55 | { | ||
56 | dUASSERT (g && g->type == dConeClass,"argument not a cone"); | ||
57 | dAASSERT (_radius > 0.f); | ||
58 | dAASSERT (_length > 0.f); | ||
59 | g->recomputePosr(); | ||
60 | dxCone *c = (dxCone*) g; | ||
61 | c->radius = _radius; | ||
62 | c->lz = _length; | ||
63 | dGeomMoved (g); | ||
64 | } | ||
65 | |||
66 | |||
67 | void dGeomConeGetParams (dGeomID g, dReal *_radius, dReal *_length) | ||
68 | { | ||
69 | dUASSERT (g && g->type == dConeClass,"argument not a cone"); | ||
70 | g->recomputePosr(); | ||
71 | dxCone *c = (dxCone*) g; | ||
72 | *_radius = c->radius; | ||
73 | *_length = c->lz; | ||
74 | } | ||
75 | |||
76 | //positive inside | ||
77 | dReal dGeomConePointDepth(dGeomID g, dReal x, dReal y, dReal z) | ||
78 | { | ||
79 | dUASSERT (g && g->type == dConeClass,"argument not a cone"); | ||
80 | |||
81 | g->recomputePosr(); | ||
82 | dxCone *cone = (dxCone*) g; | ||
83 | |||
84 | dVector3 tmp,q; | ||
85 | tmp[0] = x - cone->final_posr->pos[0]; | ||
86 | tmp[1] = y - cone->final_posr->pos[1]; | ||
87 | tmp[2] = z - cone->final_posr->pos[2]; | ||
88 | dMULTIPLY1_331 (q,cone->final_posr->R,tmp); | ||
89 | |||
90 | dReal r = cone->radius; | ||
91 | dReal h = cone->lz; | ||
92 | |||
93 | dReal d0 = (r - r*q[2]/h) - dSqrt(q[0]*q[0]+q[1]*q[1]); | ||
94 | dReal d1 = q[2]; | ||
95 | dReal d2 = h-q[2]; | ||
96 | |||
97 | if (d0 < d1) { | ||
98 | if (d0 < d2) return d0; else return d2; | ||
99 | } | ||
100 | else { | ||
101 | if (d1 < d2) return d1; else return d2; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | //plane plane | ||
106 | bool FindIntersectionPlanePlane(const dReal Plane0[4], const dReal Plane1[4], | ||
107 | dVector3 LinePos,dVector3 LineDir) | ||
108 | { | ||
109 | // If Cross(N0,N1) is zero, then either planes are parallel and separated | ||
110 | // or the same plane. In both cases, 'false' is returned. Otherwise, | ||
111 | // the intersection line is | ||
112 | // | ||
113 | // L(t) = t*Cross(N0,N1) + c0*N0 + c1*N1 | ||
114 | // | ||
115 | // for some coefficients c0 and c1 and for t any real number (the line | ||
116 | // parameter). Taking dot products with the normals, | ||
117 | // | ||
118 | // d0 = Dot(N0,L) = c0*Dot(N0,N0) + c1*Dot(N0,N1) | ||
119 | // d1 = Dot(N1,L) = c0*Dot(N0,N1) + c1*Dot(N1,N1) | ||
120 | // | ||
121 | // which are two equations in two unknowns. The solution is | ||
122 | // | ||
123 | // c0 = (Dot(N1,N1)*d0 - Dot(N0,N1)*d1)/det | ||
124 | // c1 = (Dot(N0,N0)*d1 - Dot(N0,N1)*d0)/det | ||
125 | // | ||
126 | // where det = Dot(N0,N0)*Dot(N1,N1)-Dot(N0,N1)^2. | ||
127 | /* | ||
128 | Real fN00 = rkPlane0.Normal().SquaredLength(); | ||
129 | Real fN01 = rkPlane0.Normal().Dot(rkPlane1.Normal()); | ||
130 | Real fN11 = rkPlane1.Normal().SquaredLength(); | ||
131 | Real fDet = fN00*fN11 - fN01*fN01; | ||
132 | |||
133 | if ( Math::FAbs(fDet) < gs_fEpsilon ) | ||
134 | return false; | ||
135 | |||
136 | Real fInvDet = 1.0f/fDet; | ||
137 | Real fC0 = (fN11*rkPlane0.Constant() - fN01*rkPlane1.Constant())*fInvDet; | ||
138 | Real fC1 = (fN00*rkPlane1.Constant() - fN01*rkPlane0.Constant())*fInvDet; | ||
139 | |||
140 | rkLine.Direction() = rkPlane0.Normal().Cross(rkPlane1.Normal()); | ||
141 | rkLine.Origin() = fC0*rkPlane0.Normal() + fC1*rkPlane1.Normal(); | ||
142 | return true; | ||
143 | */ | ||
144 | dReal fN00 = dLENGTHSQUARED(Plane0); | ||
145 | dReal fN01 = dDOT(Plane0,Plane1); | ||
146 | dReal fN11 = dLENGTHSQUARED(Plane1); | ||
147 | dReal fDet = fN00*fN11 - fN01*fN01; | ||
148 | |||
149 | if ( fabs(fDet) < fEPSILON) | ||
150 | return false; | ||
151 | |||
152 | dReal fInvDet = 1.0f/fDet; | ||
153 | dReal fC0 = (fN11*Plane0[3] - fN01*Plane1[3])*fInvDet; | ||
154 | dReal fC1 = (fN00*Plane1[3] - fN01*Plane0[3])*fInvDet; | ||
155 | |||
156 | dCROSS(LineDir,=,Plane0,Plane1); | ||
157 | dNormalize3(LineDir); | ||
158 | |||
159 | dVector3 Temp0,Temp1; | ||
160 | dOPC(Temp0,*,Plane0,fC0); | ||
161 | dOPC(Temp1,*,Plane1,fC1); | ||
162 | dOP(LinePos,+,Temp0,Temp1); | ||
163 | |||
164 | return true; | ||
165 | } | ||
166 | |||
167 | //plane ray | ||
168 | bool FindIntersectionPlaneRay(const dReal Plane[4], | ||
169 | const dVector3 &LinePos,const dVector3 &LineDir, | ||
170 | dReal &u,dVector3 &Pos) | ||
171 | { | ||
172 | /* | ||
173 | u = (A*X1 + B*Y1 + C*Z1 + D) / (A*(X1-X2) + B*(Y1-Y2)+C*(Z1-Z2)) | ||
174 | */ | ||
175 | dReal fDet = -dDot(Plane,LineDir,3); | ||
176 | |||
177 | if ( fabs(fDet) < fEPSILON) | ||
178 | return false; | ||
179 | |||
180 | u = (dDot(Plane,LinePos,3) - Plane[3]) / fDet; | ||
181 | dOPC(Pos,*,LineDir,u); | ||
182 | dOPE(Pos,+=,LinePos); | ||
183 | |||
184 | return true; | ||
185 | } | ||
186 | |||
187 | int SolveQuadraticPolynomial(dReal a,dReal b,dReal c,dReal &x0,dReal &x1) | ||
188 | { | ||
189 | dReal d = b*b - 4*a*c; | ||
190 | int NumRoots = 0; | ||
191 | dReal dr; | ||
192 | |||
193 | if (d < 0.f) | ||
194 | return NumRoots; | ||
195 | |||
196 | if (d == 0.f) | ||
197 | { | ||
198 | NumRoots = 1; | ||
199 | dr = 0.f; | ||
200 | } | ||
201 | else | ||
202 | { | ||
203 | NumRoots = 2; | ||
204 | dr = sqrtf(d); | ||
205 | } | ||
206 | |||
207 | x0 = (-b -dr) / (2.f * a); | ||
208 | x1 = (-b +dr) / (2.f * a); | ||
209 | |||
210 | return NumRoots; | ||
211 | } | ||
212 | /* | ||
213 | const int VALID_INTERSECTION = 1<<0; | ||
214 | const int POS_TEST_FAILEDT0 = 1<<0; | ||
215 | const int POS_TEST_FAILEDT1 = 1<<1; | ||
216 | */ | ||
217 | int ProcessConeRayIntersectionPoint( dReal r,dReal h, | ||
218 | const dVector3 &q,const dVector3 &v,dReal t, | ||
219 | dVector3 &p, | ||
220 | dVector3 &n, | ||
221 | int &f) | ||
222 | { | ||
223 | dOPC(p,*,v,t); | ||
224 | dOPE(p,+=,q); | ||
225 | n[0] = 2*p[0]; | ||
226 | n[1] = 2*p[1]; | ||
227 | n[2] = -2*p[2]*r*r/(h*h); | ||
228 | |||
229 | f = 0; | ||
230 | if (p[2] > h) return 0; | ||
231 | if (p[2] < 0) return 0; | ||
232 | if (t > 1) return 0; | ||
233 | if (t < 0) return 0; | ||
234 | |||
235 | return 1; | ||
236 | } | ||
237 | |||
238 | //cone ray | ||
239 | //line in cone space (position,direction) | ||
240 | //distance from line position (direction normalized)(if any) | ||
241 | //return the number of intersection | ||
242 | int FindIntersectionConeRay(dReal r,dReal h, | ||
243 | const dVector3 &q,const dVector3 &v,dContactGeom *pContact) | ||
244 | { | ||
245 | dVector3 qp,vp; | ||
246 | dOPE(qp,=,q); | ||
247 | dOPE(vp,=,v); | ||
248 | qp[2] = h-q[2]; | ||
249 | vp[2] = -v[2]; | ||
250 | dReal ts = (r/h); | ||
251 | ts *= ts; | ||
252 | dReal a = vp[0]*vp[0] + vp[1]*vp[1] - ts*vp[2]*vp[2]; | ||
253 | dReal b = 2.f*qp[0]*vp[0] + 2.f*qp[1]*vp[1] - 2.f*ts*qp[2]*vp[2]; | ||
254 | dReal c = qp[0]*qp[0] + qp[1]*qp[1] - ts*qp[2]*qp[2]; | ||
255 | |||
256 | /* | ||
257 | dReal a = v[0]*v[0] + v[1]*v[1] - (v[2]*v[2]*r*r) / (h*h); | ||
258 | dReal b = 2.f*q[0]*v[0] + 2.f*q[1]*v[1] + 2.f*r*r*v[2]/h - 2*r*r*q[0]*v[0]/(h*h); | ||
259 | dReal c = q[0]*q[0] + q[1]*q[1] + 2*r*r*q[2]/h - r*r*q[2]/(h*h) - r*r; | ||
260 | */ | ||
261 | int nNumRoots=SolveQuadraticPolynomial(a,b,c,pContact[0].depth,pContact[1].depth); | ||
262 | int flag = 0; | ||
263 | |||
264 | dContactGeom ValidContact[2]; | ||
265 | |||
266 | int nNumValidContacts = 0; | ||
267 | for (int i=0;i<nNumRoots;i++) | ||
268 | { | ||
269 | if (ProcessConeRayIntersectionPoint(r,h,q,v,pContact[i].depth,pContact[i].pos, | ||
270 | pContact[i].normal,flag)) | ||
271 | { | ||
272 | ValidContact[nNumValidContacts] = pContact[i]; | ||
273 | nNumValidContacts++; | ||
274 | } | ||
275 | } | ||
276 | |||
277 | dOP(qp,+,q,v); | ||
278 | |||
279 | if ((nNumValidContacts < 2) && (v[2] != 0.f)) | ||
280 | { | ||
281 | dReal d = (0.f-q[2]) / (v[2]); | ||
282 | if ((d>=0) && (d<=1)) | ||
283 | { | ||
284 | dOPC(vp,*,v,d); | ||
285 | dOP(qp,+,q,vp); | ||
286 | |||
287 | if (qp[0]*qp[0]+qp[1]*qp[1] < r*r) | ||
288 | { | ||
289 | dOPE(ValidContact[nNumValidContacts].pos,=,qp); | ||
290 | ValidContact[nNumValidContacts].normal[0] = 0.f; | ||
291 | ValidContact[nNumValidContacts].normal[1] = 0.f; | ||
292 | ValidContact[nNumValidContacts].normal[2] = -1.f; | ||
293 | ValidContact[nNumValidContacts].depth = d; | ||
294 | nNumValidContacts++; | ||
295 | } | ||
296 | } | ||
297 | } | ||
298 | |||
299 | if (nNumValidContacts == 2) | ||
300 | { | ||
301 | if (ValidContact[0].depth > ValidContact[1].depth) | ||
302 | { | ||
303 | pContact[0] = ValidContact[1]; | ||
304 | pContact[1] = ValidContact[0]; | ||
305 | } | ||
306 | else | ||
307 | { | ||
308 | pContact[0] = ValidContact[0]; | ||
309 | pContact[1] = ValidContact[1]; | ||
310 | } | ||
311 | } | ||
312 | else if (nNumValidContacts == 1) | ||
313 | { | ||
314 | pContact[0] = ValidContact[0]; | ||
315 | } | ||
316 | |||
317 | return nNumValidContacts; | ||
318 | } | ||
319 | |||
320 | int dCollideConePlane (dxGeom *o1, dxGeom *o2, int flags, | ||
321 | dContactGeom *contact, int skip) | ||
322 | { | ||
323 | dIASSERT (skip >= (int)sizeof(dContactGeom)); | ||
324 | dIASSERT (o1->type == dConeClass); | ||
325 | dIASSERT (o2->type == dPlaneClass); | ||
326 | dxCone *cone = (dxCone*) o1; | ||
327 | dxPlane *plane = (dxPlane*) o2; | ||
328 | |||
329 | contact->g1 = o1; | ||
330 | contact->g2 = o2; | ||
331 | |||
332 | dVector3 p0,p1,pp0,pp1; | ||
333 | dOPE(p0,=,cone->final_posr->pos); | ||
334 | p1[0] = cone->final_posr->R[0*4+2] * cone->lz + p0[0]; | ||
335 | p1[1] = cone->final_posr->R[1*4+2] * cone->lz + p0[1]; | ||
336 | p1[2] = cone->final_posr->R[2*4+2] * cone->lz + p0[2]; | ||
337 | |||
338 | dReal u; | ||
339 | FindIntersectionPlaneRay(plane->p,p0,plane->p,u,pp0); | ||
340 | FindIntersectionPlaneRay(plane->p,p1,plane->p,u,pp1); | ||
341 | |||
342 | if (dDISTANCE(pp0,pp1) < fEPSILON) | ||
343 | { | ||
344 | p1[0] = cone->final_posr->R[0*4+0] * cone->lz + p0[0]; | ||
345 | p1[1] = cone->final_posr->R[1*4+0] * cone->lz + p0[1]; | ||
346 | p1[2] = cone->final_posr->R[2*4+0] * cone->lz + p0[2]; | ||
347 | FindIntersectionPlaneRay(plane->p,p1,plane->p,u,pp1); | ||
348 | dIASSERT(dDISTANCE(pp0,pp1) >= fEPSILON); | ||
349 | } | ||
350 | dVector3 h,r0,r1; | ||
351 | h[0] = cone->final_posr->R[0*4+2]; | ||
352 | h[1] = cone->final_posr->R[1*4+2]; | ||
353 | h[2] = cone->final_posr->R[2*4+2]; | ||
354 | |||
355 | dOP(r0,-,pp0,pp1); | ||
356 | dCROSS(r1,=,h,r0); | ||
357 | dCROSS(r0,=,r1,h); | ||
358 | dNormalize3(r0); | ||
359 | dOPEC(h,*=,cone->lz); | ||
360 | dOPEC(r0,*=,cone->radius); | ||
361 | |||
362 | dVector3 p[3]; | ||
363 | dOP(p[0],+,cone->final_posr->pos,h); | ||
364 | dOP(p[1],+,cone->final_posr->pos,r0); | ||
365 | dOP(p[2],-,cone->final_posr->pos,r0); | ||
366 | |||
367 | int numMaxContacts = flags & 0xffff; | ||
368 | if (numMaxContacts == 0) | ||
369 | numMaxContacts = 1; | ||
370 | |||
371 | int n=0; | ||
372 | for (int i=0;i<3;i++) | ||
373 | { | ||
374 | dReal d = dGeomPlanePointDepth(o2, p[i][0], p[i][1], p[i][2]); | ||
375 | |||
376 | if (d>0.f) | ||
377 | { | ||
378 | CONTACT(contact,n*skip)->g1 = o1; | ||
379 | CONTACT(contact,n*skip)->g2 = o2; | ||
380 | dOPE(CONTACT(contact,n*skip)->normal,=,plane->p); | ||
381 | dOPE(CONTACT(contact,n*skip)->pos,=,p[i]); | ||
382 | CONTACT(contact,n*skip)->depth = d; | ||
383 | n++; | ||
384 | |||
385 | if (n == numMaxContacts) | ||
386 | return n; | ||
387 | } | ||
388 | } | ||
389 | |||
390 | return n; | ||
391 | } | ||
392 | |||
393 | int dCollideRayCone (dxGeom *o1, dxGeom *o2, int flags, | ||
394 | dContactGeom *contact, int skip) | ||
395 | { | ||
396 | dIASSERT (skip >= (int)sizeof(dContactGeom)); | ||
397 | dIASSERT (o1->type == dRayClass); | ||
398 | dIASSERT (o2->type == dConeClass); | ||
399 | dxRay *ray = (dxRay*) o1; | ||
400 | dxCone *cone = (dxCone*) o2; | ||
401 | |||
402 | contact->g1 = o1; | ||
403 | contact->g2 = o2; | ||
404 | |||
405 | dVector3 tmp,q,v; | ||
406 | tmp[0] = ray->final_posr->pos[0] - cone->final_posr->pos[0]; | ||
407 | tmp[1] = ray->final_posr->pos[1] - cone->final_posr->pos[1]; | ||
408 | tmp[2] = ray->final_posr->pos[2] - cone->final_posr->pos[2]; | ||
409 | dMULTIPLY1_331 (q,cone->final_posr->R,tmp); | ||
410 | tmp[0] = ray->final_posr->R[0*4+2] * ray->length; | ||
411 | tmp[1] = ray->final_posr->R[1*4+2] * ray->length; | ||
412 | tmp[2] = ray->final_posr->R[2*4+2] * ray->length; | ||
413 | dMULTIPLY1_331 (v,cone->final_posr->R,tmp); | ||
414 | |||
415 | dReal r = cone->radius; | ||
416 | dReal h = cone->lz; | ||
417 | |||
418 | dContactGeom Contact[2]; | ||
419 | |||
420 | if (FindIntersectionConeRay(r,h,q,v,Contact)) | ||
421 | { | ||
422 | dMULTIPLY0_331(contact->normal,cone->final_posr->R,Contact[0].normal); | ||
423 | dMULTIPLY0_331(contact->pos,cone->final_posr->R,Contact[0].pos); | ||
424 | dOPE(contact->pos,+=,cone->final_posr->pos); | ||
425 | contact->depth = Contact[0].depth * dLENGTH(v); | ||
426 | /* | ||
427 | dMatrix3 RI; | ||
428 | dRSetIdentity (RI); | ||
429 | dVector3 ss; | ||
430 | ss[0] = 0.01f; | ||
431 | ss[1] = 0.01f; | ||
432 | ss[2] = 0.01f; | ||
433 | |||
434 | dsSetColorAlpha (1,0,0,0.8f); | ||
435 | dsDrawBox(contact->pos,RI,ss); | ||
436 | */ | ||
437 | return 1; | ||
438 | } | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | int dCollideConeSphere(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) | ||
444 | { | ||
445 | dIASSERT (skip >= (int)sizeof(dContactGeom)); | ||
446 | dIASSERT (o1->type == dConeClass); | ||
447 | dIASSERT (o2->type == dSphereClass); | ||
448 | dxCone *cone = (dxCone*) o1; | ||
449 | |||
450 | dxSphere ASphere(0,cone->radius); | ||
451 | dGeomSetRotation(&ASphere,cone->final_posr->R); | ||
452 | dGeomSetPosition(&ASphere,cone->final_posr->pos[0],cone->final_posr->pos[1],cone->final_posr->pos[2]); | ||
453 | |||
454 | return dCollideSphereSphere(&ASphere, o2, flags, contact, skip); | ||
455 | } | ||
456 | |||
457 | int dCollideConeBox(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) | ||
458 | { | ||
459 | dIASSERT (skip >= (int)sizeof(dContactGeom)); | ||
460 | dIASSERT (o1->type == dConeClass); | ||
461 | dIASSERT (o2->type == dBoxClass); | ||
462 | dxCone *cone = (dxCone*) o1; | ||
463 | |||
464 | dxSphere ASphere(0,cone->radius); | ||
465 | dGeomSetRotation(&ASphere,cone->final_posr->R); | ||
466 | dGeomSetPosition(&ASphere,cone->final_posr->pos[0],cone->final_posr->pos[1],cone->final_posr->pos[2]); | ||
467 | |||
468 | return dCollideSphereBox(&ASphere, o2, flags, contact, skip); | ||
469 | } | ||
470 | |||
471 | int dCollideCCylinderCone(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) | ||
472 | { | ||
473 | dIASSERT (skip >= (int)sizeof(dContactGeom)); | ||
474 | dIASSERT (o1->type == dCCylinderClass); | ||
475 | dIASSERT (o2->type == dConeClass); | ||
476 | dxCone *cone = (dxCone*) o2; | ||
477 | |||
478 | dxSphere ASphere(0,cone->radius); | ||
479 | dGeomSetRotation(&ASphere,cone->final_posr->R); | ||
480 | dGeomSetPosition(&ASphere,cone->final_posr->pos[0],cone->final_posr->pos[1],cone->final_posr->pos[2]); | ||
481 | |||
482 | return dCollideCCylinderSphere(o1, &ASphere, flags, contact, skip); | ||
483 | } | ||
484 | |||
485 | extern int dCollideSTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); | ||
486 | |||
487 | int dCollideTriMeshCone(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) | ||
488 | { | ||
489 | dIASSERT (skip >= (int)sizeof(dContactGeom)); | ||
490 | dIASSERT (o1->type == dTriMeshClass); | ||
491 | dIASSERT (o2->type == dConeClass); | ||
492 | dxCone *cone = (dxCone*) o2; | ||
493 | |||
494 | dxSphere ASphere(0,cone->radius); | ||
495 | dGeomSetRotation(&ASphere,cone->final_posr->R); | ||
496 | dGeomSetPosition(&ASphere,cone->final_posr->pos[0],cone->final_posr->pos[1],cone->final_posr->pos[2]); | ||
497 | |||
498 | return dCollideSTL(o1, &ASphere, flags, contact, skip); | ||
499 | } | ||
500 | |||
501 | |||
502 | |||
503 | |||
504 | |||
diff --git a/libraries/ode-0.9/contrib/TerrainAndCone/dTerrainY.cpp b/libraries/ode-0.9/contrib/TerrainAndCone/dTerrainY.cpp new file mode 100644 index 0000000..ff779ac --- /dev/null +++ b/libraries/ode-0.9/contrib/TerrainAndCone/dTerrainY.cpp | |||
@@ -0,0 +1,662 @@ | |||
1 | //Benoit CHAPEROT 2003-2004 www.jstarlab.com | ||
2 | //some code inspired by Magic Software | ||
3 | #include <ode/common.h> | ||
4 | #include <ode/collision.h> | ||
5 | #include <ode/matrix.h> | ||
6 | #include <ode/rotation.h> | ||
7 | #include <ode/odemath.h> | ||
8 | #include "collision_kernel.h" | ||
9 | #include "collision_std.h" | ||
10 | #include "collision_std_internal.h" | ||
11 | #include "collision_util.h" | ||
12 | //#include <drawstuff/drawstuff.h> | ||
13 | #include "windows.h" | ||
14 | #include "ode\ode.h" | ||
15 | |||
16 | #define CONTACT(p,skip) ((dContactGeom*) (((char*)p) + (skip))) | ||
17 | #define MAXCONTACT 10 | ||
18 | #define TERRAINTOL 0.0f | ||
19 | |||
20 | static bool IsAPowerOfTwo(int f) | ||
21 | { | ||
22 | dAASSERT(f!=0); | ||
23 | while ((f&1) != 1) | ||
24 | f >>= 1; | ||
25 | |||
26 | return (f == 1); | ||
27 | } | ||
28 | |||
29 | static int GetPowerOfTwo(int f) | ||
30 | { | ||
31 | dAASSERT(f!=0); | ||
32 | int n = 0; | ||
33 | while ((f&1) != 1) | ||
34 | { | ||
35 | n++; | ||
36 | f >>= 1; | ||
37 | } | ||
38 | |||
39 | return n; | ||
40 | } | ||
41 | |||
42 | dxTerrainY::dxTerrainY (dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable) : | ||
43 | dxGeom (space,bPlaceable) | ||
44 | { | ||
45 | dIASSERT(IsAPowerOfTwo(nNumNodesPerSide)); | ||
46 | dIASSERT(pHeights); | ||
47 | dIASSERT(vLength > 0.f); | ||
48 | dIASSERT(nNumNodesPerSide > 0); | ||
49 | type = dTerrainYClass; | ||
50 | m_vLength = vLength; | ||
51 | m_pHeights = new dReal[nNumNodesPerSide * nNumNodesPerSide]; | ||
52 | dIASSERT(m_pHeights); | ||
53 | m_nNumNodesPerSide = nNumNodesPerSide; | ||
54 | m_vNodeLength = m_vLength / m_nNumNodesPerSide; | ||
55 | m_nNumNodesPerSideShift = GetPowerOfTwo(m_nNumNodesPerSide); | ||
56 | m_nNumNodesPerSideMask = m_nNumNodesPerSide - 1; | ||
57 | m_vMinHeight = dInfinity; | ||
58 | m_vMaxHeight = -dInfinity; | ||
59 | m_bFinite = bFinite; | ||
60 | |||
61 | for (int i=0;i<nNumNodesPerSide * nNumNodesPerSide;i++) | ||
62 | { | ||
63 | m_pHeights[i] = pHeights[i]; | ||
64 | if (m_pHeights[i] < m_vMinHeight) m_vMinHeight = m_pHeights[i]; | ||
65 | if (m_pHeights[i] > m_vMaxHeight) m_vMaxHeight = m_pHeights[i]; | ||
66 | } | ||
67 | } | ||
68 | |||
69 | dxTerrainY::~dxTerrainY() | ||
70 | { | ||
71 | dIASSERT(m_pHeights); | ||
72 | delete [] m_pHeights; | ||
73 | } | ||
74 | |||
75 | void dxTerrainY::computeAABB() | ||
76 | { | ||
77 | if (m_bFinite) | ||
78 | { | ||
79 | if (gflags & GEOM_PLACEABLE) | ||
80 | { | ||
81 | dReal dx[6],dy[6],dz[6]; | ||
82 | dx[0] = 0; | ||
83 | dx[1] = final_posr->R[0] * m_vLength; | ||
84 | dx[2] = final_posr->R[1] * m_vMinHeight; | ||
85 | dx[3] = final_posr->R[1] * m_vMaxHeight; | ||
86 | dx[4] = 0; | ||
87 | dx[5] = final_posr->R[2] * m_vLength; | ||
88 | |||
89 | dy[0] = 0; | ||
90 | dy[1] = final_posr->R[4] * m_vLength; | ||
91 | dy[2] = final_posr->R[5] * m_vMinHeight; | ||
92 | dy[3] = final_posr->R[5] * m_vMaxHeight; | ||
93 | dy[4] = 0; | ||
94 | dy[5] = final_posr->R[6] * m_vLength; | ||
95 | |||
96 | dz[0] = 0; | ||
97 | dz[1] = final_posr->R[8] * m_vLength; | ||
98 | dz[2] = final_posr->R[9] * m_vMinHeight; | ||
99 | dz[3] = final_posr->R[9] * m_vMaxHeight; | ||
100 | dz[4] = 0; | ||
101 | dz[5] = final_posr->R[10] * m_vLength; | ||
102 | |||
103 | aabb[0] = final_posr->pos[0] + MIN(dx[0],dx[1]) + MIN(dx[2],dx[3]) + MIN(dx[4],dx[5]); | ||
104 | aabb[1] = final_posr->pos[0] + MAX(dx[0],dx[1]) + MAX(dx[2],dx[3]) + MAX(dx[4],dx[5]); | ||
105 | aabb[2] = final_posr->pos[1] + MIN(dy[0],dy[1]) + MIN(dy[2],dy[3]) + MIN(dy[4],dy[5]); | ||
106 | aabb[3] = final_posr->pos[1] + MAX(dy[0],dy[1]) + MAX(dy[2],dy[3]) + MAX(dy[4],dy[5]); | ||
107 | aabb[4] = final_posr->pos[2] + MIN(dz[0],dz[1]) + MIN(dz[2],dz[3]) + MIN(dz[4],dz[5]); | ||
108 | aabb[5] = final_posr->pos[2] + MAX(dz[0],dz[1]) + MAX(dz[2],dz[3]) + MAX(dz[4],dz[5]); | ||
109 | } | ||
110 | else | ||
111 | { | ||
112 | aabb[0] = 0; | ||
113 | aabb[1] = m_vLength; | ||
114 | aabb[2] = m_vMinHeight; | ||
115 | aabb[3] = m_vMaxHeight; | ||
116 | aabb[4] = 0; | ||
117 | aabb[5] = m_vLength; | ||
118 | } | ||
119 | } | ||
120 | else | ||
121 | { | ||
122 | if (gflags & GEOM_PLACEABLE) | ||
123 | { | ||
124 | aabb[0] = -dInfinity; | ||
125 | aabb[1] = dInfinity; | ||
126 | aabb[2] = -dInfinity; | ||
127 | aabb[3] = dInfinity; | ||
128 | aabb[4] = -dInfinity; | ||
129 | aabb[5] = dInfinity; | ||
130 | } | ||
131 | else | ||
132 | { | ||
133 | aabb[0] = -dInfinity; | ||
134 | aabb[1] = dInfinity; | ||
135 | aabb[2] = m_vMinHeight; | ||
136 | aabb[3] = m_vMaxHeight; | ||
137 | aabb[4] = -dInfinity; | ||
138 | aabb[5] = dInfinity; | ||
139 | } | ||
140 | } | ||
141 | } | ||
142 | |||
143 | dReal dxTerrainY::GetHeight(int x,int z) | ||
144 | { | ||
145 | return m_pHeights[ (((unsigned int)(z) & m_nNumNodesPerSideMask) << m_nNumNodesPerSideShift) | ||
146 | + ((unsigned int)(x) & m_nNumNodesPerSideMask)]; | ||
147 | } | ||
148 | |||
149 | dReal dxTerrainY::GetHeight(dReal x,dReal z) | ||
150 | { | ||
151 | int nX = int(floor(x / m_vNodeLength)); | ||
152 | int nZ = int(floor(z / m_vNodeLength)); | ||
153 | dReal dx = (x - (dReal(nX) * m_vNodeLength)) / m_vNodeLength; | ||
154 | dReal dz = (z - (dReal(nZ) * m_vNodeLength)) / m_vNodeLength; | ||
155 | dIASSERT((dx >= 0.f) && (dx <= 1.f)); | ||
156 | dIASSERT((dz >= 0.f) && (dz <= 1.f)); | ||
157 | |||
158 | dReal y,y0; | ||
159 | |||
160 | if (dx + dz < 1.f) | ||
161 | { | ||
162 | y0 = GetHeight(nX,nZ); | ||
163 | y = y0 | ||
164 | + (GetHeight(nX+1,nZ) - y0) * dx | ||
165 | + (GetHeight(nX,nZ+1) - y0) * dz; | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | y0 = GetHeight(nX+1,nZ+1); | ||
170 | y = y0 | ||
171 | + (GetHeight(nX+1,nZ) - y0) * (1.f - dz) | ||
172 | + (GetHeight(nX,nZ+1) - y0) * (1.f - dx); | ||
173 | } | ||
174 | |||
175 | return y; | ||
176 | } | ||
177 | |||
178 | bool dxTerrainY::IsOnTerrain(int nx,int nz,int w,dReal *pos) | ||
179 | { | ||
180 | dVector3 Min,Max; | ||
181 | Min[0] = nx * m_vNodeLength; | ||
182 | Min[2] = nz * m_vNodeLength; | ||
183 | Max[0] = (nx+1) * m_vNodeLength; | ||
184 | Max[2] = (nz+1) * m_vNodeLength; | ||
185 | dReal Tol = m_vNodeLength * TERRAINTOL; | ||
186 | |||
187 | if ((pos[0]<Min[0]-Tol) || (pos[0]>Max[0]+Tol)) | ||
188 | return false; | ||
189 | |||
190 | if ((pos[2]<Min[2]-Tol) || (pos[2]>Max[2]+Tol)) | ||
191 | return false; | ||
192 | |||
193 | dReal dx = (pos[0] - (dReal(nx) * m_vNodeLength)) / m_vNodeLength; | ||
194 | dReal dz = (pos[2] - (dReal(nz) * m_vNodeLength)) / m_vNodeLength; | ||
195 | |||
196 | if ((w == 0) && (dx + dz > 1.f+TERRAINTOL)) | ||
197 | return false; | ||
198 | |||
199 | if ((w == 1) && (dx + dz < 1.f-TERRAINTOL)) | ||
200 | return false; | ||
201 | |||
202 | return true; | ||
203 | } | ||
204 | |||
205 | dGeomID dCreateTerrainY(dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable) | ||
206 | { | ||
207 | return new dxTerrainY(space, pHeights,vLength,nNumNodesPerSide,bFinite,bPlaceable); | ||
208 | } | ||
209 | |||
210 | dReal dGeomTerrainYPointDepth (dGeomID g, dReal x, dReal y, dReal z) | ||
211 | { | ||
212 | dUASSERT (g && g->type == dTerrainYClass,"argument not a terrain"); | ||
213 | g->recomputePosr(); | ||
214 | dxTerrainY *t = (dxTerrainY*) g; | ||
215 | return t->GetHeight(x,z) - y; | ||
216 | } | ||
217 | |||
218 | typedef dReal dGetDepthFn(dGeomID g, dReal x, dReal y, dReal z); | ||
219 | #define RECOMPUTE_RAYNORMAL | ||
220 | //#define DO_RAYDEPTH | ||
221 | |||
222 | #define DMESS(A) \ | ||
223 | dMessage(0,"Contact Plane (%d %d %d) %.5e %.5e (%.5e %.5e %.5e)(%.5e %.5e %.5e)).", \ | ||
224 | x,z,A, \ | ||
225 | pContact->depth, \ | ||
226 | dGeomSphereGetRadius(o2), \ | ||
227 | pContact->pos[0], \ | ||
228 | pContact->pos[1], \ | ||
229 | pContact->pos[2], \ | ||
230 | pContact->normal[0], \ | ||
231 | pContact->normal[1], \ | ||
232 | pContact->normal[2]); | ||
233 | /* | ||
234 | (y is up) | ||
235 | |||
236 | A-B-E.x | ||
237 | |/| | ||
238 | C-D | ||
239 | | | ||
240 | F | ||
241 | . | ||
242 | z | ||
243 | */ | ||
244 | int dxTerrainY::dCollideTerrainUnit( | ||
245 | int x,int z,dxGeom *o2,int numMaxContacts, | ||
246 | int flags,dContactGeom *contact, int skip) | ||
247 | { | ||
248 | dColliderFn *CollideRayN; | ||
249 | dColliderFn *CollideNPlane; | ||
250 | dGetDepthFn *GetDepth; | ||
251 | int numContacts = 0; | ||
252 | int numPlaneContacts = 0; | ||
253 | int i; | ||
254 | |||
255 | if (numContacts == numMaxContacts) | ||
256 | return numContacts; | ||
257 | |||
258 | dContactGeom PlaneContact[MAXCONTACT]; | ||
259 | flags = (flags & 0xffff0000) | MAXCONTACT; | ||
260 | |||
261 | switch (o2->type) | ||
262 | { | ||
263 | case dSphereClass: | ||
264 | CollideRayN = dCollideRaySphere; | ||
265 | CollideNPlane = dCollideSpherePlane; | ||
266 | GetDepth = dGeomSpherePointDepth; | ||
267 | break; | ||
268 | case dBoxClass: | ||
269 | CollideRayN = dCollideRayBox; | ||
270 | CollideNPlane = dCollideBoxPlane; | ||
271 | GetDepth = dGeomBoxPointDepth; | ||
272 | break; | ||
273 | case dCCylinderClass: | ||
274 | CollideRayN = dCollideRayCCylinder; | ||
275 | CollideNPlane = dCollideCCylinderPlane; | ||
276 | GetDepth = dGeomCCylinderPointDepth; | ||
277 | break; | ||
278 | case dRayClass: | ||
279 | CollideRayN = NULL; | ||
280 | CollideNPlane = dCollideRayPlane; | ||
281 | GetDepth = NULL; | ||
282 | break; | ||
283 | case dConeClass: | ||
284 | CollideRayN = dCollideRayCone; | ||
285 | CollideNPlane = dCollideConePlane; | ||
286 | GetDepth = dGeomConePointDepth; | ||
287 | break; | ||
288 | default: | ||
289 | dIASSERT(0); | ||
290 | } | ||
291 | |||
292 | dReal Plane[4],lBD,lCD,lBC; | ||
293 | dVector3 A,B,C,D,BD,CD,BC,AB,AC; | ||
294 | A[0] = x * m_vNodeLength; | ||
295 | A[2] = z* m_vNodeLength; | ||
296 | A[1] = GetHeight(x,z); | ||
297 | B[0] = (x+1) * m_vNodeLength; | ||
298 | B[2] = z * m_vNodeLength; | ||
299 | B[1] = GetHeight(x+1,z); | ||
300 | C[0] = x * m_vNodeLength; | ||
301 | C[2] = (z+1) * m_vNodeLength; | ||
302 | C[1] = GetHeight(x,z+1); | ||
303 | D[0] = (x+1) * m_vNodeLength; | ||
304 | D[2] = (z+1) * m_vNodeLength; | ||
305 | D[1] = GetHeight(x+1,z+1); | ||
306 | |||
307 | dOP(BC,-,C,B); | ||
308 | lBC = dLENGTH(BC); | ||
309 | dOPEC(BC,/=,lBC); | ||
310 | |||
311 | dOP(BD,-,D,B); | ||
312 | lBD = dLENGTH(BD); | ||
313 | dOPEC(BD,/=,lBD); | ||
314 | |||
315 | dOP(CD,-,D,C); | ||
316 | lCD = dLENGTH(CD); | ||
317 | dOPEC(CD,/=,lCD); | ||
318 | |||
319 | dOP(AB,-,B,A); | ||
320 | dNormalize3(AB); | ||
321 | |||
322 | dOP(AC,-,C,A); | ||
323 | dNormalize3(AC); | ||
324 | |||
325 | if (CollideRayN) | ||
326 | { | ||
327 | #ifdef RECOMPUTE_RAYNORMAL | ||
328 | dVector3 E,F; | ||
329 | dVector3 CE,FB,AD; | ||
330 | dVector3 Normal[3]; | ||
331 | E[0] = (x+2) * m_vNodeLength; | ||
332 | E[2] = z * m_vNodeLength; | ||
333 | E[1] = GetHeight(x+2,z); | ||
334 | F[0] = x * m_vNodeLength; | ||
335 | F[2] = (z+2) * m_vNodeLength; | ||
336 | F[1] = GetHeight(x,z+2); | ||
337 | dOP(AD,-,D,A); | ||
338 | dNormalize3(AD); | ||
339 | dOP(CE,-,E,C); | ||
340 | dNormalize3(CE); | ||
341 | dOP(FB,-,B,F); | ||
342 | dNormalize3(FB); | ||
343 | |||
344 | //BC | ||
345 | dCROSS(Normal[0],=,BC,AD); | ||
346 | dNormalize3(Normal[0]); | ||
347 | |||
348 | //BD | ||
349 | dCROSS(Normal[1],=,BD,CE); | ||
350 | dNormalize3(Normal[1]); | ||
351 | |||
352 | //CD | ||
353 | dCROSS(Normal[2],=,CD,FB); | ||
354 | dNormalize3(Normal[2]); | ||
355 | #endif | ||
356 | int nA[3],nB[3]; | ||
357 | dContactGeom ContactA[3],ContactB[3]; | ||
358 | dxRay rayBC(0,lBC); | ||
359 | dGeomRaySet(&rayBC, B[0], B[1], B[2], BC[0], BC[1], BC[2]); | ||
360 | nA[0] = CollideRayN(&rayBC,o2,flags,&ContactA[0],sizeof(dContactGeom)); | ||
361 | dGeomRaySet(&rayBC, C[0], C[1], C[2], -BC[0], -BC[1], -BC[2]); | ||
362 | nB[0] = CollideRayN(&rayBC,o2,flags,&ContactB[0],sizeof(dContactGeom)); | ||
363 | |||
364 | dxRay rayBD(0,lBD); | ||
365 | dGeomRaySet(&rayBD, B[0], B[1], B[2], BD[0], BD[1], BD[2]); | ||
366 | nA[1] = CollideRayN(&rayBD,o2,flags,&ContactA[1],sizeof(dContactGeom)); | ||
367 | dGeomRaySet(&rayBD, D[0], D[1], D[2], -BD[0], -BD[1], -BD[2]); | ||
368 | nB[1] = CollideRayN(&rayBD,o2,flags,&ContactB[1],sizeof(dContactGeom)); | ||
369 | |||
370 | dxRay rayCD(0,lCD); | ||
371 | dGeomRaySet(&rayCD, C[0], C[1], C[2], CD[0], CD[1], CD[2]); | ||
372 | nA[2] = CollideRayN(&rayCD,o2,flags,&ContactA[2],sizeof(dContactGeom)); | ||
373 | dGeomRaySet(&rayCD, D[0], D[1], D[2], -CD[0], -CD[1], -CD[2]); | ||
374 | nB[2] = CollideRayN(&rayCD,o2,flags,&ContactB[2],sizeof(dContactGeom)); | ||
375 | |||
376 | for (i=0;i<3;i++) | ||
377 | { | ||
378 | if (nA[i] & nB[i]) | ||
379 | { | ||
380 | dContactGeom *pContact = CONTACT(contact,numContacts*skip); | ||
381 | pContact->pos[0] = (ContactA[i].pos[0] + ContactB[i].pos[0])/2; | ||
382 | pContact->pos[1] = (ContactA[i].pos[1] + ContactB[i].pos[1])/2; | ||
383 | pContact->pos[2] = (ContactA[i].pos[2] + ContactB[i].pos[2])/2; | ||
384 | #ifdef RECOMPUTE_RAYNORMAL | ||
385 | pContact->normal[0] = -Normal[i][0]; | ||
386 | pContact->normal[1] = -Normal[i][1]; | ||
387 | pContact->normal[2] = -Normal[i][2]; | ||
388 | #else | ||
389 | pContact->normal[0] = (ContactA[i].normal[0] + ContactB[i].normal[0])/2; //0.f; | ||
390 | pContact->normal[1] = (ContactA[i].normal[1] + ContactB[i].normal[1])/2; //0.f; | ||
391 | pContact->normal[2] = (ContactA[i].normal[2] + ContactB[i].normal[2])/2; //-1.f; | ||
392 | dNormalize3(pContact->normal); | ||
393 | #endif | ||
394 | #ifdef DO_RAYDEPTH | ||
395 | dxRay rayV(0,1000.f); | ||
396 | dGeomRaySet(&rayV, pContact->pos[0], | ||
397 | pContact->pos[1], | ||
398 | pContact->pos[2], | ||
399 | -pContact->normal[0], | ||
400 | -pContact->normal[1], | ||
401 | -pContact->normal[2]); | ||
402 | |||
403 | dContactGeom ContactV; | ||
404 | if (CollideRayN(&rayV,o2,flags,&ContactV,sizeof(dContactGeom))) | ||
405 | { | ||
406 | pContact->depth = ContactV.depth; | ||
407 | numContacts++; | ||
408 | } | ||
409 | #else | ||
410 | |||
411 | if (GetDepth == NULL) | ||
412 | { | ||
413 | dxRay rayV(0,1000.f); | ||
414 | dGeomRaySet(&rayV, pContact->pos[0], | ||
415 | pContact->pos[1], | ||
416 | pContact->pos[2], | ||
417 | -pContact->normal[0], | ||
418 | -pContact->normal[1], | ||
419 | -pContact->normal[2]); | ||
420 | |||
421 | dContactGeom ContactV; | ||
422 | |||
423 | if (CollideRayN(&rayV,o2,flags,&ContactV,sizeof(dContactGeom))) | ||
424 | { | ||
425 | pContact->depth = ContactV.depth; | ||
426 | numContacts++; | ||
427 | } | ||
428 | } | ||
429 | else | ||
430 | { | ||
431 | pContact->depth = GetDepth(o2, | ||
432 | pContact->pos[0], | ||
433 | pContact->pos[1], | ||
434 | pContact->pos[2]); | ||
435 | numContacts++; | ||
436 | } | ||
437 | |||
438 | #endif | ||
439 | if (numContacts == numMaxContacts) | ||
440 | return numContacts; | ||
441 | |||
442 | } | ||
443 | } | ||
444 | } | ||
445 | |||
446 | dCROSS(Plane,=,AC,AB); | ||
447 | dNormalize3(Plane); | ||
448 | Plane[3] = Plane[0] * A[0] + Plane[1] * A[1] + Plane[2] * A[2]; | ||
449 | dxPlane planeABC(0,Plane[0],Plane[1],Plane[2],Plane[3]); | ||
450 | numPlaneContacts = CollideNPlane(o2,&planeABC,flags,PlaneContact,sizeof(dContactGeom)); | ||
451 | |||
452 | for (i=0;i<numPlaneContacts;i++) | ||
453 | { | ||
454 | if (IsOnTerrain(x,z,0,PlaneContact[i].pos)) | ||
455 | { | ||
456 | dContactGeom *pContact = CONTACT(contact,numContacts*skip); | ||
457 | pContact->pos[0] = PlaneContact[i].pos[0]; | ||
458 | pContact->pos[1] = PlaneContact[i].pos[1]; | ||
459 | pContact->pos[2] = PlaneContact[i].pos[2]; | ||
460 | pContact->normal[0] = -PlaneContact[i].normal[0]; | ||
461 | pContact->normal[1] = -PlaneContact[i].normal[1]; | ||
462 | pContact->normal[2] = -PlaneContact[i].normal[2]; | ||
463 | pContact->depth = PlaneContact[i].depth; | ||
464 | |||
465 | //DMESS(0); | ||
466 | numContacts++; | ||
467 | |||
468 | if (numContacts == numMaxContacts) | ||
469 | return numContacts; | ||
470 | } | ||
471 | } | ||
472 | |||
473 | dCROSS(Plane,=,BD,CD); | ||
474 | dNormalize3(Plane); | ||
475 | Plane[3] = Plane[0] * D[0] + Plane[1] * D[1] + Plane[2] * D[2]; | ||
476 | dxPlane planeDCB(0,Plane[0],Plane[1],Plane[2],Plane[3]); | ||
477 | numPlaneContacts = CollideNPlane(o2,&planeDCB,flags,PlaneContact,sizeof(dContactGeom)); | ||
478 | |||
479 | for (i=0;i<numPlaneContacts;i++) | ||
480 | { | ||
481 | if (IsOnTerrain(x,z,1,PlaneContact[i].pos)) | ||
482 | { | ||
483 | dContactGeom *pContact = CONTACT(contact,numContacts*skip); | ||
484 | pContact->pos[0] = PlaneContact[i].pos[0]; | ||
485 | pContact->pos[1] = PlaneContact[i].pos[1]; | ||
486 | pContact->pos[2] = PlaneContact[i].pos[2]; | ||
487 | pContact->normal[0] = -PlaneContact[i].normal[0]; | ||
488 | pContact->normal[1] = -PlaneContact[i].normal[1]; | ||
489 | pContact->normal[2] = -PlaneContact[i].normal[2]; | ||
490 | pContact->depth = PlaneContact[i].depth; | ||
491 | //DMESS(1); | ||
492 | numContacts++; | ||
493 | |||
494 | if (numContacts == numMaxContacts) | ||
495 | return numContacts; | ||
496 | } | ||
497 | } | ||
498 | |||
499 | return numContacts; | ||
500 | } | ||
501 | |||
502 | int dCollideTerrainY(dxGeom *o1, dxGeom *o2, int flags,dContactGeom *contact, int skip) | ||
503 | { | ||
504 | dIASSERT (skip >= (int)sizeof(dContactGeom)); | ||
505 | dIASSERT (o1->type == dTerrainYClass); | ||
506 | int i,j; | ||
507 | |||
508 | if ((flags & 0xffff) == 0) | ||
509 | flags = (flags & 0xffff0000) | 1; | ||
510 | |||
511 | int numMaxTerrainContacts = (flags & 0xffff); | ||
512 | dxTerrainY *terrain = (dxTerrainY*) o1; | ||
513 | |||
514 | dReal aabbbak[6]; | ||
515 | int gflagsbak; | ||
516 | |||
517 | dVector3 pos0; | ||
518 | int numTerrainContacts = 0; | ||
519 | |||
520 | dxPosR *bak; | ||
521 | dxPosR X1; | ||
522 | |||
523 | if (terrain->gflags & GEOM_PLACEABLE) | ||
524 | { | ||
525 | dOP(pos0,-,o2->final_posr->pos,terrain->final_posr->pos); | ||
526 | dMULTIPLY1_331(X1.pos,terrain->final_posr->R,pos0); | ||
527 | dMULTIPLY1_333(X1.R,terrain->final_posr->R,o2->final_posr->R); | ||
528 | bak = o2->final_posr; | ||
529 | o2->final_posr = &X1; | ||
530 | memcpy(aabbbak,o2->aabb,sizeof(dReal)*6); | ||
531 | gflagsbak = o2->gflags; | ||
532 | o2->computeAABB(); | ||
533 | } | ||
534 | |||
535 | int nMinX = int(floor(o2->aabb[0] / terrain->m_vNodeLength)); | ||
536 | int nMaxX = int(floor(o2->aabb[1] / terrain->m_vNodeLength)) + 1; | ||
537 | int nMinZ = int(floor(o2->aabb[4] / terrain->m_vNodeLength)); | ||
538 | int nMaxZ = int(floor(o2->aabb[5] / terrain->m_vNodeLength)) + 1; | ||
539 | |||
540 | if (terrain->m_bFinite) | ||
541 | { | ||
542 | nMinX = MAX(nMinX,0); | ||
543 | nMaxX = MIN(nMaxX,terrain->m_nNumNodesPerSide); | ||
544 | nMinZ = MAX(nMinZ,0); | ||
545 | nMaxZ = MIN(nMaxZ,terrain->m_nNumNodesPerSide); | ||
546 | |||
547 | if ((nMinX >= nMaxX) || (nMinZ >= nMaxZ)) | ||
548 | goto dCollideTerrainYExit; | ||
549 | } | ||
550 | |||
551 | dVector3 AabbTop; | ||
552 | AabbTop[0] = (o2->aabb[0]+o2->aabb[1]) / 2; | ||
553 | AabbTop[2] = (o2->aabb[4]+o2->aabb[5]) / 2; | ||
554 | AabbTop[1] = o2->aabb[3]; | ||
555 | if (o2->type != dRayClass) | ||
556 | { | ||
557 | dReal AabbTopDepth = terrain->GetHeight(AabbTop[0],AabbTop[2]) - AabbTop[1]; | ||
558 | if (AabbTopDepth > 0.f) | ||
559 | { | ||
560 | contact->depth = AabbTopDepth; | ||
561 | dReal MaxDepth = (o2->aabb[3]-o2->aabb[2]) / 2; | ||
562 | if (contact->depth > MaxDepth) | ||
563 | contact->depth = MaxDepth; | ||
564 | contact->g1 = o1; | ||
565 | contact->g2 = o2; | ||
566 | dOPE(contact->pos,=,AabbTop); | ||
567 | contact->normal[0] = 0.f; | ||
568 | contact->normal[1] = -1.f; | ||
569 | contact->normal[2] = 0.f; | ||
570 | |||
571 | numTerrainContacts = 1; | ||
572 | goto dCollideTerrainYExit; | ||
573 | } | ||
574 | } | ||
575 | |||
576 | for (i=nMinX;i<nMaxX;i++) | ||
577 | { | ||
578 | for (j=nMinZ;j<nMaxZ;j++) | ||
579 | { | ||
580 | numTerrainContacts += terrain->dCollideTerrainUnit( | ||
581 | i,j,o2,numMaxTerrainContacts - numTerrainContacts, | ||
582 | flags,CONTACT(contact,numTerrainContacts*skip),skip ); | ||
583 | } | ||
584 | } | ||
585 | |||
586 | dIASSERT(numTerrainContacts <= numMaxTerrainContacts); | ||
587 | |||
588 | for (i=0; i<numTerrainContacts; i++) | ||
589 | { | ||
590 | CONTACT(contact,i*skip)->g1 = o1; | ||
591 | CONTACT(contact,i*skip)->g2 = o2; | ||
592 | } | ||
593 | |||
594 | dCollideTerrainYExit: | ||
595 | |||
596 | if (terrain->gflags & GEOM_PLACEABLE) | ||
597 | { | ||
598 | o2->final_posr = bak; | ||
599 | memcpy(o2->aabb,aabbbak,sizeof(dReal)*6); | ||
600 | o2->gflags = gflagsbak; | ||
601 | |||
602 | for (i=0; i<numTerrainContacts; i++) | ||
603 | { | ||
604 | dOPE(pos0,=,CONTACT(contact,i*skip)->pos); | ||
605 | dMULTIPLY0_331(CONTACT(contact,i*skip)->pos,terrain->final_posr->R,pos0); | ||
606 | dOP(CONTACT(contact,i*skip)->pos,+,CONTACT(contact,i*skip)->pos,terrain->final_posr->pos); | ||
607 | |||
608 | dOPE(pos0,=,CONTACT(contact,i*skip)->normal); | ||
609 | dMULTIPLY0_331(CONTACT(contact,i*skip)->normal,terrain->final_posr->R,pos0); | ||
610 | } | ||
611 | } | ||
612 | |||
613 | return numTerrainContacts; | ||
614 | } | ||
615 | /* | ||
616 | void dsDrawTerrainY(int x,int z,float vLength,float vNodeLength,int nNumNodesPerSide,float *pHeights,const float *pR,const float *ppos) | ||
617 | { | ||
618 | float A[3],B[3],C[3],D[3]; | ||
619 | float R[12]; | ||
620 | float pos[3]; | ||
621 | if (pR) | ||
622 | memcpy(R,pR,sizeof(R)); | ||
623 | else | ||
624 | { | ||
625 | memset(R,0,sizeof(R)); | ||
626 | R[0] = 1.f; | ||
627 | R[5] = 1.f; | ||
628 | R[10] = 1.f; | ||
629 | } | ||
630 | |||
631 | if (ppos) | ||
632 | memcpy(pos,ppos,sizeof(pos)); | ||
633 | else | ||
634 | memset(pos,0,sizeof(pos)); | ||
635 | |||
636 | float vx,vz; | ||
637 | vx = vLength * x; | ||
638 | vz = vLength * z; | ||
639 | |||
640 | int i; | ||
641 | for (i=0;i<nNumNodesPerSide;i++) | ||
642 | { | ||
643 | for (int j=0;j<nNumNodesPerSide;j++) | ||
644 | { | ||
645 | A[0] = i * vNodeLength + vx; | ||
646 | A[2] = j * vNodeLength + vz; | ||
647 | A[1] = GetHeight(i,j,nNumNodesPerSide,pHeights); | ||
648 | B[0] = (i+1) * vNodeLength + vx; | ||
649 | B[2] = j * vNodeLength + vz; | ||
650 | B[1] = GetHeight(i+1,j,nNumNodesPerSide,pHeights); | ||
651 | C[0] = i * vNodeLength + vx; | ||
652 | C[2] = (j+1) * vNodeLength + vz; | ||
653 | C[1] = GetHeight(i,j+1,nNumNodesPerSide,pHeights); | ||
654 | D[0] = (i+1) * vNodeLength + vx; | ||
655 | D[2] = (j+1) * vNodeLength + vz; | ||
656 | D[1] = GetHeight(i+1,j+1,nNumNodesPerSide,pHeights); | ||
657 | dsDrawTriangle(pos,R,C,B,A,1); | ||
658 | dsDrawTriangle(pos,R,D,B,C,1); | ||
659 | } | ||
660 | } | ||
661 | } | ||
662 | */ | ||
diff --git a/libraries/ode-0.9/contrib/TerrainAndCone/dTerrainZ.cpp b/libraries/ode-0.9/contrib/TerrainAndCone/dTerrainZ.cpp new file mode 100644 index 0000000..d47c402 --- /dev/null +++ b/libraries/ode-0.9/contrib/TerrainAndCone/dTerrainZ.cpp | |||
@@ -0,0 +1,659 @@ | |||
1 | //Benoit CHAPEROT 2003-2004 www.jstarlab.com | ||
2 | //some code inspired by Magic Software | ||
3 | #include <ode/common.h> | ||
4 | #include <ode/collision.h> | ||
5 | #include <ode/matrix.h> | ||
6 | #include <ode/rotation.h> | ||
7 | #include <ode/odemath.h> | ||
8 | #include "collision_kernel.h" | ||
9 | #include "collision_std.h" | ||
10 | #include "collision_std_internal.h" | ||
11 | #include "collision_util.h" | ||
12 | //#include <drawstuff/drawstuff.h> | ||
13 | #include "windows.h" | ||
14 | #include "ode\ode.h" | ||
15 | |||
16 | #define CONTACT(p,skip) ((dContactGeom*) (((char*)p) + (skip))) | ||
17 | #define MAXCONTACT 10 | ||
18 | #define TERRAINTOL 0.0f | ||
19 | |||
20 | static bool IsAPowerOfTwo(int f) | ||
21 | { | ||
22 | dAASSERT(f!=0); | ||
23 | while ((f&1) != 1) | ||
24 | f >>= 1; | ||
25 | |||
26 | return (f == 1); | ||
27 | } | ||
28 | |||
29 | static int GetPowerOfTwo(int f) | ||
30 | { | ||
31 | dAASSERT(f!=0); | ||
32 | int n = 0; | ||
33 | while ((f&1) != 1) | ||
34 | { | ||
35 | n++; | ||
36 | f >>= 1; | ||
37 | } | ||
38 | |||
39 | return n; | ||
40 | } | ||
41 | |||
42 | dxTerrainZ::dxTerrainZ (dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable) : | ||
43 | dxGeom (space,bPlaceable) | ||
44 | { | ||
45 | dIASSERT(IsAPowerOfTwo(nNumNodesPerSide)); | ||
46 | dIASSERT(pHeights); | ||
47 | dIASSERT(vLength > 0.f); | ||
48 | dIASSERT(nNumNodesPerSide > 0); | ||
49 | type = dTerrainZClass; | ||
50 | m_vLength = vLength; | ||
51 | m_pHeights = new dReal[nNumNodesPerSide * nNumNodesPerSide]; | ||
52 | dIASSERT(m_pHeights); | ||
53 | m_nNumNodesPerSide = nNumNodesPerSide; | ||
54 | m_vNodeLength = m_vLength / m_nNumNodesPerSide; | ||
55 | m_nNumNodesPerSideShift = GetPowerOfTwo(m_nNumNodesPerSide); | ||
56 | m_nNumNodesPerSideMask = m_nNumNodesPerSide - 1; | ||
57 | m_vMinHeight = dInfinity; | ||
58 | m_vMaxHeight = -dInfinity; | ||
59 | m_bFinite = bFinite; | ||
60 | |||
61 | for (int i=0;i<nNumNodesPerSide * nNumNodesPerSide;i++) | ||
62 | { | ||
63 | m_pHeights[i] = pHeights[i]; | ||
64 | if (m_pHeights[i] < m_vMinHeight) m_vMinHeight = m_pHeights[i]; | ||
65 | if (m_pHeights[i] > m_vMaxHeight) m_vMaxHeight = m_pHeights[i]; | ||
66 | } | ||
67 | } | ||
68 | |||
69 | dxTerrainZ::~dxTerrainZ() | ||
70 | { | ||
71 | dIASSERT(m_pHeights); | ||
72 | delete [] m_pHeights; | ||
73 | } | ||
74 | |||
75 | void dxTerrainZ::computeAABB() | ||
76 | { | ||
77 | if (m_bFinite) | ||
78 | { | ||
79 | if (gflags & GEOM_PLACEABLE) | ||
80 | { | ||
81 | dReal dx[6],dy[6],dz[6]; | ||
82 | dx[0] = 0; | ||
83 | dx[1] = final_posr->R[0] * m_vLength; | ||
84 | dx[2] = 0; | ||
85 | dx[3] = final_posr->R[1] * m_vLength; | ||
86 | dx[4] = final_posr->R[2] * m_vMinHeight; | ||
87 | dx[5] = final_posr->R[2] * m_vMaxHeight; | ||
88 | |||
89 | dy[0] = 0; | ||
90 | dy[1] = final_posr->R[4] * m_vLength; | ||
91 | dy[2] = 0; | ||
92 | dy[3] = final_posr->R[5] * m_vLength; | ||
93 | dy[4] = final_posr->R[6] * m_vMinHeight; | ||
94 | dy[5] = final_posr->R[6] * m_vMaxHeight; | ||
95 | |||
96 | dz[0] = 0; | ||
97 | dz[1] = final_posr->R[8] * m_vLength; | ||
98 | dz[2] = 0; | ||
99 | dz[3] = final_posr->R[9] * m_vLength; | ||
100 | dz[4] = final_posr->R[10] * m_vMinHeight; | ||
101 | dz[5] = final_posr->R[10] * m_vMaxHeight; | ||
102 | |||
103 | aabb[0] = final_posr->pos[0] + MIN(dx[0],dx[1]) + MIN(dx[2],dx[3]) + MIN(dx[4],dx[5]); | ||
104 | aabb[1] = final_posr->pos[0] + MAX(dx[0],dx[1]) + MAX(dx[2],dx[3]) + MAX(dx[4],dx[5]); | ||
105 | aabb[2] = final_posr->pos[1] + MIN(dy[0],dy[1]) + MIN(dy[2],dy[3]) + MIN(dy[4],dy[5]); | ||
106 | aabb[3] = final_posr->pos[1] + MAX(dy[0],dy[1]) + MAX(dy[2],dy[3]) + MAX(dy[4],dy[5]); | ||
107 | aabb[4] = final_posr->pos[2] + MIN(dz[0],dz[1]) + MIN(dz[2],dz[3]) + MIN(dz[4],dz[5]); | ||
108 | aabb[5] = final_posr->pos[2] + MAX(dz[0],dz[1]) + MAX(dz[2],dz[3]) + MAX(dz[4],dz[5]); | ||
109 | } | ||
110 | else | ||
111 | { | ||
112 | aabb[0] = 0; | ||
113 | aabb[1] = m_vLength; | ||
114 | aabb[2] = 0; | ||
115 | aabb[3] = m_vLength; | ||
116 | aabb[4] = m_vMinHeight; | ||
117 | aabb[5] = m_vMaxHeight; | ||
118 | } | ||
119 | } | ||
120 | else | ||
121 | { | ||
122 | if (gflags & GEOM_PLACEABLE) | ||
123 | { | ||
124 | aabb[0] = -dInfinity; | ||
125 | aabb[1] = dInfinity; | ||
126 | aabb[2] = -dInfinity; | ||
127 | aabb[3] = dInfinity; | ||
128 | aabb[4] = -dInfinity; | ||
129 | aabb[5] = dInfinity; | ||
130 | } | ||
131 | else | ||
132 | { | ||
133 | aabb[0] = -dInfinity; | ||
134 | aabb[1] = dInfinity; | ||
135 | aabb[2] = -dInfinity; | ||
136 | aabb[3] = dInfinity; | ||
137 | aabb[4] = m_vMinHeight; | ||
138 | aabb[5] = m_vMaxHeight; | ||
139 | } | ||
140 | } | ||
141 | } | ||
142 | |||
143 | dReal dxTerrainZ::GetHeight(int x,int y) | ||
144 | { | ||
145 | return m_pHeights[ (((unsigned int)(y) & m_nNumNodesPerSideMask) << m_nNumNodesPerSideShift) | ||
146 | + ((unsigned int)(x) & m_nNumNodesPerSideMask)]; | ||
147 | } | ||
148 | |||
149 | dReal dxTerrainZ::GetHeight(dReal x,dReal y) | ||
150 | { | ||
151 | int nX = int(floor(x / m_vNodeLength)); | ||
152 | int nY = int(floor(y / m_vNodeLength)); | ||
153 | dReal dx = (x - (dReal(nX) * m_vNodeLength)) / m_vNodeLength; | ||
154 | dReal dy = (y - (dReal(nY) * m_vNodeLength)) / m_vNodeLength; | ||
155 | dIASSERT((dx >= 0.f) && (dx <= 1.f)); | ||
156 | dIASSERT((dy >= 0.f) && (dy <= 1.f)); | ||
157 | |||
158 | dReal z,z0; | ||
159 | |||
160 | if (dx + dy < 1.f) | ||
161 | { | ||
162 | z0 = GetHeight(nX,nY); | ||
163 | z = z0 | ||
164 | + (GetHeight(nX+1,nY) - z0) * dx | ||
165 | + (GetHeight(nX,nY+1) - z0) * dy; | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | z0 = GetHeight(nX+1,nY+1); | ||
170 | z = z0 | ||
171 | + (GetHeight(nX+1,nY) - z0) * (1.f - dy) | ||
172 | + (GetHeight(nX,nY+1) - z0) * (1.f - dx); | ||
173 | } | ||
174 | |||
175 | return z; | ||
176 | } | ||
177 | |||
178 | bool dxTerrainZ::IsOnTerrain(int nx,int ny,int w,dReal *pos) | ||
179 | { | ||
180 | dVector3 Min,Max; | ||
181 | Min[0] = nx * m_vNodeLength; | ||
182 | Min[1] = ny * m_vNodeLength; | ||
183 | Max[0] = (nx+1) * m_vNodeLength; | ||
184 | Max[1] = (ny+1) * m_vNodeLength; | ||
185 | dReal Tol = m_vNodeLength * TERRAINTOL; | ||
186 | |||
187 | if ((pos[0]<Min[0]-Tol) || (pos[0]>Max[0]+Tol)) | ||
188 | return false; | ||
189 | |||
190 | if ((pos[1]<Min[1]-Tol) || (pos[1]>Max[1]+Tol)) | ||
191 | return false; | ||
192 | |||
193 | dReal dx = (pos[0] - (dReal(nx) * m_vNodeLength)) / m_vNodeLength; | ||
194 | dReal dy = (pos[1] - (dReal(ny) * m_vNodeLength)) / m_vNodeLength; | ||
195 | |||
196 | if ((w == 0) && (dx + dy > 1.f+TERRAINTOL)) | ||
197 | return false; | ||
198 | |||
199 | if ((w == 1) && (dx + dy < 1.f-TERRAINTOL)) | ||
200 | return false; | ||
201 | |||
202 | return true; | ||
203 | } | ||
204 | |||
205 | dGeomID dCreateTerrainZ(dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable) | ||
206 | { | ||
207 | return new dxTerrainZ(space, pHeights,vLength,nNumNodesPerSide, bFinite, bPlaceable); | ||
208 | } | ||
209 | |||
210 | dReal dGeomTerrainZPointDepth (dGeomID g, dReal x, dReal y, dReal z) | ||
211 | { | ||
212 | dUASSERT (g && g->type == dTerrainZClass,"argument not a terrain"); | ||
213 | g->recomputePosr(); | ||
214 | dxTerrainZ *t = (dxTerrainZ*) g; | ||
215 | return t->GetHeight(x,y) - z; | ||
216 | } | ||
217 | |||
218 | typedef dReal dGetDepthFn(dGeomID g, dReal x, dReal y, dReal z); | ||
219 | #define RECOMPUTE_RAYNORMAL | ||
220 | //#define DO_RAYDEPTH | ||
221 | |||
222 | #define DMESS(A) \ | ||
223 | dMessage(0,"Contact Plane (%d %d %d) %.5e %.5e (%.5e %.5e %.5e)(%.5e %.5e %.5e)).", \ | ||
224 | x,y,A, \ | ||
225 | pContact->depth, \ | ||
226 | dGeomSphereGetRadius(o2), \ | ||
227 | pContact->pos[0], \ | ||
228 | pContact->pos[1], \ | ||
229 | pContact->pos[2], \ | ||
230 | pContact->normal[0], \ | ||
231 | pContact->normal[1], \ | ||
232 | pContact->normal[2]); | ||
233 | /* | ||
234 | (z is up) | ||
235 | |||
236 | y | ||
237 | . | ||
238 | F | ||
239 | | | ||
240 | C-D | ||
241 | |\| | ||
242 | A-B-E.x | ||
243 | */ | ||
244 | int dxTerrainZ::dCollideTerrainUnit( | ||
245 | int x,int y,dxGeom *o2,int numMaxContacts, | ||
246 | int flags,dContactGeom *contact, int skip) | ||
247 | { | ||
248 | dColliderFn *CollideRayN; | ||
249 | dColliderFn *CollideNPlane; | ||
250 | dGetDepthFn *GetDepth; | ||
251 | int numContacts = 0; | ||
252 | int numPlaneContacts = 0; | ||
253 | int i; | ||
254 | |||
255 | if (numContacts == numMaxContacts) | ||
256 | return numContacts; | ||
257 | |||
258 | dContactGeom PlaneContact[MAXCONTACT]; | ||
259 | flags = (flags & 0xffff0000) | MAXCONTACT; | ||
260 | |||
261 | switch (o2->type) | ||
262 | { | ||
263 | case dSphereClass: | ||
264 | CollideRayN = dCollideRaySphere; | ||
265 | CollideNPlane = dCollideSpherePlane; | ||
266 | GetDepth = dGeomSpherePointDepth; | ||
267 | break; | ||
268 | case dBoxClass: | ||
269 | CollideRayN = dCollideRayBox; | ||
270 | CollideNPlane = dCollideBoxPlane; | ||
271 | GetDepth = dGeomBoxPointDepth; | ||
272 | break; | ||
273 | case dCCylinderClass: | ||
274 | CollideRayN = dCollideRayCCylinder; | ||
275 | CollideNPlane = dCollideCCylinderPlane; | ||
276 | GetDepth = dGeomCCylinderPointDepth; | ||
277 | break; | ||
278 | case dRayClass: | ||
279 | CollideRayN = NULL; | ||
280 | CollideNPlane = dCollideRayPlane; | ||
281 | GetDepth = NULL; | ||
282 | break; | ||
283 | case dConeClass: | ||
284 | CollideRayN = dCollideRayCone; | ||
285 | CollideNPlane = dCollideConePlane; | ||
286 | GetDepth = dGeomConePointDepth; | ||
287 | break; | ||
288 | default: | ||
289 | dIASSERT(0); | ||
290 | } | ||
291 | |||
292 | dReal Plane[4],lBD,lCD,lBC; | ||
293 | dVector3 A,B,C,D,BD,CD,BC,AB,AC; | ||
294 | A[0] = x * m_vNodeLength; | ||
295 | A[1] = y * m_vNodeLength; | ||
296 | A[2] = GetHeight(x,y); | ||
297 | B[0] = (x+1) * m_vNodeLength; | ||
298 | B[1] = y * m_vNodeLength; | ||
299 | B[2] = GetHeight(x+1,y); | ||
300 | C[0] = x * m_vNodeLength; | ||
301 | C[1] = (y+1) * m_vNodeLength; | ||
302 | C[2] = GetHeight(x,y+1); | ||
303 | D[0] = (x+1) * m_vNodeLength; | ||
304 | D[1] = (y+1) * m_vNodeLength; | ||
305 | D[2] = GetHeight(x+1,y+1); | ||
306 | |||
307 | dOP(BC,-,C,B); | ||
308 | lBC = dLENGTH(BC); | ||
309 | dOPEC(BC,/=,lBC); | ||
310 | |||
311 | dOP(BD,-,D,B); | ||
312 | lBD = dLENGTH(BD); | ||
313 | dOPEC(BD,/=,lBD); | ||
314 | |||
315 | dOP(CD,-,D,C); | ||
316 | lCD = dLENGTH(CD); | ||
317 | dOPEC(CD,/=,lCD); | ||
318 | |||
319 | dOP(AB,-,B,A); | ||
320 | dNormalize3(AB); | ||
321 | |||
322 | dOP(AC,-,C,A); | ||
323 | dNormalize3(AC); | ||
324 | |||
325 | if (CollideRayN) | ||
326 | { | ||
327 | #ifdef RECOMPUTE_RAYNORMAL | ||
328 | dVector3 E,F; | ||
329 | dVector3 CE,FB,AD; | ||
330 | dVector3 Normal[3]; | ||
331 | E[0] = (x+2) * m_vNodeLength; | ||
332 | E[1] = y * m_vNodeLength; | ||
333 | E[2] = GetHeight(x+2,y); | ||
334 | F[0] = x * m_vNodeLength; | ||
335 | F[1] = (y+2) * m_vNodeLength; | ||
336 | F[2] = GetHeight(x,y+2); | ||
337 | dOP(AD,-,D,A); | ||
338 | dNormalize3(AD); | ||
339 | dOP(CE,-,E,C); | ||
340 | dNormalize3(CE); | ||
341 | dOP(FB,-,B,F); | ||
342 | dNormalize3(FB); | ||
343 | |||
344 | //BC | ||
345 | dCROSS(Normal[0],=,AD,BC); | ||
346 | dNormalize3(Normal[0]); | ||
347 | |||
348 | //BD | ||
349 | dCROSS(Normal[1],=,CE,BD); | ||
350 | dNormalize3(Normal[1]); | ||
351 | |||
352 | //CD | ||
353 | dCROSS(Normal[2],=,FB,CD); | ||
354 | dNormalize3(Normal[2]); | ||
355 | #endif | ||
356 | int nA[3],nB[3]; | ||
357 | dContactGeom ContactA[3],ContactB[3]; | ||
358 | dxRay rayBC(0,lBC); | ||
359 | dGeomRaySet(&rayBC, B[0], B[1], B[2], BC[0], BC[1], BC[2]); | ||
360 | nA[0] = CollideRayN(&rayBC,o2,flags,&ContactA[0],sizeof(dContactGeom)); | ||
361 | dGeomRaySet(&rayBC, C[0], C[1], C[2], -BC[0], -BC[1], -BC[2]); | ||
362 | nB[0] = CollideRayN(&rayBC,o2,flags,&ContactB[0],sizeof(dContactGeom)); | ||
363 | |||
364 | dxRay rayBD(0,lBD); | ||
365 | dGeomRaySet(&rayBD, B[0], B[1], B[2], BD[0], BD[1], BD[2]); | ||
366 | nA[1] = CollideRayN(&rayBD,o2,flags,&ContactA[1],sizeof(dContactGeom)); | ||
367 | dGeomRaySet(&rayBD, D[0], D[1], D[2], -BD[0], -BD[1], -BD[2]); | ||
368 | nB[1] = CollideRayN(&rayBD,o2,flags,&ContactB[1],sizeof(dContactGeom)); | ||
369 | |||
370 | dxRay rayCD(0,lCD); | ||
371 | dGeomRaySet(&rayCD, C[0], C[1], C[2], CD[0], CD[1], CD[2]); | ||
372 | nA[2] = CollideRayN(&rayCD,o2,flags,&ContactA[2],sizeof(dContactGeom)); | ||
373 | dGeomRaySet(&rayCD, D[0], D[1], D[2], -CD[0], -CD[1], -CD[2]); | ||
374 | nB[2] = CollideRayN(&rayCD,o2,flags,&ContactB[2],sizeof(dContactGeom)); | ||
375 | |||
376 | for (i=0;i<3;i++) | ||
377 | { | ||
378 | if (nA[i] & nB[i]) | ||
379 | { | ||
380 | dContactGeom *pContact = CONTACT(contact,numContacts*skip); | ||
381 | pContact->pos[0] = (ContactA[i].pos[0] + ContactB[i].pos[0])/2; | ||
382 | pContact->pos[1] = (ContactA[i].pos[1] + ContactB[i].pos[1])/2; | ||
383 | pContact->pos[2] = (ContactA[i].pos[2] + ContactB[i].pos[2])/2; | ||
384 | #ifdef RECOMPUTE_RAYNORMAL | ||
385 | pContact->normal[0] = -Normal[i][0]; | ||
386 | pContact->normal[1] = -Normal[i][1]; | ||
387 | pContact->normal[2] = -Normal[i][2]; | ||
388 | #else | ||
389 | pContact->normal[0] = (ContactA[i].normal[0] + ContactB[i].normal[0])/2; //0.f; | ||
390 | pContact->normal[1] = (ContactA[i].normal[1] + ContactB[i].normal[1])/2; //0.f; | ||
391 | pContact->normal[2] = (ContactA[i].normal[2] + ContactB[i].normal[2])/2; //-1.f; | ||
392 | dNormalize3(pContact->normal); | ||
393 | #endif | ||
394 | #ifdef DO_RAYDEPTH | ||
395 | dxRay rayV(0,1000.f); | ||
396 | dGeomRaySet(&rayV, pContact->pos[0], | ||
397 | pContact->pos[1], | ||
398 | pContact->pos[2], | ||
399 | -pContact->normal[0], | ||
400 | -pContact->normal[1], | ||
401 | -pContact->normal[2]); | ||
402 | |||
403 | dContactGeom ContactV; | ||
404 | if (CollideRayN(&rayV,o2,flags,&ContactV,sizeof(dContactGeom))) | ||
405 | { | ||
406 | pContact->depth = ContactV.depth; | ||
407 | numContacts++; | ||
408 | } | ||
409 | #else | ||
410 | if (GetDepth == NULL) | ||
411 | { | ||
412 | dxRay rayV(0,1000.f); | ||
413 | dGeomRaySet(&rayV, pContact->pos[0], | ||
414 | pContact->pos[1], | ||
415 | pContact->pos[2], | ||
416 | -pContact->normal[0], | ||
417 | -pContact->normal[1], | ||
418 | -pContact->normal[2]); | ||
419 | |||
420 | dContactGeom ContactV; | ||
421 | if (CollideRayN(&rayV,o2,flags,&ContactV,sizeof(dContactGeom))) | ||
422 | { | ||
423 | pContact->depth = ContactV.depth; | ||
424 | numContacts++; | ||
425 | } | ||
426 | } | ||
427 | else | ||
428 | { | ||
429 | pContact->depth = GetDepth(o2, | ||
430 | pContact->pos[0], | ||
431 | pContact->pos[1], | ||
432 | pContact->pos[2]); | ||
433 | numContacts++; | ||
434 | } | ||
435 | #endif | ||
436 | if (numContacts == numMaxContacts) | ||
437 | return numContacts; | ||
438 | |||
439 | } | ||
440 | } | ||
441 | } | ||
442 | |||
443 | dCROSS(Plane,=,AB,AC); | ||
444 | dNormalize3(Plane); | ||
445 | Plane[3] = Plane[0] * A[0] + Plane[1] * A[1] + Plane[2] * A[2]; | ||
446 | dxPlane planeABC(0,Plane[0],Plane[1],Plane[2],Plane[3]); | ||
447 | numPlaneContacts = CollideNPlane(o2,&planeABC,flags,PlaneContact,sizeof(dContactGeom)); | ||
448 | |||
449 | for (i=0;i<numPlaneContacts;i++) | ||
450 | { | ||
451 | if (IsOnTerrain(x,y,0,PlaneContact[i].pos)) | ||
452 | { | ||
453 | dContactGeom *pContact = CONTACT(contact,numContacts*skip); | ||
454 | pContact->pos[0] = PlaneContact[i].pos[0]; | ||
455 | pContact->pos[1] = PlaneContact[i].pos[1]; | ||
456 | pContact->pos[2] = PlaneContact[i].pos[2]; | ||
457 | pContact->normal[0] = -PlaneContact[i].normal[0]; | ||
458 | pContact->normal[1] = -PlaneContact[i].normal[1]; | ||
459 | pContact->normal[2] = -PlaneContact[i].normal[2]; | ||
460 | pContact->depth = PlaneContact[i].depth; | ||
461 | |||
462 | //DMESS(0); | ||
463 | numContacts++; | ||
464 | |||
465 | if (numContacts == numMaxContacts) | ||
466 | return numContacts; | ||
467 | } | ||
468 | } | ||
469 | |||
470 | dCROSS(Plane,=,CD,BD); | ||
471 | dNormalize3(Plane); | ||
472 | Plane[3] = Plane[0] * D[0] + Plane[1] * D[1] + Plane[2] * D[2]; | ||
473 | dxPlane planeDCB(0,Plane[0],Plane[1],Plane[2],Plane[3]); | ||
474 | numPlaneContacts = CollideNPlane(o2,&planeDCB,flags,PlaneContact,sizeof(dContactGeom)); | ||
475 | |||
476 | for (i=0;i<numPlaneContacts;i++) | ||
477 | { | ||
478 | if (IsOnTerrain(x,y,1,PlaneContact[i].pos)) | ||
479 | { | ||
480 | dContactGeom *pContact = CONTACT(contact,numContacts*skip); | ||
481 | pContact->pos[0] = PlaneContact[i].pos[0]; | ||
482 | pContact->pos[1] = PlaneContact[i].pos[1]; | ||
483 | pContact->pos[2] = PlaneContact[i].pos[2]; | ||
484 | pContact->normal[0] = -PlaneContact[i].normal[0]; | ||
485 | pContact->normal[1] = -PlaneContact[i].normal[1]; | ||
486 | pContact->normal[2] = -PlaneContact[i].normal[2]; | ||
487 | pContact->depth = PlaneContact[i].depth; | ||
488 | //DMESS(1); | ||
489 | numContacts++; | ||
490 | |||
491 | if (numContacts == numMaxContacts) | ||
492 | return numContacts; | ||
493 | } | ||
494 | } | ||
495 | |||
496 | return numContacts; | ||
497 | } | ||
498 | |||
499 | int dCollideTerrainZ(dxGeom *o1, dxGeom *o2, int flags,dContactGeom *contact, int skip) | ||
500 | { | ||
501 | dIASSERT (skip >= (int)sizeof(dContactGeom)); | ||
502 | dIASSERT (o1->type == dTerrainZClass); | ||
503 | int i,j; | ||
504 | |||
505 | if ((flags & 0xffff) == 0) | ||
506 | flags = (flags & 0xffff0000) | 1; | ||
507 | |||
508 | int numMaxTerrainContacts = (flags & 0xffff); | ||
509 | dxTerrainZ *terrain = (dxTerrainZ*) o1; | ||
510 | |||
511 | dReal aabbbak[6]; | ||
512 | int gflagsbak; | ||
513 | |||
514 | dVector3 pos0; | ||
515 | int numTerrainContacts = 0; | ||
516 | |||
517 | dxPosR *bak; | ||
518 | dxPosR X1; | ||
519 | |||
520 | if (terrain->gflags & GEOM_PLACEABLE) | ||
521 | { | ||
522 | dOP(pos0,-,o2->final_posr->pos,terrain->final_posr->pos); | ||
523 | dMULTIPLY1_331(X1.pos,terrain->final_posr->R,pos0); | ||
524 | dMULTIPLY1_333(X1.R,terrain->final_posr->R,o2->final_posr->R); | ||
525 | bak = o2->final_posr; | ||
526 | o2->final_posr = &X1; | ||
527 | memcpy(aabbbak,o2->aabb,sizeof(dReal)*6); | ||
528 | gflagsbak = o2->gflags; | ||
529 | o2->computeAABB(); | ||
530 | } | ||
531 | |||
532 | int nMinX = int(floor(o2->aabb[0] / terrain->m_vNodeLength)); | ||
533 | int nMaxX = int(floor(o2->aabb[1] / terrain->m_vNodeLength)) + 1; | ||
534 | int nMinY = int(floor(o2->aabb[2] / terrain->m_vNodeLength)); | ||
535 | int nMaxY = int(floor(o2->aabb[3] / terrain->m_vNodeLength)) + 1; | ||
536 | |||
537 | if (terrain->m_bFinite) | ||
538 | { | ||
539 | nMinX = MAX(nMinX,0); | ||
540 | nMaxX = MIN(nMaxX,terrain->m_nNumNodesPerSide); | ||
541 | nMinY = MAX(nMinY,0); | ||
542 | nMaxY = MIN(nMaxY,terrain->m_nNumNodesPerSide); | ||
543 | |||
544 | if ((nMinX >= nMaxX) || (nMinY >= nMaxY)) | ||
545 | goto dCollideTerrainZExit; | ||
546 | } | ||
547 | |||
548 | dVector3 AabbTop; | ||
549 | AabbTop[0] = (o2->aabb[0]+o2->aabb[1]) / 2; | ||
550 | AabbTop[1] = (o2->aabb[2]+o2->aabb[3]) / 2; | ||
551 | AabbTop[2] = o2->aabb[5]; | ||
552 | if (o2->type != dRayClass) | ||
553 | { | ||
554 | dReal AabbTopDepth = terrain->GetHeight(AabbTop[0],AabbTop[1]) - AabbTop[2]; | ||
555 | if (AabbTopDepth > 0.f) | ||
556 | { | ||
557 | contact->depth = AabbTopDepth; | ||
558 | dReal MaxDepth = (o2->aabb[5]-o2->aabb[4]) / 2; | ||
559 | if (contact->depth > MaxDepth) | ||
560 | contact->depth = MaxDepth; | ||
561 | contact->g1 = o1; | ||
562 | contact->g2 = o2; | ||
563 | dOPE(contact->pos,=,AabbTop); | ||
564 | contact->normal[0] = 0.f; | ||
565 | contact->normal[1] = 0.f; | ||
566 | contact->normal[2] = -1.f; | ||
567 | |||
568 | numTerrainContacts = 1; | ||
569 | goto dCollideTerrainZExit; | ||
570 | } | ||
571 | } | ||
572 | |||
573 | for (i=nMinX;i<nMaxX;i++) | ||
574 | { | ||
575 | for (j=nMinY;j<nMaxY;j++) | ||
576 | { | ||
577 | numTerrainContacts += terrain->dCollideTerrainUnit( | ||
578 | i,j,o2,numMaxTerrainContacts - numTerrainContacts, | ||
579 | flags,CONTACT(contact,numTerrainContacts*skip),skip ); | ||
580 | } | ||
581 | } | ||
582 | |||
583 | dIASSERT(numTerrainContacts <= numMaxTerrainContacts); | ||
584 | |||
585 | for (i=0; i<numTerrainContacts; i++) | ||
586 | { | ||
587 | CONTACT(contact,i*skip)->g1 = o1; | ||
588 | CONTACT(contact,i*skip)->g2 = o2; | ||
589 | } | ||
590 | |||
591 | dCollideTerrainZExit: | ||
592 | |||
593 | if (terrain->gflags & GEOM_PLACEABLE) | ||
594 | { | ||
595 | o2->final_posr = bak; | ||
596 | memcpy(o2->aabb,aabbbak,sizeof(dReal)*6); | ||
597 | o2->gflags = gflagsbak; | ||
598 | |||
599 | for (i=0; i<numTerrainContacts; i++) | ||
600 | { | ||
601 | dOPE(pos0,=,CONTACT(contact,i*skip)->pos); | ||
602 | dMULTIPLY0_331(CONTACT(contact,i*skip)->pos,terrain->final_posr->R,pos0); | ||
603 | dOP(CONTACT(contact,i*skip)->pos,+,CONTACT(contact,i*skip)->pos,terrain->final_posr->pos); | ||
604 | |||
605 | dOPE(pos0,=,CONTACT(contact,i*skip)->normal); | ||
606 | dMULTIPLY0_331(CONTACT(contact,i*skip)->normal,terrain->final_posr->R,pos0); | ||
607 | } | ||
608 | } | ||
609 | |||
610 | return numTerrainContacts; | ||
611 | } | ||
612 | /* | ||
613 | void dsDrawTerrainZ(int x,int z,float vLength,float vNodeLength,int nNumNodesPerSide,float *pHeights,const float *pR,const float *ppos) | ||
614 | { | ||
615 | float A[3],B[3],C[3],D[3]; | ||
616 | float R[12]; | ||
617 | float pos[3]; | ||
618 | if (pR) | ||
619 | memcpy(R,pR,sizeof(R)); | ||
620 | else | ||
621 | { | ||
622 | memset(R,0,sizeof(R)); | ||
623 | R[0] = 1.f; | ||
624 | R[5] = 1.f; | ||
625 | R[10] = 1.f; | ||
626 | } | ||
627 | |||
628 | if (ppos) | ||
629 | memcpy(pos,ppos,sizeof(pos)); | ||
630 | else | ||
631 | memset(pos,0,sizeof(pos)); | ||
632 | |||
633 | float vx,vz; | ||
634 | vx = vLength * x; | ||
635 | vz = vLength * z; | ||
636 | |||
637 | int i; | ||
638 | for (i=0;i<nNumNodesPerSide;i++) | ||
639 | { | ||
640 | for (int j=0;j<nNumNodesPerSide;j++) | ||
641 | { | ||
642 | A[0] = i * vNodeLength + vx; | ||
643 | A[1] = j * vNodeLength + vz; | ||
644 | A[2] = GetHeight(i,j,nNumNodesPerSide,pHeights); | ||
645 | B[0] = (i+1) * vNodeLength + vx; | ||
646 | B[1] = j * vNodeLength + vz; | ||
647 | B[2] = GetHeight(i+1,j,nNumNodesPerSide,pHeights); | ||
648 | C[0] = i * vNodeLength + vx; | ||
649 | C[1] = (j+1) * vNodeLength + vz; | ||
650 | C[2] = GetHeight(i,j+1,nNumNodesPerSide,pHeights); | ||
651 | D[0] = (i+1) * vNodeLength + vx; | ||
652 | D[1] = (j+1) * vNodeLength + vz; | ||
653 | D[2] = GetHeight(i+1,j+1,nNumNodesPerSide,pHeights); | ||
654 | dsDrawTriangle(pos,R,C,A,B,1); | ||
655 | dsDrawTriangle(pos,R,D,C,B,1); | ||
656 | } | ||
657 | } | ||
658 | } | ||
659 | */ | ||
diff --git a/libraries/ode-0.9/contrib/TerrainAndCone/readme.txt b/libraries/ode-0.9/contrib/TerrainAndCone/readme.txt new file mode 100644 index 0000000..0428846 --- /dev/null +++ b/libraries/ode-0.9/contrib/TerrainAndCone/readme.txt | |||
@@ -0,0 +1,322 @@ | |||
1 | Benoit CHAPEROT 2003-2004 www.jstarlab.com | ||
2 | Support for terrain and cones, collision and drawing. | ||
3 | |||
4 | Terrains can be with z up (dTerrainZ) or y up (dTerrainY). | ||
5 | Terrains are defined by a height field. | ||
6 | Terrains are now placeable. | ||
7 | Terrains can now be finite or infinite (repeat themselve in the x and (y or z) directions). | ||
8 | |||
9 | Terrains can potentially collide with everything that collides with planes and rays; | ||
10 | see the switch statement. | ||
11 | |||
12 | Cones currently collides only with terrain and planes and rays. | ||
13 | Cones, with high radius to height ratios are perfect to simulate vehicle wheels on terrains. | ||
14 | |||
15 | |||
16 | |||
17 | There was an error in the depths returned by dCollideTerrain. | ||
18 | Plus now contacts are not sorted according to their depths. | ||
19 | Contact sorting is now supposed to be done externally. | ||
20 | Not all dCollide functions seem to sort contacts according to depth. | ||
21 | Requesting a high number of contacts, sorting them and then considering only the most significant contacts | ||
22 | is a good way I think to improve stability. | ||
23 | * Cones Collisions with spheres, boxes, ccylinder and trimesh are now roughly approximated using sphere collisions. | ||
24 | |||
25 | You will need to complete the following operations (with ODE 0.039): | ||
26 | |||
27 | *** add to folder ode\src: | ||
28 | |||
29 | dCone.cpp | ||
30 | dTerrainY.cpp | ||
31 | dTerrainZ.cpp | ||
32 | collision_std_internal.h | ||
33 | |||
34 | On linux => edit each .cpp file and comment out #include "windows.h" & #include "ode\ode.h" | ||
35 | |||
36 | |||
37 | *** add to drawstuff\src\drawstuff.cpp: | ||
38 | |||
39 | static void drawCone(float l, float r) | ||
40 | { | ||
41 | int i; | ||
42 | float tmp,ny,nz,a,ca,sa; | ||
43 | const int n = 24; // number of sides to the cone (divisible by 4) | ||
44 | |||
45 | a = float(M_PI*2.0)/float(n); | ||
46 | sa = (float) sin(a); | ||
47 | ca = (float) cos(a); | ||
48 | |||
49 | // draw top | ||
50 | glShadeModel (GL_FLAT); | ||
51 | ny=1; nz=0; // normal vector = (0,ny,nz) | ||
52 | glBegin (GL_TRIANGLE_FAN); | ||
53 | glNormal3d (0,0,1); | ||
54 | glVertex3d (0,0,l); | ||
55 | for (i=0; i<=n; i++) { | ||
56 | if (i==1 || i==n/2+1) | ||
57 | setColor (color[0]*0.75f,color[1]*0.75f,color[2]*0.75f,color[3]); | ||
58 | glNormal3d (ny*r,nz*r,0); | ||
59 | glVertex3d (ny*r,nz*r,0); | ||
60 | if (i==1 || i==n/2+1) | ||
61 | setColor (color[0],color[1],color[2],color[3]); | ||
62 | |||
63 | // rotate ny,nz | ||
64 | tmp = ca*ny - sa*nz; | ||
65 | nz = sa*ny + ca*nz; | ||
66 | ny = tmp; | ||
67 | } | ||
68 | glEnd(); | ||
69 | |||
70 | // draw bottom | ||
71 | ny=1; nz=0; // normal vector = (0,ny,nz) | ||
72 | glBegin (GL_TRIANGLE_FAN); | ||
73 | glNormal3d (0,0,-1); | ||
74 | glVertex3d (0,0,0); | ||
75 | for (i=0; i<=n; i++) { | ||
76 | if (i==1 || i==n/2+1) | ||
77 | setColor (color[0]*0.75f,color[1]*0.75f,color[2]*0.75f,color[3]); | ||
78 | glNormal3d (0,0,-1); | ||
79 | glVertex3d (ny*r,nz*r,0); | ||
80 | if (i==1 || i==n/2+1) | ||
81 | setColor (color[0],color[1],color[2],color[3]); | ||
82 | |||
83 | // rotate ny,nz | ||
84 | tmp = ca*ny + sa*nz; | ||
85 | nz = -sa*ny + ca*nz; | ||
86 | ny = tmp; | ||
87 | } | ||
88 | glEnd(); | ||
89 | } | ||
90 | |||
91 | void dsDrawCone (const float pos[3], const float R[12], float length, float radius) | ||
92 | { | ||
93 | if (current_state != 2) dsError ("drawing function called outside simulation loop"); | ||
94 | setupDrawingMode(); | ||
95 | glShadeModel (GL_SMOOTH); | ||
96 | setTransform (pos,R); | ||
97 | drawCone (length,radius); | ||
98 | glPopMatrix(); | ||
99 | |||
100 | if (use_shadows) { | ||
101 | setShadowDrawingMode(); | ||
102 | setShadowTransform(); | ||
103 | setTransform (pos,R); | ||
104 | drawCone (length,radius); | ||
105 | glPopMatrix(); | ||
106 | glPopMatrix(); | ||
107 | glDepthRange (0,1); | ||
108 | } | ||
109 | } | ||
110 | |||
111 | void dsDrawConeD (const double pos[3], const double R[12], float length, float radius) | ||
112 | { | ||
113 | int i; | ||
114 | float pos2[3],R2[12]; | ||
115 | for (i=0; i<3; i++) pos2[i]=(float)pos[i]; | ||
116 | for (i=0; i<12; i++) R2[i]=(float)R[i]; | ||
117 | dsDrawCone(pos2,R2,length,radius); | ||
118 | } | ||
119 | |||
120 | static float GetHeight(int x,int y,int nNumNodesPerSide,float *pHeights) | ||
121 | { | ||
122 | int nNumNodesPerSideMask = nNumNodesPerSide - 1; | ||
123 | return pHeights[ (((unsigned int)(y) & nNumNodesPerSideMask) * nNumNodesPerSide) | ||
124 | + ((unsigned int)(x) & nNumNodesPerSideMask)]; | ||
125 | } | ||
126 | |||
127 | void dsDrawTerrainY(int x,int z,float vLength,float vNodeLength,int nNumNodesPerSide,float *pHeights,const float *pR,const float *ppos) | ||
128 | { | ||
129 | float A[3],B[3],C[3],D[3]; | ||
130 | float R[12]; | ||
131 | float pos[3]; | ||
132 | if (pR) | ||
133 | memcpy(R,pR,sizeof(R)); | ||
134 | else | ||
135 | { | ||
136 | memset(R,0,sizeof(R)); | ||
137 | R[0] = 1.f; | ||
138 | R[5] = 1.f; | ||
139 | R[10] = 1.f; | ||
140 | } | ||
141 | |||
142 | if (ppos) | ||
143 | memcpy(pos,ppos,sizeof(pos)); | ||
144 | else | ||
145 | memset(pos,0,sizeof(pos)); | ||
146 | |||
147 | float vx,vz; | ||
148 | vx = vLength * x; | ||
149 | vz = vLength * z; | ||
150 | |||
151 | int i; | ||
152 | for (i=0;i<nNumNodesPerSide;i++) | ||
153 | { | ||
154 | for (int j=0;j<nNumNodesPerSide;j++) | ||
155 | { | ||
156 | A[0] = i * vNodeLength + vx; | ||
157 | A[2] = j * vNodeLength + vz; | ||
158 | A[1] = GetHeight(i,j,nNumNodesPerSide,pHeights); | ||
159 | B[0] = (i+1) * vNodeLength + vx; | ||
160 | B[2] = j * vNodeLength + vz; | ||
161 | B[1] = GetHeight(i+1,j,nNumNodesPerSide,pHeights); | ||
162 | C[0] = i * vNodeLength + vx; | ||
163 | C[2] = (j+1) * vNodeLength + vz; | ||
164 | C[1] = GetHeight(i,j+1,nNumNodesPerSide,pHeights); | ||
165 | D[0] = (i+1) * vNodeLength + vx; | ||
166 | D[2] = (j+1) * vNodeLength + vz; | ||
167 | D[1] = GetHeight(i+1,j+1,nNumNodesPerSide,pHeights); | ||
168 | dsDrawTriangle(pos,R,C,B,A,1); | ||
169 | dsDrawTriangle(pos,R,D,B,C,1); | ||
170 | } | ||
171 | } | ||
172 | } | ||
173 | |||
174 | void dsDrawTerrainZ(int x,int z,float vLength,float vNodeLength,int nNumNodesPerSide,float *pHeights,const float *pR,const float *ppos) | ||
175 | { | ||
176 | float A[3],B[3],C[3],D[3]; | ||
177 | float R[12]; | ||
178 | float pos[3]; | ||
179 | if (pR) | ||
180 | memcpy(R,pR,sizeof(R)); | ||
181 | else | ||
182 | { | ||
183 | memset(R,0,sizeof(R)); | ||
184 | R[0] = 1.f; | ||
185 | R[5] = 1.f; | ||
186 | R[10] = 1.f; | ||
187 | } | ||
188 | |||
189 | if (ppos) | ||
190 | memcpy(pos,ppos,sizeof(pos)); | ||
191 | else | ||
192 | memset(pos,0,sizeof(pos)); | ||
193 | |||
194 | float vx,vz; | ||
195 | vx = vLength * x; | ||
196 | vz = vLength * z; | ||
197 | |||
198 | int i; | ||
199 | for (i=0;i<nNumNodesPerSide;i++) | ||
200 | { | ||
201 | for (int j=0;j<nNumNodesPerSide;j++) | ||
202 | { | ||
203 | A[0] = i * vNodeLength + vx; | ||
204 | A[1] = j * vNodeLength + vz; | ||
205 | A[2] = GetHeight(i,j,nNumNodesPerSide,pHeights); | ||
206 | B[0] = (i+1) * vNodeLength + vx; | ||
207 | B[1] = j * vNodeLength + vz; | ||
208 | B[2] = GetHeight(i+1,j,nNumNodesPerSide,pHeights); | ||
209 | C[0] = i * vNodeLength + vx; | ||
210 | C[1] = (j+1) * vNodeLength + vz; | ||
211 | C[2] = GetHeight(i,j+1,nNumNodesPerSide,pHeights); | ||
212 | D[0] = (i+1) * vNodeLength + vx; | ||
213 | D[1] = (j+1) * vNodeLength + vz; | ||
214 | D[2] = GetHeight(i+1,j+1,nNumNodesPerSide,pHeights); | ||
215 | dsDrawTriangle(pos,R,C,A,B,1); | ||
216 | dsDrawTriangle(pos,R,D,C,B,1); | ||
217 | } | ||
218 | } | ||
219 | } | ||
220 | |||
221 | *** add to include\drawstuff\drawstuff.h: | ||
222 | void dsDrawCone (const float pos[3], const float R[12], float length, float radius); | ||
223 | void dsDrawConeD (const double pos[3], const double R[12], float length, float radius); | ||
224 | void dsDrawTerrainY(int x,int y,float vLength,float vNodeLength,int nNumNodesPerSide,float *pHeights,const float *pR,const float *ppos); | ||
225 | void dsDrawTerrainZ(int x,int y,float vLength,float vNodeLength,int nNumNodesPerSide,float *pHeights,const float *pR,const float *ppos); | ||
226 | |||
227 | *** add in include\ode\collision.h line 77: | ||
228 | /* class numbers - each geometry object needs a unique number */ | ||
229 | enum { | ||
230 | dSphereClass = 0, | ||
231 | dBoxClass, | ||
232 | dCCylinderClass, | ||
233 | dCylinderClass, | ||
234 | dPlaneClass, | ||
235 | dRayClass, | ||
236 | dGeomTransformClass, | ||
237 | dTriMeshClass, | ||
238 | |||
239 | dTerrainYClass, //here | ||
240 | dTerrainZClass, //here | ||
241 | dConeClass, //here | ||
242 | |||
243 | dFirstSpaceClass, | ||
244 | dSimpleSpaceClass = dFirstSpaceClass, | ||
245 | dHashSpaceClass, | ||
246 | dQuadTreeSpaceClass, | ||
247 | |||
248 | dLastSpaceClass = dQuadTreeSpaceClass, | ||
249 | |||
250 | dFirstUserClass, | ||
251 | dLastUserClass = dFirstUserClass + dMaxUserClasses - 1, | ||
252 | dGeomNumClasses | ||
253 | }; | ||
254 | |||
255 | dGeomID dCreateTerrainY (dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable); | ||
256 | dReal dGeomTerrainYPointDepth (dGeomID g, dReal x, dReal y, dReal z); | ||
257 | dGeomID dCreateTerrainZ (dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable); | ||
258 | dReal dGeomTerrainZPointDepth (dGeomID g, dReal x, dReal y, dReal z); | ||
259 | |||
260 | dGeomID dCreateCone(dSpaceID space, dReal radius, dReal length); | ||
261 | void dGeomConeSetParams (dGeomID cone, dReal radius, dReal length); | ||
262 | void dGeomConeGetParams (dGeomID cone, dReal *radius, dReal *length); | ||
263 | dReal dGeomConePointDepth(dGeomID g, dReal x, dReal y, dReal z); | ||
264 | |||
265 | *** add in include\ode\odemath.h: | ||
266 | #define dOP(a,op,b,c) \ | ||
267 | (a)[0] = ((b)[0]) op ((c)[0]); \ | ||
268 | (a)[1] = ((b)[1]) op ((c)[1]); \ | ||
269 | (a)[2] = ((b)[2]) op ((c)[2]); | ||
270 | #define dOPC(a,op,b,c) \ | ||
271 | (a)[0] = ((b)[0]) op (c); \ | ||
272 | (a)[1] = ((b)[1]) op (c); \ | ||
273 | (a)[2] = ((b)[2]) op (c); | ||
274 | #define dOPE(a,op,b) \ | ||
275 | (a)[0] op ((b)[0]); \ | ||
276 | (a)[1] op ((b)[1]); \ | ||
277 | (a)[2] op ((b)[2]); | ||
278 | #define dOPEC(a,op,c) \ | ||
279 | (a)[0] op (c); \ | ||
280 | (a)[1] op (c); \ | ||
281 | (a)[2] op (c); | ||
282 | #define dLENGTH(a) \ | ||
283 | (dSqrt( ((a)[0])*((a)[0]) + ((a)[1])*((a)[1]) + ((a)[2])*((a)[2]) )); | ||
284 | #define dLENGTHSQUARED(a) \ | ||
285 | (((a)[0])*((a)[0]) + ((a)[1])*((a)[1]) + ((a)[2])*((a)[2])); | ||
286 | |||
287 | *** add in ode\src\collision_kernel.cpp function 'static void initColliders()' next to other 'setCollider' calls: | ||
288 | setCollider (dTerrainYClass,dSphereClass,&dCollideTerrainY); | ||
289 | setCollider (dTerrainYClass,dBoxClass,&dCollideTerrainY); | ||
290 | setCollider (dTerrainYClass,dCCylinderClass,&dCollideTerrainY); | ||
291 | setCollider (dTerrainYClass,dRayClass,&dCollideTerrainY); | ||
292 | setCollider (dTerrainYClass,dConeClass,&dCollideTerrainY); | ||
293 | |||
294 | setCollider (dTerrainZClass,dSphereClass,&dCollideTerrainZ); | ||
295 | setCollider (dTerrainZClass,dBoxClass,&dCollideTerrainZ); | ||
296 | setCollider (dTerrainZClass,dCCylinderClass,&dCollideTerrainZ); | ||
297 | setCollider (dTerrainZClass,dRayClass,&dCollideTerrainZ); | ||
298 | setCollider (dTerrainZClass,dConeClass,&dCollideTerrainZ); | ||
299 | |||
300 | setCollider (dRayClass,dConeClass,&dCollideRayCone); | ||
301 | setCollider (dConeClass,dPlaneClass,&dCollideConePlane); | ||
302 | setCollider (dConeClass,dSphereClass,&dCollideConeSphere); | ||
303 | setCollider (dConeClass,dBoxClass,&dCollideConeBox); | ||
304 | setCollider (dCCylinderClass,dConeClass,&dCollideCCylinderCone); | ||
305 | setCollider (dTriMeshClass,dConeClass,&dCollideTriMeshCone); | ||
306 | |||
307 | *** add in ode\src\collision_std.h: | ||
308 | int dCollideTerrainY(dxGeom *o1, dxGeom *o2, int flags,dContactGeom *contact, int skip); | ||
309 | int dCollideTerrainZ(dxGeom *o1, dxGeom *o2, int flags,dContactGeom *contact, int skip); | ||
310 | |||
311 | int dCollideConePlane (dxGeom *o1, dxGeom *o2, int flags,dContactGeom *contact, int skip); | ||
312 | int dCollideRayCone (dxGeom *o1, dxGeom *o2, int flags,dContactGeom *contact, int skip); | ||
313 | int dCollideConeSphere(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); | ||
314 | int dCollideConeBox(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); | ||
315 | int dCollideCCylinderCone(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); | ||
316 | int dCollideTriMeshCone(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip); | ||
317 | |||
318 | *** add dCone.cpp, dTerrainY.cpp and dTerrainZ.cpp to the the ODE_SRC variable in the makefile | ||
319 | On Linux => add dCone.cpp, dTerrainY.cpp and dTerrainZ.cpp to the the libode_a_SOURCES variable in the ode/src/Makefile.am file. | ||
320 | |||
321 | *** now you can now test using file test_boxstackb.cpp (to add in folder ode\test). | ||
322 | |||
diff --git a/libraries/ode-0.9/contrib/TerrainAndCone/test_boxstackb.cpp b/libraries/ode-0.9/contrib/TerrainAndCone/test_boxstackb.cpp new file mode 100644 index 0000000..f1fa592 --- /dev/null +++ b/libraries/ode-0.9/contrib/TerrainAndCone/test_boxstackb.cpp | |||
@@ -0,0 +1,1375 @@ | |||
1 | /************************************************************************* | ||
2 | |||
3 | |||
4 | * * | ||
5 | |||
6 | |||
7 | * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * | ||
8 | |||
9 | |||
10 | * All rights reserved. Email: russ@q12.org Web: www.q12.org * | ||
11 | |||
12 | |||
13 | * * | ||
14 | |||
15 | |||
16 | * This library is free software; you can redistribute it and/or * | ||
17 | |||
18 | |||
19 | * modify it under the terms of EITHER: * | ||
20 | |||
21 | |||
22 | * (1) The GNU Lesser General Public License as published by the Free * | ||
23 | |||
24 | |||
25 | * Software Foundation; either version 2.1 of the License, or (at * | ||
26 | |||
27 | |||
28 | * your option) any later version. The text of the GNU Lesser * | ||
29 | |||
30 | |||
31 | * General Public License is included with this library in the * | ||
32 | |||
33 | |||
34 | * file LICENSE.TXT. * | ||
35 | |||
36 | |||
37 | * (2) The BSD-style license that is included with this library in * | ||
38 | |||
39 | |||
40 | * the file LICENSE-BSD.TXT. * | ||
41 | |||
42 | |||
43 | * * | ||
44 | |||
45 | |||
46 | * This library is distributed in the hope that it will be useful, * | ||
47 | |||
48 | |||
49 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
50 | |||
51 | |||
52 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * | ||
53 | |||
54 | |||
55 | * LICENSE.TXT and LICENSE-BSD.TXT for more details. * | ||
56 | |||
57 | |||
58 | * * | ||
59 | |||
60 | |||
61 | *************************************************************************/ | ||
62 | |||
63 | |||
64 | |||
65 | |||
66 | |||
67 | #include <ode/ode.h> | ||
68 | |||
69 | |||
70 | #include <drawstuff/drawstuff.h> | ||
71 | |||
72 | |||
73 | |||
74 | |||
75 | |||
76 | #ifdef _MSC_VER | ||
77 | |||
78 | |||
79 | #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints | ||
80 | |||
81 | |||
82 | #endif | ||
83 | |||
84 | |||
85 | |||
86 | |||
87 | |||
88 | // select correct drawing functions | ||
89 | |||
90 | |||
91 | |||
92 | |||
93 | |||
94 | #ifdef dDOUBLE | ||
95 | |||
96 | |||
97 | #define dsDrawBox dsDrawBoxD | ||
98 | |||
99 | |||
100 | #define dsDrawSphere dsDrawSphereD | ||
101 | |||
102 | |||
103 | #define dsDrawCylinder dsDrawCylinderD | ||
104 | |||
105 | |||
106 | #define dsDrawCappedCylinder dsDrawCappedCylinderD | ||
107 | |||
108 | |||
109 | #endif | ||
110 | |||
111 | |||
112 | |||
113 | |||
114 | |||
115 | |||
116 | |||
117 | |||
118 | // some constants | ||
119 | |||
120 | |||
121 | |||
122 | |||
123 | |||
124 | const dReal vTerrainLength = 4.f; | ||
125 | |||
126 | |||
127 | const dReal vTerrainHeight = 0.5f; | ||
128 | |||
129 | |||
130 | const int TERRAINNODES = 4; | ||
131 | |||
132 | |||
133 | dReal pTerrainHeights[TERRAINNODES*TERRAINNODES]; | ||
134 | |||
135 | |||
136 | |||
137 | |||
138 | |||
139 | dGeomID terrainZ = NULL; | ||
140 | |||
141 | |||
142 | dGeomID terrainY = NULL; | ||
143 | |||
144 | |||
145 | |||
146 | |||
147 | |||
148 | #define NUM 20 // max number of objects | ||
149 | |||
150 | |||
151 | #define DENSITY (5.0) // density of all objects | ||
152 | |||
153 | |||
154 | #define GPB 3 // maximum number of geometries per body | ||
155 | |||
156 | |||
157 | #define MAX_CONTACTS 4 // maximum number of contact points per body | ||
158 | |||
159 | |||
160 | |||
161 | |||
162 | |||
163 | |||
164 | |||
165 | |||
166 | // dynamics and collision objects | ||
167 | |||
168 | |||
169 | |||
170 | |||
171 | |||
172 | struct MyObject { | ||
173 | |||
174 | |||
175 | dBodyID body; // the body | ||
176 | |||
177 | |||
178 | dGeomID geom[GPB]; // geometries representing this body | ||
179 | |||
180 | |||
181 | }; | ||
182 | |||
183 | |||
184 | |||
185 | |||
186 | |||
187 | static int num=0; // number of objects in simulation | ||
188 | |||
189 | |||
190 | static int nextobj=0; // next object to recycle if num==NUM | ||
191 | |||
192 | |||
193 | static dWorldID world; | ||
194 | |||
195 | |||
196 | static dSpaceID space; | ||
197 | |||
198 | |||
199 | static MyObject obj[NUM]; | ||
200 | |||
201 | |||
202 | static dJointGroupID contactgroup; | ||
203 | |||
204 | |||
205 | static int selected = -1; // selected object | ||
206 | |||
207 | |||
208 | static int show_aabb = 0; // show geom AABBs? | ||
209 | |||
210 | |||
211 | static int show_contacts = 0; // show contact points? | ||
212 | |||
213 | |||
214 | static int random_pos = 1; // drop objects from random position? | ||
215 | |||
216 | |||
217 | |||
218 | |||
219 | |||
220 | |||
221 | |||
222 | |||
223 | // this is called by dSpaceCollide when two objects in space are | ||
224 | |||
225 | |||
226 | // potentially colliding. | ||
227 | |||
228 | |||
229 | |||
230 | |||
231 | |||
232 | static void nearCallback (void *data, dGeomID o1, dGeomID o2) | ||
233 | |||
234 | |||
235 | { | ||
236 | |||
237 | |||
238 | int i; | ||
239 | |||
240 | |||
241 | // if (o1->body && o2->body) return; | ||
242 | |||
243 | |||
244 | |||
245 | |||
246 | |||
247 | // exit without doing anything if the two bodies are connected by a joint | ||
248 | |||
249 | |||
250 | dBodyID b1 = dGeomGetBody(o1); | ||
251 | |||
252 | |||
253 | dBodyID b2 = dGeomGetBody(o2); | ||
254 | |||
255 | |||
256 | if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return; | ||
257 | |||
258 | |||
259 | |||
260 | |||
261 | |||
262 | dContact contact[MAX_CONTACTS]; // up to MAX_CONTACTS contacts per box-box | ||
263 | |||
264 | |||
265 | for (i=0; i<MAX_CONTACTS; i++) { | ||
266 | |||
267 | |||
268 | contact[i].surface.mode = dContactBounce | dContactApprox1; //dContactSoftCFM; | ||
269 | |||
270 | |||
271 | contact[i].surface.mu = dInfinity; | ||
272 | |||
273 | |||
274 | contact[i].surface.mu2 = 0; | ||
275 | |||
276 | |||
277 | contact[i].surface.bounce = 0.1; | ||
278 | |||
279 | |||
280 | contact[i].surface.bounce_vel = 0.1; | ||
281 | |||
282 | |||
283 | contact[i].surface.soft_cfm = 0.01; | ||
284 | |||
285 | |||
286 | } | ||
287 | |||
288 | |||
289 | if (int numc = dCollide (o1,o2,MAX_CONTACTS,&contact[0].geom, | ||
290 | |||
291 | |||
292 | sizeof(dContact))) { | ||
293 | |||
294 | |||
295 | dMatrix3 RI; | ||
296 | |||
297 | |||
298 | dRSetIdentity (RI); | ||
299 | |||
300 | |||
301 | const dReal ss[3] = {0.02,0.02,0.02}; | ||
302 | |||
303 | |||
304 | for (i=0; i<numc; i++) { | ||
305 | |||
306 | |||
307 | dJointID c = dJointCreateContact (world,contactgroup,contact+i); | ||
308 | |||
309 | |||
310 | dJointAttach (c,b1,b2); | ||
311 | |||
312 | |||
313 | if (show_contacts) dsDrawBox (contact[i].geom.pos,RI,ss); | ||
314 | |||
315 | |||
316 | } | ||
317 | |||
318 | |||
319 | } | ||
320 | |||
321 | |||
322 | } | ||
323 | |||
324 | |||
325 | |||
326 | |||
327 | |||
328 | |||
329 | |||
330 | |||
331 | // start simulation - set viewpoint | ||
332 | |||
333 | |||
334 | |||
335 | |||
336 | |||
337 | static void start() | ||
338 | |||
339 | |||
340 | { | ||
341 | |||
342 | |||
343 | static float xyz[3] = {2.1640f,-1.3079f,1.7600f}; | ||
344 | |||
345 | |||
346 | static float hpr[3] = {125.5000f,-17.0000f,0.0000f}; | ||
347 | |||
348 | |||
349 | dsSetViewpoint (xyz,hpr); | ||
350 | |||
351 | |||
352 | printf ("To drop another object, press:\n"); | ||
353 | |||
354 | |||
355 | printf (" b for box.\n"); | ||
356 | |||
357 | |||
358 | printf (" s for sphere.\n"); | ||
359 | |||
360 | |||
361 | printf (" c for cylinder.\n"); | ||
362 | |||
363 | |||
364 | printf (" x for a composite object.\n"); | ||
365 | |||
366 | |||
367 | printf ("To select an object, press space.\n"); | ||
368 | |||
369 | |||
370 | printf ("To disable the selected object, press d.\n"); | ||
371 | |||
372 | |||
373 | printf ("To enable the selected object, press e.\n"); | ||
374 | |||
375 | |||
376 | printf ("To toggle showing the geom AABBs, press a.\n"); | ||
377 | |||
378 | |||
379 | printf ("To toggle showing the contact points, press t.\n"); | ||
380 | |||
381 | |||
382 | printf ("To toggle dropping from random position/orientation, press r.\n"); | ||
383 | |||
384 | |||
385 | } | ||
386 | |||
387 | |||
388 | |||
389 | |||
390 | |||
391 | |||
392 | |||
393 | |||
394 | char locase (char c) | ||
395 | |||
396 | |||
397 | { | ||
398 | |||
399 | |||
400 | if (c >= 'A' && c <= 'Z') return c - ('a'-'A'); | ||
401 | |||
402 | |||
403 | else return c; | ||
404 | |||
405 | |||
406 | } | ||
407 | |||
408 | |||
409 | |||
410 | |||
411 | |||
412 | |||
413 | |||
414 | |||
415 | // called when a key pressed | ||
416 | |||
417 | |||
418 | |||
419 | |||
420 | |||
421 | static void command (int cmd) | ||
422 | |||
423 | |||
424 | { | ||
425 | |||
426 | |||
427 | int i,j,k; | ||
428 | |||
429 | |||
430 | dReal sides[3]; | ||
431 | |||
432 | |||
433 | dMass m; | ||
434 | |||
435 | |||
436 | |||
437 | |||
438 | |||
439 | cmd = locase (cmd); | ||
440 | |||
441 | |||
442 | if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'x' | ||
443 | |||
444 | |||
445 | /* || cmd == 'l' */) { | ||
446 | |||
447 | |||
448 | if (num < NUM) { | ||
449 | |||
450 | |||
451 | i = num; | ||
452 | |||
453 | |||
454 | num++; | ||
455 | |||
456 | |||
457 | } | ||
458 | |||
459 | |||
460 | else { | ||
461 | |||
462 | |||
463 | i = nextobj; | ||
464 | |||
465 | |||
466 | nextobj++; | ||
467 | |||
468 | |||
469 | if (nextobj >= num) nextobj = 0; | ||
470 | |||
471 | |||
472 | |||
473 | |||
474 | |||
475 | // destroy the body and geoms for slot i | ||
476 | |||
477 | |||
478 | dBodyDestroy (obj[i].body); | ||
479 | |||
480 | |||
481 | for (k=0; k < GPB; k++) { | ||
482 | |||
483 | |||
484 | if (obj[i].geom[k]) dGeomDestroy (obj[i].geom[k]); | ||
485 | |||
486 | |||
487 | } | ||
488 | |||
489 | |||
490 | memset (&obj[i],0,sizeof(obj[i])); | ||
491 | |||
492 | |||
493 | } | ||
494 | |||
495 | |||
496 | |||
497 | |||
498 | |||
499 | obj[i].body = dBodyCreate (world); | ||
500 | |||
501 | |||
502 | for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1; | ||
503 | |||
504 | |||
505 | |||
506 | |||
507 | |||
508 | dMatrix3 R; | ||
509 | |||
510 | |||
511 | if (random_pos) { | ||
512 | |||
513 | |||
514 | dBodySetPosition (obj[i].body, | ||
515 | |||
516 | |||
517 | dRandReal()*2-1,dRandReal()*2+1,dRandReal()+3); | ||
518 | |||
519 | |||
520 | dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0, | ||
521 | |||
522 | |||
523 | dRandReal()*2.0-1.0,dRandReal()*10.0-5.0); | ||
524 | |||
525 | |||
526 | } | ||
527 | |||
528 | |||
529 | else { | ||
530 | |||
531 | |||
532 | dReal maxheight = 0; | ||
533 | |||
534 | |||
535 | for (k=0; k<num; k++) { | ||
536 | |||
537 | |||
538 | const dReal *pos = dBodyGetPosition (obj[k].body); | ||
539 | |||
540 | |||
541 | if (pos[2] > maxheight) maxheight = pos[2]; | ||
542 | |||
543 | |||
544 | } | ||
545 | |||
546 | |||
547 | dBodySetPosition (obj[i].body, 0,maxheight+1,maxheight+3); | ||
548 | |||
549 | |||
550 | dRFromAxisAndAngle (R,0,0,1,dRandReal()*10.0-5.0); | ||
551 | |||
552 | |||
553 | } | ||
554 | |||
555 | |||
556 | dBodySetRotation (obj[i].body,R); | ||
557 | |||
558 | |||
559 | dBodySetData (obj[i].body,(void*) i); | ||
560 | |||
561 | |||
562 | |||
563 | |||
564 | |||
565 | if (cmd == 'b') { | ||
566 | |||
567 | |||
568 | dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]); | ||
569 | |||
570 | |||
571 | obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]); | ||
572 | |||
573 | |||
574 | } | ||
575 | |||
576 | |||
577 | else if (cmd == 'c') { | ||
578 | |||
579 | |||
580 | sides[0] *= 0.5; | ||
581 | |||
582 | |||
583 | dMassSetCappedCylinder (&m,DENSITY,3,sides[0],sides[1]); | ||
584 | |||
585 | |||
586 | obj[i].geom[0] = dCreateCCylinder (space,sides[0],sides[1]); | ||
587 | |||
588 | |||
589 | } | ||
590 | |||
591 | |||
592 | /* | ||
593 | |||
594 | |||
595 | // cylinder option not yet implemented | ||
596 | |||
597 | |||
598 | else if (cmd == 'l') { | ||
599 | |||
600 | |||
601 | sides[1] *= 0.5; | ||
602 | |||
603 | |||
604 | dMassSetCappedCylinder (&m,DENSITY,3,sides[0],sides[1]); | ||
605 | |||
606 | |||
607 | obj[i].geom[0] = dCreateCylinder (space,sides[0],sides[1]); | ||
608 | |||
609 | |||
610 | } | ||
611 | |||
612 | |||
613 | */ | ||
614 | |||
615 | |||
616 | else if (cmd == 's') { | ||
617 | |||
618 | |||
619 | sides[0] *= 0.5; | ||
620 | |||
621 | |||
622 | dMassSetSphere (&m,DENSITY,sides[0]); | ||
623 | |||
624 | |||
625 | obj[i].geom[0] = dCreateSphere (space,sides[0]); | ||
626 | |||
627 | |||
628 | } | ||
629 | |||
630 | |||
631 | else if (cmd == 'x') { | ||
632 | |||
633 | |||
634 | dGeomID g2[GPB]; // encapsulated geometries | ||
635 | |||
636 | |||
637 | dReal dpos[GPB][3]; // delta-positions for encapsulated geometries | ||
638 | |||
639 | |||
640 | |||
641 | |||
642 | |||
643 | // start accumulating masses for the encapsulated geometries | ||
644 | |||
645 | |||
646 | dMass m2; | ||
647 | |||
648 | |||
649 | dMassSetZero (&m); | ||
650 | |||
651 | |||
652 | |||
653 | |||
654 | |||
655 | // set random delta positions | ||
656 | |||
657 | |||
658 | for (j=0; j<GPB; j++) { | ||
659 | |||
660 | |||
661 | for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15; | ||
662 | |||
663 | |||
664 | } | ||
665 | |||
666 | |||
667 | |||
668 | |||
669 | |||
670 | for (k=0; k<GPB; k++) { | ||
671 | |||
672 | |||
673 | obj[i].geom[k] = dCreateGeomTransform (space); | ||
674 | |||
675 | |||
676 | dGeomTransformSetCleanup (obj[i].geom[k],1); | ||
677 | |||
678 | |||
679 | if (k==0) { | ||
680 | |||
681 | |||
682 | dReal radius = dRandReal()*0.25+0.05; | ||
683 | |||
684 | |||
685 | g2[k] = dCreateSphere (0,radius); | ||
686 | |||
687 | |||
688 | dMassSetSphere (&m2,DENSITY,radius); | ||
689 | |||
690 | |||
691 | } | ||
692 | |||
693 | |||
694 | else if (k==1) { | ||
695 | |||
696 | |||
697 | g2[k] = dCreateBox (0,sides[0],sides[1],sides[2]); | ||
698 | |||
699 | |||
700 | dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]); | ||
701 | |||
702 | |||
703 | } | ||
704 | |||
705 | |||
706 | else { | ||
707 | |||
708 | |||
709 | dReal radius = dRandReal()*0.1+0.05; | ||
710 | |||
711 | |||
712 | dReal length = dRandReal()*1.0+0.1; | ||
713 | |||
714 | |||
715 | g2[k] = dCreateCCylinder (0,radius,length); | ||
716 | |||
717 | |||
718 | dMassSetCappedCylinder (&m2,DENSITY,3,radius,length); | ||
719 | |||
720 | |||
721 | } | ||
722 | |||
723 | |||
724 | dGeomTransformSetGeom (obj[i].geom[k],g2[k]); | ||
725 | |||
726 | |||
727 | |||
728 | |||
729 | |||
730 | // set the transformation (adjust the mass too) | ||
731 | |||
732 | |||
733 | dGeomSetPosition (g2[k],dpos[k][0],dpos[k][1],dpos[k][2]); | ||
734 | |||
735 | |||
736 | dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]); | ||
737 | |||
738 | |||
739 | dMatrix3 Rtx; | ||
740 | |||
741 | |||
742 | dRFromAxisAndAngle (Rtx,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0, | ||
743 | |||
744 | |||
745 | dRandReal()*2.0-1.0,dRandReal()*10.0-5.0); | ||
746 | |||
747 | |||
748 | dGeomSetRotation (g2[k],Rtx); | ||
749 | |||
750 | |||
751 | dMassRotate (&m2,Rtx); | ||
752 | |||
753 | |||
754 | |||
755 | |||
756 | |||
757 | // add to the total mass | ||
758 | |||
759 | |||
760 | dMassAdd (&m,&m2); | ||
761 | |||
762 | |||
763 | } | ||
764 | |||
765 | |||
766 | |||
767 | |||
768 | |||
769 | // move all encapsulated objects so that the center of mass is (0,0,0) | ||
770 | |||
771 | |||
772 | for (k=0; k<2; k++) { | ||
773 | |||
774 | |||
775 | dGeomSetPosition (g2[k], | ||
776 | |||
777 | |||
778 | dpos[k][0]-m.c[0], | ||
779 | |||
780 | |||
781 | dpos[k][1]-m.c[1], | ||
782 | |||
783 | |||
784 | dpos[k][2]-m.c[2]); | ||
785 | |||
786 | |||
787 | } | ||
788 | |||
789 | |||
790 | dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]); | ||
791 | |||
792 | |||
793 | } | ||
794 | |||
795 | |||
796 | |||
797 | |||
798 | |||
799 | for (k=0; k < GPB; k++) { | ||
800 | |||
801 | |||
802 | if (obj[i].geom[k]) dGeomSetBody (obj[i].geom[k],obj[i].body); | ||
803 | |||
804 | |||
805 | } | ||
806 | |||
807 | |||
808 | |||
809 | |||
810 | |||
811 | dBodySetMass (obj[i].body,&m); | ||
812 | |||
813 | |||
814 | } | ||
815 | |||
816 | |||
817 | |||
818 | |||
819 | |||
820 | if (cmd == ' ') { | ||
821 | |||
822 | |||
823 | selected++; | ||
824 | |||
825 | |||
826 | if (selected >= num) selected = 0; | ||
827 | |||
828 | |||
829 | if (selected < 0) selected = 0; | ||
830 | |||
831 | |||
832 | } | ||
833 | |||
834 | |||
835 | else if (cmd == 'd' && selected >= 0 && selected < num) { | ||
836 | |||
837 | |||
838 | dBodyDisable (obj[selected].body); | ||
839 | |||
840 | |||
841 | } | ||
842 | |||
843 | |||
844 | else if (cmd == 'e' && selected >= 0 && selected < num) { | ||
845 | |||
846 | |||
847 | dBodyEnable (obj[selected].body); | ||
848 | |||
849 | |||
850 | } | ||
851 | |||
852 | |||
853 | else if (cmd == 'a') { | ||
854 | |||
855 | |||
856 | show_aabb ^= 1; | ||
857 | |||
858 | |||
859 | } | ||
860 | |||
861 | |||
862 | else if (cmd == 't') { | ||
863 | |||
864 | |||
865 | show_contacts ^= 1; | ||
866 | |||
867 | |||
868 | } | ||
869 | |||
870 | |||
871 | else if (cmd == 'r') { | ||
872 | |||
873 | |||
874 | random_pos ^= 1; | ||
875 | |||
876 | |||
877 | } | ||
878 | |||
879 | |||
880 | } | ||
881 | |||
882 | |||
883 | |||
884 | |||
885 | |||
886 | |||
887 | |||
888 | |||
889 | // draw a geom | ||
890 | |||
891 | |||
892 | |||
893 | |||
894 | |||
895 | void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb) | ||
896 | |||
897 | |||
898 | { | ||
899 | |||
900 | |||
901 | int i; | ||
902 | |||
903 | |||
904 | |||
905 | |||
906 | |||
907 | if (!g) return; | ||
908 | |||
909 | |||
910 | if (!pos) pos = dGeomGetPosition (g); | ||
911 | |||
912 | |||
913 | if (!R) R = dGeomGetRotation (g); | ||
914 | |||
915 | |||
916 | |||
917 | |||
918 | |||
919 | int type = dGeomGetClass (g); | ||
920 | |||
921 | |||
922 | if (type == dBoxClass) { | ||
923 | |||
924 | |||
925 | dVector3 sides; | ||
926 | |||
927 | |||
928 | dGeomBoxGetLengths (g,sides); | ||
929 | |||
930 | |||
931 | dsDrawBox (pos,R,sides); | ||
932 | |||
933 | |||
934 | } | ||
935 | |||
936 | |||
937 | else if (type == dSphereClass) { | ||
938 | |||
939 | |||
940 | dsDrawSphere (pos,R,dGeomSphereGetRadius (g)); | ||
941 | |||
942 | |||
943 | } | ||
944 | |||
945 | |||
946 | else if (type == dCCylinderClass) { | ||
947 | |||
948 | |||
949 | dReal radius,length; | ||
950 | |||
951 | |||
952 | dGeomCCylinderGetParams (g,&radius,&length); | ||
953 | |||
954 | |||
955 | dsDrawCappedCylinder (pos,R,length,radius); | ||
956 | |||
957 | |||
958 | } | ||
959 | |||
960 | |||
961 | /* | ||
962 | |||
963 | |||
964 | // cylinder option not yet implemented | ||
965 | |||
966 | |||
967 | else if (type == dCylinderClass) { | ||
968 | |||
969 | |||
970 | dReal radius,length; | ||
971 | |||
972 | |||
973 | dGeomCylinderGetParams (g,&radius,&length); | ||
974 | |||
975 | |||
976 | dsDrawCylinder (pos,R,length,radius); | ||
977 | |||
978 | |||
979 | } | ||
980 | |||
981 | |||
982 | */ | ||
983 | |||
984 | |||
985 | else if (type == dGeomTransformClass) { | ||
986 | |||
987 | |||
988 | dGeomID g2 = dGeomTransformGetGeom (g); | ||
989 | |||
990 | |||
991 | const dReal *pos2 = dGeomGetPosition (g2); | ||
992 | |||
993 | |||
994 | const dReal *R2 = dGeomGetRotation (g2); | ||
995 | |||
996 | |||
997 | dVector3 actual_pos; | ||
998 | |||
999 | |||
1000 | dMatrix3 actual_R; | ||
1001 | |||
1002 | |||
1003 | dMULTIPLY0_331 (actual_pos,R,pos2); | ||
1004 | |||
1005 | |||
1006 | actual_pos[0] += pos[0]; | ||
1007 | |||
1008 | |||
1009 | actual_pos[1] += pos[1]; | ||
1010 | |||
1011 | |||
1012 | actual_pos[2] += pos[2]; | ||
1013 | |||
1014 | |||
1015 | dMULTIPLY0_333 (actual_R,R,R2); | ||
1016 | |||
1017 | |||
1018 | drawGeom (g2,actual_pos,actual_R,0); | ||
1019 | |||
1020 | |||
1021 | } | ||
1022 | |||
1023 | |||
1024 | |||
1025 | |||
1026 | |||
1027 | if (show_aabb) { | ||
1028 | |||
1029 | |||
1030 | // draw the bounding box for this geom | ||
1031 | |||
1032 | |||
1033 | dReal aabb[6]; | ||
1034 | |||
1035 | |||
1036 | dGeomGetAABB (g,aabb); | ||
1037 | |||
1038 | |||
1039 | dVector3 bbpos; | ||
1040 | |||
1041 | |||
1042 | for (i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]); | ||
1043 | |||
1044 | |||
1045 | dVector3 bbsides; | ||
1046 | |||
1047 | |||
1048 | for (i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2]; | ||
1049 | |||
1050 | |||
1051 | dMatrix3 RI; | ||
1052 | |||
1053 | |||
1054 | dRSetIdentity (RI); | ||
1055 | |||
1056 | |||
1057 | dsSetColorAlpha (1,0,0,0.5); | ||
1058 | |||
1059 | |||
1060 | dsDrawBox (bbpos,RI,bbsides); | ||
1061 | |||
1062 | |||
1063 | } | ||
1064 | |||
1065 | |||
1066 | } | ||
1067 | |||
1068 | |||
1069 | |||
1070 | |||
1071 | |||
1072 | |||
1073 | |||
1074 | |||
1075 | // simulation loop | ||
1076 | |||
1077 | |||
1078 | |||
1079 | |||
1080 | |||
1081 | static void simLoop (int pause) | ||
1082 | |||
1083 | |||
1084 | { | ||
1085 | |||
1086 | |||
1087 | dsSetColor (0,0,2); | ||
1088 | |||
1089 | |||
1090 | dSpaceCollide (space,0,&nearCallback); | ||
1091 | |||
1092 | |||
1093 | if (!pause) dWorldStep (world,0.05); | ||
1094 | |||
1095 | |||
1096 | |||
1097 | |||
1098 | |||
1099 | dAASSERT(terrainY); | ||
1100 | |||
1101 | |||
1102 | dAASSERT(terrainZ); | ||
1103 | |||
1104 | |||
1105 | dsSetColor (0,1,0); | ||
1106 | |||
1107 | |||
1108 | dsDrawTerrainY(0,0,vTerrainLength,vTerrainLength/TERRAINNODES,TERRAINNODES,pTerrainHeights,dGeomGetRotation(terrainY),dGeomGetPosition(terrainY)); | ||
1109 | |||
1110 | |||
1111 | dsDrawTerrainZ(0,0,vTerrainLength,vTerrainLength/TERRAINNODES,TERRAINNODES,pTerrainHeights,dGeomGetRotation(terrainZ),dGeomGetPosition(terrainZ)); | ||
1112 | |||
1113 | |||
1114 | |||
1115 | |||
1116 | |||
1117 | if (show_aabb) | ||
1118 | |||
1119 | |||
1120 | { | ||
1121 | |||
1122 | |||
1123 | dReal aabb[6]; | ||
1124 | |||
1125 | |||
1126 | dGeomGetAABB (terrainY,aabb); | ||
1127 | |||
1128 | |||
1129 | dVector3 bbpos; | ||
1130 | |||
1131 | |||
1132 | int i; | ||
1133 | |||
1134 | |||
1135 | for (i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]); | ||
1136 | |||
1137 | |||
1138 | dVector3 bbsides; | ||
1139 | |||
1140 | |||
1141 | for (i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2]; | ||
1142 | |||
1143 | |||
1144 | dMatrix3 RI; | ||
1145 | |||
1146 | |||
1147 | dRSetIdentity (RI); | ||
1148 | |||
1149 | |||
1150 | dsSetColorAlpha (1,0,0,0.5); | ||
1151 | |||
1152 | |||
1153 | dsDrawBox (bbpos,RI,bbsides); | ||
1154 | |||
1155 | |||
1156 | |||
1157 | |||
1158 | |||
1159 | dGeomGetAABB (terrainZ,aabb); | ||
1160 | |||
1161 | |||
1162 | for (i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]); | ||
1163 | |||
1164 | |||
1165 | for (i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2]; | ||
1166 | |||
1167 | |||
1168 | dsDrawBox (bbpos,RI,bbsides); | ||
1169 | |||
1170 | |||
1171 | } | ||
1172 | |||
1173 | |||
1174 | |||
1175 | |||
1176 | |||
1177 | dsSetColor (1,1,0); | ||
1178 | |||
1179 | |||
1180 | |||
1181 | |||
1182 | |||
1183 | // remove all contact joints | ||
1184 | |||
1185 | |||
1186 | dJointGroupEmpty (contactgroup); | ||
1187 | |||
1188 | |||
1189 | |||
1190 | |||
1191 | |||
1192 | dsSetColor (1,1,0); | ||
1193 | |||
1194 | |||
1195 | dsSetTexture (DS_WOOD); | ||
1196 | |||
1197 | |||
1198 | for (int i=0; i<num; i++) { | ||
1199 | |||
1200 | |||
1201 | for (int j=0; j < GPB; j++) { | ||
1202 | |||
1203 | |||
1204 | if (i==selected) { | ||
1205 | |||
1206 | |||
1207 | dsSetColor (0,0.7,1); | ||
1208 | |||
1209 | |||
1210 | } | ||
1211 | |||
1212 | |||
1213 | else if (! dBodyIsEnabled (obj[i].body)) { | ||
1214 | |||
1215 | |||
1216 | dsSetColor (1,0,0); | ||
1217 | |||
1218 | |||
1219 | } | ||
1220 | |||
1221 | |||
1222 | else { | ||
1223 | |||
1224 | |||
1225 | dsSetColor (1,1,0); | ||
1226 | |||
1227 | |||
1228 | } | ||
1229 | |||
1230 | |||
1231 | drawGeom (obj[i].geom[j],0,0,show_aabb); | ||
1232 | |||
1233 | |||
1234 | } | ||
1235 | |||
1236 | |||
1237 | } | ||
1238 | |||
1239 | |||
1240 | } | ||
1241 | |||
1242 | |||
1243 | |||
1244 | |||
1245 | |||
1246 | |||
1247 | |||
1248 | |||
1249 | int main (int argc, char **argv) | ||
1250 | |||
1251 | |||
1252 | { | ||
1253 | |||
1254 | |||
1255 | // setup pointers to drawstuff callback functions | ||
1256 | |||
1257 | |||
1258 | dsFunctions fn; | ||
1259 | |||
1260 | |||
1261 | fn.version = DS_VERSION; | ||
1262 | |||
1263 | |||
1264 | fn.start = &start; | ||
1265 | |||
1266 | |||
1267 | fn.step = &simLoop; | ||
1268 | |||
1269 | |||
1270 | fn.command = &command; | ||
1271 | |||
1272 | |||
1273 | fn.stop = 0; | ||
1274 | |||
1275 | |||
1276 | fn.path_to_textures = "../../drawstuff/textures"; | ||
1277 | |||
1278 | |||
1279 | if(argc==2) | ||
1280 | { | ||
1281 | fn.path_to_textures = argv[1]; | ||
1282 | } | ||
1283 | |||
1284 | |||
1285 | |||
1286 | // create world | ||
1287 | |||
1288 | |||
1289 | |||
1290 | |||
1291 | |||
1292 | world = dWorldCreate(); | ||
1293 | |||
1294 | |||
1295 | space = dHashSpaceCreate (0); | ||
1296 | |||
1297 | |||
1298 | contactgroup = dJointGroupCreate (0); | ||
1299 | |||
1300 | |||
1301 | dWorldSetGravity (world,0,0,-0.5); //-0.5 | ||
1302 | |||
1303 | |||
1304 | dWorldSetCFM (world,1e-5); | ||
1305 | |||
1306 | |||
1307 | dCreatePlane (space,0,0,1,0); | ||
1308 | |||
1309 | |||
1310 | memset (obj,0,sizeof(obj)); | ||
1311 | |||
1312 | |||
1313 | |||
1314 | |||
1315 | |||
1316 | for (int i=0;i<TERRAINNODES*TERRAINNODES;i++) pTerrainHeights[i] = vTerrainHeight * dRandReal(); | ||
1317 | |||
1318 | |||
1319 | terrainY = dCreateTerrainY(space,pTerrainHeights,vTerrainLength,TERRAINNODES,1,1); | ||
1320 | |||
1321 | |||
1322 | terrainZ = dCreateTerrainZ(space,pTerrainHeights,vTerrainLength,TERRAINNODES,1,1); | ||
1323 | |||
1324 | |||
1325 | |||
1326 | |||
1327 | |||
1328 | dMatrix3 R; | ||
1329 | |||
1330 | |||
1331 | dRFromZAxis(R, 0.2f, 0.2f, 0.2f); | ||
1332 | |||
1333 | |||
1334 | dGeomSetPosition(terrainY,0.f,0.f,0.5f); | ||
1335 | |||
1336 | |||
1337 | dGeomSetRotation(terrainY,R); | ||
1338 | |||
1339 | |||
1340 | dGeomSetPosition(terrainZ,0.f,0.f,0.5f); | ||
1341 | |||
1342 | |||
1343 | dGeomSetRotation(terrainZ,R); | ||
1344 | |||
1345 | |||
1346 | |||
1347 | |||
1348 | |||
1349 | // run simulation | ||
1350 | |||
1351 | |||
1352 | dsSimulationLoop (argc,argv,352,288,&fn); | ||
1353 | |||
1354 | |||
1355 | |||
1356 | |||
1357 | |||
1358 | dJointGroupDestroy (contactgroup); | ||
1359 | |||
1360 | |||
1361 | dSpaceDestroy (space); | ||
1362 | |||
1363 | |||
1364 | dWorldDestroy (world); | ||
1365 | |||
1366 | |||
1367 | |||
1368 | |||
1369 | |||
1370 | return 0; | ||
1371 | |||
1372 | |||
1373 | } | ||
1374 | |||
1375 | |||
diff --git a/libraries/ode-0.9/contrib/dCylinder/dCylinder.cpp b/libraries/ode-0.9/contrib/dCylinder/dCylinder.cpp new file mode 100644 index 0000000..215da25 --- /dev/null +++ b/libraries/ode-0.9/contrib/dCylinder/dCylinder.cpp | |||
@@ -0,0 +1,1445 @@ | |||
1 | #include <ode/ode.h> | ||
2 | #include "dCylinder.h" | ||
3 | // given a pointer `p' to a dContactGeom, return the dContactGeom at | ||
4 | // p + skip bytes. | ||
5 | |||
6 | struct dxCylinder { // cylinder | ||
7 | dReal radius,lz; // radius, length along y axis // | ||
8 | }; | ||
9 | |||
10 | int dCylinderClassUser = -1; | ||
11 | |||
12 | #define NUMC_MASK (0xffff) | ||
13 | |||
14 | #define CONTACT(p,skip) ((dContactGeom*) (((char*)p) + (skip))) | ||
15 | |||
16 | ///////////////////////////////////////////////////////////////////////////////////////////////// | ||
17 | /////////////////////////////circleIntersection////////////////////////////////////////////////// | ||
18 | //this does following: | ||
19 | //takes two circles as normals to planes n1,n2, center points cp1,cp2,and radiuses r1,r2 | ||
20 | //finds line on which circles' planes intersect | ||
21 | //finds four points O1,O2 - intersection between the line and sphere with center cp1 radius r1 | ||
22 | // O3,O4 - intersection between the line and sphere with center cp2 radius r2 | ||
23 | //returns false if there is no intersection | ||
24 | //computes distances O1-O3, O1-O4, O2-O3, O2-O4 | ||
25 | //in "point" returns mean point between intersection points with smallest distance | ||
26 | ///////////////////////////////////////////////////////////////////////////////////////////////// | ||
27 | inline bool circleIntersection(const dReal* n1,const dReal* cp1,dReal r1,const dReal* n2,const dReal* cp2,dReal r2,dVector3 point){ | ||
28 | dReal c1=dDOT14(cp1,n1); | ||
29 | dReal c2=dDOT14(cp2,n2); | ||
30 | dReal cos=dDOT44(n1,n2); | ||
31 | dReal cos_2=cos*cos; | ||
32 | dReal sin_2=1-cos_2; | ||
33 | dReal p1=(c1-c2*cos)/sin_2; | ||
34 | dReal p2=(c2-c1*cos)/sin_2; | ||
35 | dVector3 lp={p1*n1[0]+p2*n2[0],p1*n1[4]+p2*n2[4],p1*n1[8]+p2*n2[8]}; | ||
36 | dVector3 n; | ||
37 | dCROSS144(n,=,n1,n2); | ||
38 | dVector3 LC1={lp[0]-cp1[0],lp[1]-cp1[1],lp[2]-cp1[2]}; | ||
39 | dVector3 LC2={lp[0]-cp2[0],lp[1]-cp2[1],lp[2]-cp2[2]}; | ||
40 | dReal A,B,C,B_A,B_A_2,D; | ||
41 | dReal t1,t2,t3,t4; | ||
42 | A=dDOT(n,n); | ||
43 | B=dDOT(LC1,n); | ||
44 | C=dDOT(LC1,LC1)-r1*r1; | ||
45 | B_A=B/A; | ||
46 | B_A_2=B_A*B_A; | ||
47 | D=B_A_2-C; | ||
48 | if(D<0.f){ //somewhat strange solution | ||
49 | //- it is needed to set some | ||
50 | //axis to sepparate cylinders | ||
51 | //when their edges approach | ||
52 | t1=-B_A+sqrtf(-D); | ||
53 | t2=-B_A-sqrtf(-D); | ||
54 | // return false; | ||
55 | } | ||
56 | else{ | ||
57 | t1=-B_A-sqrtf(D); | ||
58 | t2=-B_A+sqrtf(D); | ||
59 | } | ||
60 | B=dDOT(LC2,n); | ||
61 | C=dDOT(LC2,LC2)-r2*r2; | ||
62 | B_A=B/A; | ||
63 | B_A_2=B_A*B_A; | ||
64 | D=B_A_2-C; | ||
65 | |||
66 | if(D<0.f) { | ||
67 | t3=-B_A+sqrtf(-D); | ||
68 | t4=-B_A-sqrtf(-D); | ||
69 | // return false; | ||
70 | } | ||
71 | else{ | ||
72 | t3=-B_A-sqrtf(D); | ||
73 | t4=-B_A+sqrtf(D); | ||
74 | } | ||
75 | dVector3 O1={lp[0]+n[0]*t1,lp[1]+n[1]*t1,lp[2]+n[2]*t1}; | ||
76 | dVector3 O2={lp[0]+n[0]*t2,lp[1]+n[1]*t2,lp[2]+n[2]*t2}; | ||
77 | |||
78 | dVector3 O3={lp[0]+n[0]*t3,lp[1]+n[1]*t3,lp[2]+n[2]*t3}; | ||
79 | dVector3 O4={lp[0]+n[0]*t4,lp[1]+n[1]*t4,lp[2]+n[2]*t4}; | ||
80 | |||
81 | dVector3 L1_3={O3[0]-O1[0],O3[1]-O1[1],O3[2]-O1[2]}; | ||
82 | dVector3 L1_4={O4[0]-O1[0],O4[1]-O1[1],O4[2]-O1[2]}; | ||
83 | |||
84 | dVector3 L2_3={O3[0]-O2[0],O3[1]-O2[1],O3[2]-O2[2]}; | ||
85 | dVector3 L2_4={O4[0]-O2[0],O4[1]-O2[1],O4[2]-O2[2]}; | ||
86 | |||
87 | |||
88 | dReal l1_3=dDOT(L1_3,L1_3); | ||
89 | dReal l1_4=dDOT(L1_4,L1_4); | ||
90 | |||
91 | dReal l2_3=dDOT(L2_3,L2_3); | ||
92 | dReal l2_4=dDOT(L2_4,L2_4); | ||
93 | |||
94 | |||
95 | if (l1_3<l1_4) | ||
96 | if(l2_3<l2_4) | ||
97 | if(l1_3<l2_3) | ||
98 | { | ||
99 | //l1_3; | ||
100 | point[0]=0.5f*(O1[0]+O3[0]); | ||
101 | point[1]=0.5f*(O1[1]+O3[1]); | ||
102 | point[2]=0.5f*(O1[2]+O3[2]); | ||
103 | } | ||
104 | else{ | ||
105 | //l2_3; | ||
106 | point[0]=0.5f*(O2[0]+O3[0]); | ||
107 | point[1]=0.5f*(O2[1]+O3[1]); | ||
108 | point[2]=0.5f*(O2[2]+O3[2]); | ||
109 | } | ||
110 | else | ||
111 | if(l1_3<l2_4) | ||
112 | { | ||
113 | //l1_3; | ||
114 | point[0]=0.5f*(O1[0]+O3[0]); | ||
115 | point[1]=0.5f*(O1[1]+O3[1]); | ||
116 | point[2]=0.5f*(O1[2]+O3[2]); | ||
117 | } | ||
118 | else{ | ||
119 | //l2_4; | ||
120 | point[0]=0.5f*(O2[0]+O4[0]); | ||
121 | point[1]=0.5f*(O2[1]+O4[1]); | ||
122 | point[2]=0.5f*(O2[2]+O4[2]); | ||
123 | } | ||
124 | |||
125 | else | ||
126 | if(l2_3<l2_4) | ||
127 | if(l1_4<l2_3) | ||
128 | { | ||
129 | //l1_4; | ||
130 | point[0]=0.5f*(O1[0]+O4[0]); | ||
131 | point[1]=0.5f*(O1[1]+O4[1]); | ||
132 | point[2]=0.5f*(O1[2]+O4[2]); | ||
133 | } | ||
134 | else{ | ||
135 | //l2_3; | ||
136 | point[0]=0.5f*(O2[0]+O3[0]); | ||
137 | point[1]=0.5f*(O2[1]+O3[1]); | ||
138 | point[2]=0.5f*(O2[2]+O3[2]); | ||
139 | } | ||
140 | else | ||
141 | if(l1_4<l2_4) | ||
142 | { | ||
143 | //l1_4; | ||
144 | point[0]=0.5f*(O1[0]+O4[0]); | ||
145 | point[1]=0.5f*(O1[1]+O4[1]); | ||
146 | point[2]=0.5f*(O1[2]+O4[2]); | ||
147 | } | ||
148 | else{ | ||
149 | //l2_4; | ||
150 | point[0]=0.5f*(O2[0]+O4[0]); | ||
151 | point[1]=0.5f*(O2[1]+O4[1]); | ||
152 | point[2]=0.5f*(O2[2]+O4[2]); | ||
153 | } | ||
154 | |||
155 | return true; | ||
156 | } | ||
157 | |||
158 | |||
159 | |||
160 | |||
161 | void lineClosestApproach (const dVector3 pa, const dVector3 ua, | ||
162 | const dVector3 pb, const dVector3 ub, | ||
163 | dReal *alpha, dReal *beta) | ||
164 | { | ||
165 | dVector3 p; | ||
166 | p[0] = pb[0] - pa[0]; | ||
167 | p[1] = pb[1] - pa[1]; | ||
168 | p[2] = pb[2] - pa[2]; | ||
169 | dReal uaub = dDOT(ua,ub); | ||
170 | dReal q1 = dDOT(ua,p); | ||
171 | dReal q2 = -dDOT(ub,p); | ||
172 | dReal d = 1-uaub*uaub; | ||
173 | if (d <= 0) { | ||
174 | // @@@ this needs to be made more robust | ||
175 | *alpha = 0; | ||
176 | *beta = 0; | ||
177 | } | ||
178 | else { | ||
179 | d = dRecip(d); | ||
180 | *alpha = (q1 + uaub*q2)*d; | ||
181 | *beta = (uaub*q1 + q2)*d; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | |||
186 | // @@@ some stuff to optimize here, reuse code in contact point calculations. | ||
187 | |||
188 | extern "C" int dCylBox (const dVector3 p1, const dMatrix3 R1, | ||
189 | const dReal radius,const dReal lz, const dVector3 p2, | ||
190 | const dMatrix3 R2, const dVector3 side2, | ||
191 | dVector3 normal, dReal *depth, int *code, | ||
192 | int maxc, dContactGeom *contact, int skip) | ||
193 | { | ||
194 | dVector3 p,pp,normalC; | ||
195 | const dReal *normalR = 0; | ||
196 | dReal B1,B2,B3,R11,R12,R13,R21,R22,R23,R31,R32,R33, | ||
197 | Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l,sQ21,sQ22,sQ23; | ||
198 | int i,invert_normal; | ||
199 | |||
200 | // get vector from centers of box 1 to box 2, relative to box 1 | ||
201 | p[0] = p2[0] - p1[0]; | ||
202 | p[1] = p2[1] - p1[1]; | ||
203 | p[2] = p2[2] - p1[2]; | ||
204 | dMULTIPLY1_331 (pp,R1,p); // get pp = p relative to body 1 | ||
205 | |||
206 | // get side lengths / 2 | ||
207 | //A1 =radius; A2 = lz*REAL(0.5); A3 = radius; | ||
208 | dReal hlz=lz/2.f; | ||
209 | B1 = side2[0]*REAL(0.5); B2 = side2[1]*REAL(0.5); B3 = side2[2]*REAL(0.5); | ||
210 | |||
211 | // Rij is R1'*R2, i.e. the relative rotation between R1 and R2 | ||
212 | R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2); | ||
213 | R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2); | ||
214 | R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2); | ||
215 | |||
216 | Q11 = dFabs(R11); Q12 = dFabs(R12); Q13 = dFabs(R13); | ||
217 | Q21 = dFabs(R21); Q22 = dFabs(R22); Q23 = dFabs(R23); | ||
218 | Q31 = dFabs(R31); Q32 = dFabs(R32); Q33 = dFabs(R33); | ||
219 | |||
220 | |||
221 | // * see if the axis separates the box with cylinder. if so, return 0. | ||
222 | // * find the depth of the penetration along the separating axis (s2) | ||
223 | // * if this is the largest depth so far, record it. | ||
224 | // the normal vector will be set to the separating axis with the smallest | ||
225 | // depth. note: normalR is set to point to a column of R1 or R2 if that is | ||
226 | // the smallest depth normal so far. otherwise normalR is 0 and normalC is | ||
227 | // set to a vector relative to body 1. invert_normal is 1 if the sign of | ||
228 | // the normal should be flipped. | ||
229 | |||
230 | #define TEST(expr1,expr2,norm,cc) \ | ||
231 | s2 = dFabs(expr1) - (expr2); \ | ||
232 | if (s2 > 0) return 0; \ | ||
233 | if (s2 > s) { \ | ||
234 | s = s2; \ | ||
235 | normalR = norm; \ | ||
236 | invert_normal = ((expr1) < 0); \ | ||
237 | *code = (cc); \ | ||
238 | } | ||
239 | |||
240 | s = -dInfinity; | ||
241 | invert_normal = 0; | ||
242 | *code = 0; | ||
243 | |||
244 | // separating axis = cylinder ax u2 | ||
245 | //used when a box vertex touches a flat face of the cylinder | ||
246 | TEST (pp[1],(hlz + B1*Q21 + B2*Q22 + B3*Q23),R1+1,0); | ||
247 | |||
248 | |||
249 | // separating axis = box axis v1,v2,v3 | ||
250 | //used when cylinder edge touches box face | ||
251 | //there is two ways to compute sQ: sQ21=sqrtf(1.f-Q21*Q21); or sQ21=sqrtf(Q23*Q23+Q22*Q22); | ||
252 | //if we did not need Q23 and Q22 the first way might be used to quiken the routine but then it need to | ||
253 | //check if Q21<=1.f, becouse it may slightly exeed 1.f. | ||
254 | |||
255 | |||
256 | sQ21=sqrtf(Q23*Q23+Q22*Q22); | ||
257 | TEST (dDOT41(R2+0,p),(radius*sQ21 + hlz*Q21 + B1),R2+0,1); | ||
258 | |||
259 | sQ22=sqrtf(Q23*Q23+Q21*Q21); | ||
260 | TEST (dDOT41(R2+1,p),(radius*sQ22 + hlz*Q22 + B2),R2+1,2); | ||
261 | |||
262 | sQ23=sqrtf(Q22*Q22+Q21*Q21); | ||
263 | TEST (dDOT41(R2+2,p),(radius*sQ23 + hlz*Q23 + B3),R2+2,3); | ||
264 | |||
265 | |||
266 | #undef TEST | ||
267 | #define TEST(expr1,expr2,n1,n2,n3,cc) \ | ||
268 | s2 = dFabs(expr1) - (expr2); \ | ||
269 | if (s2 > 0) return 0; \ | ||
270 | if (s2 > s) { \ | ||
271 | s = s2; \ | ||
272 | normalR = 0; \ | ||
273 | normalC[0] = (n1); normalC[1] = (n2); normalC[2] = (n3); \ | ||
274 | invert_normal = ((expr1) < 0); \ | ||
275 | *code = (cc); \ | ||
276 | } | ||
277 | |||
278 | |||
279 | |||
280 | // separating axis is a normal to the cylinder axis passing across the nearest box vertex | ||
281 | //used when a box vertex touches the lateral surface of the cylinder | ||
282 | |||
283 | dReal proj,boxProj,cos,sin,cos1,cos3; | ||
284 | dVector3 tAx,Ax,pb; | ||
285 | { | ||
286 | //making Ax which is perpendicular to cyl ax to box position// | ||
287 | proj=dDOT14(p2,R1+1)-dDOT14(p1,R1+1); | ||
288 | |||
289 | Ax[0]=p2[0]-p1[0]-R1[1]*proj; | ||
290 | Ax[1]=p2[1]-p1[1]-R1[5]*proj; | ||
291 | Ax[2]=p2[2]-p1[2]-R1[9]*proj; | ||
292 | dNormalize3(Ax); | ||
293 | //using Ax find box vertex which is nearest to the cylinder axis | ||
294 | dReal sign; | ||
295 | |||
296 | for (i=0; i<3; i++) pb[i] = p2[i]; | ||
297 | sign = (dDOT14(Ax,R2+0) > 0) ? REAL(-1.0) : REAL(1.0); | ||
298 | for (i=0; i<3; i++) pb[i] += sign * B1 * R2[i*4]; | ||
299 | sign = (dDOT14(Ax,R2+1) > 0) ? REAL(-1.0) : REAL(1.0); | ||
300 | for (i=0; i<3; i++) pb[i] += sign * B2 * R2[i*4+1]; | ||
301 | sign = (dDOT14(Ax,R2+2) > 0) ? REAL(-1.0) : REAL(1.0); | ||
302 | for (i=0; i<3; i++) pb[i] += sign * B3 * R2[i*4+2]; | ||
303 | |||
304 | //building axis which is normal to cylinder ax to the nearest box vertex | ||
305 | proj=dDOT14(pb,R1+1)-dDOT14(p1,R1+1); | ||
306 | |||
307 | Ax[0]=pb[0]-p1[0]-R1[1]*proj; | ||
308 | Ax[1]=pb[1]-p1[1]-R1[5]*proj; | ||
309 | Ax[2]=pb[2]-p1[2]-R1[9]*proj; | ||
310 | dNormalize3(Ax); | ||
311 | } | ||
312 | |||
313 | boxProj=dFabs(dDOT14(Ax,R2+0)*B1)+ | ||
314 | dFabs(dDOT14(Ax,R2+1)*B2)+ | ||
315 | dFabs(dDOT14(Ax,R2+2)*B3); | ||
316 | |||
317 | TEST(p[0]*Ax[0]+p[1]*Ax[1]+p[2]*Ax[2],(radius+boxProj),Ax[0],Ax[1],Ax[2],4); | ||
318 | |||
319 | |||
320 | //next three test used to handle collisions between cylinder circles and box ages | ||
321 | proj=dDOT14(p1,R2+0)-dDOT14(p2,R2+0); | ||
322 | |||
323 | tAx[0]=-p1[0]+p2[0]+R2[0]*proj; | ||
324 | tAx[1]=-p1[1]+p2[1]+R2[4]*proj; | ||
325 | tAx[2]=-p1[2]+p2[2]+R2[8]*proj; | ||
326 | dNormalize3(tAx); | ||
327 | |||
328 | //now tAx is normal to first ax of the box to cylinder center | ||
329 | //making perpendicular to tAx lying in the plane which is normal to the cylinder axis | ||
330 | //it is tangent in the point where projection of tAx on cylinder's ring intersect edge circle | ||
331 | |||
332 | cos=dDOT14(tAx,R1+0); | ||
333 | sin=dDOT14(tAx,R1+2); | ||
334 | tAx[0]=R1[2]*cos-R1[0]*sin; | ||
335 | tAx[1]=R1[6]*cos-R1[4]*sin; | ||
336 | tAx[2]=R1[10]*cos-R1[8]*sin; | ||
337 | |||
338 | |||
339 | //use cross between tAx and first ax of the box as separating axix | ||
340 | |||
341 | dCROSS114(Ax,=,tAx,R2+0); | ||
342 | dNormalize3(Ax); | ||
343 | |||
344 | boxProj=dFabs(dDOT14(Ax,R2+1)*B2)+ | ||
345 | dFabs(dDOT14(Ax,R2+0)*B1)+ | ||
346 | dFabs(dDOT14(Ax,R2+2)*B3); | ||
347 | |||
348 | cos=dFabs(dDOT14(Ax,R1+1)); | ||
349 | cos1=dDOT14(Ax,R1+0); | ||
350 | cos3=dDOT14(Ax,R1+2); | ||
351 | sin=sqrtf(cos1*cos1+cos3*cos3); | ||
352 | |||
353 | TEST(p[0]*Ax[0]+p[1]*Ax[1]+p[2]*Ax[2],(sin*radius+cos*hlz+boxProj),Ax[0],Ax[1],Ax[2],5); | ||
354 | |||
355 | |||
356 | //same thing with the second axis of the box | ||
357 | proj=dDOT14(p1,R2+1)-dDOT14(p2,R2+1); | ||
358 | |||
359 | tAx[0]=-p1[0]+p2[0]+R2[1]*proj; | ||
360 | tAx[1]=-p1[1]+p2[1]+R2[5]*proj; | ||
361 | tAx[2]=-p1[2]+p2[2]+R2[9]*proj; | ||
362 | dNormalize3(tAx); | ||
363 | |||
364 | |||
365 | cos=dDOT14(tAx,R1+0); | ||
366 | sin=dDOT14(tAx,R1+2); | ||
367 | tAx[0]=R1[2]*cos-R1[0]*sin; | ||
368 | tAx[1]=R1[6]*cos-R1[4]*sin; | ||
369 | tAx[2]=R1[10]*cos-R1[8]*sin; | ||
370 | |||
371 | dCROSS114(Ax,=,tAx,R2+1); | ||
372 | dNormalize3(Ax); | ||
373 | |||
374 | boxProj=dFabs(dDOT14(Ax,R2+0)*B1)+ | ||
375 | dFabs(dDOT14(Ax,R2+1)*B2)+ | ||
376 | dFabs(dDOT14(Ax,R2+2)*B3); | ||
377 | |||
378 | cos=dFabs(dDOT14(Ax,R1+1)); | ||
379 | cos1=dDOT14(Ax,R1+0); | ||
380 | cos3=dDOT14(Ax,R1+2); | ||
381 | sin=sqrtf(cos1*cos1+cos3*cos3); | ||
382 | TEST(p[0]*Ax[0]+p[1]*Ax[1]+p[2]*Ax[2],(sin*radius+cos*hlz+boxProj),Ax[0],Ax[1],Ax[2],6); | ||
383 | |||
384 | //same thing with the third axis of the box | ||
385 | proj=dDOT14(p1,R2+2)-dDOT14(p2,R2+2); | ||
386 | |||
387 | Ax[0]=-p1[0]+p2[0]+R2[2]*proj; | ||
388 | Ax[1]=-p1[1]+p2[1]+R2[6]*proj; | ||
389 | Ax[2]=-p1[2]+p2[2]+R2[10]*proj; | ||
390 | dNormalize3(tAx); | ||
391 | |||
392 | cos=dDOT14(tAx,R1+0); | ||
393 | sin=dDOT14(tAx,R1+2); | ||
394 | tAx[0]=R1[2]*cos-R1[0]*sin; | ||
395 | tAx[1]=R1[6]*cos-R1[4]*sin; | ||
396 | tAx[2]=R1[10]*cos-R1[8]*sin; | ||
397 | |||
398 | dCROSS114(Ax,=,tAx,R2+2); | ||
399 | dNormalize3(Ax); | ||
400 | boxProj=dFabs(dDOT14(Ax,R2+1)*B2)+ | ||
401 | dFabs(dDOT14(Ax,R2+2)*B3)+ | ||
402 | dFabs(dDOT14(Ax,R2+0)*B1); | ||
403 | |||
404 | cos=dFabs(dDOT14(Ax,R1+1)); | ||
405 | cos1=dDOT14(Ax,R1+0); | ||
406 | cos3=dDOT14(Ax,R1+2); | ||
407 | sin=sqrtf(cos1*cos1+cos3*cos3); | ||
408 | TEST(p[0]*Ax[0]+p[1]*Ax[1]+p[2]*Ax[2],(sin*radius+cos*hlz+boxProj),Ax[0],Ax[1],Ax[2],7); | ||
409 | |||
410 | |||
411 | #undef TEST | ||
412 | |||
413 | // note: cross product axes need to be scaled when s is computed. | ||
414 | // normal (n1,n2,n3) is relative to box 1. | ||
415 | |||
416 | #define TEST(expr1,expr2,n1,n2,n3,cc) \ | ||
417 | s2 = dFabs(expr1) - (expr2); \ | ||
418 | if (s2 > 0) return 0; \ | ||
419 | l = dSqrt ((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \ | ||
420 | if (l > 0) { \ | ||
421 | s2 /= l; \ | ||
422 | if (s2 > s) { \ | ||
423 | s = s2; \ | ||
424 | normalR = 0; \ | ||
425 | normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \ | ||
426 | invert_normal = ((expr1) < 0); \ | ||
427 | *code = (cc); \ | ||
428 | } \ | ||
429 | } | ||
430 | |||
431 | //crosses between cylinder axis and box axes | ||
432 | // separating axis = u2 x (v1,v2,v3) | ||
433 | TEST(pp[0]*R31-pp[2]*R11,(radius+B2*Q23+B3*Q22),R31,0,-R11,8); | ||
434 | TEST(pp[0]*R32-pp[2]*R12,(radius+B1*Q23+B3*Q21),R32,0,-R12,9); | ||
435 | TEST(pp[0]*R33-pp[2]*R13,(radius+B1*Q22+B2*Q21),R33,0,-R13,10); | ||
436 | |||
437 | |||
438 | #undef TEST | ||
439 | |||
440 | // if we get to this point, the boxes interpenetrate. compute the normal | ||
441 | // in global coordinates. | ||
442 | if (normalR) { | ||
443 | normal[0] = normalR[0]; | ||
444 | normal[1] = normalR[4]; | ||
445 | normal[2] = normalR[8]; | ||
446 | } | ||
447 | else { | ||
448 | if(*code>7) dMULTIPLY0_331 (normal,R1,normalC); | ||
449 | else {normal[0] =normalC[0];normal[1] = normalC[1];normal[2] = normalC[2];} | ||
450 | } | ||
451 | if (invert_normal) { | ||
452 | normal[0] = -normal[0]; | ||
453 | normal[1] = -normal[1]; | ||
454 | normal[2] = -normal[2]; | ||
455 | } | ||
456 | *depth = -s; | ||
457 | |||
458 | // compute contact point(s) | ||
459 | |||
460 | if (*code > 7) { | ||
461 | //find point on the cylinder pa deepest along normal | ||
462 | dVector3 pa; | ||
463 | dReal sign, cos1,cos3,factor; | ||
464 | |||
465 | |||
466 | for (i=0; i<3; i++) pa[i] = p1[i]; | ||
467 | |||
468 | cos1 = dDOT14(normal,R1+0); | ||
469 | cos3 = dDOT14(normal,R1+2) ; | ||
470 | factor=sqrtf(cos1*cos1+cos3*cos3); | ||
471 | |||
472 | cos1/=factor; | ||
473 | cos3/=factor; | ||
474 | |||
475 | for (i=0; i<3; i++) pa[i] += cos1 * radius * R1[i*4]; | ||
476 | |||
477 | sign = (dDOT14(normal,R1+1) > 0) ? REAL(1.0) : REAL(-1.0); | ||
478 | for (i=0; i<3; i++) pa[i] += sign * hlz * R1[i*4+1]; | ||
479 | |||
480 | |||
481 | for (i=0; i<3; i++) pa[i] += cos3 * radius * R1[i*4+2]; | ||
482 | |||
483 | // find vertex of the box deepest along normal | ||
484 | dVector3 pb; | ||
485 | for (i=0; i<3; i++) pb[i] = p2[i]; | ||
486 | sign = (dDOT14(normal,R2+0) > 0) ? REAL(-1.0) : REAL(1.0); | ||
487 | for (i=0; i<3; i++) pb[i] += sign * B1 * R2[i*4]; | ||
488 | sign = (dDOT14(normal,R2+1) > 0) ? REAL(-1.0) : REAL(1.0); | ||
489 | for (i=0; i<3; i++) pb[i] += sign * B2 * R2[i*4+1]; | ||
490 | sign = (dDOT14(normal,R2+2) > 0) ? REAL(-1.0) : REAL(1.0); | ||
491 | for (i=0; i<3; i++) pb[i] += sign * B3 * R2[i*4+2]; | ||
492 | |||
493 | |||
494 | dReal alpha,beta; | ||
495 | dVector3 ua,ub; | ||
496 | for (i=0; i<3; i++) ua[i] = R1[1 + i*4]; | ||
497 | for (i=0; i<3; i++) ub[i] = R2[*code-8 + i*4]; | ||
498 | |||
499 | lineClosestApproach (pa,ua,pb,ub,&alpha,&beta); | ||
500 | for (i=0; i<3; i++) pa[i] += ua[i]*alpha; | ||
501 | for (i=0; i<3; i++) pb[i] += ub[i]*beta; | ||
502 | |||
503 | for (i=0; i<3; i++) contact[0].pos[i] = REAL(0.5)*(pa[i]+pb[i]); | ||
504 | contact[0].depth = *depth; | ||
505 | return 1; | ||
506 | } | ||
507 | |||
508 | |||
509 | if(*code==4){ | ||
510 | for (i=0; i<3; i++) contact[0].pos[i] = pb[i]; | ||
511 | contact[0].depth = *depth; | ||
512 | return 1; | ||
513 | } | ||
514 | |||
515 | |||
516 | dVector3 vertex; | ||
517 | if (*code == 0) { | ||
518 | |||
519 | dReal sign; | ||
520 | for (i=0; i<3; i++) vertex[i] = p2[i]; | ||
521 | sign = (dDOT14(normal,R2+0) > 0) ? REAL(-1.0) : REAL(1.0); | ||
522 | for (i=0; i<3; i++) vertex[i] += sign * B1 * R2[i*4]; | ||
523 | sign = (dDOT14(normal,R2+1) > 0) ? REAL(-1.0) : REAL(1.0); | ||
524 | for (i=0; i<3; i++) vertex[i] += sign * B2 * R2[i*4+1]; | ||
525 | sign = (dDOT14(normal,R2+2) > 0) ? REAL(-1.0) : REAL(1.0); | ||
526 | for (i=0; i<3; i++) vertex[i] += sign * B3 * R2[i*4+2]; | ||
527 | } | ||
528 | else { | ||
529 | |||
530 | dReal sign,cos1,cos3,factor; | ||
531 | for (i=0; i<3; i++) vertex[i] = p1[i]; | ||
532 | cos1 = dDOT14(normal,R1+0) ; | ||
533 | cos3 = dDOT14(normal,R1+2); | ||
534 | factor=sqrtf(cos1*cos1+cos3*cos3); | ||
535 | factor= factor ? factor : 1.f; | ||
536 | cos1/=factor; | ||
537 | cos3/=factor; | ||
538 | for (i=0; i<3; i++) vertex[i] += cos1 * radius * R1[i*4]; | ||
539 | |||
540 | sign = (dDOT14(normal,R1+1) > 0) ? REAL(1.0) : REAL(-1.0); | ||
541 | for (i=0; i<3; i++) vertex[i] += sign * hlz * R1[i*4+1]; | ||
542 | |||
543 | for (i=0; i<3; i++) vertex[i] += cos3 * radius * R1[i*4+2]; | ||
544 | } | ||
545 | for (i=0; i<3; i++) contact[0].pos[i] = vertex[i]; | ||
546 | contact[0].depth = *depth; | ||
547 | return 1; | ||
548 | } | ||
549 | |||
550 | //**************************************************************************** | ||
551 | |||
552 | extern "C" int dCylCyl (const dVector3 p1, const dMatrix3 R1, | ||
553 | const dReal radius1,const dReal lz1, const dVector3 p2, | ||
554 | const dMatrix3 R2, const dReal radius2,const dReal lz2, | ||
555 | dVector3 normal, dReal *depth, int *code, | ||
556 | int maxc, dContactGeom *contact, int skip) | ||
557 | { | ||
558 | dVector3 p,pp1,pp2,normalC; | ||
559 | const dReal *normalR = 0; | ||
560 | dReal hlz1,hlz2,s,s2; | ||
561 | int i,invert_normal; | ||
562 | |||
563 | // get vector from centers of box 1 to box 2, relative to box 1 | ||
564 | p[0] = p2[0] - p1[0]; | ||
565 | p[1] = p2[1] - p1[1]; | ||
566 | p[2] = p2[2] - p1[2]; | ||
567 | dMULTIPLY1_331 (pp1,R1,p); // get pp1 = p relative to body 1 | ||
568 | dMULTIPLY1_331 (pp2,R2,p); | ||
569 | // get side lengths / 2 | ||
570 | hlz1 = lz1*REAL(0.5); | ||
571 | hlz2 = lz2*REAL(0.5); | ||
572 | |||
573 | dReal proj,cos,sin,cos1,cos3; | ||
574 | |||
575 | |||
576 | |||
577 | #define TEST(expr1,expr2,norm,cc) \ | ||
578 | s2 = dFabs(expr1) - (expr2); \ | ||
579 | if (s2 > 0) return 0; \ | ||
580 | if (s2 > s) { \ | ||
581 | s = s2; \ | ||
582 | normalR = norm; \ | ||
583 | invert_normal = ((expr1) < 0); \ | ||
584 | *code = (cc); \ | ||
585 | } | ||
586 | |||
587 | s = -dInfinity; | ||
588 | invert_normal = 0; | ||
589 | *code = 0; | ||
590 | |||
591 | cos=dFabs(dDOT44(R1+1,R2+1)); | ||
592 | sin=sqrtf(1.f-(cos>1.f ? 1.f : cos)); | ||
593 | |||
594 | TEST (pp1[1],(hlz1 + radius2*sin + hlz2*cos ),R1+1,0);//pp | ||
595 | |||
596 | TEST (pp2[1],(radius1*sin + hlz1*cos + hlz2),R2+1,1); | ||
597 | |||
598 | |||
599 | |||
600 | // note: cross product axes need to be scaled when s is computed. | ||
601 | |||
602 | #undef TEST | ||
603 | #define TEST(expr1,expr2,n1,n2,n3,cc) \ | ||
604 | s2 = dFabs(expr1) - (expr2); \ | ||
605 | if (s2 > 0) return 0; \ | ||
606 | if (s2 > s) { \ | ||
607 | s = s2; \ | ||
608 | normalR = 0; \ | ||
609 | normalC[0] = (n1); normalC[1] = (n2); normalC[2] = (n3); \ | ||
610 | invert_normal = ((expr1) < 0); \ | ||
611 | *code = (cc); \ | ||
612 | } | ||
613 | |||
614 | |||
615 | dVector3 tAx,Ax,pa,pb; | ||
616 | |||
617 | //cross between cylinders' axes | ||
618 | dCROSS144(Ax,=,R1+1,R2+1); | ||
619 | dNormalize3(Ax); | ||
620 | TEST(p[0]*Ax[0]+p[1]*Ax[1]+p[2]*Ax[2],radius1+radius2,Ax[0],Ax[1],Ax[2],6); | ||
621 | |||
622 | |||
623 | { | ||
624 | |||
625 | dReal sign, factor; | ||
626 | |||
627 | //making ax which is perpendicular to cyl1 ax passing across cyl2 position// | ||
628 | //(project p on cyl1 flat surface ) | ||
629 | for (i=0; i<3; i++) pb[i] = p2[i]; | ||
630 | //cos1 = dDOT14(p,R1+0); | ||
631 | //cos3 = dDOT14(p,R1+2) ; | ||
632 | tAx[0]=pp1[0]*R1[0]+pp1[2]*R1[2]; | ||
633 | tAx[1]=pp1[0]*R1[4]+pp1[2]*R1[6]; | ||
634 | tAx[2]=pp1[0]*R1[8]+pp1[2]*R1[10]; | ||
635 | dNormalize3(tAx); | ||
636 | |||
637 | //find deepest point pb of cyl2 on opposite direction of tAx | ||
638 | cos1 = dDOT14(tAx,R2+0); | ||
639 | cos3 = dDOT14(tAx,R2+2) ; | ||
640 | factor=sqrtf(cos1*cos1+cos3*cos3); | ||
641 | cos1/=factor; | ||
642 | cos3/=factor; | ||
643 | for (i=0; i<3; i++) pb[i] -= cos1 * radius2 * R2[i*4]; | ||
644 | |||
645 | sign = (dDOT14(tAx,R2+1) > 0) ? REAL(1.0) : REAL(-1.0); | ||
646 | for (i=0; i<3; i++) pb[i] -= sign * hlz2 * R2[i*4+1]; | ||
647 | |||
648 | for (i=0; i<3; i++) pb[i] -= cos3 * radius2 * R2[i*4+2]; | ||
649 | |||
650 | //making perpendicular to cyl1 ax passing across pb | ||
651 | proj=dDOT14(pb,R1+1)-dDOT14(p1,R1+1); | ||
652 | |||
653 | Ax[0]=pb[0]-p1[0]-R1[1]*proj; | ||
654 | Ax[1]=pb[1]-p1[1]-R1[5]*proj; | ||
655 | Ax[2]=pb[2]-p1[2]-R1[9]*proj; | ||
656 | |||
657 | } | ||
658 | |||
659 | dNormalize3(Ax); | ||
660 | |||
661 | |||
662 | cos=dFabs(dDOT14(Ax,R2+1)); | ||
663 | cos1=dDOT14(Ax,R2+0); | ||
664 | cos3=dDOT14(Ax,R2+2); | ||
665 | sin=sqrtf(cos1*cos1+cos3*cos3); | ||
666 | |||
667 | TEST(p[0]*Ax[0]+p[1]*Ax[1]+p[2]*Ax[2],radius1+cos*hlz2+sin*radius2,Ax[0],Ax[1],Ax[2],3); | ||
668 | |||
669 | |||
670 | |||
671 | { | ||
672 | |||
673 | dReal sign, factor; | ||
674 | |||
675 | for (i=0; i<3; i++) pa[i] = p1[i]; | ||
676 | |||
677 | //making ax which is perpendicular to cyl2 ax passing across cyl1 position// | ||
678 | //(project p on cyl2 flat surface ) | ||
679 | //cos1 = dDOT14(p,R2+0); | ||
680 | //cos3 = dDOT14(p,R2+2) ; | ||
681 | tAx[0]=pp2[0]*R2[0]+pp2[2]*R2[2]; | ||
682 | tAx[1]=pp2[0]*R2[4]+pp2[2]*R2[6]; | ||
683 | tAx[2]=pp2[0]*R2[8]+pp2[2]*R2[10]; | ||
684 | dNormalize3(tAx); | ||
685 | |||
686 | cos1 = dDOT14(tAx,R1+0); | ||
687 | cos3 = dDOT14(tAx,R1+2) ; | ||
688 | factor=sqrtf(cos1*cos1+cos3*cos3); | ||
689 | cos1/=factor; | ||
690 | cos3/=factor; | ||
691 | |||
692 | //find deepest point pa of cyl2 on direction of tAx | ||
693 | for (i=0; i<3; i++) pa[i] += cos1 * radius1 * R1[i*4]; | ||
694 | |||
695 | sign = (dDOT14(tAx,R1+1) > 0) ? REAL(1.0) : REAL(-1.0); | ||
696 | for (i=0; i<3; i++) pa[i] += sign * hlz1 * R1[i*4+1]; | ||
697 | |||
698 | |||
699 | for (i=0; i<3; i++) pa[i] += cos3 * radius1 * R1[i*4+2]; | ||
700 | |||
701 | proj=dDOT14(pa,R2+1)-dDOT14(p2,R2+1); | ||
702 | |||
703 | Ax[0]=pa[0]-p2[0]-R2[1]*proj; | ||
704 | Ax[1]=pa[1]-p2[1]-R2[5]*proj; | ||
705 | Ax[2]=pa[2]-p2[2]-R2[9]*proj; | ||
706 | |||
707 | } | ||
708 | dNormalize3(Ax); | ||
709 | |||
710 | |||
711 | |||
712 | cos=dFabs(dDOT14(Ax,R1+1)); | ||
713 | cos1=dDOT14(Ax,R1+0); | ||
714 | cos3=dDOT14(Ax,R1+2); | ||
715 | sin=sqrtf(cos1*cos1+cos3*cos3); | ||
716 | |||
717 | TEST(p[0]*Ax[0]+p[1]*Ax[1]+p[2]*Ax[2],radius2+cos*hlz1+sin*radius1,Ax[0],Ax[1],Ax[2],4); | ||
718 | |||
719 | |||
720 | ////test circl | ||
721 | |||
722 | //@ this needed to set right normal when cylinders edges intersect | ||
723 | //@ the most precise axis for this test may be found as a line between nearest points of two | ||
724 | //@ circles. But it needs comparatively a lot of computation. | ||
725 | //@ I use a trick which lets not to solve quadric equation. | ||
726 | //@ In the case when cylinder eidges touches the test below rather accurate. | ||
727 | //@ I still not sure about problems with sepparation but they have not been revealed during testing. | ||
728 | dVector3 point; | ||
729 | { | ||
730 | dVector3 ca,cb; | ||
731 | dReal sign; | ||
732 | for (i=0; i<3; i++) ca[i] = p1[i]; | ||
733 | for (i=0; i<3; i++) cb[i] = p2[i]; | ||
734 | //find two nearest flat rings | ||
735 | sign = (pp1[1] > 0) ? REAL(1.0) : REAL(-1.0); | ||
736 | for (i=0; i<3; i++) ca[i] += sign * hlz1 * R1[i*4+1]; | ||
737 | |||
738 | sign = (pp2[1] > 0) ? REAL(1.0) : REAL(-1.0); | ||
739 | for (i=0; i<3; i++) cb[i] -= sign * hlz2 * R2[i*4+1]; | ||
740 | |||
741 | dVector3 tAx,tAx1; | ||
742 | circleIntersection(R1+1,ca,radius1,R2+1,cb,radius2,point); | ||
743 | |||
744 | Ax[0]=point[0]-ca[0]; | ||
745 | Ax[1]=point[1]-ca[1]; | ||
746 | Ax[2]=point[2]-ca[2]; | ||
747 | |||
748 | cos1 = dDOT14(Ax,R1+0); | ||
749 | cos3 = dDOT14(Ax,R1+2) ; | ||
750 | |||
751 | tAx[0]=cos3*R1[0]-cos1*R1[2]; | ||
752 | tAx[1]=cos3*R1[4]-cos1*R1[6]; | ||
753 | tAx[2]=cos3*R1[8]-cos1*R1[10]; | ||
754 | |||
755 | Ax[0]=point[0]-cb[0]; | ||
756 | Ax[1]=point[1]-cb[1]; | ||
757 | Ax[2]=point[2]-cb[2]; | ||
758 | |||
759 | |||
760 | cos1 = dDOT14(Ax,R2+0); | ||
761 | cos3 = dDOT14(Ax,R2+2) ; | ||
762 | |||
763 | tAx1[0]=cos3*R2[0]-cos1*R2[2]; | ||
764 | tAx1[1]=cos3*R2[4]-cos1*R2[6]; | ||
765 | tAx1[2]=cos3*R2[8]-cos1*R2[10]; | ||
766 | dCROSS(Ax,=,tAx,tAx1); | ||
767 | |||
768 | |||
769 | |||
770 | |||
771 | dNormalize3(Ax); | ||
772 | dReal cyl1Pr,cyl2Pr; | ||
773 | |||
774 | cos=dFabs(dDOT14(Ax,R1+1)); | ||
775 | cos1=dDOT14(Ax,R1+0); | ||
776 | cos3=dDOT14(Ax,R1+2); | ||
777 | sin=sqrtf(cos1*cos1+cos3*cos3); | ||
778 | cyl1Pr=cos*hlz1+sin*radius1; | ||
779 | |||
780 | cos=dFabs(dDOT14(Ax,R2+1)); | ||
781 | cos1=dDOT14(Ax,R2+0); | ||
782 | cos3=dDOT14(Ax,R2+2); | ||
783 | sin=sqrtf(cos1*cos1+cos3*cos3); | ||
784 | cyl2Pr=cos*hlz2+sin*radius2; | ||
785 | TEST(p[0]*Ax[0]+p[1]*Ax[1]+p[2]*Ax[2],cyl1Pr+cyl2Pr,Ax[0],Ax[1],Ax[2],5); | ||
786 | |||
787 | |||
788 | } | ||
789 | |||
790 | |||
791 | #undef TEST | ||
792 | |||
793 | |||
794 | |||
795 | // if we get to this point, the cylinders interpenetrate. compute the normal | ||
796 | // in global coordinates. | ||
797 | if (normalR) { | ||
798 | normal[0] = normalR[0]; | ||
799 | normal[1] = normalR[4]; | ||
800 | normal[2] = normalR[8]; | ||
801 | } | ||
802 | else { | ||
803 | normal[0] =normalC[0];normal[1] = normalC[1];normal[2] = normalC[2]; | ||
804 | } | ||
805 | if (invert_normal) { | ||
806 | normal[0] = -normal[0]; | ||
807 | normal[1] = -normal[1]; | ||
808 | normal[2] = -normal[2]; | ||
809 | } | ||
810 | |||
811 | *depth = -s; | ||
812 | |||
813 | // compute contact point(s) | ||
814 | |||
815 | if(*code==3){ | ||
816 | for (i=0; i<3; i++) contact[0].pos[i] = pb[i]; | ||
817 | contact[0].depth = *depth; | ||
818 | return 1; | ||
819 | } | ||
820 | |||
821 | if(*code==4){ | ||
822 | for (i=0; i<3; i++) contact[0].pos[i] = pa[i]; | ||
823 | contact[0].depth = *depth; | ||
824 | return 1; | ||
825 | } | ||
826 | |||
827 | if(*code==5){ | ||
828 | for (i=0; i<3; i++) contact[0].pos[i] = point[i]; | ||
829 | contact[0].depth = *depth; | ||
830 | return 1; | ||
831 | } | ||
832 | |||
833 | if (*code == 6) { | ||
834 | dVector3 pa; | ||
835 | dReal sign, cos1,cos3,factor; | ||
836 | |||
837 | |||
838 | for (i=0; i<3; i++) pa[i] = p1[i]; | ||
839 | |||
840 | cos1 = dDOT14(normal,R1+0); | ||
841 | cos3 = dDOT14(normal,R1+2) ; | ||
842 | factor=sqrtf(cos1*cos1+cos3*cos3); | ||
843 | |||
844 | cos1/=factor; | ||
845 | cos3/=factor; | ||
846 | |||
847 | for (i=0; i<3; i++) pa[i] += cos1 * radius1 * R1[i*4]; | ||
848 | |||
849 | sign = (dDOT14(normal,R1+1) > 0) ? REAL(1.0) : REAL(-1.0); | ||
850 | for (i=0; i<3; i++) pa[i] += sign * hlz1 * R1[i*4+1]; | ||
851 | |||
852 | |||
853 | for (i=0; i<3; i++) pa[i] += cos3 * radius1 * R1[i*4+2]; | ||
854 | |||
855 | // find a point pb on the intersecting edge of cylinder 2 | ||
856 | dVector3 pb; | ||
857 | for (i=0; i<3; i++) pb[i] = p2[i]; | ||
858 | cos1 = dDOT14(normal,R2+0); | ||
859 | cos3 = dDOT14(normal,R2+2) ; | ||
860 | factor=sqrtf(cos1*cos1+cos3*cos3); | ||
861 | |||
862 | cos1/=factor; | ||
863 | cos3/=factor; | ||
864 | |||
865 | for (i=0; i<3; i++) pb[i] -= cos1 * radius2 * R2[i*4]; | ||
866 | |||
867 | sign = (dDOT14(normal,R2+1) > 0) ? REAL(1.0) : REAL(-1.0); | ||
868 | for (i=0; i<3; i++) pb[i] -= sign * hlz2 * R2[i*4+1]; | ||
869 | |||
870 | |||
871 | for (i=0; i<3; i++) pb[i] -= cos3 * radius2 * R2[i*4+2]; | ||
872 | |||
873 | |||
874 | dReal alpha,beta; | ||
875 | dVector3 ua,ub; | ||
876 | for (i=0; i<3; i++) ua[i] = R1[1 + i*4]; | ||
877 | for (i=0; i<3; i++) ub[i] = R2[1 + i*4]; | ||
878 | lineClosestApproach (pa,ua,pb,ub,&alpha,&beta); | ||
879 | for (i=0; i<3; i++) pa[i] += ua[i]*alpha; | ||
880 | for (i=0; i<3; i++) pb[i] += ub[i]*beta; | ||
881 | |||
882 | for (i=0; i<3; i++) contact[0].pos[i] = REAL(0.5)*(pa[i]+pb[i]); | ||
883 | contact[0].depth = *depth; | ||
884 | return 1; | ||
885 | } | ||
886 | |||
887 | // okay, we have a face-something intersection (because the separating | ||
888 | // axis is perpendicular to a face). | ||
889 | |||
890 | // @@@ temporary: make deepest point on the "other" cylinder the contact point. | ||
891 | // @@@ this kind of works, but we need multiple contact points for stability, | ||
892 | // @@@ especially for face-face contact. | ||
893 | |||
894 | dVector3 vertex; | ||
895 | if (*code == 0) { | ||
896 | // flat face from cylinder 1 touches a edge/face from cylinder 2. | ||
897 | dReal sign,cos1,cos3,factor; | ||
898 | for (i=0; i<3; i++) vertex[i] = p2[i]; | ||
899 | cos1 = dDOT14(normal,R2+0) ; | ||
900 | cos3 = dDOT14(normal,R2+2); | ||
901 | factor=sqrtf(cos1*cos1+cos3*cos3); | ||
902 | |||
903 | cos1/=factor; | ||
904 | cos3/=factor; | ||
905 | for (i=0; i<3; i++) vertex[i] -= cos1 * radius2 * R2[i*4]; | ||
906 | |||
907 | sign = (dDOT14(normal,R1+1) > 0) ? REAL(1.0) : REAL(-1.0); | ||
908 | for (i=0; i<3; i++) vertex[i] -= sign * hlz2 * R2[i*4+1]; | ||
909 | |||
910 | for (i=0; i<3; i++) vertex[i] -= cos3 * radius2 * R2[i*4+2]; | ||
911 | } | ||
912 | else { | ||
913 | // flat face from cylinder 2 touches a edge/face from cylinder 1. | ||
914 | dReal sign,cos1,cos3,factor; | ||
915 | for (i=0; i<3; i++) vertex[i] = p1[i]; | ||
916 | cos1 = dDOT14(normal,R1+0) ; | ||
917 | cos3 = dDOT14(normal,R1+2); | ||
918 | factor=sqrtf(cos1*cos1+cos3*cos3); | ||
919 | |||
920 | cos1/=factor; | ||
921 | cos3/=factor; | ||
922 | for (i=0; i<3; i++) vertex[i] += cos1 * radius1 * R1[i*4]; | ||
923 | |||
924 | sign = (dDOT14(normal,R1+1) > 0) ? REAL(1.0) : REAL(-1.0); | ||
925 | for (i=0; i<3; i++) vertex[i] += sign * hlz1 * R1[i*4+1]; | ||
926 | |||
927 | for (i=0; i<3; i++) vertex[i] += cos3 * radius1 * R1[i*4+2]; | ||
928 | } | ||
929 | for (i=0; i<3; i++) contact[0].pos[i] = vertex[i]; | ||
930 | contact[0].depth = *depth; | ||
931 | return 1; | ||
932 | } | ||
933 | |||
934 | //**************************************************************************** | ||
935 | |||
936 | |||
937 | int dCollideCylS (dxGeom *o1, dxGeom *o2, int flags, | ||
938 | dContactGeom *contact, int skip) | ||
939 | { | ||
940 | |||
941 | |||
942 | dIASSERT (skip >= (int)sizeof(dContactGeom)); | ||
943 | dIASSERT (dGeomGetClass(o2) == dSphereClass); | ||
944 | dIASSERT (dGeomGetClass(o1) == dCylinderClassUser); | ||
945 | const dReal* p1=dGeomGetPosition(o1); | ||
946 | const dReal* p2=dGeomGetPosition(o2); | ||
947 | const dReal* R=dGeomGetRotation(o1); | ||
948 | dVector3 p,normalC,normal; | ||
949 | const dReal *normalR = 0; | ||
950 | dReal cylRadius; | ||
951 | dReal hl; | ||
952 | dGeomCylinderGetParams(o1,&cylRadius,&hl); | ||
953 | dReal sphereRadius; | ||
954 | sphereRadius=dGeomSphereGetRadius(o2); | ||
955 | |||
956 | int i,invert_normal; | ||
957 | |||
958 | // get vector from centers of cyl to shere | ||
959 | p[0] = p2[0] - p1[0]; | ||
960 | p[1] = p2[1] - p1[1]; | ||
961 | p[2] = p2[2] - p1[2]; | ||
962 | |||
963 | dReal s,s2; | ||
964 | unsigned char code; | ||
965 | #define TEST(expr1,expr2,norm,cc) \ | ||
966 | s2 = dFabs(expr1) - (expr2); \ | ||
967 | if (s2 > 0) return 0; \ | ||
968 | if (s2 > s) { \ | ||
969 | s = s2; \ | ||
970 | normalR = norm; \ | ||
971 | invert_normal = ((expr1) < 0); \ | ||
972 | code = (cc); \ | ||
973 | } | ||
974 | |||
975 | s = -dInfinity; | ||
976 | invert_normal = 0; | ||
977 | code = 0; | ||
978 | |||
979 | // separating axis cyl ax | ||
980 | |||
981 | TEST (dDOT14(p,R+1),sphereRadius+hl,R+1,2); | ||
982 | // note: cross product axes need to be scaled when s is computed. | ||
983 | // normal (n1,n2,n3) is relative to | ||
984 | #undef TEST | ||
985 | #define TEST(expr1,expr2,n1,n2,n3,cc) \ | ||
986 | s2 = dFabs(expr1) - (expr2); \ | ||
987 | if (s2 > 0) return 0; \ | ||
988 | if (s2 > s) { \ | ||
989 | s = s2; \ | ||
990 | normalR = 0; \ | ||
991 | normalC[0] = (n1); normalC[1] = (n2); normalC[2] = (n3); \ | ||
992 | invert_normal = ((expr1) < 0); \ | ||
993 | code = (cc); \ | ||
994 | } | ||
995 | |||
996 | //making ax which is perpendicular to cyl1 ax to sphere center// | ||
997 | |||
998 | dReal proj,cos,sin,cos1,cos3; | ||
999 | dVector3 Ax; | ||
1000 | proj=dDOT14(p2,R+1)-dDOT14(p1,R+1); | ||
1001 | |||
1002 | Ax[0]=p2[0]-p1[0]-R[1]*proj; | ||
1003 | Ax[1]=p2[1]-p1[1]-R[5]*proj; | ||
1004 | Ax[2]=p2[2]-p1[2]-R[9]*proj; | ||
1005 | dNormalize3(Ax); | ||
1006 | TEST(dDOT(p,Ax),sphereRadius+cylRadius,Ax[0],Ax[1],Ax[2],9); | ||
1007 | |||
1008 | |||
1009 | Ax[0]=p[0]; | ||
1010 | Ax[1]=p[1]; | ||
1011 | Ax[2]=p[2]; | ||
1012 | dNormalize3(Ax); | ||
1013 | |||
1014 | dVector3 pa; | ||
1015 | dReal sign, factor; | ||
1016 | for (i=0; i<3; i++) pa[i] = p1[i]; | ||
1017 | |||
1018 | cos1 = dDOT14(Ax,R+0); | ||
1019 | cos3 = dDOT14(Ax,R+2) ; | ||
1020 | factor=sqrtf(cos1*cos1+cos3*cos3); | ||
1021 | cos1/=factor; | ||
1022 | cos3/=factor; | ||
1023 | for (i=0; i<3; i++) pa[i] += cos1 * cylRadius * R[i*4]; | ||
1024 | sign = (dDOT14(normal,R+1) > 0) ? REAL(1.0) : REAL(-1.0); | ||
1025 | for (i=0; i<3; i++) pa[i] += sign * hl * R[i*4+1]; | ||
1026 | for (i=0; i<3; i++) pa[i] += cos3 * cylRadius * R[i*4+2]; | ||
1027 | |||
1028 | Ax[0]=p2[0]-pa[0]; | ||
1029 | Ax[1]=p2[1]-pa[1]; | ||
1030 | Ax[2]=p2[2]-pa[2]; | ||
1031 | dNormalize3(Ax); | ||
1032 | |||
1033 | cos=dFabs(dDOT14(Ax,R+1)); | ||
1034 | cos1=dDOT14(Ax,R+0); | ||
1035 | cos3=dDOT14(Ax,R+2); | ||
1036 | sin=sqrtf(cos1*cos1+cos3*cos3); | ||
1037 | TEST(dDOT(p,Ax),sphereRadius+cylRadius*sin+hl*cos,Ax[0],Ax[1],Ax[2],14); | ||
1038 | |||
1039 | |||
1040 | #undef TEST | ||
1041 | |||
1042 | if (normalR) { | ||
1043 | normal[0] = normalR[0]; | ||
1044 | normal[1] = normalR[4]; | ||
1045 | normal[2] = normalR[8]; | ||
1046 | } | ||
1047 | else { | ||
1048 | |||
1049 | normal[0] = normalC[0]; | ||
1050 | normal[1] = normalC[1]; | ||
1051 | normal[2] = normalC[2]; | ||
1052 | } | ||
1053 | if (invert_normal) { | ||
1054 | normal[0] = -normal[0]; | ||
1055 | normal[1] = -normal[1]; | ||
1056 | normal[2] = -normal[2]; | ||
1057 | } | ||
1058 | // compute contact point(s) | ||
1059 | contact->depth=-s; | ||
1060 | contact->normal[0]=-normal[0]; | ||
1061 | contact->normal[1]=-normal[1]; | ||
1062 | contact->normal[2]=-normal[2]; | ||
1063 | contact->g1=const_cast<dxGeom*> (o1); | ||
1064 | contact->g2=const_cast<dxGeom*> (o2); | ||
1065 | contact->pos[0]=p2[0]-normal[0]*sphereRadius; | ||
1066 | contact->pos[1]=p2[1]-normal[1]*sphereRadius; | ||
1067 | contact->pos[2]=p2[2]-normal[2]*sphereRadius; | ||
1068 | return 1; | ||
1069 | } | ||
1070 | |||
1071 | |||
1072 | |||
1073 | int dCollideCylB (dxGeom *o1, dxGeom *o2, int flags, | ||
1074 | dContactGeom *contact, int skip) | ||
1075 | { | ||
1076 | dVector3 normal; | ||
1077 | dReal depth; | ||
1078 | int code; | ||
1079 | dReal cylRadius,cylLength; | ||
1080 | dVector3 boxSides; | ||
1081 | dGeomCylinderGetParams(o1,&cylRadius,&cylLength); | ||
1082 | dGeomBoxGetLengths(o2,boxSides); | ||
1083 | int num = dCylBox(dGeomGetPosition(o1),dGeomGetRotation(o1),cylRadius,cylLength, | ||
1084 | dGeomGetPosition(o2),dGeomGetRotation(o2),boxSides, | ||
1085 | normal,&depth,&code,flags & NUMC_MASK,contact,skip); | ||
1086 | for (int i=0; i<num; i++) { | ||
1087 | CONTACT(contact,i*skip)->normal[0] = -normal[0]; | ||
1088 | CONTACT(contact,i*skip)->normal[1] = -normal[1]; | ||
1089 | CONTACT(contact,i*skip)->normal[2] = -normal[2]; | ||
1090 | CONTACT(contact,i*skip)->g1 = const_cast<dxGeom*> (o1); | ||
1091 | CONTACT(contact,i*skip)->g2 = const_cast<dxGeom*> (o2); | ||
1092 | } | ||
1093 | return num; | ||
1094 | } | ||
1095 | |||
1096 | int dCollideCylCyl (dxGeom *o1, dxGeom *o2, int flags, | ||
1097 | dContactGeom *contact, int skip) | ||
1098 | { | ||
1099 | dVector3 normal; | ||
1100 | dReal depth; | ||
1101 | int code; | ||
1102 | dReal cylRadius1,cylRadius2; | ||
1103 | dReal cylLength1,cylLength2; | ||
1104 | dGeomCylinderGetParams(o1,&cylRadius1,&cylLength1); | ||
1105 | dGeomCylinderGetParams(o2,&cylRadius2,&cylLength2); | ||
1106 | int num = dCylCyl (dGeomGetPosition(o1),dGeomGetRotation(o1),cylRadius1,cylLength1, | ||
1107 | dGeomGetPosition(o2),dGeomGetRotation(o2),cylRadius2,cylLength2, | ||
1108 | normal,&depth,&code,flags & NUMC_MASK,contact,skip); | ||
1109 | |||
1110 | for (int i=0; i<num; i++) { | ||
1111 | CONTACT(contact,i*skip)->normal[0] = -normal[0]; | ||
1112 | CONTACT(contact,i*skip)->normal[1] = -normal[1]; | ||
1113 | CONTACT(contact,i*skip)->normal[2] = -normal[2]; | ||
1114 | CONTACT(contact,i*skip)->g1 = const_cast<dxGeom*> (o1); | ||
1115 | CONTACT(contact,i*skip)->g2 = const_cast<dxGeom*> (o2); | ||
1116 | } | ||
1117 | return num; | ||
1118 | } | ||
1119 | |||
1120 | struct dxPlane { | ||
1121 | dReal p[4]; | ||
1122 | }; | ||
1123 | |||
1124 | |||
1125 | int dCollideCylPlane | ||
1126 | ( | ||
1127 | dxGeom *o1, dxGeom *o2, int flags, | ||
1128 | dContactGeom *contact, int skip){ | ||
1129 | dIASSERT (skip >= (int)sizeof(dContactGeom)); | ||
1130 | dIASSERT (dGeomGetClass(o1) == dCylinderClassUser); | ||
1131 | dIASSERT (dGeomGetClass(o2) == dPlaneClass); | ||
1132 | contact->g1 = const_cast<dxGeom*> (o1); | ||
1133 | contact->g2 = const_cast<dxGeom*> (o2); | ||
1134 | |||
1135 | unsigned int ret = 0; | ||
1136 | |||
1137 | dReal radius; | ||
1138 | dReal hlz; | ||
1139 | dGeomCylinderGetParams(o1,&radius,&hlz); | ||
1140 | hlz /= 2; | ||
1141 | |||
1142 | const dReal *R = dGeomGetRotation(o1);// rotation of cylinder | ||
1143 | const dReal* p = dGeomGetPosition(o1); | ||
1144 | dVector4 n; // normal vector | ||
1145 | dReal pp; | ||
1146 | dGeomPlaneGetParams (o2, n); | ||
1147 | pp=n[3]; | ||
1148 | dReal cos1,sin1; | ||
1149 | cos1=dFabs(dDOT14(n,R+1)); | ||
1150 | |||
1151 | cos1=cos1<REAL(1.) ? cos1 : REAL(1.); //cos1 may slightly exeed 1.f | ||
1152 | sin1=sqrtf(REAL(1.)-cos1*cos1); | ||
1153 | ////////////////////////////// | ||
1154 | |||
1155 | dReal sidePr=cos1*hlz+sin1*radius; | ||
1156 | |||
1157 | dReal dist=-pp+dDOT(n,p); | ||
1158 | dReal outDepth=sidePr-dist; | ||
1159 | |||
1160 | if(outDepth<0.f) return 0; | ||
1161 | |||
1162 | dVector3 pos; | ||
1163 | |||
1164 | |||
1165 | /////////////////////////////////////////// from geom.cpp dCollideBP | ||
1166 | dReal Q1 = dDOT14(n,R+0); | ||
1167 | dReal Q2 = dDOT14(n,R+1); | ||
1168 | dReal Q3 = dDOT14(n,R+2); | ||
1169 | dReal factor =sqrtf(Q1*Q1+Q3*Q3); | ||
1170 | factor= factor ? factor :1.f; | ||
1171 | dReal A1 = radius * Q1/factor; | ||
1172 | dReal A2 = hlz*Q2; | ||
1173 | dReal A3 = radius * Q3/factor; | ||
1174 | |||
1175 | pos[0]=p[0]; | ||
1176 | pos[1]=p[1]; | ||
1177 | pos[2]=p[2]; | ||
1178 | |||
1179 | pos[0]-= A1*R[0]; | ||
1180 | pos[1]-= A1*R[4]; | ||
1181 | pos[2]-= A1*R[8]; | ||
1182 | |||
1183 | pos[0]-= A3*R[2]; | ||
1184 | pos[1]-= A3*R[6]; | ||
1185 | pos[2]-= A3*R[10]; | ||
1186 | |||
1187 | pos[0]-= A2>0 ? hlz*R[1]:-hlz*R[1]; | ||
1188 | pos[1]-= A2>0 ? hlz*R[5]:-hlz*R[5]; | ||
1189 | pos[2]-= A2>0 ? hlz*R[9]:-hlz*R[9]; | ||
1190 | |||
1191 | |||
1192 | |||
1193 | contact->pos[0] = pos[0]; | ||
1194 | contact->pos[1] = pos[1]; | ||
1195 | contact->pos[2] = pos[2]; | ||
1196 | contact->depth = outDepth; | ||
1197 | ret=1; | ||
1198 | |||
1199 | if(dFabs(Q2)>M_SQRT1_2){ | ||
1200 | |||
1201 | CONTACT(contact,ret*skip)->pos[0]=pos[0]+2.f*A1*R[0]; | ||
1202 | CONTACT(contact,ret*skip)->pos[1]=pos[1]+2.f*A1*R[4]; | ||
1203 | CONTACT(contact,ret*skip)->pos[2]=pos[2]+2.f*A1*R[8]; | ||
1204 | CONTACT(contact,ret*skip)->depth=outDepth-dFabs(Q1*2.f*A1); | ||
1205 | |||
1206 | if(CONTACT(contact,ret*skip)->depth>0.f) | ||
1207 | ret++; | ||
1208 | |||
1209 | |||
1210 | CONTACT(contact,ret*skip)->pos[0]=pos[0]+2.f*A3*R[2]; | ||
1211 | CONTACT(contact,ret*skip)->pos[1]=pos[1]+2.f*A3*R[6]; | ||
1212 | CONTACT(contact,ret*skip)->pos[2]=pos[2]+2.f*A3*R[10]; | ||
1213 | CONTACT(contact,ret*skip)->depth=outDepth-dFabs(Q3*2.f*A3); | ||
1214 | |||
1215 | if(CONTACT(contact,ret*skip)->depth>0.f) ret++; | ||
1216 | } else { | ||
1217 | |||
1218 | CONTACT(contact,ret*skip)->pos[0]=pos[0]+2.f*(A2>0 ? hlz*R[1]:-hlz*R[1]); | ||
1219 | CONTACT(contact,ret*skip)->pos[1]=pos[1]+2.f*(A2>0 ? hlz*R[5]:-hlz*R[5]); | ||
1220 | CONTACT(contact,ret*skip)->pos[2]=pos[2]+2.f*(A2>0 ? hlz*R[9]:-hlz*R[9]); | ||
1221 | CONTACT(contact,ret*skip)->depth=outDepth-dFabs(Q2*2.f*A2); | ||
1222 | |||
1223 | if(CONTACT(contact,ret*skip)->depth>0.f) ret++; | ||
1224 | } | ||
1225 | |||
1226 | |||
1227 | |||
1228 | for (unsigned int i=0; i<ret; i++) { | ||
1229 | CONTACT(contact,i*skip)->g1 = const_cast<dxGeom*> (o1); | ||
1230 | CONTACT(contact,i*skip)->g2 = const_cast<dxGeom*> (o2); | ||
1231 | CONTACT(contact,i*skip)->normal[0] =n[0]; | ||
1232 | CONTACT(contact,i*skip)->normal[1] =n[1]; | ||
1233 | CONTACT(contact,i*skip)->normal[2] =n[2]; | ||
1234 | } | ||
1235 | return ret; | ||
1236 | } | ||
1237 | |||
1238 | int dCollideCylRay(dxGeom *o1, dxGeom *o2, int flags, | ||
1239 | dContactGeom *contact, int skip) { | ||
1240 | dIASSERT (skip >= (int)sizeof(dContactGeom)); | ||
1241 | dIASSERT (dGeomGetClass(o1) == dCylinderClassUser); | ||
1242 | dIASSERT (dGeomGetClass(o2) == dRayClass); | ||
1243 | contact->g1 = const_cast<dxGeom*> (o1); | ||
1244 | contact->g2 = const_cast<dxGeom*> (o2); | ||
1245 | dReal radius; | ||
1246 | dReal lz; | ||
1247 | dGeomCylinderGetParams(o1,&radius,&lz); | ||
1248 | dReal lz2=lz*REAL(0.5); | ||
1249 | const dReal *R = dGeomGetRotation(o1); // rotation of the cylinder | ||
1250 | const dReal *p = dGeomGetPosition(o1); // position of the cylinder | ||
1251 | dVector3 start,dir; | ||
1252 | dGeomRayGet(o2,start,dir); // position and orientation of the ray | ||
1253 | dReal length = dGeomRayGetLength(o2); | ||
1254 | |||
1255 | // compute some useful info | ||
1256 | dVector3 cs,q,r; | ||
1257 | dReal C,k; | ||
1258 | cs[0] = start[0] - p[0]; | ||
1259 | cs[1] = start[1] - p[1]; | ||
1260 | cs[2] = start[2] - p[2]; | ||
1261 | k = dDOT41(R+1,cs); // position of ray start along cyl axis (Y) | ||
1262 | q[0] = k*R[0*4+1] - cs[0]; | ||
1263 | q[1] = k*R[1*4+1] - cs[1]; | ||
1264 | q[2] = k*R[2*4+1] - cs[2]; | ||
1265 | C = dDOT(q,q) - radius*radius; | ||
1266 | // if C < 0 then ray start position within infinite extension of cylinder | ||
1267 | // if ray start position is inside the cylinder | ||
1268 | int inside_cyl=0; | ||
1269 | if (C<0 && !(k<-lz2 || k>lz2)) inside_cyl=1; | ||
1270 | // compute ray collision with infinite cylinder, except for the case where | ||
1271 | // the ray is outside the cylinder but within the infinite cylinder | ||
1272 | // (it that case the ray can only hit endcaps) | ||
1273 | if (!inside_cyl && C < 0) { | ||
1274 | // set k to cap position to check | ||
1275 | if (k < 0) k = -lz2; else k = lz2; | ||
1276 | } | ||
1277 | else { | ||
1278 | dReal uv = dDOT41(R+1,dir); | ||
1279 | r[0] = uv*R[0*4+1] - dir[0]; | ||
1280 | r[1] = uv*R[1*4+1] - dir[1]; | ||
1281 | r[2] = uv*R[2*4+1] - dir[2]; | ||
1282 | dReal A = dDOT(r,r); | ||
1283 | dReal B = 2*dDOT(q,r); | ||
1284 | k = B*B-4*A*C; | ||
1285 | if (k < 0) { | ||
1286 | // the ray does not intersect the infinite cylinder, but if the ray is | ||
1287 | // inside and parallel to the cylinder axis it may intersect the end | ||
1288 | // caps. set k to cap position to check. | ||
1289 | if (!inside_cyl) return 0; | ||
1290 | if (uv < 0) k = -lz2; else k = lz2; | ||
1291 | } | ||
1292 | else { | ||
1293 | k = dSqrt(k); | ||
1294 | A = dRecip (2*A); | ||
1295 | dReal alpha = (-B-k)*A; | ||
1296 | if (alpha < 0) { | ||
1297 | alpha = (-B+k)*A; | ||
1298 | if (alpha<0) return 0; | ||
1299 | } | ||
1300 | if (alpha>length) return 0; | ||
1301 | // the ray intersects the infinite cylinder. check to see if the | ||
1302 | // intersection point is between the caps | ||
1303 | contact->pos[0] = start[0] + alpha*dir[0]; | ||
1304 | contact->pos[1] = start[1] + alpha*dir[1]; | ||
1305 | contact->pos[2] = start[2] + alpha*dir[2]; | ||
1306 | q[0] = contact->pos[0] - p[0]; | ||
1307 | q[1] = contact->pos[1] - p[1]; | ||
1308 | q[2] = contact->pos[2] - p[2]; | ||
1309 | k = dDOT14(q,R+1); | ||
1310 | dReal nsign = inside_cyl ? -1 : 1; | ||
1311 | if (k >= -lz2 && k <= lz2) { | ||
1312 | contact->normal[0] = nsign * (contact->pos[0] - | ||
1313 | (p[0] + k*R[0*4+1])); | ||
1314 | contact->normal[1] = nsign * (contact->pos[1] - | ||
1315 | (p[1] + k*R[1*4+1])); | ||
1316 | contact->normal[2] = nsign * (contact->pos[2] - | ||
1317 | (p[2] + k*R[2*4+1])); | ||
1318 | dNormalize3 (contact->normal); | ||
1319 | contact->depth = alpha; | ||
1320 | return 1; | ||
1321 | } | ||
1322 | // the infinite cylinder intersection point is not between the caps. | ||
1323 | // set k to cap position to check. | ||
1324 | if (k < 0) k = -lz2; else k = lz2; | ||
1325 | } | ||
1326 | } | ||
1327 | // check for ray intersection with the caps. k must indicate the cap | ||
1328 | // position to check | ||
1329 | // perform a ray plan interesection | ||
1330 | // R+1 is the plan normal | ||
1331 | q[0] = start[0] - (p[0] + k*R[0*4+1]); | ||
1332 | q[1] = start[1] - (p[1] + k*R[1*4+1]); | ||
1333 | q[2] = start[2] - (p[2] + k*R[2*4+1]); | ||
1334 | dReal alpha = -dDOT14(q,R+1); | ||
1335 | dReal k2 = dDOT14(dir,R+1); | ||
1336 | if (k2==0) return 0; // ray parallel to the plane | ||
1337 | alpha/=k2; | ||
1338 | if (alpha<0 || alpha>length) return 0; // too short | ||
1339 | contact->pos[0]=start[0]+alpha*dir[0]; | ||
1340 | contact->pos[1]=start[1]+alpha*dir[1]; | ||
1341 | contact->pos[2]=start[2]+alpha*dir[2]; | ||
1342 | dReal nsign = (k<0)?-1:1; | ||
1343 | contact->normal[0]=nsign*R[0*4+1]; | ||
1344 | contact->normal[1]=nsign*R[1*4+1]; | ||
1345 | contact->normal[2]=nsign*R[2*4+1]; | ||
1346 | contact->depth=alpha; | ||
1347 | return 1; | ||
1348 | } | ||
1349 | |||
1350 | static dColliderFn * dCylinderColliderFn (int num) | ||
1351 | { | ||
1352 | if (num == dBoxClass) return (dColliderFn *) &dCollideCylB; | ||
1353 | else if (num == dSphereClass) return (dColliderFn *) &dCollideCylS; | ||
1354 | else if (num == dCylinderClassUser) return (dColliderFn *) &dCollideCylCyl; | ||
1355 | else if (num == dPlaneClass) return (dColliderFn *) &dCollideCylPlane; | ||
1356 | else if (num == dRayClass) return (dColliderFn *) &dCollideCylRay; | ||
1357 | return 0; | ||
1358 | } | ||
1359 | |||
1360 | |||
1361 | static void dCylinderAABB (dxGeom *geom, dReal aabb[6]) | ||
1362 | { | ||
1363 | dReal radius,lz; | ||
1364 | dGeomCylinderGetParams(geom,&radius,&lz); | ||
1365 | const dReal* R= dGeomGetRotation(geom); | ||
1366 | const dReal* pos= dGeomGetPosition(geom); | ||
1367 | dReal xrange = dFabs (R[0] *radius) + | ||
1368 | REAL(0.5) *dFabs (R[1] * lz) + dFabs (R[2] * radius); | ||
1369 | |||
1370 | dReal yrange = dFabs (R[4] *radius) + | ||
1371 | REAL(0.5) * dFabs (R[5] * lz) + dFabs (R[6] * radius); | ||
1372 | |||
1373 | dReal zrange = dFabs (R[8] * radius) + | ||
1374 | REAL(0.5) *dFabs (R[9] * lz) + dFabs (R[10] * radius); | ||
1375 | |||
1376 | aabb[0] = pos[0] - xrange; | ||
1377 | aabb[1] = pos[0] + xrange; | ||
1378 | aabb[2] = pos[1] - yrange; | ||
1379 | aabb[3] = pos[1] + yrange; | ||
1380 | aabb[4] = pos[2] - zrange; | ||
1381 | aabb[5] = pos[2] + zrange; | ||
1382 | } | ||
1383 | |||
1384 | dxGeom *dCreateCylinder (dSpaceID space, dReal r, dReal lz) | ||
1385 | { | ||
1386 | dAASSERT (r > 0 && lz > 0); | ||
1387 | if (dCylinderClassUser == -1) | ||
1388 | { | ||
1389 | dGeomClass c; | ||
1390 | c.bytes = sizeof (dxCylinder); | ||
1391 | c.collider = &dCylinderColliderFn; | ||
1392 | c.aabb = &dCylinderAABB; | ||
1393 | c.aabb_test = 0; | ||
1394 | c.dtor = 0; | ||
1395 | dCylinderClassUser=dCreateGeomClass (&c); | ||
1396 | |||
1397 | } | ||
1398 | |||
1399 | dGeomID g = dCreateGeom (dCylinderClassUser); | ||
1400 | if (space) dSpaceAdd (space,g); | ||
1401 | dxCylinder *c = (dxCylinder*) dGeomGetClassData(g); | ||
1402 | |||
1403 | c->radius = r; | ||
1404 | c->lz = lz; | ||
1405 | return g; | ||
1406 | } | ||
1407 | |||
1408 | |||
1409 | |||
1410 | void dGeomCylinderSetParams (dGeomID g, dReal radius, dReal length) | ||
1411 | { | ||
1412 | dUASSERT (g && dGeomGetClass(g) == dCylinderClassUser,"argument not a cylinder"); | ||
1413 | dAASSERT (radius > 0 && length > 0); | ||
1414 | dxCylinder *c = (dxCylinder*) dGeomGetClassData(g); | ||
1415 | c->radius = radius; | ||
1416 | c->lz = length; | ||
1417 | } | ||
1418 | |||
1419 | |||
1420 | |||
1421 | void dGeomCylinderGetParams (dGeomID g, dReal *radius, dReal *length) | ||
1422 | { | ||
1423 | dUASSERT (g && dGeomGetClass(g) == dCylinderClassUser ,"argument not a cylinder"); | ||
1424 | dxCylinder *c = (dxCylinder*) dGeomGetClassData(g); | ||
1425 | *radius = c->radius; | ||
1426 | *length = c->lz; | ||
1427 | } | ||
1428 | |||
1429 | /* | ||
1430 | void dMassSetCylinder (dMass *m, dReal density, | ||
1431 | dReal radius, dReal length) | ||
1432 | { | ||
1433 | dAASSERT (m); | ||
1434 | dMassSetZero (m); | ||
1435 | dReal M = length*M_PI*radius*radius*density; | ||
1436 | m->mass = M; | ||
1437 | m->_I(0,0) = M/REAL(4.0) * (ly*ly + lz*lz); | ||
1438 | m->_I(1,1) = M/REAL(12.0) * (lx*lx + lz*lz); | ||
1439 | m->_I(2,2) = M/REAL(4.0) * (lx*lx + ly*ly); | ||
1440 | |||
1441 | # ifndef dNODEBUG | ||
1442 | checkMass (m); | ||
1443 | # endif | ||
1444 | } | ||
1445 | */ | ||
diff --git a/libraries/ode-0.9/contrib/dCylinder/dCylinder.h b/libraries/ode-0.9/contrib/dCylinder/dCylinder.h new file mode 100644 index 0000000..06e3a0b --- /dev/null +++ b/libraries/ode-0.9/contrib/dCylinder/dCylinder.h | |||
@@ -0,0 +1,14 @@ | |||
1 | |||
2 | #ifndef dCylinder_h | ||
3 | #define dCylinder_h | ||
4 | |||
5 | struct dxCylinder; | ||
6 | extern int dCylinderClassUser; | ||
7 | |||
8 | |||
9 | dxGeom *dCreateCylinder (dSpaceID space, dReal r, dReal lz); | ||
10 | void dGeomCylinderSetParams (dGeomID g, dReal radius, dReal length); | ||
11 | |||
12 | void dGeomCylinderGetParams (dGeomID g, dReal *radius, dReal *length); | ||
13 | #endif //dCylinder_h | ||
14 | |||
diff --git a/libraries/ode-0.9/contrib/dCylinder/readme.txt b/libraries/ode-0.9/contrib/dCylinder/readme.txt new file mode 100644 index 0000000..facd13e --- /dev/null +++ b/libraries/ode-0.9/contrib/dCylinder/readme.txt | |||
@@ -0,0 +1,62 @@ | |||
1 | readme.txt | ||
2 | |||
3 | WARNING: THIS IS NOT VERY RELIABLE CODE. IT HAS BUGS. YOUR | ||
4 | SUCCESS MAY VARY. CONTRIBUTIONS OF FIXES/REWRITES ARE | ||
5 | WELCOME. | ||
6 | |||
7 | /////////////////////////////////////////////////////////////////////// | ||
8 | |||
9 | Cylinder geometry class. | ||
10 | |||
11 | New in this version: | ||
12 | |||
13 | Cylinder class implemented as User Geometry Class so it now can be | ||
14 | used with old and new ODE collision detection. | ||
15 | |||
16 | Cylinder - Ray has been contributed by Olivier Michel. | ||
17 | |||
18 | THE IDENTIFIER dCylinderClass HAS BEEN REPLACED BY dCylinderClassUser | ||
19 | |||
20 | to avoid conflict with dCylinderClass in the enum definite in collision.h | ||
21 | |||
22 | /////////////////////////////////////////////////////////////////////// | ||
23 | The dCylinder class includes the following collisions: | ||
24 | |||
25 | Cylinder - Box | ||
26 | Cylinder - Cylinder | ||
27 | Cylinder - Sphere | ||
28 | Cylinder - Plane | ||
29 | Cylinder - Ray (contributed by Olivier Michel) | ||
30 | |||
31 | Cylinder aligned along axis - Y when created. (Not like Capped | ||
32 | Cylinder which aligned along axis - Z). | ||
33 | |||
34 | Interface is just the same as Capped Cylinder has. | ||
35 | |||
36 | Use functions which have one "C" instead of double "C". | ||
37 | |||
38 | to create: | ||
39 | dGeomID dCreateCylinder (dSpaceID space, dReal radius, dReal length); | ||
40 | |||
41 | to set params: | ||
42 | void dGeomCylinderSetParams (dGeomID cylinder, | ||
43 | dReal radius, dReal length); | ||
44 | |||
45 | |||
46 | to get params: | ||
47 | void dGeomCylinderGetParams (dGeomID cylinder, | ||
48 | dReal *radius, dReal *length); | ||
49 | |||
50 | Return in radius and length the parameters of the given cylinder. | ||
51 | |||
52 | Identification number of the class: | ||
53 | dCylinderClassUser | ||
54 | |||
55 | I do not include a function that sets inertia tensor for cylinder. | ||
56 | One may use existing ODE functions dMassSetCappedCylinder or dMassSetBox. | ||
57 | To set exact tensor for cylinder use dMassSetParameters. | ||
58 | Remember cylinder aligned along axis - Y. | ||
59 | |||
60 | /////////////////////////////////////////////////////////////////////////// | ||
61 | Konstantin Slipchenko | ||
62 | February 5, 2002 | ||
diff --git a/libraries/ode-0.9/contrib/dRay/Include/dRay.h b/libraries/ode-0.9/contrib/dRay/Include/dRay.h new file mode 100644 index 0000000..f6caea8 --- /dev/null +++ b/libraries/ode-0.9/contrib/dRay/Include/dRay.h | |||
@@ -0,0 +1,15 @@ | |||
1 | #include "ode\ode.h" | ||
2 | |||
3 | /* Class ID */ | ||
4 | extern int dRayClass; | ||
5 | |||
6 | /* Creates a ray */ | ||
7 | dxGeom* dGeomCreateRay(dSpaceID space, dReal Length); | ||
8 | |||
9 | /* Set/Get length */ | ||
10 | void dGeomRaySetLength(dxGeom* g, dReal Length); | ||
11 | dReal dGeomRayGetLength(dxGeom* g); | ||
12 | |||
13 | /* Utility function to override the ray's pos + rot */ | ||
14 | void dGeomRaySet(dxGeom* g, dVector3 Origin, dVector3 Direction); | ||
15 | void dGeomRayGet(dxGeom* g, dVector3 Origin, dVector3 Direction); | ||
diff --git a/libraries/ode-0.9/contrib/dRay/README.txt b/libraries/ode-0.9/contrib/dRay/README.txt new file mode 100644 index 0000000..8997208 --- /dev/null +++ b/libraries/ode-0.9/contrib/dRay/README.txt | |||
@@ -0,0 +1,16 @@ | |||
1 | From: "Erwin de Vries" <erwin@vo.com> | ||
2 | To: <ode@q12.org> | ||
3 | Subject: [ODE] dRay class | ||
4 | Date: Thu, 25 Jul 2002 13:05:28 +0200 | ||
5 | |||
6 | Yesterday and today i've written a dRay class. It interacts with dPlane, | ||
7 | dSphere, dBox and dCCylinder. It does not generate full contact information. | ||
8 | It only generates the pos member. I dont think its useful to anyone to go | ||
9 | through hoops and find a reasonable normal and penetration depth, as i dont | ||
10 | think anyone will want to use it for dynamics. Just for CD. | ||
11 | |||
12 | It should compile in single and double precision mode, and should be | ||
13 | platform independant. I hope. | ||
14 | |||
15 | The next Tri-Collider release using Opcode 1.1 will also implement a ray | ||
16 | collision function along with some other not too interesting improvements. | ||
diff --git a/libraries/ode-0.9/contrib/dRay/Test/test_ray.cpp b/libraries/ode-0.9/contrib/dRay/Test/test_ray.cpp new file mode 100644 index 0000000..faa8b14 --- /dev/null +++ b/libraries/ode-0.9/contrib/dRay/Test/test_ray.cpp | |||
@@ -0,0 +1,1372 @@ | |||
1 | /************************************************************************* | ||
2 | |||
3 | |||
4 | * * | ||
5 | |||
6 | |||
7 | * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * | ||
8 | |||
9 | |||
10 | * All rights reserved. Email: russ@q12.org Web: www.q12.org * | ||
11 | |||
12 | |||
13 | * * | ||
14 | |||
15 | |||
16 | * This library is free software; you can redistribute it and/or * | ||
17 | |||
18 | |||
19 | * modify it under the terms of EITHER: * | ||
20 | |||
21 | |||
22 | * (1) The GNU Lesser General Public License as published by the Free * | ||
23 | |||
24 | |||
25 | * Software Foundation; either version 2.1 of the License, or (at * | ||
26 | |||
27 | |||
28 | * your option) any later version. The text of the GNU Lesser * | ||
29 | |||
30 | |||
31 | * General Public License is included with this library in the * | ||
32 | |||
33 | |||
34 | * file LICENSE.TXT. * | ||
35 | |||
36 | |||
37 | * (2) The BSD-style license that is included with this library in * | ||
38 | |||
39 | |||
40 | * the file LICENSE-BSD.TXT. * | ||
41 | |||
42 | |||
43 | * * | ||
44 | |||
45 | |||
46 | * This library is distributed in the hope that it will be useful, * | ||
47 | |||
48 | |||
49 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
50 | |||
51 | |||
52 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * | ||
53 | |||
54 | |||
55 | * LICENSE.TXT and LICENSE-BSD.TXT for more details. * | ||
56 | |||
57 | |||
58 | * * | ||
59 | |||
60 | |||
61 | *************************************************************************/ | ||
62 | |||
63 | |||
64 | |||
65 | |||
66 | |||
67 | #include <ode/ode.h> | ||
68 | |||
69 | |||
70 | #include <dRay.h> | ||
71 | |||
72 | |||
73 | #include <drawstuff/drawstuff.h> | ||
74 | |||
75 | |||
76 | |||
77 | |||
78 | |||
79 | #ifdef _MSC_VER | ||
80 | |||
81 | |||
82 | #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints | ||
83 | |||
84 | |||
85 | #endif | ||
86 | |||
87 | |||
88 | |||
89 | |||
90 | |||
91 | // select correct drawing functions | ||
92 | |||
93 | |||
94 | |||
95 | |||
96 | |||
97 | #ifdef dDOUBLE | ||
98 | |||
99 | |||
100 | #define dsDrawBox dsDrawBoxD | ||
101 | |||
102 | |||
103 | #define dsDrawSphere dsDrawSphereD | ||
104 | |||
105 | |||
106 | #define dsDrawCylinder dsDrawCylinderD | ||
107 | |||
108 | |||
109 | #define dsDrawCappedCylinder dsDrawCappedCylinderD | ||
110 | |||
111 | |||
112 | #endif | ||
113 | |||
114 | |||
115 | |||
116 | |||
117 | |||
118 | |||
119 | |||
120 | |||
121 | // some constants | ||
122 | |||
123 | |||
124 | |||
125 | |||
126 | |||
127 | #define NUM 20 // max number of objects | ||
128 | |||
129 | |||
130 | #define DENSITY (5.0) // density of all objects | ||
131 | |||
132 | |||
133 | #define GPB 3 // maximum number of geometries per body | ||
134 | |||
135 | |||
136 | |||
137 | |||
138 | |||
139 | |||
140 | |||
141 | |||
142 | // dynamics and collision objects | ||
143 | |||
144 | |||
145 | |||
146 | |||
147 | |||
148 | struct MyObject { | ||
149 | |||
150 | |||
151 | dBodyID body; // the body | ||
152 | |||
153 | |||
154 | dGeomID geom[GPB]; // geometries representing this body | ||
155 | |||
156 | |||
157 | }; | ||
158 | |||
159 | |||
160 | |||
161 | |||
162 | |||
163 | static int num=0; // number of objects in simulation | ||
164 | |||
165 | |||
166 | static int nextobj=0; // next object to recycle if num==NUM | ||
167 | |||
168 | |||
169 | static dWorldID world; | ||
170 | |||
171 | |||
172 | static dSpaceID space; | ||
173 | |||
174 | |||
175 | static MyObject obj[NUM]; | ||
176 | |||
177 | |||
178 | static dJointGroupID contactgroup; | ||
179 | |||
180 | |||
181 | static int selected = -1; // selected object | ||
182 | |||
183 | |||
184 | |||
185 | |||
186 | |||
187 | static dGeomID* Rays; | ||
188 | |||
189 | |||
190 | static int RayCount; | ||
191 | |||
192 | |||
193 | |||
194 | |||
195 | |||
196 | // this is called by dSpaceCollide when two objects in space are | ||
197 | |||
198 | |||
199 | // potentially colliding. | ||
200 | |||
201 | |||
202 | |||
203 | |||
204 | |||
205 | static void nearCallback (void *data, dGeomID o1, dGeomID o2) | ||
206 | |||
207 | |||
208 | { | ||
209 | |||
210 | |||
211 | int i; | ||
212 | |||
213 | |||
214 | // if (o1->body && o2->body) return; | ||
215 | |||
216 | |||
217 | |||
218 | |||
219 | |||
220 | // exit without doing anything if the two bodies are connected by a joint | ||
221 | |||
222 | |||
223 | dBodyID b1 = dGeomGetBody(o1); | ||
224 | |||
225 | |||
226 | dBodyID b2 = dGeomGetBody(o2); | ||
227 | |||
228 | |||
229 | if (b1 && b2 && dAreConnected (b1,b2)) return; | ||
230 | |||
231 | |||
232 | |||
233 | |||
234 | |||
235 | dContact contact[32]; // up to 3 contacts per box | ||
236 | |||
237 | |||
238 | for (i=0; i<32; i++) { | ||
239 | |||
240 | |||
241 | contact[i].surface.mode = dContactBounce; //dContactMu2; | ||
242 | |||
243 | |||
244 | contact[i].surface.mu = dInfinity; | ||
245 | |||
246 | |||
247 | contact[i].surface.mu2 = 0; | ||
248 | |||
249 | |||
250 | contact[i].surface.bounce = 0.5; | ||
251 | |||
252 | |||
253 | contact[i].surface.bounce_vel = 0.1; | ||
254 | |||
255 | |||
256 | } | ||
257 | |||
258 | |||
259 | if (int numc = dCollide (o1,o2,3,&contact[0].geom,sizeof(dContact))) { | ||
260 | |||
261 | |||
262 | dMatrix3 RI; | ||
263 | |||
264 | |||
265 | dRSetIdentity (RI); | ||
266 | |||
267 | |||
268 | const dReal ss[3] = {0.02,0.02,0.02}; | ||
269 | |||
270 | |||
271 | for (i=0; i<numc; i++) { | ||
272 | |||
273 | |||
274 | if (dGeomGetClass(o1) == dRayClass || dGeomGetClass(o2) == dRayClass){ | ||
275 | |||
276 | |||
277 | dMatrix3 Rotation; | ||
278 | |||
279 | |||
280 | dRSetIdentity(Rotation); | ||
281 | |||
282 | |||
283 | dsDrawSphere(contact[i].geom.pos, Rotation, REAL(0.01)); | ||
284 | |||
285 | |||
286 | continue; | ||
287 | |||
288 | |||
289 | } | ||
290 | |||
291 | |||
292 | |||
293 | |||
294 | |||
295 | dJointID c = dJointCreateContact (world,contactgroup,contact+i); | ||
296 | |||
297 | |||
298 | dJointAttach (c,b1,b2); | ||
299 | |||
300 | |||
301 | //dsDrawBox (contact[i].geom.pos,RI,ss); | ||
302 | |||
303 | |||
304 | |||
305 | |||
306 | |||
307 | |||
308 | |||
309 | |||
310 | } | ||
311 | |||
312 | |||
313 | } | ||
314 | |||
315 | |||
316 | } | ||
317 | |||
318 | |||
319 | |||
320 | |||
321 | |||
322 | // start simulation - set viewpoint | ||
323 | |||
324 | |||
325 | |||
326 | |||
327 | |||
328 | static void start() | ||
329 | |||
330 | |||
331 | { | ||
332 | |||
333 | |||
334 | static float xyz[3] = {2.1640f,-1.3079f,1.7600f}; | ||
335 | |||
336 | |||
337 | static float hpr[3] = {125.5000f,-17.0000f,0.0000f}; | ||
338 | |||
339 | |||
340 | dsSetViewpoint (xyz,hpr); | ||
341 | |||
342 | |||
343 | printf ("To drop another object, press:\n"); | ||
344 | |||
345 | |||
346 | printf (" b for box.\n"); | ||
347 | |||
348 | |||
349 | printf (" s for sphere.\n"); | ||
350 | |||
351 | |||
352 | printf (" c for cylinder.\n"); | ||
353 | |||
354 | |||
355 | printf (" x for a composite object.\n"); | ||
356 | |||
357 | |||
358 | printf ("To select an object, press space.\n"); | ||
359 | |||
360 | |||
361 | printf ("To disable the selected object, press d.\n"); | ||
362 | |||
363 | |||
364 | printf ("To enable the selected object, press e.\n"); | ||
365 | |||
366 | |||
367 | } | ||
368 | |||
369 | |||
370 | |||
371 | |||
372 | |||
373 | |||
374 | |||
375 | |||
376 | char locase (char c) | ||
377 | |||
378 | |||
379 | { | ||
380 | |||
381 | |||
382 | if (c >= 'A' && c <= 'Z') return c - ('a'-'A'); | ||
383 | |||
384 | |||
385 | else return c; | ||
386 | |||
387 | |||
388 | } | ||
389 | |||
390 | |||
391 | |||
392 | |||
393 | |||
394 | |||
395 | |||
396 | |||
397 | // called when a key pressed | ||
398 | |||
399 | |||
400 | |||
401 | |||
402 | |||
403 | static void command (int cmd) | ||
404 | |||
405 | |||
406 | { | ||
407 | |||
408 | |||
409 | int i,j,k; | ||
410 | |||
411 | |||
412 | dReal sides[3]; | ||
413 | |||
414 | |||
415 | dMass m; | ||
416 | |||
417 | |||
418 | |||
419 | |||
420 | |||
421 | cmd = locase (cmd); | ||
422 | |||
423 | |||
424 | if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'x') { | ||
425 | |||
426 | |||
427 | if (num < NUM) { | ||
428 | |||
429 | |||
430 | i = num; | ||
431 | |||
432 | |||
433 | num++; | ||
434 | |||
435 | |||
436 | } | ||
437 | |||
438 | |||
439 | else { | ||
440 | |||
441 | |||
442 | i = nextobj; | ||
443 | |||
444 | |||
445 | nextobj++; | ||
446 | |||
447 | |||
448 | if (nextobj >= num) nextobj = 0; | ||
449 | |||
450 | |||
451 | |||
452 | |||
453 | |||
454 | // destroy the body and geoms for slot i | ||
455 | |||
456 | |||
457 | dBodyDestroy (obj[i].body); | ||
458 | |||
459 | |||
460 | for (k=0; k < GPB; k++) { | ||
461 | |||
462 | |||
463 | if (obj[i].geom[k]) dGeomDestroy (obj[i].geom[k]); | ||
464 | |||
465 | |||
466 | } | ||
467 | |||
468 | |||
469 | memset (&obj[i],0,sizeof(obj[i])); | ||
470 | |||
471 | |||
472 | } | ||
473 | |||
474 | |||
475 | |||
476 | |||
477 | |||
478 | obj[i].body = dBodyCreate (world); | ||
479 | |||
480 | |||
481 | for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1; | ||
482 | |||
483 | |||
484 | |||
485 | |||
486 | |||
487 | dBodySetPosition (obj[i].body, | ||
488 | |||
489 | |||
490 | dRandReal()*2-1,dRandReal()*2-1,dRandReal()+1); | ||
491 | |||
492 | |||
493 | dMatrix3 R; | ||
494 | |||
495 | |||
496 | dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0, | ||
497 | |||
498 | |||
499 | dRandReal()*2.0-1.0,dRandReal()*10.0-5.0); | ||
500 | |||
501 | |||
502 | dBodySetRotation (obj[i].body,R); | ||
503 | |||
504 | |||
505 | dBodySetData (obj[i].body,(void*) i); | ||
506 | |||
507 | |||
508 | |||
509 | |||
510 | |||
511 | if (cmd == 'b') { | ||
512 | |||
513 | |||
514 | dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]); | ||
515 | |||
516 | |||
517 | obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]); | ||
518 | |||
519 | |||
520 | } | ||
521 | |||
522 | |||
523 | else if (cmd == 'c') { | ||
524 | |||
525 | |||
526 | sides[0] *= 0.5; | ||
527 | |||
528 | |||
529 | dMassSetCappedCylinder (&m,DENSITY,3,sides[0],sides[1]); | ||
530 | |||
531 | |||
532 | obj[i].geom[0] = dCreateCCylinder (space,sides[0],sides[1]); | ||
533 | |||
534 | |||
535 | } | ||
536 | |||
537 | |||
538 | else if (cmd == 's') { | ||
539 | |||
540 | |||
541 | sides[0] *= 0.5; | ||
542 | |||
543 | |||
544 | dMassSetSphere (&m,DENSITY,sides[0]); | ||
545 | |||
546 | |||
547 | obj[i].geom[0] = dCreateSphere (space,sides[0]); | ||
548 | |||
549 | |||
550 | } | ||
551 | |||
552 | |||
553 | else if (cmd == 'x') { | ||
554 | |||
555 | |||
556 | dGeomID g2[GPB]; // encapsulated geometries | ||
557 | |||
558 | |||
559 | dReal dpos[GPB][3]; // delta-positions for encapsulated geometries | ||
560 | |||
561 | |||
562 | |||
563 | |||
564 | |||
565 | // start accumulating masses for the encapsulated geometries | ||
566 | |||
567 | |||
568 | dMass m2; | ||
569 | |||
570 | |||
571 | dMassSetZero (&m); | ||
572 | |||
573 | |||
574 | |||
575 | |||
576 | |||
577 | // set random delta positions | ||
578 | |||
579 | |||
580 | for (j=0; j<GPB; j++) { | ||
581 | |||
582 | |||
583 | for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15; | ||
584 | |||
585 | |||
586 | } | ||
587 | |||
588 | |||
589 | |||
590 | |||
591 | |||
592 | for (k=0; k<3; k++) { | ||
593 | |||
594 | |||
595 | obj[i].geom[k] = dCreateGeomTransform (space); | ||
596 | |||
597 | |||
598 | dGeomTransformSetCleanup (obj[i].geom[k],1); | ||
599 | |||
600 | |||
601 | if (k==0) { | ||
602 | |||
603 | |||
604 | dReal radius = dRandReal()*0.25+0.05; | ||
605 | |||
606 | |||
607 | g2[k] = dCreateSphere (0,radius); | ||
608 | |||
609 | |||
610 | dMassSetSphere (&m2,DENSITY,radius); | ||
611 | |||
612 | |||
613 | } | ||
614 | |||
615 | |||
616 | else if (k==1) { | ||
617 | |||
618 | |||
619 | g2[k] = dCreateBox (0,sides[0],sides[1],sides[2]); | ||
620 | |||
621 | |||
622 | dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]); | ||
623 | |||
624 | |||
625 | } | ||
626 | |||
627 | |||
628 | else { | ||
629 | |||
630 | |||
631 | dReal radius = dRandReal()*0.1+0.05; | ||
632 | |||
633 | |||
634 | dReal length = dRandReal()*1.0+0.1; | ||
635 | |||
636 | |||
637 | g2[k] = dCreateCCylinder (0,radius,length); | ||
638 | |||
639 | |||
640 | dMassSetCappedCylinder (&m2,DENSITY,3,radius,length); | ||
641 | |||
642 | |||
643 | } | ||
644 | |||
645 | |||
646 | dGeomTransformSetGeom (obj[i].geom[k],g2[k]); | ||
647 | |||
648 | |||
649 | |||
650 | |||
651 | |||
652 | // set the transformation (adjust the mass too) | ||
653 | |||
654 | |||
655 | dGeomSetPosition (g2[k],dpos[k][0],dpos[k][1],dpos[k][2]); | ||
656 | |||
657 | |||
658 | dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]); | ||
659 | |||
660 | |||
661 | dMatrix3 Rtx; | ||
662 | |||
663 | |||
664 | dRFromAxisAndAngle (Rtx,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0, | ||
665 | |||
666 | |||
667 | dRandReal()*2.0-1.0,dRandReal()*10.0-5.0); | ||
668 | |||
669 | |||
670 | dGeomSetRotation (g2[k],Rtx); | ||
671 | |||
672 | |||
673 | dMassRotate (&m2,Rtx); | ||
674 | |||
675 | |||
676 | |||
677 | |||
678 | |||
679 | // add to the total mass | ||
680 | |||
681 | |||
682 | dMassAdd (&m,&m2); | ||
683 | |||
684 | |||
685 | } | ||
686 | |||
687 | |||
688 | |||
689 | |||
690 | |||
691 | // move all encapsulated objects so that the center of mass is (0,0,0) | ||
692 | |||
693 | |||
694 | for (k=0; k<2; k++) { | ||
695 | |||
696 | |||
697 | dGeomSetPosition (g2[k], | ||
698 | |||
699 | |||
700 | dpos[k][0]-m.c[0], | ||
701 | |||
702 | |||
703 | dpos[k][1]-m.c[1], | ||
704 | |||
705 | |||
706 | dpos[k][2]-m.c[2]); | ||
707 | |||
708 | |||
709 | } | ||
710 | |||
711 | |||
712 | dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]); | ||
713 | |||
714 | |||
715 | } | ||
716 | |||
717 | |||
718 | |||
719 | |||
720 | |||
721 | for (k=0; k < GPB; k++) { | ||
722 | |||
723 | |||
724 | if (obj[i].geom[k]) dGeomSetBody (obj[i].geom[k],obj[i].body); | ||
725 | |||
726 | |||
727 | } | ||
728 | |||
729 | |||
730 | |||
731 | |||
732 | |||
733 | dBodySetMass (obj[i].body,&m); | ||
734 | |||
735 | |||
736 | } | ||
737 | |||
738 | |||
739 | |||
740 | |||
741 | |||
742 | if (cmd == ' ') { | ||
743 | |||
744 | |||
745 | selected++; | ||
746 | |||
747 | |||
748 | if (selected >= num) selected = 0; | ||
749 | |||
750 | |||
751 | if (selected < 0) selected = 0; | ||
752 | |||
753 | |||
754 | } | ||
755 | |||
756 | |||
757 | else if (cmd == 'd' && selected >= 0 && selected < num) { | ||
758 | |||
759 | |||
760 | dBodyDisable (obj[selected].body); | ||
761 | |||
762 | |||
763 | } | ||
764 | |||
765 | |||
766 | else if (cmd == 'e' && selected >= 0 && selected < num) { | ||
767 | |||
768 | |||
769 | dBodyEnable (obj[selected].body); | ||
770 | |||
771 | |||
772 | } | ||
773 | |||
774 | |||
775 | } | ||
776 | |||
777 | |||
778 | |||
779 | |||
780 | |||
781 | |||
782 | |||
783 | |||
784 | // draw a geom | ||
785 | |||
786 | |||
787 | |||
788 | |||
789 | |||
790 | void drawGeom (dGeomID g, const dReal *pos, const dReal *R) | ||
791 | |||
792 | |||
793 | { | ||
794 | |||
795 | |||
796 | if (!g) return; | ||
797 | |||
798 | |||
799 | if (!pos) pos = dGeomGetPosition (g); | ||
800 | |||
801 | |||
802 | if (!R) R = dGeomGetRotation (g); | ||
803 | |||
804 | |||
805 | |||
806 | |||
807 | |||
808 | int type = dGeomGetClass (g); | ||
809 | |||
810 | |||
811 | if (type == dBoxClass) { | ||
812 | |||
813 | |||
814 | dVector3 sides; | ||
815 | |||
816 | |||
817 | dGeomBoxGetLengths (g,sides); | ||
818 | |||
819 | |||
820 | dsDrawBox (pos,R,sides); | ||
821 | |||
822 | |||
823 | } | ||
824 | |||
825 | |||
826 | else if (type == dSphereClass) { | ||
827 | |||
828 | |||
829 | dsDrawSphere (pos,R,dGeomSphereGetRadius (g)); | ||
830 | |||
831 | |||
832 | } | ||
833 | |||
834 | |||
835 | else if (type == dCCylinderClass) { | ||
836 | |||
837 | |||
838 | dReal radius,length; | ||
839 | |||
840 | |||
841 | dGeomCCylinderGetParams (g,&radius,&length); | ||
842 | |||
843 | |||
844 | dsDrawCappedCylinder (pos,R,length,radius); | ||
845 | |||
846 | |||
847 | } | ||
848 | |||
849 | |||
850 | else if (type == dGeomTransformClass) { | ||
851 | |||
852 | |||
853 | dGeomID g2 = dGeomTransformGetGeom (g); | ||
854 | |||
855 | |||
856 | const dReal *pos2 = dGeomGetPosition (g2); | ||
857 | |||
858 | |||
859 | const dReal *R2 = dGeomGetRotation (g2); | ||
860 | |||
861 | |||
862 | dVector3 actual_pos; | ||
863 | |||
864 | |||
865 | dMatrix3 actual_R; | ||
866 | |||
867 | |||
868 | dMULTIPLY0_331 (actual_pos,R,pos2); | ||
869 | |||
870 | |||
871 | actual_pos[0] += pos[0]; | ||
872 | |||
873 | |||
874 | actual_pos[1] += pos[1]; | ||
875 | |||
876 | |||
877 | actual_pos[2] += pos[2]; | ||
878 | |||
879 | |||
880 | dMULTIPLY0_333 (actual_R,R,R2); | ||
881 | |||
882 | |||
883 | drawGeom (g2,actual_pos,actual_R); | ||
884 | |||
885 | |||
886 | } | ||
887 | |||
888 | |||
889 | } | ||
890 | |||
891 | |||
892 | |||
893 | |||
894 | |||
895 | |||
896 | |||
897 | |||
898 | // simulation loop | ||
899 | |||
900 | |||
901 | |||
902 | |||
903 | |||
904 | static void simLoop (int pause) | ||
905 | |||
906 | |||
907 | { | ||
908 | |||
909 | |||
910 | dsSetColor (0,0,2); | ||
911 | |||
912 | |||
913 | dSpaceCollide (space,0,&nearCallback); | ||
914 | |||
915 | |||
916 | if (!pause) dWorldStep (world,0.05); | ||
917 | |||
918 | |||
919 | |||
920 | |||
921 | |||
922 | // remove all contact joints | ||
923 | |||
924 | |||
925 | dJointGroupEmpty (contactgroup); | ||
926 | |||
927 | |||
928 | |||
929 | |||
930 | |||
931 | dsSetColor (1,1,0); | ||
932 | |||
933 | |||
934 | dsSetTexture (DS_WOOD); | ||
935 | |||
936 | |||
937 | for (int i=0; i<num; i++) { | ||
938 | |||
939 | |||
940 | int color_changed = 0; | ||
941 | |||
942 | |||
943 | if (i==selected) { | ||
944 | |||
945 | |||
946 | dsSetColor (0,0.7,1); | ||
947 | |||
948 | |||
949 | color_changed = 1; | ||
950 | |||
951 | |||
952 | } | ||
953 | |||
954 | |||
955 | else if (! dBodyIsEnabled (obj[i].body)) { | ||
956 | |||
957 | |||
958 | dsSetColor (1,0,0); | ||
959 | |||
960 | |||
961 | color_changed = 1; | ||
962 | |||
963 | |||
964 | } | ||
965 | |||
966 | |||
967 | for (int j=0; j < GPB; j++) drawGeom (obj[i].geom[j],0,0); | ||
968 | |||
969 | |||
970 | if (color_changed) dsSetColor (1,1,0); | ||
971 | |||
972 | |||
973 | } | ||
974 | |||
975 | |||
976 | |||
977 | |||
978 | |||
979 | {for (int i = 0; i < RayCount; i++){ | ||
980 | |||
981 | |||
982 | dVector3 Origin, Direction; | ||
983 | |||
984 | |||
985 | dGeomRayGet(Rays[i], Origin, Direction); | ||
986 | |||
987 | |||
988 | |||
989 | |||
990 | |||
991 | dReal Length = dGeomRayGetLength(Rays[i]); | ||
992 | |||
993 | |||
994 | |||
995 | |||
996 | |||
997 | dVector3 End; | ||
998 | |||
999 | |||
1000 | End[0] = Origin[0] + (Direction[0] * Length); | ||
1001 | |||
1002 | |||
1003 | End[1] = Origin[1] + (Direction[1] * Length); | ||
1004 | |||
1005 | |||
1006 | End[2] = Origin[2] + (Direction[2] * Length); | ||
1007 | |||
1008 | |||
1009 | End[3] = Origin[3] + (Direction[3] * Length); | ||
1010 | |||
1011 | |||
1012 | |||
1013 | |||
1014 | |||
1015 | dsDrawLine(Origin, End); | ||
1016 | |||
1017 | |||
1018 | }} | ||
1019 | |||
1020 | |||
1021 | } | ||
1022 | |||
1023 | |||
1024 | |||
1025 | |||
1026 | |||
1027 | |||
1028 | |||
1029 | |||
1030 | int main (int argc, char **argv) | ||
1031 | |||
1032 | |||
1033 | { | ||
1034 | |||
1035 | |||
1036 | // setup pointers to drawstuff callback functions | ||
1037 | |||
1038 | |||
1039 | dsFunctions fn; | ||
1040 | |||
1041 | |||
1042 | fn.version = DS_VERSION; | ||
1043 | |||
1044 | |||
1045 | fn.start = &start; | ||
1046 | |||
1047 | |||
1048 | fn.step = &simLoop; | ||
1049 | |||
1050 | |||
1051 | fn.command = &command; | ||
1052 | |||
1053 | |||
1054 | fn.stop = 0; | ||
1055 | |||
1056 | |||
1057 | fn.path_to_textures = "../../drawstuff/textures"; | ||
1058 | |||
1059 | |||
1060 | if(argc==2) | ||
1061 | { | ||
1062 | fn.path_to_textures = argv[1]; | ||
1063 | } | ||
1064 | |||
1065 | |||
1066 | |||
1067 | // create world | ||
1068 | |||
1069 | |||
1070 | |||
1071 | |||
1072 | |||
1073 | world = dWorldCreate(); | ||
1074 | |||
1075 | |||
1076 | space = dHashSpaceCreate(); | ||
1077 | |||
1078 | |||
1079 | contactgroup = dJointGroupCreate (0); | ||
1080 | |||
1081 | |||
1082 | dWorldSetGravity (world,0,0,-0.5); | ||
1083 | |||
1084 | |||
1085 | dWorldSetCFM (world,1e-5); | ||
1086 | |||
1087 | |||
1088 | dCreatePlane (space,0,0,1,0); | ||
1089 | |||
1090 | |||
1091 | memset (obj,0,sizeof(obj)); | ||
1092 | |||
1093 | |||
1094 | |||
1095 | |||
1096 | |||
1097 | dVector3 Origin, Direction; | ||
1098 | |||
1099 | |||
1100 | |||
1101 | |||
1102 | |||
1103 | RayCount = 5; | ||
1104 | |||
1105 | |||
1106 | Rays = new dGeomID[RayCount]; | ||
1107 | |||
1108 | |||
1109 | |||
1110 | |||
1111 | |||
1112 | /* Ray 0 */ | ||
1113 | |||
1114 | |||
1115 | Origin[0] = 1; | ||
1116 | |||
1117 | |||
1118 | Origin[1] = 1; | ||
1119 | |||
1120 | |||
1121 | Origin[2] = 1.5; | ||
1122 | |||
1123 | |||
1124 | Origin[3] = 0; | ||
1125 | |||
1126 | |||
1127 | |||
1128 | |||
1129 | |||
1130 | Direction[0] = 0.0f; | ||
1131 | |||
1132 | |||
1133 | Direction[1] = 0.0f; | ||
1134 | |||
1135 | |||
1136 | Direction[2] = -1; | ||
1137 | |||
1138 | |||
1139 | Direction[3] = 0; | ||
1140 | |||
1141 | |||
1142 | |||
1143 | |||
1144 | |||
1145 | dNormalize3(Direction); | ||
1146 | |||
1147 | |||
1148 | |||
1149 | |||
1150 | |||
1151 | Rays[0] = dGeomCreateRay(space, 5.0f); | ||
1152 | |||
1153 | |||
1154 | dGeomRaySet(Rays[0], Origin, Direction); | ||
1155 | |||
1156 | |||
1157 | |||
1158 | |||
1159 | |||
1160 | /* Ray 1 */ | ||
1161 | |||
1162 | |||
1163 | Origin[0] = 0; | ||
1164 | |||
1165 | |||
1166 | Origin[1] = 10; | ||
1167 | |||
1168 | |||
1169 | Origin[2] = 0.25; | ||
1170 | |||
1171 | |||
1172 | Origin[3] = 0; | ||
1173 | |||
1174 | |||
1175 | |||
1176 | |||
1177 | |||
1178 | Direction[0] = 0.0f; | ||
1179 | |||
1180 | |||
1181 | Direction[1] = -1.0f; | ||
1182 | |||
1183 | |||
1184 | Direction[2] = 0.0f; | ||
1185 | |||
1186 | |||
1187 | Direction[3] = 0; | ||
1188 | |||
1189 | |||
1190 | |||
1191 | |||
1192 | |||
1193 | dNormalize3(Direction); | ||
1194 | |||
1195 | |||
1196 | |||
1197 | |||
1198 | |||
1199 | Rays[1] = dGeomCreateRay(space, 20.0f); | ||
1200 | |||
1201 | |||
1202 | dGeomRaySet(Rays[1], Origin, Direction); | ||
1203 | |||
1204 | |||
1205 | |||
1206 | |||
1207 | |||
1208 | /* Ray 2 */ | ||
1209 | |||
1210 | |||
1211 | Origin[0] = -10; | ||
1212 | |||
1213 | |||
1214 | Origin[1] = 0; | ||
1215 | |||
1216 | |||
1217 | Origin[2] = 0.20; | ||
1218 | |||
1219 | |||
1220 | Origin[3] = 0; | ||
1221 | |||
1222 | |||
1223 | |||
1224 | |||
1225 | |||
1226 | Direction[0] = 1.0f; | ||
1227 | |||
1228 | |||
1229 | Direction[1] = 0.0f; | ||
1230 | |||
1231 | |||
1232 | Direction[2] = 0.0f; | ||
1233 | |||
1234 | |||
1235 | Direction[3] = 0; | ||
1236 | |||
1237 | |||
1238 | |||
1239 | |||
1240 | |||
1241 | dNormalize3(Direction); | ||
1242 | |||
1243 | |||
1244 | |||
1245 | |||
1246 | |||
1247 | Rays[2] = dGeomCreateRay(space, 20.0f); | ||
1248 | |||
1249 | |||
1250 | dGeomRaySet(Rays[2], Origin, Direction); | ||
1251 | |||
1252 | |||
1253 | |||
1254 | |||
1255 | |||
1256 | /* Ray 3 */ | ||
1257 | |||
1258 | |||
1259 | Origin[0] = -9; | ||
1260 | |||
1261 | |||
1262 | Origin[1] = 11; | ||
1263 | |||
1264 | |||
1265 | Origin[2] = 0.15; | ||
1266 | |||
1267 | |||
1268 | Origin[3] = 0; | ||
1269 | |||
1270 | |||
1271 | |||
1272 | |||
1273 | |||
1274 | Direction[0] = 1.0f; | ||
1275 | |||
1276 | |||
1277 | Direction[1] = -1.0f; | ||
1278 | |||
1279 | |||
1280 | Direction[2] = 0.0f; | ||
1281 | |||
1282 | |||
1283 | Direction[3] = 0; | ||
1284 | |||
1285 | |||
1286 | |||
1287 | |||
1288 | |||
1289 | dNormalize3(Direction); | ||
1290 | |||
1291 | |||
1292 | |||
1293 | |||
1294 | |||
1295 | Rays[3] = dGeomCreateRay(space, 20.0f); | ||
1296 | |||
1297 | |||
1298 | dGeomRaySet(Rays[3], Origin, Direction); | ||
1299 | |||
1300 | |||
1301 | |||
1302 | |||
1303 | |||
1304 | /* Ray 4 */ | ||
1305 | |||
1306 | |||
1307 | Origin[0] = -0.1; | ||
1308 | |||
1309 | |||
1310 | Origin[1] = 0.3; | ||
1311 | |||
1312 | |||
1313 | Origin[2] = 0.30; | ||
1314 | |||
1315 | |||
1316 | Origin[3] = 0; | ||
1317 | |||
1318 | |||
1319 | |||
1320 | |||
1321 | |||
1322 | Direction[0] = 0.3f; | ||
1323 | |||
1324 | |||
1325 | Direction[1] = 0.5f; | ||
1326 | |||
1327 | |||
1328 | Direction[2] = 1.0f; | ||
1329 | |||
1330 | |||
1331 | Direction[3] = 0; | ||
1332 | |||
1333 | |||
1334 | |||
1335 | |||
1336 | |||
1337 | Rays[4] = dGeomCreateRay(space, 5.0f); | ||
1338 | |||
1339 | |||
1340 | dGeomRaySet(Rays[4], Origin, Direction); | ||
1341 | |||
1342 | |||
1343 | |||
1344 | |||
1345 | |||
1346 | // run simulation | ||
1347 | |||
1348 | |||
1349 | dsSimulationLoop (argc,argv,352,288,&fn); | ||
1350 | |||
1351 | |||
1352 | |||
1353 | |||
1354 | |||
1355 | dJointGroupDestroy (contactgroup); | ||
1356 | |||
1357 | |||
1358 | dSpaceDestroy (space); | ||
1359 | |||
1360 | |||
1361 | dWorldDestroy (world); | ||
1362 | |||
1363 | |||
1364 | |||
1365 | |||
1366 | |||
1367 | return 0; | ||
1368 | |||
1369 | |||
1370 | } | ||
1371 | |||
1372 | |||
diff --git a/libraries/ode-0.9/contrib/dRay/dRay.cpp b/libraries/ode-0.9/contrib/dRay/dRay.cpp new file mode 100644 index 0000000..e3a426e --- /dev/null +++ b/libraries/ode-0.9/contrib/dRay/dRay.cpp | |||
@@ -0,0 +1,119 @@ | |||
1 | #include "Include\dRay.h" | ||
2 | #include "dxRay.h" | ||
3 | |||
4 | int dRayClass = -1; | ||
5 | |||
6 | void dAABBRay(dxGeom* Ray, dReal AABB[6]){ | ||
7 | dVector3 Start, End; | ||
8 | dGeomRayGet(Ray, Start, End); | ||
9 | dReal Length = dGeomRayGetLength(Ray); | ||
10 | |||
11 | End[0] = Start[0] + End[0] * Length; | ||
12 | End[1] = Start[1] + End[1] * Length; | ||
13 | End[2] = Start[2] + End[2] * Length; | ||
14 | End[3] = Start[3] + End[3] * Length; | ||
15 | |||
16 | if (Start[0] < End[0]){ | ||
17 | AABB[0] = Start[0]; | ||
18 | AABB[1] = End[0]; | ||
19 | } | ||
20 | else{ | ||
21 | AABB[0] = End[0]; | ||
22 | AABB[1] = Start[0]; | ||
23 | } | ||
24 | |||
25 | if (Start[1] < End[1]){ | ||
26 | AABB[2] = Start[1]; | ||
27 | AABB[3] = End[1]; | ||
28 | } | ||
29 | else{ | ||
30 | AABB[2] = End[1]; | ||
31 | AABB[3] = Start[1]; | ||
32 | } | ||
33 | |||
34 | if (Start[2] < End[2]){ | ||
35 | AABB[4] = Start[2]; | ||
36 | AABB[5] = End[2]; | ||
37 | } | ||
38 | else{ | ||
39 | AABB[4] = End[2]; | ||
40 | AABB[5] = Start[2]; | ||
41 | } | ||
42 | // Should we tweak the box to have a minimum size for axis aligned lines? How small should it be? | ||
43 | } | ||
44 | |||
45 | dColliderFn* dRayColliderFn(int num){ | ||
46 | if (num == dPlaneClass) return (dColliderFn*)&dCollidePR; | ||
47 | if (num == dSphereClass) return (dColliderFn*)&dCollideSR; | ||
48 | if (num == dBoxClass) return (dColliderFn*)&dCollideBR; | ||
49 | if (num == dCCylinderClass) return (dColliderFn*)&dCollideCCR; | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | dxGeom* dGeomCreateRay(dSpaceID space, dReal Length){ | ||
54 | if (dRayClass == -1){ | ||
55 | dGeomClass c; | ||
56 | c.bytes = sizeof(dxRay); | ||
57 | c.collider = &dRayColliderFn; | ||
58 | c.aabb = &dAABBRay; | ||
59 | c.aabb_test = 0; | ||
60 | c.dtor = 0; | ||
61 | |||
62 | dRayClass = dCreateGeomClass(&c); | ||
63 | } | ||
64 | |||
65 | dxGeom* g = dCreateGeom(dRayClass); | ||
66 | if (space) dSpaceAdd(space, g); | ||
67 | |||
68 | dGeomRaySetLength(g, Length); | ||
69 | return g; | ||
70 | } | ||
71 | |||
72 | void dGeomRaySetLength(dxGeom* g, dReal Length){ | ||
73 | ((dxRay*)dGeomGetClassData(g))->Length = Length; | ||
74 | } | ||
75 | |||
76 | dReal dGeomRayGetLength(dxGeom* g){ | ||
77 | return ((dxRay*)dGeomGetClassData(g))->Length; | ||
78 | } | ||
79 | |||
80 | void dGeomRaySet(dxGeom* g, dVector3 Origin, dVector3 Direction){ | ||
81 | dGeomSetPosition(g, Origin[0], Origin[1], Origin[2]); | ||
82 | |||
83 | dVector3 Up, Right; | ||
84 | dPlaneSpace(Direction, Up, Right); | ||
85 | |||
86 | Origin[3] = Up[3] = Right[3] = REAL(0.0); | ||
87 | |||
88 | dMatrix3 Rotation; | ||
89 | Rotation[0 * 4 + 0] = Right[0]; | ||
90 | Rotation[1 * 4 + 0] = Right[1]; | ||
91 | Rotation[2 * 4 + 0] = Right[2]; | ||
92 | Rotation[3 * 4 + 0] = Right[3]; | ||
93 | |||
94 | Rotation[0 * 4 + 1] = Up[0]; | ||
95 | Rotation[1 * 4 + 1] = Up[1]; | ||
96 | Rotation[2 * 4 + 1] = Up[2]; | ||
97 | Rotation[3 * 4 + 1] = Up[3]; | ||
98 | |||
99 | Rotation[0 * 4 + 2] = Direction[0]; | ||
100 | Rotation[1 * 4 + 2] = Direction[1]; | ||
101 | Rotation[2 * 4 + 2] = Direction[2]; | ||
102 | Rotation[3 * 4 + 2] = Direction[3]; | ||
103 | |||
104 | dGeomSetRotation(g, Rotation); | ||
105 | } | ||
106 | |||
107 | void dGeomRayGet(dxGeom* g, dVector3 Origin, dVector3 Direction){ | ||
108 | const dReal* Position = dGeomGetPosition(g); | ||
109 | Origin[0] = Position[0]; | ||
110 | Origin[1] = Position[1]; | ||
111 | Origin[2] = Position[2]; | ||
112 | Origin[3] = Position[3]; | ||
113 | |||
114 | const dReal* Rotation = dGeomGetRotation(g); | ||
115 | Direction[0] = Rotation[0 * 4 + 2]; | ||
116 | Direction[1] = Rotation[1 * 4 + 2]; | ||
117 | Direction[2] = Rotation[2 * 4 + 2]; | ||
118 | Direction[3] = Rotation[3 * 4 + 2]; | ||
119 | } \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/dRay/dRay_Box.cpp b/libraries/ode-0.9/contrib/dRay/dRay_Box.cpp new file mode 100644 index 0000000..d2a0d9c --- /dev/null +++ b/libraries/ode-0.9/contrib/dRay/dRay_Box.cpp | |||
@@ -0,0 +1,134 @@ | |||
1 | // Ripped from Magic Software | ||
2 | |||
3 | #include "Include\dRay.h" | ||
4 | #include "dxRay.h" | ||
5 | |||
6 | bool Clip(dReal Denom, dReal Numer, dReal& T0, dReal& T1){ | ||
7 | // Return value is 'true' if line segment intersects the current test | ||
8 | // plane. Otherwise 'false' is returned in which case the line segment | ||
9 | // is entirely clipped. | ||
10 | |||
11 | if (Denom > REAL(0.0)){ | ||
12 | if (Numer > Denom * T1){ | ||
13 | return false; | ||
14 | } | ||
15 | |||
16 | if (Numer > Denom * T0){ | ||
17 | T0 = Numer / Denom; | ||
18 | } | ||
19 | return true; | ||
20 | } | ||
21 | else if (Denom < REAL(0.0)){ | ||
22 | if (Numer > Denom * T0){ | ||
23 | return false; | ||
24 | } | ||
25 | |||
26 | if (Numer > Denom * T1){ | ||
27 | T1 = Numer / Denom; | ||
28 | } | ||
29 | return true; | ||
30 | } | ||
31 | else return Numer <= REAL(0.0); | ||
32 | } | ||
33 | |||
34 | bool FindIntersection(const dVector3 Origin, const dVector3 Direction, const dVector3 Extents, dReal& T0, dReal& T1){ | ||
35 | dReal SaveT0 = T0; | ||
36 | dReal SaveT1 = T1; | ||
37 | |||
38 | bool NotEntirelyClipped = | ||
39 | Clip(+Direction[0], -Origin[0] - Extents[0], T0, T1) && | ||
40 | Clip(-Direction[0], +Origin[0] - Extents[0], T0, T1) && | ||
41 | Clip(+Direction[1], -Origin[1] - Extents[1], T0, T1) && | ||
42 | Clip(-Direction[1], +Origin[1] - Extents[1], T0, T1) && | ||
43 | Clip(+Direction[2], -Origin[2] - Extents[2], T0, T1) && | ||
44 | Clip(-Direction[2], +Origin[2] - Extents[2], T0, T1); | ||
45 | |||
46 | return NotEntirelyClipped && (T0 != SaveT0 || T1 != SaveT1); | ||
47 | } | ||
48 | |||
49 | int dCollideBR(dxGeom* RayGeom, dxGeom* BoxGeom, int Flags, dContactGeom* Contacts, int Stride){ | ||
50 | const dVector3& Position = *(const dVector3*)dGeomGetPosition(BoxGeom); | ||
51 | const dMatrix3& Rotation = *(const dMatrix3*)dGeomGetRotation(BoxGeom); | ||
52 | dVector3 Extents; | ||
53 | dGeomBoxGetLengths(BoxGeom, Extents); | ||
54 | Extents[0] /= 2; | ||
55 | Extents[1] /= 2; | ||
56 | Extents[2] /= 2; | ||
57 | Extents[3] /= 2; | ||
58 | |||
59 | dVector3 Origin, Direction; | ||
60 | dGeomRayGet(RayGeom, Origin, Direction); | ||
61 | dReal Length = dGeomRayGetLength(RayGeom); | ||
62 | |||
63 | dVector3 Diff; | ||
64 | Diff[0] = Origin[0] - Position[0]; | ||
65 | Diff[1] = Origin[1] - Position[1]; | ||
66 | Diff[2] = Origin[2] - Position[2]; | ||
67 | Diff[3] = Origin[3] - Position[3]; | ||
68 | |||
69 | Direction[0] *= Length; | ||
70 | Direction[1] *= Length; | ||
71 | Direction[2] *= Length; | ||
72 | Direction[3] *= Length; | ||
73 | |||
74 | dVector3 Rot[3]; | ||
75 | Decompose(Rotation, Rot); | ||
76 | |||
77 | dVector3 TransOrigin; | ||
78 | TransOrigin[0] = dDOT(Diff, Rot[0]); | ||
79 | TransOrigin[1] = dDOT(Diff, Rot[1]); | ||
80 | TransOrigin[2] = dDOT(Diff, Rot[2]); | ||
81 | TransOrigin[3] = REAL(0.0); | ||
82 | |||
83 | dVector3 TransDirection; | ||
84 | TransDirection[0] = dDOT(Direction, Rot[0]); | ||
85 | TransDirection[1] = dDOT(Direction, Rot[1]); | ||
86 | TransDirection[2] = dDOT(Direction, Rot[2]); | ||
87 | TransDirection[3] = REAL(0.0); | ||
88 | |||
89 | dReal T[2]; | ||
90 | T[0] = 0.0f; | ||
91 | T[1] = dInfinity; | ||
92 | |||
93 | bool Intersect = FindIntersection(TransOrigin, TransDirection, Extents, T[0], T[1]); | ||
94 | |||
95 | if (Intersect){ | ||
96 | if (T[0] > REAL(0.0)){ | ||
97 | dContactGeom* Contact0 = CONTACT(Flags, Contacts, 0, Stride); | ||
98 | Contact0->pos[0] = Origin[0] + T[0] * Direction[0]; | ||
99 | Contact0->pos[1] = Origin[1] + T[0] * Direction[1]; | ||
100 | Contact0->pos[2] = Origin[2] + T[0] * Direction[2]; | ||
101 | Contact0->pos[3] = Origin[3] + T[0] * Direction[3]; | ||
102 | //Contact0->normal = 0; | ||
103 | Contact0->depth = 0.0f; | ||
104 | Contact0->g1 = RayGeom; | ||
105 | Contact0->g2 = BoxGeom; | ||
106 | |||
107 | dContactGeom* Contact1 = CONTACT(Flags, Contacts, 1, Stride); | ||
108 | Contact1->pos[0] = Origin[0] + T[1] * Direction[0]; | ||
109 | Contact1->pos[1] = Origin[1] + T[1] * Direction[1]; | ||
110 | Contact1->pos[2] = Origin[2] + T[1] * Direction[2]; | ||
111 | Contact1->pos[3] = Origin[3] + T[1] * Direction[3]; | ||
112 | //Contact1->normal = 0; | ||
113 | Contact1->depth = 0.0f; | ||
114 | Contact1->g1 = RayGeom; | ||
115 | Contact1->g2 = BoxGeom; | ||
116 | |||
117 | return 2; | ||
118 | } | ||
119 | else{ | ||
120 | dContactGeom* Contact = CONTACT(Flags, Contacts, 0, Stride); | ||
121 | Contact->pos[0] = Origin[0] + T[1] * Direction[0]; | ||
122 | Contact->pos[1] = Origin[1] + T[1] * Direction[1]; | ||
123 | Contact->pos[2] = Origin[2] + T[1] * Direction[2]; | ||
124 | Contact->pos[3] = Origin[3] + T[1] * Direction[3]; | ||
125 | //Contact->normal = 0; | ||
126 | Contact->depth = 0.0f; | ||
127 | Contact->g1 = RayGeom; | ||
128 | Contact->g2 = BoxGeom; | ||
129 | |||
130 | return 1; | ||
131 | } | ||
132 | } | ||
133 | else return 0; | ||
134 | } \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/dRay/dRay_CCylinder.cpp b/libraries/ode-0.9/contrib/dRay/dRay_CCylinder.cpp new file mode 100644 index 0000000..b9ea0c0 --- /dev/null +++ b/libraries/ode-0.9/contrib/dRay/dRay_CCylinder.cpp | |||
@@ -0,0 +1,199 @@ | |||
1 | // Ripped from Magic Software | ||
2 | |||
3 | #include "Include\dRay.h" | ||
4 | #include "dxRay.h" | ||
5 | |||
6 | int Find(const dVector3 Origin, dVector3 Direction, dReal Length, const dVector3 CCPos, const dMatrix3 CCRot, dReal CCRadius, dReal CCLength, dReal T[2]){ | ||
7 | dVector3 U, V, W; | ||
8 | Decompose(CCRot, U, V, W); | ||
9 | |||
10 | dVector3 CCOrigin; | ||
11 | CCOrigin[0] = CCPos[0] - (W[0] * CCLength / 2); | ||
12 | CCOrigin[1] = CCPos[1] - (W[1] * CCLength / 2); | ||
13 | CCOrigin[2] = CCPos[2] - (W[2] * CCLength / 2); | ||
14 | CCOrigin[3] = CCPos[3] - (W[3] * CCLength / 2); | ||
15 | |||
16 | dVector3 D; | ||
17 | D[0] = dDOT(U, Direction); | ||
18 | D[1] = dDOT(V, Direction); | ||
19 | D[2] = dDOT(W, Direction); | ||
20 | |||
21 | dReal DMag = Length; | ||
22 | dReal InvDMag = REAL(1.0) / DMag; | ||
23 | |||
24 | dVector3 Diff; | ||
25 | Diff[0] = Origin[0] - CCOrigin[0]; | ||
26 | Diff[1] = Origin[1] - CCOrigin[1]; | ||
27 | Diff[2] = Origin[2] - CCOrigin[2]; | ||
28 | Diff[3] = Origin[3] - CCOrigin[3]; | ||
29 | |||
30 | dVector3 P; | ||
31 | P[0] = dDOT(U, Diff); | ||
32 | P[1] = dDOT(V, Diff); | ||
33 | P[2] = dDOT(W, Diff); | ||
34 | |||
35 | dReal CCRadiusSq = CCRadius * CCRadius; | ||
36 | |||
37 | dReal Epsilon = 1e-12f; | ||
38 | |||
39 | if (dFabs(D[2]) >= REAL(1.0) - Epsilon){ // line is parallel to capsule axis | ||
40 | dReal Discr = CCRadiusSq - P[0] * P[0] - P[1] * P[1]; | ||
41 | |||
42 | if (Discr >= REAL(0.0)){ | ||
43 | dReal Root = dSqrt(Discr); | ||
44 | T[0] = (-P[2] + Root) * InvDMag; | ||
45 | T[1] = (CCLength - P[2] + Root) * InvDMag; | ||
46 | return 2; | ||
47 | } | ||
48 | else return 0; | ||
49 | } | ||
50 | |||
51 | // test intersection with infinite cylinder | ||
52 | dReal A = D[0] * D[0] + D[1] * D[1]; | ||
53 | dReal B = P[0] * D[0] + P[1] * D[1]; | ||
54 | dReal C = P[0] * P[0] + P[1] * P[1] - CCRadiusSq; | ||
55 | dReal Discr = B * B - A * C; | ||
56 | if (Discr < REAL(0.0)){ // line does not intersect infinite cylinder | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | int Count = 0; | ||
61 | |||
62 | if (Discr > REAL(0.0)){ // line intersects infinite cylinder in two places | ||
63 | dReal Root = dSqrt(Discr); | ||
64 | dReal Inv = REAL(1.0) / A; | ||
65 | |||
66 | dReal TTemp = (-B - Root) * Inv; | ||
67 | |||
68 | dReal Tmp = P[2] + TTemp * D[2]; | ||
69 | if (REAL(0.0) <= Tmp && Tmp <= CCLength){ | ||
70 | T[Count++] = TTemp * InvDMag; | ||
71 | } | ||
72 | |||
73 | |||
74 | TTemp = (-B + Root) * Inv; | ||
75 | Tmp = P[2] + TTemp * D[2]; | ||
76 | if (REAL(0.0) <= Tmp && Tmp <= CCLength){ | ||
77 | T[Count++] = TTemp * InvDMag; | ||
78 | } | ||
79 | |||
80 | if (Count == 2){ // line intersects capsule wall in two places | ||
81 | return 2; | ||
82 | } | ||
83 | } | ||
84 | else{ // line is tangent to infinite cylinder | ||
85 | dReal TTemp = -B / A; | ||
86 | dReal Tmp = P[2] + TTemp * D[2]; | ||
87 | if (REAL(0.0) <= Tmp && Tmp <= CCLength){ | ||
88 | T[0] = TTemp * InvDMag; | ||
89 | return 1; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | // test intersection with bottom hemisphere | ||
94 | // fA = 1 | ||
95 | B += P[2] * D[2]; | ||
96 | C += P[2] * P[2]; | ||
97 | Discr = B * B - C; | ||
98 | if (Discr > REAL(0.0)){ | ||
99 | dReal Root = dSqrt(Discr); | ||
100 | dReal TTemp = -B - Root; | ||
101 | dReal Tmp = P[2] + TTemp * D[2]; | ||
102 | if (Tmp <= REAL(0.0)){ | ||
103 | T[Count++] = TTemp * InvDMag; | ||
104 | if (Count == 2){ | ||
105 | return 2; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | TTemp = -B + Root; | ||
110 | Tmp = P[2] + TTemp * D[2]; | ||
111 | if (Tmp <= REAL(0.0)){ | ||
112 | T[Count++] = TTemp * InvDMag; | ||
113 | if (Count == 2){ | ||
114 | return 2; | ||
115 | } | ||
116 | } | ||
117 | } | ||
118 | else if (Discr == REAL(0.0)){ | ||
119 | dReal TTemp = -B; | ||
120 | dReal Tmp = P[2] + TTemp * D[2]; | ||
121 | if (Tmp <= REAL(0.0)){ | ||
122 | T[Count++] = TTemp * InvDMag; | ||
123 | if (Count == 2){ | ||
124 | return 2; | ||
125 | } | ||
126 | } | ||
127 | } | ||
128 | |||
129 | // test intersection with top hemisphere | ||
130 | // fA = 1 | ||
131 | B -= D[2] * CCLength; | ||
132 | C += CCLength * (CCLength - REAL(2.0) * P[2]); | ||
133 | |||
134 | Discr = B * B - C; | ||
135 | if (Discr > REAL(0.0)){ | ||
136 | dReal Root = dSqrt(Discr); | ||
137 | dReal TTemp = -B - Root; | ||
138 | dReal Tmp = P[2] + TTemp * D[2]; | ||
139 | if (Tmp >= CCLength){ | ||
140 | |||
141 | T[Count++] = TTemp * InvDMag; | ||
142 | if (Count == 2){ | ||
143 | return 2; | ||
144 | } | ||
145 | } | ||
146 | |||
147 | TTemp = -B + Root; | ||
148 | Tmp = P[2] + TTemp * D[2]; | ||
149 | if (Tmp >= CCLength){ | ||
150 | T[Count++] = TTemp * InvDMag; | ||
151 | if (Count == 2){ | ||
152 | return 2; | ||
153 | } | ||
154 | } | ||
155 | } | ||
156 | else if (Discr == REAL(0.0)){ | ||
157 | dReal TTemp = -B; | ||
158 | dReal Tmp = P[2] + TTemp * D[2]; | ||
159 | if (Tmp >= CCLength){ | ||
160 | T[Count++] = TTemp * InvDMag; | ||
161 | if (Count == 2){ | ||
162 | return 2; | ||
163 | } | ||
164 | } | ||
165 | } | ||
166 | return Count; | ||
167 | } | ||
168 | |||
169 | int dCollideCCR(dxGeom* RayGeom, dxGeom* CCGeom, int Flags, dContactGeom* Contacts, int Stride){ | ||
170 | const dVector3& CCPos = *(const dVector3*)dGeomGetPosition(CCGeom); | ||
171 | const dMatrix3& CCRot = *(const dMatrix3*)dGeomGetRotation(CCGeom); | ||
172 | |||
173 | dReal CCRadius, CCLength; | ||
174 | dGeomCCylinderGetParams(CCGeom, &CCRadius, &CCLength); | ||
175 | |||
176 | dVector3 Origin, Direction; | ||
177 | dGeomRayGet(RayGeom, Origin, Direction); | ||
178 | dReal Length = dGeomRayGetLength(RayGeom); | ||
179 | |||
180 | dReal T[2]; | ||
181 | int Count = Find(Origin, Direction, Length, CCPos, CCRot, CCRadius, CCLength, T); | ||
182 | int ContactCount = 0; | ||
183 | for (int i = 0; i < Count; i++){ | ||
184 | if (T[i] >= 0.0){ | ||
185 | dContactGeom* Contact = CONTACT(Flags, Contacts, ContactCount, Stride); | ||
186 | Contact->pos[0] = Origin[0] + T[i] * Direction[0] * Length; | ||
187 | Contact->pos[1] = Origin[1] + T[i] * Direction[1] * Length; | ||
188 | Contact->pos[2] = Origin[2] + T[i] * Direction[2] * Length; | ||
189 | Contact->pos[3] = Origin[3] + T[i] * Direction[3] * Length; | ||
190 | //Contact->normal = 0; | ||
191 | Contact->depth = 0.0f; | ||
192 | Contact->g1 = RayGeom; | ||
193 | Contact->g2 = CCGeom; | ||
194 | |||
195 | ContactCount++; | ||
196 | } | ||
197 | } | ||
198 | return ContactCount; | ||
199 | } \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/dRay/dRay_Plane.cpp b/libraries/ode-0.9/contrib/dRay/dRay_Plane.cpp new file mode 100644 index 0000000..cf03c5b --- /dev/null +++ b/libraries/ode-0.9/contrib/dRay/dRay_Plane.cpp | |||
@@ -0,0 +1,35 @@ | |||
1 | // Ripped from Paul Bourke | ||
2 | |||
3 | #include "Include\dRay.h" | ||
4 | #include "dxRay.h" | ||
5 | |||
6 | int dCollidePR(dxGeom* RayGeom, dxGeom* PlaneGeom, int Flags, dContactGeom* Contact, int Stride){ | ||
7 | dVector3 Plane; | ||
8 | dGeomPlaneGetParams(PlaneGeom, Plane); | ||
9 | |||
10 | dVector3 Origin, Direction; | ||
11 | dGeomRayGet(RayGeom, Origin, Direction); | ||
12 | |||
13 | dReal Length = dGeomRayGetLength(RayGeom); | ||
14 | |||
15 | dReal Denom = Plane[0] * Direction[0] + Plane[1] * Direction[1] + Plane[2] * Direction[2]; | ||
16 | if (dFabs(Denom) < 0.00001f){ | ||
17 | return 0; // Ray never hits | ||
18 | } | ||
19 | |||
20 | float T = -(Plane[3] + Plane[0] * Origin[0] + Plane[1] * Origin[1] + Plane[2] * Origin[2]) / Denom; | ||
21 | |||
22 | if (T < 0 || T > Length){ | ||
23 | return 0; // Ray hits but not within boundaries | ||
24 | } | ||
25 | |||
26 | Contact->pos[0] = Origin[0] + T * Direction[0]; | ||
27 | Contact->pos[1] = Origin[1] + T * Direction[1]; | ||
28 | Contact->pos[2] = Origin[2] + T * Direction[2]; | ||
29 | Contact->pos[3] = REAL(0.0); | ||
30 | //Contact->normal = 0; | ||
31 | Contact->depth = 0.0f; | ||
32 | Contact->g1 = RayGeom; | ||
33 | Contact->g2 = PlaneGeom; | ||
34 | return 1; | ||
35 | } \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/dRay/dRay_Sphere.cpp b/libraries/ode-0.9/contrib/dRay/dRay_Sphere.cpp new file mode 100644 index 0000000..8e1ac39 --- /dev/null +++ b/libraries/ode-0.9/contrib/dRay/dRay_Sphere.cpp | |||
@@ -0,0 +1,95 @@ | |||
1 | // Ripped from Magic Software | ||
2 | |||
3 | #include "Include\dRay.h" | ||
4 | #include "dxRay.h" | ||
5 | |||
6 | int dCollideSR(dxGeom* RayGeom, dxGeom* SphereGeom, int Flags, dContactGeom* Contacts, int Stride){ | ||
7 | const dVector3& Position = *(const dVector3*)dGeomGetPosition(SphereGeom); | ||
8 | dReal Radius = dGeomSphereGetRadius(SphereGeom); | ||
9 | |||
10 | dVector3 Origin, Direction; | ||
11 | dGeomRayGet(RayGeom, Origin, Direction); | ||
12 | dReal Length = dGeomRayGetLength(RayGeom); | ||
13 | |||
14 | dVector3 Diff; | ||
15 | Diff[0] = Origin[0] - Position[0]; | ||
16 | Diff[1] = Origin[1] - Position[1]; | ||
17 | Diff[2] = Origin[2] - Position[2]; | ||
18 | Diff[3] = Origin[3] - Position[3]; | ||
19 | |||
20 | Direction[0] *= Length; | ||
21 | Direction[1] *= Length; | ||
22 | Direction[2] *= Length; | ||
23 | Direction[3] *= Length; | ||
24 | |||
25 | dReal A = Length * Length; | ||
26 | dReal B = dDOT(Diff, Direction); | ||
27 | dReal C = dDOT(Diff, Diff) - (Radius * Radius); | ||
28 | |||
29 | dReal Discr = B * B - A * C; | ||
30 | if (Discr < REAL(0.0)){ | ||
31 | return 0; | ||
32 | } | ||
33 | else if (Discr > REAL(0.0)){ | ||
34 | dReal T[2]; | ||
35 | dReal Root = dSqrt(Discr); | ||
36 | dReal InvA = REAL(1.0) / A; | ||
37 | T[0] = (-B - Root) * InvA; | ||
38 | T[1] = (-B + Root) * InvA; | ||
39 | |||
40 | if (T[0] >= REAL(0.0)){ | ||
41 | dContactGeom* Contact0 = CONTACT(Flags, Contacts, 0, Stride); | ||
42 | Contact0->pos[0] = Origin[0] + T[0] * Direction[0]; | ||
43 | Contact0->pos[1] = Origin[1] + T[0] * Direction[1]; | ||
44 | Contact0->pos[2] = Origin[2] + T[0] * Direction[2]; | ||
45 | Contact0->pos[3] = Origin[3] + T[0] * Direction[3]; | ||
46 | //Contact0->normal = 0; | ||
47 | Contact0->depth = 0.0f; | ||
48 | Contact0->g1 = RayGeom; | ||
49 | Contact0->g2 = SphereGeom; | ||
50 | |||
51 | dContactGeom* Contact1 = CONTACT(Flags, Contacts, 1, Stride); | ||
52 | Contact1->pos[0] = Origin[0] + T[1] * Direction[0]; | ||
53 | Contact1->pos[1] = Origin[1] + T[1] * Direction[1]; | ||
54 | Contact1->pos[2] = Origin[2] + T[1] * Direction[2]; | ||
55 | Contact1->pos[3] = Origin[3] + T[1] * Direction[3]; | ||
56 | //Contact1->normal = 0; | ||
57 | Contact1->depth = 0.0f; | ||
58 | Contact1->g1 = RayGeom; | ||
59 | Contact1->g2 = SphereGeom; | ||
60 | |||
61 | return 2; | ||
62 | } | ||
63 | else if (T[1] >= REAL(0.0)){ | ||
64 | dContactGeom* Contact = CONTACT(Flags, Contacts, 1, Stride); | ||
65 | Contact->pos[0] = Origin[0] + T[1] * Direction[0]; | ||
66 | Contact->pos[1] = Origin[1] + T[1] * Direction[1]; | ||
67 | Contact->pos[2] = Origin[2] + T[1] * Direction[2]; | ||
68 | Contact->pos[3] = Origin[3] + T[1] * Direction[3]; | ||
69 | //Contact->normal = 0; | ||
70 | Contact->depth = 0.0f; | ||
71 | Contact->g1 = RayGeom; | ||
72 | Contact->g2 = SphereGeom; | ||
73 | |||
74 | return 1; | ||
75 | } | ||
76 | else return 0; | ||
77 | } | ||
78 | else{ | ||
79 | dReal T; | ||
80 | T = -B / A; | ||
81 | if (T >= REAL(0.0)){ | ||
82 | dContactGeom* Contact = CONTACT(Flags, Contacts, 0, Stride); | ||
83 | Contact->pos[0] = Origin[0] + T * Direction[0]; | ||
84 | Contact->pos[1] = Origin[1] + T * Direction[1]; | ||
85 | Contact->pos[2] = Origin[2] + T * Direction[2]; | ||
86 | Contact->pos[3] = Origin[3] + T * Direction[3]; | ||
87 | //Contact->normal = 0; | ||
88 | Contact->depth = 0.0f; | ||
89 | Contact->g1 = RayGeom; | ||
90 | Contact->g2 = SphereGeom; | ||
91 | return 1; | ||
92 | } | ||
93 | else return 0; | ||
94 | } | ||
95 | } \ No newline at end of file | ||
diff --git a/libraries/ode-0.9/contrib/dRay/dxRay.h b/libraries/ode-0.9/contrib/dRay/dxRay.h new file mode 100644 index 0000000..0fd1d2d --- /dev/null +++ b/libraries/ode-0.9/contrib/dRay/dxRay.h | |||
@@ -0,0 +1,32 @@ | |||
1 | struct dxRay{ | ||
2 | dReal Length; | ||
3 | }; | ||
4 | |||
5 | inline void Decompose(const dMatrix3 Matrix, dVector3 Right, dVector3 Up, dVector3 Direction){ | ||
6 | Right[0] = Matrix[0 * 4 + 0]; | ||
7 | Right[1] = Matrix[1 * 4 + 0]; | ||
8 | Right[2] = Matrix[2 * 4 + 0]; | ||
9 | Right[3] = Matrix[3 * 4 + 0]; | ||
10 | Up[0] = Matrix[0 * 4 + 1]; | ||
11 | Up[1] = Matrix[1 * 4 + 1]; | ||
12 | Up[2] = Matrix[2 * 4 + 1]; | ||
13 | Up[3] = Matrix[3 * 4 + 1]; | ||
14 | Direction[0] = Matrix[0 * 4 + 2]; | ||
15 | Direction[1] = Matrix[1 * 4 + 2]; | ||
16 | Direction[2] = Matrix[2 * 4 + 2]; | ||
17 | Direction[3] = Matrix[3 * 4 + 2]; | ||
18 | } | ||
19 | |||
20 | inline void Decompose(const dMatrix3 Matrix, dVector3 Vectors[3]){ | ||
21 | Decompose(Matrix, Vectors[0], Vectors[1], Vectors[2]); | ||
22 | } | ||
23 | |||
24 | inline dContactGeom* CONTACT(int Flags, dContactGeom* Contacts, int Index, int Stride){ | ||
25 | dIASSERT(Index >= 0 && Index < (Flags & 0x0ffff)); | ||
26 | return ((dContactGeom*)(((char*)Contacts) + (Index * Stride))); | ||
27 | } | ||
28 | |||
29 | int dCollidePR(dxGeom* RayGeom, dxGeom* PlaneGeom, int Flags, dContactGeom* Contacts, int Stride); | ||
30 | int dCollideSR(dxGeom* RayGeom, dxGeom* SphereGeom, int Flags, dContactGeom* Contacts, int Stride); | ||
31 | int dCollideBR(dxGeom* RayGeom, dxGeom* BoxGeom, int Flags, dContactGeom* Contacts, int Stride); | ||
32 | int dCollideCCR(dxGeom* RayGeom, dxGeom* CCylinderGeom, int Flags, dContactGeom* Contacts, int Stride); \ No newline at end of file | ||