Added: dSpaceSetSublevel/dSpaceGetSublevel and possibility to collide a space as...
[ode.git] / ode / src / util.cpp
blobc808c6c60a56d2e0de3015bc6d9a842029a79350
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 *************************************************************************/
23 #include "ode/ode.h"
24 #include "objects.h"
25 #include "joint.h"
26 #include "util.h"
28 #define ALLOCA dALLOCA16
30 //****************************************************************************
31 // Auto disabling
33 void dInternalHandleAutoDisabling (dxWorld *world, dReal stepsize)
35 dxBody *bb;
36 for ( bb=world->firstbody; bb; bb=(dxBody*)bb->next )
38 // don't freeze objects mid-air (patch 1586738)
39 if ( bb->firstjoint == NULL ) continue;
41 // nothing to do unless this body is currently enabled and has
42 // the auto-disable flag set
43 if ( (bb->flags & (dxBodyAutoDisable|dxBodyDisabled)) != dxBodyAutoDisable ) continue;
45 // if sampling / threshold testing is disabled, we can never sleep.
46 if ( bb->adis.average_samples == 0 ) continue;
49 // see if the body is idle
52 #ifndef dNODEBUG
53 // sanity check
54 if ( bb->average_counter >= bb->adis.average_samples )
56 dUASSERT( bb->average_counter < bb->adis.average_samples, "buffer overflow" );
58 // something is going wrong, reset the average-calculations
59 bb->average_ready = 0; // not ready for average calculation
60 bb->average_counter = 0; // reset the buffer index
62 #endif // dNODEBUG
64 // sample the linear and angular velocity
65 bb->average_lvel_buffer[bb->average_counter][0] = bb->lvel[0];
66 bb->average_lvel_buffer[bb->average_counter][1] = bb->lvel[1];
67 bb->average_lvel_buffer[bb->average_counter][2] = bb->lvel[2];
68 bb->average_avel_buffer[bb->average_counter][0] = bb->avel[0];
69 bb->average_avel_buffer[bb->average_counter][1] = bb->avel[1];
70 bb->average_avel_buffer[bb->average_counter][2] = bb->avel[2];
71 bb->average_counter++;
73 // buffer ready test
74 if ( bb->average_counter >= bb->adis.average_samples )
76 bb->average_counter = 0; // fill the buffer from the beginning
77 bb->average_ready = 1; // this body is ready now for average calculation
80 int idle = 0; // Assume it's in motion unless we have samples to disprove it.
82 // enough samples?
83 if ( bb->average_ready )
85 idle = 1; // Initial assumption: IDLE
87 // the sample buffers are filled and ready for calculation
88 dVector3 average_lvel, average_avel;
90 // Store first velocity samples
91 average_lvel[0] = bb->average_lvel_buffer[0][0];
92 average_avel[0] = bb->average_avel_buffer[0][0];
93 average_lvel[1] = bb->average_lvel_buffer[0][1];
94 average_avel[1] = bb->average_avel_buffer[0][1];
95 average_lvel[2] = bb->average_lvel_buffer[0][2];
96 average_avel[2] = bb->average_avel_buffer[0][2];
98 // If we're not in "instantaneous mode"
99 if ( bb->adis.average_samples > 1 )
101 // add remaining velocities together
102 for ( unsigned int i = 1; i < bb->adis.average_samples; ++i )
104 average_lvel[0] += bb->average_lvel_buffer[i][0];
105 average_avel[0] += bb->average_avel_buffer[i][0];
106 average_lvel[1] += bb->average_lvel_buffer[i][1];
107 average_avel[1] += bb->average_avel_buffer[i][1];
108 average_lvel[2] += bb->average_lvel_buffer[i][2];
109 average_avel[2] += bb->average_avel_buffer[i][2];
112 // make average
113 dReal r1 = dReal( 1.0 ) / dReal( bb->adis.average_samples );
115 average_lvel[0] *= r1;
116 average_avel[0] *= r1;
117 average_lvel[1] *= r1;
118 average_avel[1] *= r1;
119 average_lvel[2] *= r1;
120 average_avel[2] *= r1;
123 // threshold test
124 dReal av_lspeed, av_aspeed;
125 av_lspeed = dDOT( average_lvel, average_lvel );
126 if ( av_lspeed > bb->adis.linear_average_threshold )
128 idle = 0; // average linear velocity is too high for idle
130 else
132 av_aspeed = dDOT( average_avel, average_avel );
133 if ( av_aspeed > bb->adis.angular_average_threshold )
135 idle = 0; // average angular velocity is too high for idle
140 // if it's idle, accumulate steps and time.
141 // these counters won't overflow because this code doesn't run for disabled bodies.
142 if (idle) {
143 bb->adis_stepsleft--;
144 bb->adis_timeleft -= stepsize;
146 else {
147 // Reset countdowns
148 bb->adis_stepsleft = bb->adis.idle_steps;
149 bb->adis_timeleft = bb->adis.idle_time;
152 // disable the body if it's idle for a long enough time
153 if ( bb->adis_stepsleft <= 0 && bb->adis_timeleft <= 0 )
155 bb->flags |= dxBodyDisabled; // set the disable flag
157 // disabling bodies should also include resetting the velocity
158 // should prevent jittering in big "islands"
159 bb->lvel[0] = 0;
160 bb->lvel[1] = 0;
161 bb->lvel[2] = 0;
162 bb->avel[0] = 0;
163 bb->avel[1] = 0;
164 bb->avel[2] = 0;
170 //****************************************************************************
171 // body rotation
173 // return sin(x)/x. this has a singularity at 0 so special handling is needed
174 // for small arguments.
176 static inline dReal sinc (dReal x)
178 // if |x| < 1e-4 then use a taylor series expansion. this two term expansion
179 // is actually accurate to one LS bit within this range if double precision
180 // is being used - so don't worry!
181 if (dFabs(x) < 1.0e-4) return REAL(1.0) - x*x*REAL(0.166666666666666666667);
182 else return dSin(x)/x;
186 // given a body b, apply its linear and angular rotation over the time
187 // interval h, thereby adjusting its position and orientation.
189 void dxStepBody (dxBody *b, dReal h)
191 // cap the angular velocity
192 if (b->flags & dxBodyMaxAngularSpeed) {
193 const dReal max_ang_speed = b->max_angular_speed;
194 const dReal aspeed = dDOT( b->avel, b->avel );
195 if (aspeed > max_ang_speed*max_ang_speed) {
196 const dReal coef = max_ang_speed/dSqrt(aspeed);
197 dOPEC(b->avel, *=, coef);
200 // end of angular velocity cap
203 int j;
205 // handle linear velocity
206 for (j=0; j<3; j++) b->posr.pos[j] += h * b->lvel[j];
208 if (b->flags & dxBodyFlagFiniteRotation) {
209 dVector3 irv; // infitesimal rotation vector
210 dQuaternion q; // quaternion for finite rotation
212 if (b->flags & dxBodyFlagFiniteRotationAxis) {
213 // split the angular velocity vector into a component along the finite
214 // rotation axis, and a component orthogonal to it.
215 dVector3 frv; // finite rotation vector
216 dReal k = dDOT (b->finite_rot_axis,b->avel);
217 frv[0] = b->finite_rot_axis[0] * k;
218 frv[1] = b->finite_rot_axis[1] * k;
219 frv[2] = b->finite_rot_axis[2] * k;
220 irv[0] = b->avel[0] - frv[0];
221 irv[1] = b->avel[1] - frv[1];
222 irv[2] = b->avel[2] - frv[2];
224 // make a rotation quaternion q that corresponds to frv * h.
225 // compare this with the full-finite-rotation case below.
226 h *= REAL(0.5);
227 dReal theta = k * h;
228 q[0] = dCos(theta);
229 dReal s = sinc(theta) * h;
230 q[1] = frv[0] * s;
231 q[2] = frv[1] * s;
232 q[3] = frv[2] * s;
234 else {
235 // make a rotation quaternion q that corresponds to w * h
236 dReal wlen = dSqrt (b->avel[0]*b->avel[0] + b->avel[1]*b->avel[1] +
237 b->avel[2]*b->avel[2]);
238 h *= REAL(0.5);
239 dReal theta = wlen * h;
240 q[0] = dCos(theta);
241 dReal s = sinc(theta) * h;
242 q[1] = b->avel[0] * s;
243 q[2] = b->avel[1] * s;
244 q[3] = b->avel[2] * s;
247 // do the finite rotation
248 dQuaternion q2;
249 dQMultiply0 (q2,q,b->q);
250 for (j=0; j<4; j++) b->q[j] = q2[j];
252 // do the infitesimal rotation if required
253 if (b->flags & dxBodyFlagFiniteRotationAxis) {
254 dReal dq[4];
255 dWtoDQ (irv,b->q,dq);
256 for (j=0; j<4; j++) b->q[j] += h * dq[j];
259 else {
260 // the normal way - do an infitesimal rotation
261 dReal dq[4];
262 dWtoDQ (b->avel,b->q,dq);
263 for (j=0; j<4; j++) b->q[j] += h * dq[j];
266 // normalize the quaternion and convert it to a rotation matrix
267 dNormalize4 (b->q);
268 dQtoR (b->q,b->posr.R);
270 // notify all attached geoms that this body has moved
271 for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
272 dGeomMoved (geom);
274 // notify the user
275 if (b->moved_callback)
276 b->moved_callback(b);
279 // damping
280 if (b->flags & dxBodyLinearDamping) {
281 const dReal lin_threshold = b->dampingp.linear_threshold;
282 const dReal lin_speed = dDOT( b->lvel, b->lvel );
283 if ( lin_speed > lin_threshold) {
284 const dReal k = 1 - b->dampingp.linear_scale;
285 dOPEC(b->lvel, *=, k);
288 if (b->flags & dxBodyAngularDamping) {
289 const dReal ang_threshold = b->dampingp.angular_threshold;
290 const dReal ang_speed = dDOT( b->avel, b->avel );
291 if ( ang_speed > ang_threshold) {
292 const dReal k = 1 - b->dampingp.angular_scale;
293 dOPEC(b->avel, *=, k);
299 //****************************************************************************
300 // island processing
302 // this groups all joints and bodies in a world into islands. all objects
303 // in an island are reachable by going through connected bodies and joints.
304 // each island can be simulated separately.
305 // note that joints that are not attached to anything will not be included
306 // in any island, an so they do not affect the simulation.
308 // this function starts new island from unvisited bodies. however, it will
309 // never start a new islands from a disabled body. thus islands of disabled
310 // bodies will not be included in the simulation. disabled bodies are
311 // re-enabled if they are found to be part of an active island.
313 void dxProcessIslands (dxWorld *world, dReal stepsize, dstepper_fn_t stepper)
315 dxBody *b,*bb,**body;
316 dxJoint *j,**joint;
318 // nothing to do if no bodies
319 if (world->nb <= 0) return;
321 // handle auto-disabling of bodies
322 dInternalHandleAutoDisabling (world,stepsize);
324 // make arrays for body and joint lists (for a single island) to go into
325 body = (dxBody**) ALLOCA (world->nb * sizeof(dxBody*));
326 joint = (dxJoint**) ALLOCA (world->nj * sizeof(dxJoint*));
327 int bcount = 0; // number of bodies in `body'
328 int jcount = 0; // number of joints in `joint'
330 // set all body/joint tags to 0
331 for (b=world->firstbody; b; b=(dxBody*)b->next) b->tag = 0;
332 for (j=world->firstjoint; j; j=(dxJoint*)j->next) j->tag = 0;
334 // allocate a stack of unvisited bodies in the island. the maximum size of
335 // the stack can be the lesser of the number of bodies or joints, because
336 // new bodies are only ever added to the stack by going through untagged
337 // joints. all the bodies in the stack must be tagged!
338 int stackalloc = (world->nj < world->nb) ? world->nj : world->nb;
339 dxBody **stack = (dxBody**) ALLOCA (stackalloc * sizeof(dxBody*));
341 for (bb=world->firstbody; bb; bb=(dxBody*)bb->next) {
342 // get bb = the next enabled, untagged body, and tag it
343 if (bb->tag || (bb->flags & dxBodyDisabled)) continue;
344 bb->tag = 1;
346 // tag all bodies and joints starting from bb.
347 int stacksize = 0;
348 b = bb;
349 body[0] = bb;
350 bcount = 1;
351 jcount = 0;
352 goto quickstart;
353 while (stacksize > 0) {
354 b = stack[--stacksize]; // pop body off stack
355 body[bcount++] = b; // put body on body list
356 quickstart:
358 // traverse and tag all body's joints, add untagged connected bodies
359 // to stack
360 for (dxJointNode *n=b->firstjoint; n; n=n->next) {
361 if (!n->joint->tag) {
362 n->joint->tag = 1;
363 joint[jcount++] = n->joint;
364 if (n->body && !n->body->tag) {
365 n->body->tag = 1;
366 stack[stacksize++] = n->body;
370 dIASSERT(stacksize <= world->nb);
371 dIASSERT(stacksize <= world->nj);
374 // now do something with body and joint lists
375 stepper (world,body,bcount,joint,jcount,stepsize);
377 // what we've just done may have altered the body/joint tag values.
378 // we must make sure that these tags are nonzero.
379 // also make sure all bodies are in the enabled state.
380 int i;
381 for (i=0; i<bcount; i++) {
382 body[i]->tag = 1;
383 body[i]->flags &= ~dxBodyDisabled;
385 for (i=0; i<jcount; i++) joint[i]->tag = 1;
388 // if debugging, check that all objects (except for disabled bodies,
389 // unconnected joints, and joints that are connected to disabled bodies)
390 // were tagged.
391 # ifndef dNODEBUG
392 for (b=world->firstbody; b; b=(dxBody*)b->next) {
393 if (b->flags & dxBodyDisabled) {
394 if (b->tag) dDebug (0,"disabled body tagged");
396 else {
397 if (!b->tag) dDebug (0,"enabled body not tagged");
400 for (j=world->firstjoint; j; j=(dxJoint*)j->next) {
401 if ((j->node[0].body && (j->node[0].body->flags & dxBodyDisabled)==0) ||
402 (j->node[1].body && (j->node[1].body->flags & dxBodyDisabled)==0)) {
403 if (!j->tag) dDebug (0,"attached enabled joint not tagged");
405 else {
406 if (j->tag) dDebug (0,"unattached or disabled joint tagged");
409 # endif