2
* $Id: OdePhysicsEnvironment.cpp 16596 2008-09-18 16:43:31Z ton $
4
* ***** BEGIN GPL LICENSE BLOCK *****
6
* The contents of this file may be used under the terms of either the GNU
7
* General Public License Version 2 or later (the "GPL", see
8
* http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or
9
* later (the "BL", see http://www.blender.org/BL/ ) which has to be
10
* bought from the Blender Foundation to become active, in which case the
11
* above mentioned GPL option does not apply.
13
* The Original Code is Copyright (C) 2002 by NaN Holding BV.
14
* All rights reserved.
16
* The Original Code is: all of this file.
18
* Contributor(s): none yet.
20
* ***** END GPL LICENSE BLOCK *****
22
#include "OdePhysicsEnvironment.h"
23
#include "PHY_IMotionState.h"
24
#include "OdePhysicsController.h"
27
#include <../ode/src/joint.h>
28
#include <ode/odemath.h>
30
ODEPhysicsEnvironment::ODEPhysicsEnvironment()
32
m_OdeWorld = dWorldCreate();
33
m_OdeSpace = dHashSpaceCreate();
34
m_OdeContactGroup = dJointGroupCreate (0);
35
dWorldSetCFM (m_OdeWorld,1e-5f);
37
m_JointGroup = dJointGroupCreate(0);
39
setFixedTimeStep(true,1.f/60.f);
44
ODEPhysicsEnvironment::~ODEPhysicsEnvironment()
46
dJointGroupDestroy (m_OdeContactGroup);
47
dJointGroupDestroy (m_JointGroup);
49
dSpaceDestroy (m_OdeSpace);
50
dWorldDestroy (m_OdeWorld);
55
void ODEPhysicsEnvironment::setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep)
57
m_useFixedTimeStep = useFixedTimeStep;
61
m_fixedTimeStep = fixedTimeStep;
64
m_fixedTimeStep = 0.f;
68
//todo:implement fixed timestepping
71
float ODEPhysicsEnvironment::getFixedTimeStep()
73
return m_fixedTimeStep;
78
bool ODEPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep1)
81
float deltaTime = timeStep1;
84
if (m_useFixedTimeStep)
86
m_currentTime += timeStep1;
87
// equal to subSampling (might be a little smaller).
88
numSteps = (int)(m_currentTime / m_fixedTimeStep);
89
m_currentTime -= m_fixedTimeStep * (float)numSteps;
90
deltaTime = m_fixedTimeStep;
91
//todo: experiment by smoothing the remaining time over the substeps
94
for (int i=0;i<numSteps;i++)
96
// ode collision update
97
dSpaceCollide (m_OdeSpace,this,&ODEPhysicsEnvironment::OdeNearCallback);
99
int m_odeContacts = GetNumOdeContacts();
101
//physics integrator + resolver update
102
//dWorldStep (m_OdeWorld,deltaTime);
103
//dWorldQuickStep (m_OdeWorld,deltaTime);
104
//dWorldID w, dReal stepsize)
106
//clear collision points
107
this->ClearOdeContactGroup();
112
void ODEPhysicsEnvironment::setGravity(float x,float y,float z)
114
dWorldSetGravity (m_OdeWorld,x,y,z);
119
int ODEPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
120
float pivotX,float pivotY,float pivotZ,float axisX,float axisY,float axisZ)
123
int constraintid = 0;
124
ODEPhysicsController* dynactrl = (ODEPhysicsController*)ctrl;
125
ODEPhysicsController* dynactrl2 = (ODEPhysicsController*)ctrl2;
129
case PHY_POINT2POINT_CONSTRAINT:
133
dJointID jointid = dJointCreateBall (m_OdeWorld,m_JointGroup);
134
struct dxBody* bodyid1 = dynactrl->GetOdeBodyId();
135
struct dxBody* bodyid2=0;
136
const dReal* pos = dBodyGetPosition(bodyid1);
137
const dReal* R = dBodyGetRotation(bodyid1);
138
dReal offset[3] = {pivotX,pivotY,pivotZ};
140
dMULTIPLY0_331 (newoffset,R,offset);
141
newoffset[0] += pos[0];
142
newoffset[1] += pos[1];
143
newoffset[2] += pos[2];
147
bodyid2 = dynactrl2->GetOdeBodyId();
149
dJointAttach (jointid, bodyid1, bodyid2);
151
dJointSetBallAnchor (jointid, newoffset[0], newoffset[1], newoffset[2]);
153
constraintid = (int) jointid;
157
case PHY_LINEHINGE_CONSTRAINT:
161
dJointID jointid = dJointCreateHinge (m_OdeWorld,m_JointGroup);
162
struct dxBody* bodyid1 = dynactrl->GetOdeBodyId();
163
struct dxBody* bodyid2=0;
164
const dReal* pos = dBodyGetPosition(bodyid1);
165
const dReal* R = dBodyGetRotation(bodyid1);
166
dReal offset[3] = {pivotX,pivotY,pivotZ};
167
dReal axisset[3] = {axisX,axisY,axisZ};
171
dMULTIPLY0_331 (newaxis,R,axisset);
173
dMULTIPLY0_331 (newoffset,R,offset);
174
newoffset[0] += pos[0];
175
newoffset[1] += pos[1];
176
newoffset[2] += pos[2];
180
bodyid2 = dynactrl2->GetOdeBodyId();
182
dJointAttach (jointid, bodyid1, bodyid2);
184
dJointSetHingeAnchor (jointid, newoffset[0], newoffset[1], newoffset[2]);
185
dJointSetHingeAxis(jointid,newaxis[0],newaxis[1],newaxis[2]);
187
constraintid = (int) jointid;
201
void ODEPhysicsEnvironment::removeConstraint(void *constraintid)
205
dJointDestroy((dJointID) constraintid);
209
PHY_IPhysicsController* ODEPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ)
213
//collision detection / raytesting
218
void ODEPhysicsEnvironment::OdeNearCallback (void *data, dGeomID o1, dGeomID o2)
220
// \todo if this is a registered collision sensor
224
// if (o1->body && o2->body) return;
225
ODEPhysicsEnvironment* env = (ODEPhysicsEnvironment*) data;
228
b1 = dGeomGetBody(o1);
229
b2 = dGeomGetBody(o2);
230
// exit without doing anything if the two bodies are connected by a joint
231
if (b1 && b2 && dAreConnected (b1,b2)) return;
233
ODEPhysicsController * ctrl1 =(ODEPhysicsController *)dGeomGetData(o1);
234
ODEPhysicsController * ctrl2 =(ODEPhysicsController *)dGeomGetData(o2);
235
float friction=ctrl1->getFriction();
236
float restitution = ctrl1->getRestitution();
237
//for friction, take minimum
239
friction=(friction < ctrl2->getFriction() ?
240
friction :ctrl2->getFriction());
242
//restitution:take minimum
243
restitution = restitution < ctrl2->getRestitution()?
244
restitution : ctrl2->getRestitution();
246
dContact contact[3]; // up to 3 contacts per box
247
for (i=0; i<3; i++) {
248
contact[i].surface.mode = dContactBounce; //dContactMu2;
249
contact[i].surface.mu = friction;//dInfinity;
250
contact[i].surface.mu2 = 0;
251
contact[i].surface.bounce = restitution;//0.5;
252
contact[i].surface.bounce_vel = 0.1f;
253
contact[i].surface.slip1=0.0;
256
if (int numc = dCollide (o1,o2,3,&contact[0].geom,sizeof(dContact))) {
258
// dRSetIdentity (RI);
259
// const dReal ss[3] = {0.02,0.02,0.02};
260
for (i=0; i<numc; i++) {
261
dJointID c = dJointCreateContact (env->m_OdeWorld,env->m_OdeContactGroup,contact+i);
262
dJointAttach (c,b1,b2);
268
void ODEPhysicsEnvironment::ClearOdeContactGroup()
270
dJointGroupEmpty (m_OdeContactGroup);
273
int ODEPhysicsEnvironment::GetNumOdeContacts()
275
return m_OdeContactGroup->num;