forked from bartvdbraak/blender
first checkin of ode blender engine files
This commit is contained in:
parent
bdad961ce3
commit
b7dadcfefd
236
source/gameengine/Ketsji/KX_OdePhysicsController.cpp
Normal file
236
source/gameengine/Ketsji/KX_OdePhysicsController.cpp
Normal file
@ -0,0 +1,236 @@
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
||||
*
|
||||
* The contents of this file may be used under the terms of either the GNU
|
||||
* General Public License Version 2 or later (the "GPL", see
|
||||
* http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or
|
||||
* later (the "BL", see http://www.blender.org/BL/ ) which has to be
|
||||
* bought from the Blender Foundation to become active, in which case the
|
||||
* above mentioned GPL option does not apply.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
*/
|
||||
#include "KX_OdePhysicsController.h"
|
||||
#include "KX_GameObject.h"
|
||||
#include "KX_MotionState.h"
|
||||
|
||||
|
||||
KX_OdePhysicsController::KX_OdePhysicsController(
|
||||
bool dyna,
|
||||
bool fullRigidBody,
|
||||
bool phantom,
|
||||
class PHY_IMotionState* motionstate,
|
||||
struct dxSpace* space,
|
||||
struct dxWorld* world,
|
||||
float mass,
|
||||
float friction,
|
||||
float restitution,
|
||||
bool implicitsphere,
|
||||
float center[3],
|
||||
float extends[3],
|
||||
float radius
|
||||
)
|
||||
: KX_IPhysicsController(dyna,(PHY_IPhysicsController*)this),
|
||||
ODEPhysicsController(
|
||||
dyna,fullRigidBody,phantom,motionstate,
|
||||
space,world,mass,friction,restitution,
|
||||
implicitsphere,center,extends,radius)
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
bool KX_OdePhysicsController::Update(double time)
|
||||
{
|
||||
return SynchronizeMotionStates(time);
|
||||
}
|
||||
|
||||
void KX_OdePhysicsController::SetObject (SG_IObject* object)
|
||||
{
|
||||
SG_Controller::SetObject(object);
|
||||
|
||||
// cheating here...
|
||||
KX_GameObject* gameobj = (KX_GameObject*) object->GetSGClientObject();
|
||||
gameobj->m_pPhysicsController1 = this;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void KX_OdePhysicsController::applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse)
|
||||
{
|
||||
ODEPhysicsController::applyImpulse(attach[0],attach[1],attach[2],impulse[0],impulse[1],impulse[2]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void KX_OdePhysicsController::RelativeTranslate(const MT_Vector3& dloc,bool local)
|
||||
{
|
||||
ODEPhysicsController::RelativeTranslate(dloc[0],dloc[1],dloc[2],local);
|
||||
|
||||
}
|
||||
void KX_OdePhysicsController::RelativeRotate(const MT_Matrix3x3& drot,bool local)
|
||||
{
|
||||
double oldmat[12];
|
||||
drot.getValue(oldmat);
|
||||
float newmat[9];
|
||||
float *m = &newmat[0];
|
||||
double *orgm = &oldmat[0];
|
||||
|
||||
*m++ = *orgm++;*m++ = *orgm++;*m++ = *orgm++;orgm++;
|
||||
*m++ = *orgm++;*m++ = *orgm++;*m++ = *orgm++;orgm++;
|
||||
*m++ = *orgm++;*m++ = *orgm++;*m++ = *orgm++;orgm++;
|
||||
|
||||
ODEPhysicsController::RelativeRotate(newmat,local);
|
||||
|
||||
}
|
||||
|
||||
void KX_OdePhysicsController::ApplyTorque(const MT_Vector3& torque,bool local)
|
||||
{
|
||||
ODEPhysicsController::ApplyTorque(torque[0],torque[1],torque[2],local);
|
||||
|
||||
}
|
||||
void KX_OdePhysicsController::ApplyForce(const MT_Vector3& force,bool local)
|
||||
{
|
||||
ODEPhysicsController::ApplyForce(force[0],force[1],force[2],local);
|
||||
|
||||
}
|
||||
MT_Vector3 KX_OdePhysicsController::GetLinearVelocity()
|
||||
{
|
||||
return MT_Vector3(0,0,0);
|
||||
}
|
||||
|
||||
MT_Vector3 KX_OdePhysicsController::GetVelocity(const MT_Point3& pos)
|
||||
{
|
||||
return MT_Vector3(0,0,0);
|
||||
}
|
||||
|
||||
void KX_OdePhysicsController::SetAngularVelocity(const MT_Vector3& ang_vel,bool local)
|
||||
{
|
||||
|
||||
}
|
||||
void KX_OdePhysicsController::SetLinearVelocity(const MT_Vector3& lin_vel,bool local)
|
||||
{
|
||||
ODEPhysicsController::SetLinearVelocity(lin_vel[0],lin_vel[1],lin_vel[2],local);
|
||||
}
|
||||
|
||||
void KX_OdePhysicsController::setOrientation(const MT_Quaternion& orn)
|
||||
{
|
||||
ODEPhysicsController::setOrientation(orn[0],orn[1],orn[2],orn[3]);
|
||||
}
|
||||
|
||||
void KX_OdePhysicsController::getOrientation(MT_Quaternion& orn)
|
||||
{
|
||||
float florn[4];
|
||||
florn[0]=orn[0];
|
||||
florn[1]=orn[1];
|
||||
florn[2]=orn[2];
|
||||
florn[3]=orn[3];
|
||||
ODEPhysicsController::getOrientation(florn[0],florn[1],florn[2],florn[3]);
|
||||
orn[0] = florn[0];
|
||||
orn[1] = florn[1];
|
||||
orn[2] = florn[2];
|
||||
orn[3] = florn[3];
|
||||
|
||||
|
||||
}
|
||||
|
||||
void KX_OdePhysicsController::setPosition(const MT_Point3& pos)
|
||||
{
|
||||
ODEPhysicsController::setPosition(pos[0],pos[1],pos[2]);
|
||||
}
|
||||
|
||||
void KX_OdePhysicsController::setScaling(const MT_Vector3& scaling)
|
||||
{
|
||||
}
|
||||
|
||||
MT_Scalar KX_OdePhysicsController::GetMass()
|
||||
{
|
||||
return ODEPhysicsController::getMass();
|
||||
}
|
||||
|
||||
MT_Vector3 KX_OdePhysicsController::getReactionForce()
|
||||
{
|
||||
return MT_Vector3(0,0,0);
|
||||
}
|
||||
void KX_OdePhysicsController::setRigidBody(bool rigid)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void KX_OdePhysicsController::SuspendDynamics()
|
||||
{
|
||||
ODEPhysicsController::SuspendDynamics();
|
||||
}
|
||||
void KX_OdePhysicsController::RestoreDynamics()
|
||||
{
|
||||
ODEPhysicsController::RestoreDynamics();
|
||||
}
|
||||
|
||||
|
||||
SG_Controller* KX_OdePhysicsController::GetReplica(class SG_Node* destnode)
|
||||
{
|
||||
PHY_IMotionState* motionstate = new KX_MotionState(destnode);
|
||||
KX_OdePhysicsController* copyctrl = new KX_OdePhysicsController(*this);
|
||||
|
||||
// nlin: copied from KX_SumoPhysicsController.cpp. Not 100% sure what this does....
|
||||
// furthermore, the parentctrl is not used in ODEPhysicsController::PostProcessReplica, but
|
||||
// maybe it can/should be used in the future...
|
||||
|
||||
// begin copy block ------------------------------------------------------------------
|
||||
|
||||
//parentcontroller is here be able to avoid collisions between parent/child
|
||||
|
||||
PHY_IPhysicsController* parentctrl = NULL;
|
||||
|
||||
if (destnode != destnode->GetRootSGParent())
|
||||
{
|
||||
KX_GameObject* clientgameobj = (KX_GameObject*) destnode->GetRootSGParent()->GetSGClientObject();
|
||||
if (clientgameobj)
|
||||
{
|
||||
parentctrl = (KX_OdePhysicsController*)clientgameobj->GetPhysicsController();
|
||||
} else
|
||||
{
|
||||
// it could be a false node, try the children
|
||||
NodeList::const_iterator childit;
|
||||
for (
|
||||
childit = destnode->GetSGChildren().begin();
|
||||
childit!= destnode->GetSGChildren().end();
|
||||
++childit
|
||||
) {
|
||||
KX_GameObject* clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
|
||||
if (clientgameobj)
|
||||
{
|
||||
parentctrl = (KX_OdePhysicsController*)clientgameobj->GetPhysicsController();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// end copy block ------------------------------------------------------------------
|
||||
|
||||
copyctrl->PostProcessReplica(motionstate, this);
|
||||
|
||||
return copyctrl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void KX_OdePhysicsController::SetSumoTransform(bool nondynaonly)
|
||||
{
|
||||
|
||||
}
|
||||
// todo: remove next line !
|
||||
void KX_OdePhysicsController::SetSimulatedTime(double time)
|
||||
{
|
||||
|
||||
}
|
||||
|
100
source/gameengine/Ketsji/KX_OdePhysicsController.h
Normal file
100
source/gameengine/Ketsji/KX_OdePhysicsController.h
Normal file
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
||||
*
|
||||
* The contents of this file may be used under the terms of either the GNU
|
||||
* General Public License Version 2 or later (the "GPL", see
|
||||
* http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or
|
||||
* later (the "BL", see http://www.blender.org/BL/ ) which has to be
|
||||
* bought from the Blender Foundation to become active, in which case the
|
||||
* above mentioned GPL option does not apply.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
*/
|
||||
#ifndef __KX_ODEPHYSICSCONTROLLER_H
|
||||
#define __KX_ODEPHYSICSCONTROLLER_H
|
||||
|
||||
#include "KX_IPhysicsController.h"
|
||||
#include "OdePhysicsController.h"
|
||||
|
||||
|
||||
/**
|
||||
Physics Controller, a special kind of Scene Graph Transformation Controller.
|
||||
It get's callbacks from Physics in case a transformation change took place.
|
||||
Each time the scene graph get's updated, the controller get's a chance
|
||||
in the 'Update' method to reflect changed.
|
||||
*/
|
||||
|
||||
class KX_OdePhysicsController : public KX_IPhysicsController, public ODEPhysicsController
|
||||
|
||||
{
|
||||
|
||||
public:
|
||||
KX_OdePhysicsController(
|
||||
bool dyna,
|
||||
bool fullRigidBody,
|
||||
bool phantom,
|
||||
class PHY_IMotionState* motionstate,
|
||||
struct dxSpace* space,
|
||||
struct dxWorld* world,
|
||||
float mass,
|
||||
float friction,
|
||||
float restitution,
|
||||
bool implicitsphere,
|
||||
float center[3],
|
||||
float extends[3],
|
||||
float radius);
|
||||
|
||||
virtual ~KX_OdePhysicsController() {};
|
||||
|
||||
virtual void applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse);
|
||||
virtual void SetObject (SG_IObject* object);
|
||||
|
||||
virtual void RelativeTranslate(const MT_Vector3& dloc,bool local);
|
||||
virtual void RelativeRotate(const MT_Matrix3x3& drot,bool local);
|
||||
virtual void ApplyTorque(const MT_Vector3& torque,bool local);
|
||||
virtual void ApplyForce(const MT_Vector3& force,bool local);
|
||||
virtual MT_Vector3 GetLinearVelocity();
|
||||
virtual MT_Vector3 GetVelocity(const MT_Point3& pos);
|
||||
virtual void SetAngularVelocity(const MT_Vector3& ang_vel,bool local);
|
||||
virtual void SetLinearVelocity(const MT_Vector3& lin_vel,bool local);
|
||||
virtual void getOrientation(MT_Quaternion& orn);
|
||||
virtual void setOrientation(const MT_Quaternion& orn);
|
||||
virtual void setPosition(const MT_Point3& pos);
|
||||
virtual void setScaling(const MT_Vector3& scaling);
|
||||
virtual MT_Scalar GetMass();
|
||||
virtual MT_Vector3 getReactionForce();
|
||||
virtual void setRigidBody(bool rigid);
|
||||
|
||||
virtual void SuspendDynamics();
|
||||
virtual void RestoreDynamics();
|
||||
|
||||
|
||||
virtual SG_Controller* GetReplica(class SG_Node* destnode);
|
||||
|
||||
|
||||
virtual void SetSumoTransform(bool nondynaonly);
|
||||
// todo: remove next line !
|
||||
virtual void SetSimulatedTime(double time);
|
||||
|
||||
// call from scene graph to update
|
||||
virtual bool Update(double time);
|
||||
|
||||
void
|
||||
SetOption(
|
||||
int option,
|
||||
int value
|
||||
){
|
||||
// intentionally empty
|
||||
};
|
||||
|
||||
};
|
||||
#endif //__KX_ODEPHYSICSCONTROLLER_H
|
50
source/gameengine/Physics/BlOde/Makefile
Normal file
50
source/gameengine/Physics/BlOde/Makefile
Normal file
@ -0,0 +1,50 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version. The Blender
|
||||
# Foundation also sells licenses for use in proprietary software under
|
||||
# the Blender License. See http://www.blender.org/BL/ for information
|
||||
# about this.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
# All rights reserved.
|
||||
#
|
||||
# The Original Code is: all of this file.
|
||||
#
|
||||
# Contributor(s): none yet.
|
||||
#
|
||||
# ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
#
|
||||
#
|
||||
|
||||
LIBNAME = blode
|
||||
DIR = $(OCGDIR)/gameengine/blphys/$(LIBNAME)
|
||||
|
||||
include nan_compile.mk
|
||||
|
||||
CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
|
||||
|
||||
CPPFLAGS += -I$(OPENGL_HEADERS)
|
||||
CPPFLAGS += -I$(NAN_STRING)/include
|
||||
CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
|
||||
CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO)/include -I$(NAN_MOTO)/include
|
||||
CPPFLAGS += -I$(NAN_ODE)/include
|
||||
CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
|
||||
CPPFLAGS += -I../../Physics/common
|
||||
CPPFLAGS += -I../../Physics/Dummy
|
||||
# nlin: fix this, should put in NAN_ODE dir
|
||||
CPPFLAGS += -I./ode/ode/include
|
577
source/gameengine/Physics/BlOde/OdePhysicsController.cpp
Normal file
577
source/gameengine/Physics/BlOde/OdePhysicsController.cpp
Normal file
@ -0,0 +1,577 @@
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
||||
*
|
||||
* The contents of this file may be used under the terms of either the GNU
|
||||
* General Public License Version 2 or later (the "GPL", see
|
||||
* http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or
|
||||
* later (the "BL", see http://www.blender.org/BL/ ) which has to be
|
||||
* bought from the Blender Foundation to become active, in which case the
|
||||
* above mentioned GPL option does not apply.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
*/
|
||||
#include "OdePhysicsController.h"
|
||||
#include "PHY_IMotionState.h"
|
||||
|
||||
#include <ode/ode.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// general to-do list for ODE physics. This is maintained in doxygen format.
|
||||
//
|
||||
/// \todo determine assignment time for bounding spheres.
|
||||
///
|
||||
/// it appears you have to select "sphere" for bounding volume AND "draw bounds"
|
||||
/// in order for a bounding sphere to be generated. otherwise a box is generated.
|
||||
/// determine exactly when and how the bounding volumes are generated and make
|
||||
/// this consistent.
|
||||
/// }
|
||||
///
|
||||
/// \todo bounding sphere size incorrect
|
||||
///
|
||||
/// it appears NOT to use the size of the shown bounding sphere (button "draw bounds").
|
||||
/// it appears instead to use the size of the "size" dynamic parameter in the
|
||||
/// gamebuttons but this "size" draws an incorrectly-sized circle on screen for the
|
||||
/// bounding sphere (leftover skewed size calculation from sumo?) so figure out WHERE
|
||||
/// its getting the radius from.
|
||||
///
|
||||
/// \todo ODE collisions must fire collision actuator
|
||||
///
|
||||
/// See OdePhysicsEnvironment::OdeNearCallback. If a sensor was created to check
|
||||
/// for the presence of this collision, then in the NearCallback you need to
|
||||
/// take appropriate action regarding the sensor - something like checking its
|
||||
/// controller and if needed firing its actuator. Need to find similar code in
|
||||
/// Fuzzics which fires collision controllers/actuators.
|
||||
///
|
||||
/// \todo Are ghost collisions possible?
|
||||
///
|
||||
/// How do ghost collisions work? Do they require collision detection through ODE
|
||||
/// and NON-CREATION of contact-joint in OdeNearCallback? Currently OdeNearCallback
|
||||
/// creates joints ALWAYS for collisions.
|
||||
///
|
||||
/// \todo Why is KX_GameObject::addLinearVelocity commented out?
|
||||
///
|
||||
/// Try putting this code back in.
|
||||
///
|
||||
/// \todo Too many non-dynamic actors bogs down ODE physics
|
||||
///
|
||||
/// Lots of "geoms" (ODE static geometry) probably slows down ode. Try a test file
|
||||
/// with lots of static geometry - the game performance in Blender says it is
|
||||
/// spending all its time in physics, and I bet all that time is in collision
|
||||
/// detection. It's ode's non-hierarchical collision detection.
|
||||
/// try making a separate ode test program (not within blender) with 1000 geoms and
|
||||
/// see how fast it is. if it is really slow, there is the culprit.
|
||||
/// isnt someone working on an improved ODE collision detector? check
|
||||
/// ode mailing list.
|
||||
///
|
||||
///
|
||||
/// \todo support collision of dynas with non-dynamic triangle meshes
|
||||
///
|
||||
/// ODE has trimesh-collision support but only for trimeshes without a transform
|
||||
/// matrix. update ODE tricollider to support a transform matrix. this will allow
|
||||
/// moving trimeshes non-dynamically (e.g. through Ipos). then collide trimeshes
|
||||
/// with dynas. this allows dynamic primitives (spheres, boxes) to collide with
|
||||
/// non-dynamic or kinematically controlled tri-meshes. full dynamic trimesh to
|
||||
/// dynamic trimesh support is hard because it requires (a) collision and penetration
|
||||
/// depth for trimesh to trimesh and (hard to compute) (b) an intertia tensor
|
||||
/// (easy to compute).
|
||||
///
|
||||
/// a triangle mesh collision geometry should be created when the blender
|
||||
/// bounding volume (F9, EDITBUTTONS) is set to "polyheder", since this is
|
||||
/// currently the place where sphere/box selection is made
|
||||
///
|
||||
/// \todo specify ODE ERP+CFM in blender interface
|
||||
///
|
||||
/// when ODE physics selected, have to be able to set global cfm and erp.
|
||||
/// per-joint erp/cfm could be handled in constraint window.
|
||||
///
|
||||
/// \todo moving infinite mass objects should impart extra impulse to objects they collide with
|
||||
///
|
||||
/// currently ODE's ERP pushes them apart but doesn't account for their motion.
|
||||
///
|
||||
/// \todo allow tweaking bounding volume size
|
||||
///
|
||||
/// the scene converter currently uses the blender bounding volume of the selected
|
||||
/// object as the geometry for ODE collision purposes. this is good and automatic
|
||||
/// intuitive - lets you choose between cube, sphere, mesh. but you need to be able
|
||||
/// to tweak this size for physics.
|
||||
///
|
||||
/// \todo off center meshes totally wrong for ode
|
||||
///
|
||||
/// ode uses x, y, z extents regradless of center. then places geom at center of object.
|
||||
/// but visual geom is not necessarily at center. need to detect off-center situations.
|
||||
/// then do what? treat it as an encapsulated off-center mass, or recenter it?
|
||||
///
|
||||
/// i.o.w. recalculate center, or recalculate mass distribution (using encapsulation)?
|
||||
///
|
||||
/// \todo allow off-center mass
|
||||
///
|
||||
/// using ode geometry encapsulators
|
||||
///
|
||||
/// \todo allow entering compound geoms for complex collision shapes specified as a union of simpler shapes
|
||||
///
|
||||
/// The collision shape for arbitrary triangle meshes can probably in general be
|
||||
///well approximated by a compound ODE geometry object, which is merely a combination
|
||||
///of many primitives (capsule, sphere, box). I eventually want to add the ability
|
||||
///to associate compound geometry objects with Blender gameobjects. I think one
|
||||
///way of doing this would be to add a new button in the GameButtons, "RigidBodyCompound".
|
||||
///If the object is "Dynamic" + "RigidBody", then the object's bounding volume (sphere,
|
||||
///box) is created. If an object is "Dynamic" + "RigidBodyCompound", then the object itself
|
||||
///will merely create a "wrapper" compound object, with the actual geometry objects
|
||||
///being created from the object's children in Blender. E.g. if I wanted to make a
|
||||
///compound collision object consisting of a sphere and 2 boxes, I would create a
|
||||
///parent gameobject with the actual triangle mesh, and set its GameButtons to
|
||||
///"RigidBodyCompound". I would then create 3 children of this object, 1 sphere and
|
||||
///2 boxes, and set the GameButtons for the children to be "RigidBody". Then at
|
||||
///scene conversion time, the scene converter sees "RigidBodyCompound" for the
|
||||
///top-level object, then appropriately traverses the children and creates the compound
|
||||
///collision geometry consisting of 2 boxes and a sphere. In this way, arbitrary
|
||||
///mesh-mesh collision becomes much less necessary - the artist can (or must,
|
||||
///depending on your point of view!) approximate the collision shape for arbitrary
|
||||
///meshes with a combination of one or more primitive shapes. I think using the
|
||||
///parent/child relationship in Blender and a new button "RigidBodyCompound" for the
|
||||
///parent object of a compound is a feasible way of doing this in Blender.
|
||||
///
|
||||
///See ODE demo test_boxstack and look at the code when you drop a compound object
|
||||
///with the "X" key.
|
||||
///
|
||||
/// \todo add visual specification of constraints
|
||||
///
|
||||
/// extend the armature constraint system. by using empties and constraining one empty
|
||||
/// to "copy location" of another, you can get a p2p constraint between the two empties.
|
||||
/// by making the two empties each a parent of a blender object, you effectively have
|
||||
/// a p2p constraint between 2 blender bodies. the scene converter can detect these
|
||||
/// empties, detect the constraint, and generate an ODE constraint.
|
||||
///
|
||||
/// then add a new constraint type "hinge" and "slider" to correspond to ODE joints.
|
||||
/// e.g. a slider would be a constraint which restricts the axis of its object to lie
|
||||
/// along the same line as another axis of a different object. e.g. you constrain x-axis
|
||||
/// of one empty to lie along the same line as the z-axis of another empty; this gives
|
||||
/// a slider joint.
|
||||
///
|
||||
/// open questions: how to handle powered joints? to what extent should/must constraints
|
||||
/// be enforced during modeling? use CCD-style algorithm in modeler to enforce constraints?
|
||||
/// how about ODE powered constraints e.g. motors?
|
||||
///
|
||||
/// \todo enable suspension of bodies
|
||||
/// ODE offers native support for suspending dynas. but what about suspending non-dynas
|
||||
/// (e.g. geoms)? suspending geoms is also necessary to ease the load of ODE's (simple?)
|
||||
/// collision detector. suspending dynas and geoms is important for the activity culling,
|
||||
/// which apparently works at a simple level. perhaps suspension should actually
|
||||
/// remove or insert geoms/dynas into the ODE space/world? is this operation (insertion/
|
||||
/// removal) fast enough at run-time? test it. if fast enough, then suspension=remove from
|
||||
/// ODE simulation, awakening=insertion into ODE simulation.
|
||||
///
|
||||
/// \todo python interface for tweaking constraints via python
|
||||
///
|
||||
/// \todo raytesting to support gameengine sensors that need it
|
||||
|
||||
ODEPhysicsController::ODEPhysicsController(bool dyna, bool fullRigidBody,
|
||||
bool phantom, class PHY_IMotionState* motionstate, struct dxSpace* space,
|
||||
struct dxWorld* world, float mass,float friction,float restitution,
|
||||
bool implicitsphere,float center[3],float extents[3],float radius)
|
||||
:
|
||||
m_OdeDyna(dyna),
|
||||
m_firstTime(true),
|
||||
m_bFullRigidBody(fullRigidBody),
|
||||
m_bPhantom(phantom),
|
||||
m_bKinematic(false),
|
||||
m_bPrevKinematic(false),
|
||||
m_MotionState(motionstate),
|
||||
m_OdeSuspendDynamics(false),
|
||||
m_space(space),
|
||||
m_world(world),
|
||||
m_mass(mass),
|
||||
m_friction(friction),
|
||||
m_restitution(restitution),
|
||||
m_bodyId(0),
|
||||
m_geomId(0),
|
||||
m_implicitsphere(implicitsphere),
|
||||
m_radius(radius)
|
||||
{
|
||||
m_center[0] = center[0];
|
||||
m_center[1] = center[1];
|
||||
m_center[2] = center[2];
|
||||
m_extends[0] = extents[0];
|
||||
m_extends[1] = extents[1];
|
||||
m_extends[2] = extents[2];
|
||||
};
|
||||
|
||||
|
||||
ODEPhysicsController::~ODEPhysicsController()
|
||||
{
|
||||
if (m_geomId)
|
||||
{
|
||||
dGeomDestroy (m_geomId);
|
||||
}
|
||||
}
|
||||
|
||||
float ODEPhysicsController::getMass()
|
||||
{
|
||||
dMass mass;
|
||||
dBodyGetMass(m_bodyId,&mass);
|
||||
return mass.mass;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
/// \todo Impart some extra impulse to dynamic objects when they collide with kinematically controlled "static" objects (ODE geoms), by using last 2 frames as 1st order approximation to the linear/angular velocity, and computing an appropriate impulse. Sumo (old physics engine) did this, see for details.
|
||||
/// \todo handle scaling of static ODE geoms or fail with error message if Ipo tries to change scale of a static geom object
|
||||
|
||||
bool ODEPhysicsController::SynchronizeMotionStates(float time)
|
||||
{
|
||||
/**
|
||||
'Late binding' of the rigidbody, because the World Scaling is not available until the scenegraph is traversed
|
||||
*/
|
||||
|
||||
|
||||
if (m_firstTime)
|
||||
{
|
||||
m_firstTime=false;
|
||||
|
||||
m_MotionState->calculateWorldTransformations();
|
||||
|
||||
dQuaternion worldquat;
|
||||
float worldpos[3];
|
||||
|
||||
m_MotionState->getWorldOrientation(worldquat[1],worldquat[2],worldquat[3],worldquat[0]);
|
||||
m_MotionState->getWorldPosition(worldpos[0],worldpos[1],worldpos[2]);
|
||||
|
||||
float scaling[3];
|
||||
m_MotionState->getWorldScaling(scaling[0],scaling[1],scaling[2]);
|
||||
|
||||
if (!m_bPhantom)
|
||||
{
|
||||
if (m_implicitsphere)
|
||||
{
|
||||
m_geomId = dCreateSphere (m_space,m_radius*scaling[0]);
|
||||
} else
|
||||
{
|
||||
m_geomId = dCreateBox (m_space, m_extends[0]*scaling[0],m_extends[1]*scaling[1],m_extends[2]*scaling[2]);
|
||||
}
|
||||
} else
|
||||
{
|
||||
m_geomId=0;
|
||||
}
|
||||
|
||||
if (m_geomId)
|
||||
dGeomSetData(m_geomId,this);
|
||||
|
||||
if (!this->m_OdeDyna)
|
||||
{
|
||||
if (!m_bPhantom)
|
||||
{
|
||||
dGeomSetPosition (this->m_geomId,worldpos[0],worldpos[1],worldpos[2]);
|
||||
dMatrix3 R;
|
||||
dQtoR (worldquat, R);
|
||||
dGeomSetRotation (this->m_geomId,R);
|
||||
}
|
||||
} else
|
||||
{
|
||||
//it's dynamic, so create a 'model'
|
||||
m_bodyId = dBodyCreate(this->m_world);
|
||||
dBodySetPosition (m_bodyId,worldpos[0],worldpos[1],worldpos[2]);
|
||||
dBodySetQuaternion (this->m_bodyId,worldquat);
|
||||
//this contains both scalar mass and inertia tensor
|
||||
dMass m;
|
||||
float length=1,width=1,height=1;
|
||||
dMassSetBox (&m,1,m_extends[0]*scaling[0],m_extends[1]*scaling[1],m_extends[2]*scaling[2]);
|
||||
dMassAdjust (&m,this->m_mass);
|
||||
dBodySetMass (m_bodyId,&m);
|
||||
|
||||
if (!m_bPhantom)
|
||||
{
|
||||
dGeomSetBody (m_geomId,m_bodyId);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (this->m_OdeDyna && !m_bFullRigidBody)
|
||||
{
|
||||
// ?? huh? what to do here?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (m_OdeDyna)
|
||||
{
|
||||
if (this->m_OdeSuspendDynamics)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const float* worldPos = dBodyGetPosition(m_bodyId);
|
||||
m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]);
|
||||
|
||||
const float* worldquat = dBodyGetQuaternion(m_bodyId);
|
||||
m_MotionState->setWorldOrientation(worldquat[1],worldquat[2],worldquat[3],worldquat[0]);
|
||||
}
|
||||
else {
|
||||
// not a dyna, so dynamics (i.e. this controller) has not updated
|
||||
// anything. BUT! an Ipo or something else might have changed the
|
||||
// position/orientation of this geometry.
|
||||
// so update the static geom position
|
||||
|
||||
/// \todo impart some extra impulse to colliding objects!
|
||||
dQuaternion worldquat;
|
||||
float worldpos[3];
|
||||
|
||||
m_MotionState->getWorldOrientation(worldquat[1],worldquat[2],worldquat[3],worldquat[0]);
|
||||
m_MotionState->getWorldPosition(worldpos[0],worldpos[1],worldpos[2]);
|
||||
|
||||
float scaling[3];
|
||||
m_MotionState->getWorldScaling(scaling[0],scaling[1],scaling[2]);
|
||||
|
||||
/// \todo handle scaling! what if Ipo changes scale of object?
|
||||
// Must propagate to geom... is scaling geoms possible with ODE? Also
|
||||
// what about scaling trimeshes, that is certainly difficult...
|
||||
dGeomSetPosition (this->m_geomId,worldpos[0],worldpos[1],worldpos[2]);
|
||||
dMatrix3 R;
|
||||
dQtoR (worldquat, R);
|
||||
dGeomSetRotation (this->m_geomId,R);
|
||||
}
|
||||
|
||||
return false; //it update the worldpos
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// kinematic methods
|
||||
void ODEPhysicsController::RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local)
|
||||
{
|
||||
|
||||
}
|
||||
void ODEPhysicsController::RelativeRotate(const float drot[9],bool local)
|
||||
{
|
||||
}
|
||||
void ODEPhysicsController::setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal)
|
||||
{
|
||||
|
||||
dQuaternion worldquat;
|
||||
worldquat[0] = quatReal;
|
||||
worldquat[1] = quatImag0;
|
||||
worldquat[2] = quatImag1;
|
||||
worldquat[3] = quatImag2;
|
||||
|
||||
if (!this->m_OdeDyna)
|
||||
{
|
||||
dMatrix3 R;
|
||||
dQtoR (worldquat, R);
|
||||
dGeomSetRotation (this->m_geomId,R);
|
||||
} else
|
||||
{
|
||||
dBodySetQuaternion (m_bodyId,worldquat);
|
||||
this->m_MotionState->setWorldOrientation(quatImag0,quatImag1,quatImag2,quatReal);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ODEPhysicsController::getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal)
|
||||
{
|
||||
float q[4];
|
||||
this->m_MotionState->getWorldOrientation(q[0],q[1],q[2],q[3]);
|
||||
quatImag0=q[0];
|
||||
quatImag1=q[1];
|
||||
quatImag2=q[2];
|
||||
quatReal=q[3];
|
||||
}
|
||||
|
||||
void ODEPhysicsController::setPosition(float posX,float posY,float posZ)
|
||||
{
|
||||
if (!m_bPhantom)
|
||||
{
|
||||
if (!this->m_OdeDyna)
|
||||
{
|
||||
dGeomSetPosition (m_geomId, posX, posY, posZ);
|
||||
} else
|
||||
{
|
||||
dBodySetPosition (m_bodyId, posX, posY, posZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
void ODEPhysicsController::setScaling(float scaleX,float scaleY,float scaleZ)
|
||||
{
|
||||
}
|
||||
|
||||
// physics methods
|
||||
void ODEPhysicsController::ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local)
|
||||
{
|
||||
if (m_OdeDyna) {
|
||||
if(local) {
|
||||
dBodyAddRelTorque(m_bodyId, torqueX, torqueY, torqueZ);
|
||||
} else {
|
||||
dBodyAddTorque (m_bodyId, torqueX, torqueY, torqueZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ODEPhysicsController::ApplyForce(float forceX,float forceY,float forceZ,bool local)
|
||||
{
|
||||
if (m_OdeDyna) {
|
||||
if(local) {
|
||||
dBodyAddRelForce(m_bodyId, forceX, forceY, forceZ);
|
||||
} else {
|
||||
dBodyAddForce (m_bodyId, forceX, forceY, forceZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ODEPhysicsController::SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local)
|
||||
{
|
||||
if (m_OdeDyna) {
|
||||
if(local) {
|
||||
// TODO: translate angular vel into local frame, then apply
|
||||
} else {
|
||||
dBodySetAngularVel (m_bodyId, ang_velX,ang_velY,ang_velZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ODEPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local)
|
||||
{
|
||||
if (m_OdeDyna)
|
||||
{
|
||||
dVector3 vel = {lin_velX,lin_velY,lin_velZ};
|
||||
if (local)
|
||||
{
|
||||
dMatrix3 worldmat;
|
||||
dVector3 localvel;
|
||||
dQuaternion worldquat;
|
||||
m_MotionState->getWorldOrientation(worldquat[1],worldquat[2],worldquat[3],worldquat[0]);
|
||||
dQtoR (worldquat, worldmat);
|
||||
|
||||
dMULTIPLY0_331 (localvel,worldmat,vel);
|
||||
dBodySetLinearVel (m_bodyId, localvel[0],localvel[1],localvel[2]);
|
||||
|
||||
} else
|
||||
{
|
||||
dBodySetLinearVel (m_bodyId, lin_velX,lin_velY,lin_velZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ODEPhysicsController::applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ)
|
||||
{
|
||||
if (m_OdeDyna)
|
||||
{
|
||||
//apply linear and angular effect
|
||||
const dReal* linvel = dBodyGetLinearVel(m_bodyId);
|
||||
float mass = getMass();
|
||||
if (mass >= 0.00001f)
|
||||
{
|
||||
float massinv = 1.f/mass;
|
||||
float newvel[3];
|
||||
newvel[0]=linvel[0]+impulseX*massinv;
|
||||
newvel[1]=linvel[1]+impulseY*massinv;
|
||||
newvel[2]=linvel[2]+impulseZ*massinv;
|
||||
dBodySetLinearVel(m_bodyId,newvel[0],newvel[1],newvel[2]);
|
||||
|
||||
const float* worldPos = dBodyGetPosition(m_bodyId);
|
||||
|
||||
const float* angvelc = dBodyGetAngularVel (m_bodyId);
|
||||
float angvel[3];
|
||||
angvel[0]=angvelc[0];
|
||||
angvel[1]=angvelc[1];
|
||||
angvel[2]=angvelc[2];
|
||||
|
||||
dVector3 impulse;
|
||||
impulse[0]=impulseX;
|
||||
impulse[1]=impulseY;
|
||||
impulse[2]=impulseZ;
|
||||
|
||||
dVector3 ap;
|
||||
ap[0]=attachX-worldPos[0];
|
||||
ap[1]=attachY-worldPos[1];
|
||||
ap[2]=attachZ-worldPos[2];
|
||||
|
||||
dCROSS(angvel,+=,ap,impulse);
|
||||
dBodySetAngularVel(m_bodyId,angvel[0],angvel[1],angvel[2]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ODEPhysicsController::SuspendDynamics()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ODEPhysicsController::RestoreDynamics()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
reading out information from physics
|
||||
*/
|
||||
void ODEPhysicsController::GetLinearVelocity(float& linvX,float& linvY,float& linvZ)
|
||||
{
|
||||
if (m_OdeDyna)
|
||||
{
|
||||
const float* vel = dBodyGetLinearVel(m_bodyId);
|
||||
linvX = vel[0];
|
||||
linvY = vel[1];
|
||||
linvZ = vel[2];
|
||||
} else
|
||||
{
|
||||
linvX = 0.f;
|
||||
linvY = 0.f;
|
||||
linvZ = 0.f;
|
||||
|
||||
}
|
||||
}
|
||||
/**
|
||||
GetVelocity parameters are in geometric coordinates (Origin is not center of mass!).
|
||||
*/
|
||||
void ODEPhysicsController::GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ODEPhysicsController::getReactionForce(float& forceX,float& forceY,float& forceZ)
|
||||
{
|
||||
|
||||
}
|
||||
void ODEPhysicsController::setRigidBody(bool rigid)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ODEPhysicsController::PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl)
|
||||
{
|
||||
m_MotionState = motionstate;
|
||||
m_bKinematic = false;
|
||||
m_bPrevKinematic = false;
|
||||
m_firstTime = true;
|
||||
}
|
||||
|
||||
|
||||
void ODEPhysicsController::SetSimulatedTime(float time)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ODEPhysicsController::WriteMotionStateToDynamics(bool nondynaonly)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
150
source/gameengine/Physics/BlOde/OdePhysicsController.h
Normal file
150
source/gameengine/Physics/BlOde/OdePhysicsController.h
Normal file
@ -0,0 +1,150 @@
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
||||
*
|
||||
* The contents of this file may be used under the terms of either the GNU
|
||||
* General Public License Version 2 or later (the "GPL", see
|
||||
* http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or
|
||||
* later (the "BL", see http://www.blender.org/BL/ ) which has to be
|
||||
* bought from the Blender Foundation to become active, in which case the
|
||||
* above mentioned GPL option does not apply.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
*/
|
||||
#ifndef __ODE_PHYSICSCONTROLLER_H
|
||||
#define __ODE_PHYSICSCONTROLLER_H
|
||||
|
||||
|
||||
#include "PHY_IPhysicsController.h"
|
||||
|
||||
|
||||
/**
|
||||
ODE Physics Controller, a special kind of a PhysicsController.
|
||||
A Physics Controller is a special kind of Scene Graph Transformation Controller.
|
||||
Each time the scene graph get's updated, the controller get's a chance
|
||||
in the 'Update' method to reflect changes.
|
||||
*/
|
||||
|
||||
class ODEPhysicsController : public PHY_IPhysicsController
|
||||
|
||||
{
|
||||
|
||||
bool m_OdeDyna;
|
||||
|
||||
public:
|
||||
ODEPhysicsController(
|
||||
bool dyna,
|
||||
bool fullRigidBody,
|
||||
bool phantom,
|
||||
class PHY_IMotionState* motionstate,
|
||||
struct dxSpace* space,
|
||||
struct dxWorld* world,
|
||||
float mass,
|
||||
float friction,
|
||||
float restitution,
|
||||
bool implicitsphere,
|
||||
float center[3],
|
||||
float extends[3],
|
||||
float radius);
|
||||
|
||||
virtual ~ODEPhysicsController();
|
||||
|
||||
// kinematic methods
|
||||
virtual void RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local);
|
||||
virtual void RelativeRotate(const float drot[9],bool local);
|
||||
virtual void getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal);
|
||||
virtual void setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal);
|
||||
virtual void setPosition(float posX,float posY,float posZ);
|
||||
virtual void setScaling(float scaleX,float scaleY,float scaleZ);
|
||||
|
||||
// physics methods
|
||||
virtual void ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local);
|
||||
virtual void ApplyForce(float forceX,float forceY,float forceZ,bool local);
|
||||
virtual void SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local);
|
||||
virtual void SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local);
|
||||
virtual void applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ);
|
||||
virtual void SetActive(bool active){};
|
||||
virtual void SuspendDynamics();
|
||||
virtual void RestoreDynamics();
|
||||
|
||||
|
||||
/**
|
||||
reading out information from physics
|
||||
*/
|
||||
virtual void GetLinearVelocity(float& linvX,float& linvY,float& linvZ);
|
||||
/**
|
||||
GetVelocity parameters are in geometric coordinates (Origin is not center of mass!).
|
||||
*/
|
||||
virtual void GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ);
|
||||
virtual float getMass();
|
||||
virtual void getReactionForce(float& forceX,float& forceY,float& forceZ);
|
||||
virtual void setRigidBody(bool rigid);
|
||||
|
||||
|
||||
virtual void PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl);
|
||||
|
||||
// \todo remove next line !
|
||||
virtual void SetSimulatedTime(float time);
|
||||
|
||||
|
||||
virtual void WriteDynamicsToMotionState() {};
|
||||
virtual void WriteMotionStateToDynamics(bool nondynaonly);
|
||||
|
||||
/**
|
||||
call from Scene Graph Node to 'update'.
|
||||
*/
|
||||
virtual bool SynchronizeMotionStates(float time);
|
||||
|
||||
// clientinfo for raycasts for example
|
||||
virtual void* getClientInfo() { return m_clientInfo;}
|
||||
virtual void setClientInfo(void* clientinfo) {m_clientInfo = clientinfo;};
|
||||
void* m_clientInfo;
|
||||
|
||||
struct dxBody* GetOdeBodyId() { return m_bodyId; }
|
||||
|
||||
float getFriction() { return m_friction;}
|
||||
float getRestitution() { return m_restitution;}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
bool m_firstTime;
|
||||
bool m_bFullRigidBody;
|
||||
bool m_bPhantom; // special flag for objects that are not affected by physics 'resolver'
|
||||
|
||||
// data to calculate fake velocities for kinematic objects (non-dynas)
|
||||
bool m_bKinematic;
|
||||
bool m_bPrevKinematic;
|
||||
|
||||
|
||||
float m_lastTime;
|
||||
bool m_OdeSuspendDynamics;
|
||||
class PHY_IMotionState* m_MotionState;
|
||||
|
||||
//Ode specific members
|
||||
struct dxBody* m_bodyId;
|
||||
struct dxGeom* m_geomId;
|
||||
struct dxSpace* m_space;
|
||||
struct dxWorld* m_world;
|
||||
float m_mass;
|
||||
float m_friction;
|
||||
float m_restitution;
|
||||
bool m_implicitsphere;
|
||||
float m_center[3];
|
||||
float m_extends[3];
|
||||
float m_radius;
|
||||
};
|
||||
|
||||
#endif //__ODE_PHYSICSCONTROLLER_H
|
||||
|
||||
|
||||
|
233
source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp
Normal file
233
source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp
Normal file
@ -0,0 +1,233 @@
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
||||
*
|
||||
* The contents of this file may be used under the terms of either the GNU
|
||||
* General Public License Version 2 or later (the "GPL", see
|
||||
* http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or
|
||||
* later (the "BL", see http://www.blender.org/BL/ ) which has to be
|
||||
* bought from the Blender Foundation to become active, in which case the
|
||||
* above mentioned GPL option does not apply.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
*/
|
||||
#include "OdePhysicsEnvironment.h"
|
||||
#include "PHY_IMotionState.h"
|
||||
#include "OdePhysicsController.h"
|
||||
|
||||
// Ode
|
||||
#include <ode/config.h>
|
||||
#include <ode/ode.h>
|
||||
#include <../ode/src/joint.h>
|
||||
#include <ode/odemath.h>
|
||||
|
||||
|
||||
ODEPhysicsEnvironment::ODEPhysicsEnvironment()
|
||||
{
|
||||
m_OdeWorld = dWorldCreate();
|
||||
m_OdeSpace = dHashSpaceCreate();
|
||||
m_OdeContactGroup = dJointGroupCreate (0);
|
||||
dWorldSetCFM (m_OdeWorld,1e-5f);
|
||||
|
||||
m_JointGroup = dJointGroupCreate(0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
ODEPhysicsEnvironment::~ODEPhysicsEnvironment()
|
||||
{
|
||||
dJointGroupDestroy (m_OdeContactGroup);
|
||||
dJointGroupDestroy (m_JointGroup);
|
||||
|
||||
dSpaceDestroy (m_OdeSpace);
|
||||
dWorldDestroy (m_OdeWorld);
|
||||
}
|
||||
|
||||
void ODEPhysicsEnvironment::proceed(double timeStep)
|
||||
{
|
||||
// ode collision update
|
||||
dSpaceCollide (m_OdeSpace,this,&ODEPhysicsEnvironment::OdeNearCallback);
|
||||
|
||||
int m_odeContacts = GetNumOdeContacts();
|
||||
|
||||
//physics integrator + resolver update
|
||||
dWorldStep (m_OdeWorld,timeStep);
|
||||
|
||||
//clear collision points
|
||||
this->ClearOdeContactGroup();
|
||||
}
|
||||
|
||||
void ODEPhysicsEnvironment::setGravity(float x,float y,float z)
|
||||
{
|
||||
dWorldSetGravity (m_OdeWorld,x,y,z);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ODEPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
|
||||
float pivotX,float pivotY,float pivotZ,float axisX,float axisY,float axisZ)
|
||||
{
|
||||
|
||||
int constraintid = 0;
|
||||
ODEPhysicsController* dynactrl = (ODEPhysicsController*)ctrl;
|
||||
ODEPhysicsController* dynactrl2 = (ODEPhysicsController*)ctrl2;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PHY_POINT2POINT_CONSTRAINT:
|
||||
{
|
||||
if (dynactrl)
|
||||
{
|
||||
dJointID jointid = dJointCreateBall (m_OdeWorld,m_JointGroup);
|
||||
struct dxBody* bodyid1 = dynactrl->GetOdeBodyId();
|
||||
struct dxBody* bodyid2=0;
|
||||
const float* pos = dBodyGetPosition(bodyid1);
|
||||
const float* R = dBodyGetRotation(bodyid1);
|
||||
float offset[3] = {pivotX,pivotY,pivotZ};
|
||||
float newoffset[3];
|
||||
dMULTIPLY0_331 (newoffset,R,offset);
|
||||
newoffset[0] += pos[0];
|
||||
newoffset[1] += pos[1];
|
||||
newoffset[2] += pos[2];
|
||||
|
||||
|
||||
if (dynactrl2)
|
||||
bodyid2 = dynactrl2->GetOdeBodyId();
|
||||
|
||||
dJointAttach (jointid, bodyid1, bodyid2);
|
||||
|
||||
dJointSetBallAnchor (jointid, newoffset[0], newoffset[1], newoffset[2]);
|
||||
|
||||
constraintid = (int) jointid;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PHY_LINEHINGE_CONSTRAINT:
|
||||
{
|
||||
if (dynactrl)
|
||||
{
|
||||
dJointID jointid = dJointCreateHinge (m_OdeWorld,m_JointGroup);
|
||||
struct dxBody* bodyid1 = dynactrl->GetOdeBodyId();
|
||||
struct dxBody* bodyid2=0;
|
||||
const float* pos = dBodyGetPosition(bodyid1);
|
||||
const float* R = dBodyGetRotation(bodyid1);
|
||||
float offset[3] = {pivotX,pivotY,pivotZ};
|
||||
float axisset[3] = {axisX,axisY,axisZ};
|
||||
|
||||
float newoffset[3];
|
||||
float newaxis[3];
|
||||
dMULTIPLY0_331 (newaxis,R,axisset);
|
||||
|
||||
dMULTIPLY0_331 (newoffset,R,offset);
|
||||
newoffset[0] += pos[0];
|
||||
newoffset[1] += pos[1];
|
||||
newoffset[2] += pos[2];
|
||||
|
||||
|
||||
if (dynactrl2)
|
||||
bodyid2 = dynactrl2->GetOdeBodyId();
|
||||
|
||||
dJointAttach (jointid, bodyid1, bodyid2);
|
||||
|
||||
dJointSetHingeAnchor (jointid, newoffset[0], newoffset[1], newoffset[2]);
|
||||
dJointSetHingeAxis(jointid,newaxis[0],newaxis[1],newaxis[2]);
|
||||
|
||||
constraintid = (int) jointid;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
//not yet
|
||||
}
|
||||
}
|
||||
|
||||
return constraintid;
|
||||
|
||||
}
|
||||
|
||||
void ODEPhysicsEnvironment::removeConstraint(int constraintid)
|
||||
{
|
||||
if (constraintid)
|
||||
{
|
||||
dJointDestroy((dJointID) constraintid);
|
||||
}
|
||||
}
|
||||
|
||||
PHY_IPhysicsController* ODEPhysicsEnvironment::rayTest(void* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ,
|
||||
float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ)
|
||||
{
|
||||
//collision detection / raytesting
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void ODEPhysicsEnvironment::OdeNearCallback (void *data, dGeomID o1, dGeomID o2)
|
||||
{
|
||||
// \todo if this is a registered collision sensor
|
||||
// fire the callback
|
||||
|
||||
int i;
|
||||
// if (o1->body && o2->body) return;
|
||||
ODEPhysicsEnvironment* env = (ODEPhysicsEnvironment*) data;
|
||||
dBodyID b1,b2;
|
||||
|
||||
b1 = dGeomGetBody(o1);
|
||||
b2 = dGeomGetBody(o2);
|
||||
// exit without doing anything if the two bodies are connected by a joint
|
||||
if (b1 && b2 && dAreConnected (b1,b2)) return;
|
||||
|
||||
ODEPhysicsController * ctrl1 =(ODEPhysicsController *)dGeomGetData(o1);
|
||||
ODEPhysicsController * ctrl2 =(ODEPhysicsController *)dGeomGetData(o2);
|
||||
float friction=ctrl1->getFriction();
|
||||
float restitution = ctrl1->getRestitution();
|
||||
//for friction, take minimum
|
||||
|
||||
friction=(friction < ctrl2->getFriction() ?
|
||||
friction :ctrl2->getFriction());
|
||||
|
||||
//restitution:take minimum
|
||||
restitution = restitution < ctrl2->getRestitution()?
|
||||
restitution : ctrl2->getRestitution();
|
||||
|
||||
dContact contact[3]; // up to 3 contacts per box
|
||||
for (i=0; i<3; i++) {
|
||||
contact[i].surface.mode = dContactBounce; //dContactMu2;
|
||||
contact[i].surface.mu = friction;//dInfinity;
|
||||
contact[i].surface.mu2 = 0;
|
||||
contact[i].surface.bounce = restitution;//0.5;
|
||||
contact[i].surface.bounce_vel = 0.1f;
|
||||
contact[i].surface.slip1=0.0;
|
||||
}
|
||||
|
||||
if (int numc = dCollide (o1,o2,3,&contact[0].geom,sizeof(dContact))) {
|
||||
// dMatrix3 RI;
|
||||
// dRSetIdentity (RI);
|
||||
// const dReal ss[3] = {0.02,0.02,0.02};
|
||||
for (i=0; i<numc; i++) {
|
||||
dJointID c = dJointCreateContact (env->m_OdeWorld,env->m_OdeContactGroup,contact+i);
|
||||
dJointAttach (c,b1,b2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODEPhysicsEnvironment::ClearOdeContactGroup()
|
||||
{
|
||||
dJointGroupEmpty (m_OdeContactGroup);
|
||||
}
|
||||
|
||||
int ODEPhysicsEnvironment::GetNumOdeContacts()
|
||||
{
|
||||
return m_OdeContactGroup->num;
|
||||
}
|
||||
|
73
source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
Normal file
73
source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
Normal file
@ -0,0 +1,73 @@
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
||||
*
|
||||
* The contents of this file may be used under the terms of either the GNU
|
||||
* General Public License Version 2 or later (the "GPL", see
|
||||
* http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or
|
||||
* later (the "BL", see http://www.blender.org/BL/ ) which has to be
|
||||
* bought from the Blender Foundation to become active, in which case the
|
||||
* above mentioned GPL option does not apply.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
*/
|
||||
#ifndef _ODEPHYSICSENVIRONMENT
|
||||
#define _ODEPHYSICSENVIRONMENT
|
||||
|
||||
|
||||
#include "PHY_IPhysicsEnvironment.h"
|
||||
|
||||
|
||||
/**
|
||||
* Physics Environment takes care of stepping the simulation and is a container for physics entities (rigidbodies,constraints, materials etc.)
|
||||
* A derived class may be able to 'construct' entities by loading and/or converting
|
||||
*/
|
||||
class ODEPhysicsEnvironment : public PHY_IPhysicsEnvironment
|
||||
{
|
||||
|
||||
public:
|
||||
ODEPhysicsEnvironment();
|
||||
virtual ~ODEPhysicsEnvironment();
|
||||
// Perform an integration step of duration 'timeStep'.
|
||||
virtual void proceed(double timeStep);
|
||||
virtual void setGravity(float x,float y,float z);
|
||||
virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
|
||||
float pivotX,float pivotY,float pivotZ,
|
||||
float axisX,float axisY,float axisZ);
|
||||
|
||||
virtual void removeConstraint(int constraintid);
|
||||
virtual PHY_IPhysicsController* rayTest(void* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ,
|
||||
float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ);
|
||||
|
||||
struct dxWorld* GetOdeWorld() { return m_OdeWorld; };
|
||||
struct dxSpace* GetOdeSpace() { return m_OdeSpace;};
|
||||
|
||||
private:
|
||||
|
||||
|
||||
// ODE physics response
|
||||
struct dxWorld* m_OdeWorld;
|
||||
// ODE collision detection
|
||||
struct dxSpace* m_OdeSpace;
|
||||
void ClearOdeContactGroup();
|
||||
struct dxJointGroup* m_OdeContactGroup;
|
||||
struct dxJointGroup* m_JointGroup;
|
||||
|
||||
static void OdeNearCallback(void *data, struct dxGeom* o1, struct dxGeom* o2);
|
||||
int GetNumOdeContacts();
|
||||
|
||||
};
|
||||
|
||||
#endif //_ODEPHYSICSENVIRONMENT
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user