Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/gameengine/Physics')
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp91
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h70
-rw-r--r--source/gameengine/Physics/Dummy/Makefile47
-rw-r--r--source/gameengine/Physics/Makefile40
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/Makefile9
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_Callback.h10
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_ClientObjectInfo.h15
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h36
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h36
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h280
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_Props.h60
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h129
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/sample/Makefile25
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/sample/particle.cpp705
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/sample/particle0.cpp691
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/src/Makefile13
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/src/SM_FhObject.cpp115
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp953
-rw-r--r--source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp179
-rw-r--r--source/gameengine/Physics/Sumo/Makefile47
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsController.cpp462
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsController.h171
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp103
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h88
-rw-r--r--source/gameengine/Physics/Sumo/convert.txt35
-rw-r--r--source/gameengine/Physics/Sumo/include/interpolator.h27
-rw-r--r--source/gameengine/Physics/Sumo/include/solid.h195
-rw-r--r--source/gameengine/Physics/Sumo/include/solid_broadphase.h38
-rw-r--r--source/gameengine/Physics/Sumo/include/solid_types.h14
-rw-r--r--source/gameengine/Physics/common/Makefile59
-rw-r--r--source/gameengine/Physics/common/PHY_DynamicTypes.h68
-rw-r--r--source/gameengine/Physics/common/PHY_IMotionState.cpp37
-rw-r--r--source/gameengine/Physics/common/PHY_IMotionState.h57
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsController.cpp39
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsController.h89
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsEnvironment.cpp45
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h60
-rw-r--r--source/gameengine/Physics/common/PHY_Pro.h60
38 files changed, 5198 insertions, 0 deletions
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
new file mode 100644
index 00000000000..bc88ae7012d
--- /dev/null
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
@@ -0,0 +1,91 @@
+/**
+ * $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 *****
+ */
+#include "DummyPhysicsEnvironment.h"
+#include "PHY_IMotionState.h"
+
+
+
+DummyPhysicsEnvironment::DummyPhysicsEnvironment()
+{
+ // create physicsengine data
+}
+
+
+
+DummyPhysicsEnvironment::~DummyPhysicsEnvironment()
+{
+ //destroy physicsengine data
+}
+
+void DummyPhysicsEnvironment::proceed(double timeStep)
+{
+ //step physics simulation, typically perform
+
+ //collision detection
+ //solve constraints
+ //integrate solution
+
+}
+
+void DummyPhysicsEnvironment::setGravity(float x,float y,float z)
+{
+}
+
+
+
+
+
+
+
+int DummyPhysicsEnvironment::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;
+ return constraintid;
+
+}
+
+void DummyPhysicsEnvironment::removeConstraint(int constraintid)
+{
+ if (constraintid)
+ {
+ }
+}
+
+PHY_IPhysicsController* DummyPhysicsEnvironment::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;
+}
+
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
new file mode 100644
index 00000000000..874b747849d
--- /dev/null
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
@@ -0,0 +1,70 @@
+/**
+ * $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 *****
+ */
+#ifndef _DUMMYPHYSICSENVIRONMENT
+#define _DUMMYPHYSICSENVIRONMENT
+
+
+#include "PHY_IPhysicsEnvironment.h"
+
+/**
+* DummyPhysicsEnvironment is an empty placeholder
+* Alternatives are ODE,Sumo and Dynamo PhysicsEnvironments
+* Use DummyPhysicsEnvironment as a base to integrate your own physics engine
+* 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 DummyPhysicsEnvironment : public PHY_IPhysicsEnvironment
+{
+
+public:
+ DummyPhysicsEnvironment ();
+ virtual ~DummyPhysicsEnvironment ();
+// 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);
+
+
+};
+
+#endif //_DUMMYPHYSICSENVIRONMENT
+
+
+
diff --git a/source/gameengine/Physics/Dummy/Makefile b/source/gameengine/Physics/Dummy/Makefile
new file mode 100644
index 00000000000..4ef37cf97ce
--- /dev/null
+++ b/source/gameengine/Physics/Dummy/Makefile
@@ -0,0 +1,47 @@
+#
+# $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 = dummy
+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_GUARDEDALLOC)/include
+CPPFLAGS += -I../../Physics/common
+CPPFLAGS += -I../../Physics/Dummy
diff --git a/source/gameengine/Physics/Makefile b/source/gameengine/Physics/Makefile
new file mode 100644
index 00000000000..c04ccb175aa
--- /dev/null
+++ b/source/gameengine/Physics/Makefile
@@ -0,0 +1,40 @@
+#
+# $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 *****
+#
+# Bounces make to subdirectories.
+
+include nan_definitions.mk
+
+SOURCEDIR = source/gameengine/Physics
+DIR = $(OCGDIR)/gameengine/blphys
+DIRS = common Sumo Dummy
+
+include nan_subdirs.mk
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/Makefile b/source/gameengine/Physics/Sumo/Fuzzics/Makefile
new file mode 100644
index 00000000000..d721a416862
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/Makefile
@@ -0,0 +1,9 @@
+#
+# $Id$
+# Copyright (C) 2001 NaN Technologies B.V.
+# Bounce make to subdirectories.
+
+SOURCEDIR = source/sumo/Fuzzics
+DIRS = src
+
+include nan_subdirs.mk
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Callback.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Callback.h
new file mode 100644
index 00000000000..a43ddbec483
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Callback.h
@@ -0,0 +1,10 @@
+#ifndef SM_CALLBACK_H
+#define SM_CALLBACK_H
+
+class SM_Callback {
+public:
+ virtual void do_me() = 0;
+};
+
+#endif
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_ClientObjectInfo.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_ClientObjectInfo.h
new file mode 100644
index 00000000000..2063892e671
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_ClientObjectInfo.h
@@ -0,0 +1,15 @@
+#ifndef __SM_CLIENTOBJECT_INFO_H
+#define __SM_CLIENTOBJECT_INFO_H
+
+/**
+ * Client Type and Additional Info. This structure can be use instead of a bare void* pointer, for safeness, and additional info for callbacks
+ */
+
+struct SM_ClientObjectInfo
+{
+ int m_type;
+ void* m_clientobject;
+ void* m_auxilary_info;
+};
+
+#endif //__SM_CLIENTOBJECT_INFO_H
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h
new file mode 100644
index 00000000000..4aac43f6712
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h
@@ -0,0 +1,36 @@
+#ifndef SM_FHOBJECT_H
+#define SM_FHOBJECT_H
+
+#include "SM_Object.h"
+
+class SM_FhObject : public SM_Object {
+public:
+ SM_FhObject() {}
+ SM_FhObject(const MT_Vector3& ray, SM_Object *client_object) :
+ SM_Object(DT_Ray(ray[0], ray[1], ray[2]), 0, 0, 0),
+ m_ray(ray),
+ m_ray_direction(ray.normalized()),
+ m_client_object(client_object) {}
+
+ const MT_Vector3& getRay() const { return m_ray; }
+ MT_Point3 getSpot() const { return m_pos + m_ray; }
+ const MT_Vector3& getRayDirection() const { return m_ray_direction; }
+ SM_Object *getClientObject() const { return m_client_object; }
+
+ static void ray_hit(void *client_data,
+ void *object1,
+ void *object2,
+ const DT_CollData *coll_data);
+
+private:
+ MT_Vector3 m_ray;
+ MT_Vector3 m_ray_direction;
+ SM_Object *m_client_object;
+};
+
+#endif
+
+
+
+
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h
new file mode 100644
index 00000000000..9c6a9ddaec2
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h
@@ -0,0 +1,36 @@
+#ifndef SM_MOTIONSTATE_H
+#define SM_MOTIONSTATE_H
+
+#include "MT_Transform.h"
+
+class SM_MotionState {
+public:
+ SM_MotionState() :
+ m_pos(0.0, 0.0, 0.0),
+ m_orn(0.0, 0.0, 0.0, 1.0),
+ m_lin_vel(0.0, 0.0, 0.0),
+ m_ang_vel(0.0, 0.0, 0.0)
+ {}
+
+ void setPosition(const MT_Point3& pos) { m_pos = pos; }
+ void setOrientation(const MT_Quaternion& orn) { m_orn = orn; }
+ void setLinearVelocity(const MT_Vector3& lin_vel) { m_lin_vel = lin_vel; }
+ void setAngularVelocity(const MT_Vector3& ang_vel) { m_ang_vel = ang_vel; }
+
+ const MT_Point3& getPosition() const { return m_pos; }
+ const MT_Quaternion& getOrientation() const { return m_orn; }
+ const MT_Vector3& getLinearVelocity() const { return m_lin_vel; }
+ const MT_Vector3& getAngularVelocity() const { return m_ang_vel; }
+
+ virtual MT_Transform getTransform() const {
+ return MT_Transform(m_pos, m_orn);
+ }
+
+protected:
+ MT_Point3 m_pos;
+ MT_Quaternion m_orn;
+ MT_Vector3 m_lin_vel;
+ MT_Vector3 m_ang_vel;
+};
+
+#endif
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h
new file mode 100644
index 00000000000..670da6e71db
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h
@@ -0,0 +1,280 @@
+#ifndef SM_OBJECT_H
+#define SM_OBJECT_H
+
+#include <vector>
+
+#include "solid.h"
+
+#include "SM_Callback.h"
+#include "SM_MotionState.h"
+#include <stdio.h>
+
+
+class SM_FhObject;
+
+
+// Properties of dynamic objects
+struct SM_ShapeProps {
+ MT_Scalar m_mass; // Total mass
+ MT_Scalar m_inertia; // Inertia, should be a tensor some time
+ MT_Scalar m_lin_drag; // Linear drag (air, water) 0 = concrete, 1 = vacuum
+ MT_Scalar m_ang_drag; // Angular drag
+ MT_Scalar m_friction_scaling[3]; // Scaling for anisotropic friction. Component in range [0, 1]
+ bool m_do_anisotropic; // Should I do anisotropic friction?
+ bool m_do_fh; // Should the object have a linear Fh spring?
+ bool m_do_rot_fh; // Should the object have an angular Fh spring?
+};
+
+
+// Properties of collidable objects (non-ghost objects)
+struct SM_MaterialProps {
+ MT_Scalar m_restitution; // restitution of energie after a collision 0 = inelastic, 1 = elastic
+ MT_Scalar m_friction; // Coulomb friction (= ratio between the normal en maximum friction force)
+ MT_Scalar m_fh_spring; // Spring constant (both linear and angular)
+ MT_Scalar m_fh_damping; // Damping factor (linear and angular) in range [0, 1]
+ MT_Scalar m_fh_distance; // The range above the surface where Fh is active.
+ bool m_fh_normal; // Should the object slide off slopes?
+};
+
+
+class SM_Object : public SM_MotionState {
+public:
+ SM_Object() ;
+ SM_Object(
+ DT_ShapeHandle shape,
+ const SM_MaterialProps *materialProps,
+ const SM_ShapeProps *shapeProps,
+ SM_Object *dynamicParent
+ );
+
+ virtual ~SM_Object();
+
+ bool isDynamic() const;
+
+ /* nzc experimental. There seem to be two places where kinematics
+ * are evaluated: proceedKinematic (called from SM_Scene) and
+ * proceed() in this object. I'll just try and bunge these out for
+ * now. */
+
+ void suspend(void);
+ void resume(void);
+
+ void suspendDynamics();
+
+ void restoreDynamics();
+
+ bool isGhost() const;
+
+ void suspendMaterial();
+
+ void restoreMaterial();
+
+ SM_FhObject *getFhObject() const;
+
+ void registerCallback(SM_Callback& callback);
+
+ void calcXform();
+ void notifyClient();
+
+ // Save the current state information for use in the
+ // velocity computation in the next frame.
+
+ void proceedKinematic(MT_Scalar timeStep);
+
+ void saveReactionForce(MT_Scalar timeStep) ;
+
+ void clearForce() ;
+
+ void clearMomentum() ;
+
+ void setMargin(MT_Scalar margin) ;
+
+ MT_Scalar getMargin() const ;
+
+ const SM_MaterialProps *getMaterialProps() const ;
+
+ const SM_ShapeProps *getShapeProps() const ;
+
+ void setPosition(const MT_Point3& pos);
+ void setOrientation(const MT_Quaternion& orn);
+ void setScaling(const MT_Vector3& scaling);
+
+
+ /**
+ * set an external velocity. This velocity complements
+ * the physics velocity. So setting it does not override the
+ * physics velocity. It is your responsibility to clear
+ * this external velocity. This velocity is not subject to
+ * friction or damping.
+ */
+
+
+ void setExternalLinearVelocity(const MT_Vector3& lin_vel) ;
+ void addExternalLinearVelocity(const MT_Vector3& lin_vel) ;
+
+ /** Override the physics velocity */
+
+ void addLinearVelocity(const MT_Vector3& lin_vel);
+ void setLinearVelocity(const MT_Vector3& lin_vel);
+
+ /**
+ * Set an external angular velocity. This velocity complemetns
+ * the physics angular velocity so does not override it. It is
+ * your responsibility to clear this velocity. This velocity
+ * is not subject to friction or damping.
+ */
+
+ void setExternalAngularVelocity(const MT_Vector3& ang_vel) ;
+ void addExternalAngularVelocity(const MT_Vector3& ang_vel);
+
+ /** Override the physics angular velocity */
+
+ void addAngularVelocity(const MT_Vector3& ang_vel);
+ void setAngularVelocity(const MT_Vector3& ang_vel);
+
+ /** Clear the external velocities */
+
+ void clearCombinedVelocities();
+
+ /**
+ * Tell the physics system to combine the external velocity
+ * with the physics velocity.
+ */
+
+ void resolveCombinedVelocities(
+ const MT_Vector3 & lin_vel,
+ const MT_Vector3 & ang_vel
+ ) ;
+
+
+
+ MT_Scalar getInvMass() const;
+
+ MT_Scalar getInvInertia() const ;
+
+ void applyForceField(const MT_Vector3& accel) ;
+
+ void applyCenterForce(const MT_Vector3& force) ;
+
+ void applyTorque(const MT_Vector3& torque) ;
+
+ void applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse) ;
+
+ void applyCenterImpulse(const MT_Vector3& impulse);
+
+ void applyAngularImpulse(const MT_Vector3& impulse);
+
+ MT_Point3 getWorldCoord(const MT_Point3& local) const;
+
+ MT_Vector3 getVelocity(const MT_Point3& local) const;
+
+
+ const MT_Vector3& getReactionForce() const ;
+
+ void getMatrix(double *m) const ;
+
+ const double *getMatrix() const ;
+
+ // Still need this???
+ const MT_Transform& getScaledTransform() const;
+
+ DT_ObjectHandle getObjectHandle() const ;
+ DT_ShapeHandle getShapeHandle() const ;
+
+ void setClientObject(void *clientobj) ;
+ void *getClientObject() ;
+
+ SM_Object *getDynamicParent() ;
+
+ void integrateForces(MT_Scalar timeStep);
+ void integrateMomentum(MT_Scalar timeSteo);
+
+ void setRigidBody(bool is_rigid_body) ;
+
+ bool isRigidBody() const ;
+
+
+ // This is the callback for handling collisions of dynamic objects
+ static
+ void
+ boing(
+ void *client_data,
+ void *object1,
+ void *object2,
+ const DT_CollData *coll_data
+ );
+
+private:
+
+ // return the actual linear_velocity of this object this
+ // is the addition of m_combined_lin_vel and m_lin_vel.
+
+ const
+ MT_Vector3
+ actualLinVelocity(
+ ) const ;
+
+ const
+ MT_Vector3
+ actualAngVelocity(
+ ) const ;
+
+ typedef std::vector<SM_Callback *> T_CallbackList;
+
+
+ T_CallbackList m_callbackList; // Each object can have multiple callbacks from the client (=game engine)
+ SM_Object *m_dynamicParent; // Collisions between parent and children are ignored
+
+ // as the collision callback now has only information
+ // on an SM_Object, there must be a way that the SM_Object client
+ // can identify it's clientdata after a collision
+ void *m_client_object;
+
+ DT_ShapeHandle m_shape; // Shape for collision detection
+
+ // Material and shape properties are not owned by this class.
+
+ const SM_MaterialProps *m_materialProps;
+ const SM_MaterialProps *m_materialPropsBackup; // Backup in case the object temporarily becomes a ghost.
+ const SM_ShapeProps *m_shapeProps;
+ const SM_ShapeProps *m_shapePropsBackup; // Backup in case the object's dynamics is temporarily suspended
+ DT_ObjectHandle m_object; // A handle to the corresponding object in SOLID.
+ MT_Scalar m_margin; // Offset for the object's shape (also for collision detection)
+ MT_Vector3 m_scaling; // Non-uniform scaling of the object's shape
+
+ double m_ogl_matrix[16]; // An OpenGL-type 4x4 matrix
+ MT_Transform m_xform; // The object's local coordinate system
+ MT_Transform m_prev_xform; // The object's local coordinate system in the previous frame
+ SM_MotionState m_prev_state; // The object's motion state in the previous frame
+ MT_Scalar m_timeStep; // The duration of the last frame
+
+ MT_Vector3 m_reaction_impulse; // The accumulated impulse resulting from collisions
+ MT_Vector3 m_reaction_force; // The reaction force derived from the reaction impulse
+
+ unsigned int m_kinematic : 1; // Have I been displaced (translated, rotated, scaled) in this frame?
+ unsigned int m_prev_kinematic : 1; // Have I been displaced (translated, rotated, scaled) in the previous frame?
+ unsigned int m_is_rigid_body : 1; // Should friction give me a change in angular momentum?
+
+ MT_Vector3 m_lin_mom; // Linear momentum (linear velocity times mass)
+ MT_Vector3 m_ang_mom; // Angular momentum (angualr velocity times inertia)
+ MT_Vector3 m_force; // Force on center of mass (afffects linear momentum)
+ MT_Vector3 m_torque; // Torque around center of mass (affects angualr momentum)
+
+ // Here are the values of externally set linear and angular
+ // velocity. These are updated from the outside
+ // (actuators and python) each frame and combined with the
+ // physics values. At the end of each frame (at the end of a
+ // call to proceed) they are set to zero. This allows the
+ // outside world to contribute to the velocity of an object
+ // but still have it react to physics.
+
+ MT_Vector3 m_combined_lin_vel;
+ MT_Vector3 m_combined_ang_vel;
+
+ // The force and torque are the accumulated forces and torques applied by the client (game logic, python).
+
+ SM_FhObject *m_fh_object; // The ray object used for Fh
+ bool m_suspended; // Is this object frozen?
+};
+
+#endif
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Props.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Props.h
new file mode 100644
index 00000000000..0b2efacac2a
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Props.h
@@ -0,0 +1,60 @@
+/**
+ * $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 *****
+ */
+#ifndef SM_PROPSH
+#define SM_PROPSH
+
+#include <MT_Scalar.h>
+
+// Properties of dynamic objects
+struct SM_ShapeProps {
+ MT_Scalar m_mass; // Total mass
+ MT_Scalar m_inertia; // Inertia, should be a tensor some time
+ MT_Scalar m_lin_drag; // Linear drag (air, water) 0 = concrete, 1 = vacuum
+ MT_Scalar m_ang_drag; // Angular drag
+ MT_Scalar m_friction_scaling[3]; // Scaling for anisotropic friction. Component in range [0, 1]
+ bool m_do_anisotropic; // Should I do anisotropic friction?
+ bool m_do_fh; // Should the object have a linear Fh spring?
+ bool m_do_rot_fh; // Should the object have an angular Fh spring?
+};
+
+
+// Properties of collidable objects (non-ghost objects)
+struct SM_MaterialProps {
+ MT_Scalar m_restitution; // restitution of energie after a collision 0 = inelastic, 1 = elastic
+ MT_Scalar m_friction; // Coulomb friction (= ratio between the normal en maximum friction force)
+ MT_Scalar m_fh_spring; // Spring constant (both linear and angular)
+ MT_Scalar m_fh_damping; // Damping factor (linear and angular) in range [0, 1]
+ MT_Scalar m_fh_distance; // The range above the surface where Fh is active.
+ bool m_fh_normal; // Should the object slide off slopes?
+};
+
+#endif //SM_PROPSH
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h
new file mode 100644
index 00000000000..761e6c7c449
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h
@@ -0,0 +1,129 @@
+/**
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * The physics scene.
+ */
+
+#ifndef SM_SCENE_H
+#define SM_SCENE_H
+
+#pragma warning (disable : 4786)
+
+#include <vector>
+#include <set>
+#include <utility> //needed for pair
+
+#include "solid.h"
+
+#include "MT_Vector3.h"
+#include "MT_Point3.h"
+
+class SM_Object;
+
+class SM_Scene {
+public:
+ SM_Scene() :
+ m_scene(DT_CreateScene()),
+ m_respTable(DT_CreateRespTable()),
+ m_secondaryRespTable(0),
+ m_forceField(0.0, 0.0, 0.0)
+ {}
+
+ ~SM_Scene() {
+ DT_DeleteRespTable(m_respTable);
+ DT_DeleteScene(m_scene);
+ }
+
+ DT_RespTableHandle getRespTableHandle() const {
+ return m_respTable;
+ }
+
+ const MT_Vector3& getForceField() const {
+ return m_forceField;
+ }
+
+ MT_Vector3& getForceField() {
+ return m_forceField;
+ }
+
+ void setForceField(const MT_Vector3& forceField) {
+ m_forceField = forceField;
+ }
+
+ void add(SM_Object& object);
+ void remove(SM_Object& object);
+
+ void addPair(SM_Object *obj1, SM_Object *obj2) {
+ m_pairList.insert(std::make_pair(obj1, obj2));
+ }
+
+ void clearPairs() {
+ m_pairList.clear();
+ }
+
+ void setSecondaryRespTable(DT_RespTableHandle secondaryRespTable) {
+ m_secondaryRespTable = secondaryRespTable;
+ }
+
+
+ // Perform an integration step of duration 'timeStep'.
+ // 'subSampling' is the maximum duration of a substep, i.e.,
+ // The maximum time interval between two collision checks.
+ // 'subSampling' can be used to control aliasing effects
+ // (fast moving objects traversing through walls and such).
+ void proceed(MT_Scalar timeStep, MT_Scalar subSampling);
+
+ /**
+ * Test whether any objects lie on the line defined by from and
+ * to. The search returns the first such bject starting at from,
+ * or NULL if there was none.
+ * @returns A reference to the object, or NULL if there was none.
+ * @param ignore_client Do not look for collisions with this
+ * object. This can be useful to avoid self-hits if
+ * starting from the location of an object.
+ * @param from The start point, in world coordinates, of the search.
+ * @param to The end point, in world coordinates, of the search.
+ * @param result A store to return the point where intersection
+ * took place (if there was an intersection).
+ * @param normal A store to return the normal of the hit object on
+ * the location of the intersection, if it took place.
+ */
+ SM_Object *rayTest(void *ignore_client,
+ const MT_Point3& from, const MT_Point3& to,
+ MT_Point3& result, MT_Vector3& normal) const;
+
+private:
+
+ // Clear the user set velocities.
+ void clearObjectCombinedVelocities();
+
+ /** internal type */
+ typedef std::vector<SM_Object *> T_ObjectList;
+ /** internal type */
+ typedef std::set<std::pair<SM_Object *, SM_Object *> > T_PairList;
+
+ /** Handle to the scene in SOLID */
+ DT_SceneHandle m_scene;
+ /** Following response table contains the callbacks for the dynmics */
+ DT_RespTableHandle m_respTable;
+ /**
+ * Following response table contains callbacks for the client (=
+ * game engine) */
+ DT_RespTableHandle m_secondaryRespTable; // Handle
+
+ /** The acceleration from the force field */
+ MT_Vector3 m_forceField;
+
+ /**
+ * The list of objects that receive motion updates and do
+ * collision tests. */
+ T_ObjectList m_objectList;
+
+ /**
+ * A list with pairs of objects that collided the previous
+ * timestep. The list is built during the proceed(). During that
+ * time, it is not valid. */
+ T_PairList m_pairList;
+};
+
+#endif
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/sample/Makefile b/source/gameengine/Physics/Sumo/Fuzzics/sample/Makefile
new file mode 100644
index 00000000000..672dff39028
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/sample/Makefile
@@ -0,0 +1,25 @@
+#
+# $Id$
+# Copyright (C) 2001 NaN Technologies B.V.
+
+DIR = $(OCGDIR)/sumo
+ALLTARGETS = $(OBJS) $(DIR)/$(DEBUG_DIR)particle $(DIR)/$(DEBUG_DIR)particle0
+
+include nan_compile.mk
+
+CPPFLAGS = -I../../include -I../include -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
+clean::
+ @$(RM) $(DIR)/particle $(DIR)/particle0
+ @$(RM) $(DIR)/debug/particle $(DIR)/debug/particle0
+
+LDFLAGS = -L$(DIR) -L/usr/X11R6/lib
+OGL_LDLIBS = -lglut -lGLU -lGL -pthread
+LDLIBS = -lfuzzics -lsolid $(NAN_MOTO)/lib/libmoto.a $(OGL_LDLIBS)
+
+$(DIR)/$(DEBUG_DIR)particle: particle.o $(DIR)/$(DEBUG_DIR)libfuzzics.a $(DIR)/$(DEBUG_DIR)libsolid.a
+ $(CCC) $(CCFLAGS) $(CPPFLAGS) $(LDFLAGS) $< -o $@ $(LDLIBS)
+
+$(DIR)/$(DEBUG_DIR)particle0: particle0.o $(DIR)/$(DEBUG_DIR)libfuzzics.a $(DIR)/$(DEBUG_DIR)libsolid.a
+ $(CCC) $(CCFLAGS) $(CPPFLAGS) $(LDFLAGS) $< -o $@ $(LDLIBS)
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/sample/particle.cpp b/source/gameengine/Physics/Sumo/Fuzzics/sample/particle.cpp
new file mode 100644
index 00000000000..e8e78d89a4e
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/sample/particle.cpp
@@ -0,0 +1,705 @@
+//#define FAKE_IT
+#define USE_COMPLEX
+#define QUADS
+
+#include <algorithm>
+#include <new>
+#include <GL/glut.h>
+
+#include "MT_MinMax.h"
+#include "MT_Point3.h"
+#include "MT_Vector3.h"
+#include "MT_Quaternion.h"
+#include "MT_Matrix3x3.h"
+#include "MT_Transform.h"
+
+#include "SM_Object.h"
+#include "SM_FhObject.h"
+#include "SM_Scene.h"
+
+#include "solid.h"
+
+const MT_Scalar bowl_curv = 0.10;
+const MT_Scalar timeStep = 0.02;
+const MT_Scalar ground_margin = 0.0;
+const MT_Scalar sphere_radius = 0.5;
+
+const MT_Vector3 gravity(0, -9.8, 0);
+
+static MT_Scalar DISTANCE = 5;
+
+static MT_Scalar ele = 0, azi = 0;
+static MT_Point3 eye(0, 0, DISTANCE);
+static MT_Point3 center(0, 0, 0);
+
+inline double irnd() { return 2 * MT_random() - 1; }
+
+static const double SCALE_BOTTOM = 0.5;
+static const double SCALE_FACTOR = 2.0;
+
+SM_ShapeProps g_shapeProps = {
+ 1.0, // mass
+ 1.0, // inertia
+ 0.1, // linear drag
+ 0.1, // angular drag
+ { 1.0, 0.0, 0.0 }, // anisotropic friction
+ false, // do anisotropic friction?
+ true, // do fh?
+ true // do rot fh?
+};
+
+SM_MaterialProps g_materialProps = {
+ 0.7, // restitution
+ 0.0, // friction
+ 10.0, // Fh spring constant
+ 1.0, // Fh damping
+ 0.5, // Fh distance
+ true // Fh leveling
+};
+
+
+void toggleIdle();
+
+
+void newRandom();
+
+void coordSystem() {
+ glDisable(GL_LIGHTING);
+ glBegin(GL_LINES);
+ glColor3f(1, 0, 0);
+ glVertex3d(0, 0, 0);
+ glVertex3d(10, 0, 0);
+ glColor3f(0, 1, 0);
+ glVertex3d(0, 0, 0);
+ glVertex3d(0, 10, 0);
+ glColor3f(0, 0, 1);
+ glVertex3d(0, 0, 0);
+ glVertex3d(0, 0, 10);
+ glEnd();
+ glEnable(GL_LIGHTING);
+}
+
+
+void display_bbox(const MT_Point3& min, const MT_Point3& max) {
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glColor3f(0, 1, 1);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glBegin(GL_QUAD_STRIP);
+ glVertex3d(min[0], min[1], min[2]);
+ glVertex3d(min[0], min[1], max[2]);
+ glVertex3d(max[0], min[1], min[2]);
+ glVertex3d(max[0], min[1], max[2]);
+ glVertex3d(max[0], max[1], min[2]);
+ glVertex3d(max[0], max[1], max[2]);
+ glVertex3d(min[0], max[1], min[2]);
+ glVertex3d(min[0], max[1], max[2]);
+ glVertex3d(min[0], min[1], min[2]);
+ glVertex3d(min[0], min[1], max[2]);
+ glEnd();
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_DEPTH_TEST);
+}
+
+
+
+
+class GLShape {
+public:
+ virtual void paint(GLdouble *m) const = 0;
+};
+
+
+class GLSphere : public GLShape {
+ MT_Scalar radius;
+public:
+ GLSphere(MT_Scalar r) : radius(r) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ glutSolidSphere(radius, 20, 20);
+ glPopMatrix();
+ }
+};
+
+
+class GLBox : public GLShape {
+ MT_Vector3 extent;
+public:
+ GLBox(MT_Scalar x, MT_Scalar y, MT_Scalar z) :
+ extent(x, y, z) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ glPushMatrix();
+ glScaled(extent[0], extent[1], extent[2]);
+ glutSolidCube(1.0);
+ glPopMatrix();
+ glPopMatrix();
+ }
+};
+
+
+class GLCone : public GLShape {
+ MT_Scalar bottomRadius;
+ MT_Scalar height;
+ mutable GLuint displayList;
+
+public:
+ GLCone(MT_Scalar r, MT_Scalar h) :
+ bottomRadius(r),
+ height(h),
+ displayList(0) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ if (displayList) glCallList(displayList);
+ else {
+ GLUquadricObj *quadObj = gluNewQuadric();
+ displayList = glGenLists(1);
+ glNewList(displayList, GL_COMPILE_AND_EXECUTE);
+ glPushMatrix();
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ glTranslatef(0.0, 0.0, -1.0);
+ gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL);
+ gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH);
+ gluCylinder(quadObj, bottomRadius, 0, height, 15, 10);
+ glPopMatrix();
+ glEndList();
+ }
+ glPopMatrix();
+ }
+};
+
+class GLCylinder : public GLShape {
+ MT_Scalar radius;
+ MT_Scalar height;
+ mutable GLuint displayList;
+
+public:
+ GLCylinder(MT_Scalar r, MT_Scalar h) :
+ radius(r),
+ height(h),
+ displayList(0) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ if (displayList) glCallList(displayList);
+ else {
+ GLUquadricObj *quadObj = gluNewQuadric();
+ displayList = glGenLists(1);
+ glNewList(displayList, GL_COMPILE_AND_EXECUTE);
+ glPushMatrix();
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ glTranslatef(0.0, 0.0, -1.0);
+ gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL);
+ gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH);
+ gluCylinder(quadObj, radius, radius, height, 15, 10);
+ glPopMatrix ();
+ glEndList();
+ }
+ glPopMatrix();
+ }
+};
+
+class Object;
+
+class Callback : public SM_Callback {
+public:
+ Callback(Object& object) : m_object(object) {}
+
+ virtual void do_me();
+
+private:
+ Object& m_object;
+};
+
+
+class Object {
+public:
+ Object(GLShape *gl_shape, SM_Object& object) :
+ m_gl_shape(gl_shape),
+ m_object(object),
+ m_callback(*this)
+ {
+ m_object.registerCallback(m_callback);
+ }
+
+ ~Object() {}
+
+ void paint() {
+ if (m_gl_shape) {
+ m_gl_shape->paint(m);
+ // display_bbox(m_bbox.lower(), m_bbox.upper());
+ }
+ }
+
+ void print_reaction_force() const {
+ std::cout << m_object.getReactionForce() << std::endl;
+ }
+
+ MT_Vector3 getAhead() {
+ return MT_Vector3(&m[4]);
+ }
+
+ MT_Vector3 getUp() {
+ return MT_Vector3(&m[8]);
+ }
+
+ void clearMomentum() {
+ m_object.clearMomentum();
+ }
+
+ void setMargin(MT_Scalar margin) {
+ m_object.setMargin(margin);
+ }
+
+ void setScaling(const MT_Vector3& scaling) {
+ m_object.setScaling(scaling);
+ }
+
+ const MT_Point3& getPosition() {
+ return m_object.getPosition();
+ }
+
+ void setPosition(const MT_Point3& pos) {
+ m_object.setPosition(pos);
+ }
+
+ void setOrientation(const MT_Quaternion& orn) {
+ m_object.setOrientation(orn);
+ }
+
+ void applyCenterForce(const MT_Vector3& force) {
+ m_object.applyCenterForce(force);
+ }
+
+ void applyTorque(const MT_Vector3& torque) {
+ m_object.applyTorque(torque);
+ }
+
+ MT_Point3 getWorldCoord(const MT_Point3& local) const {
+ return m_object.getWorldCoord(local);
+ }
+
+ MT_Vector3 getLinearVelocity() const {
+ return m_object.getLinearVelocity();
+ }
+
+ MT_Vector3 getAngularVelocity() const {
+ return m_object.getAngularVelocity();
+ }
+
+ void setMatrix() {
+ m_object.calcXform();
+ m_object.getMatrix(m);
+ }
+
+ const double *getMatrix() {
+ m_object.calcXform();
+ return m_object.getMatrix();
+ }
+
+private:
+ GLShape *m_gl_shape;
+ SM_Object& m_object;
+ DT_Scalar m[16];
+ Callback m_callback;
+};
+
+
+
+const MT_Scalar SPACE_SIZE = 2;
+
+static GLSphere gl_sphere(sphere_radius);
+static GLBox gl_ground(50.0, 0.0, 50.0);
+
+
+
+#ifdef USE_COMPLEX
+
+const int GRID_SCALE = 10;
+const MT_Scalar GRID_UNIT = 25.0 / GRID_SCALE;
+
+DT_ShapeHandle createComplex() {
+ DT_ShapeHandle shape = DT_NewComplexShape();
+ for (int i0 = -GRID_SCALE; i0 != GRID_SCALE; ++i0) {
+ for (int j0 = -GRID_SCALE; j0 != GRID_SCALE; ++j0) {
+ int i1 = i0 + 1;
+ int j1 = j0 + 1;
+#ifdef QUADS
+ DT_Begin();
+ DT_Vertex(GRID_UNIT * i0, bowl_curv * i0*i0, GRID_UNIT * j0);
+ DT_Vertex(GRID_UNIT * i0, bowl_curv * i0*i0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, bowl_curv * i1*i1, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, bowl_curv * i1*i1, GRID_UNIT * j0);
+ DT_End();
+#else
+ DT_Begin();
+ DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j0);
+ DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j1);
+ DT_End();
+
+ DT_Begin();
+ DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j0);
+ DT_End();
+#endif
+
+ }
+ }
+ DT_EndComplexShape();
+ return shape;
+}
+
+
+static DT_ShapeHandle ground_shape = createComplex();
+
+#else
+
+static DT_ShapeHandle ground_shape = DT_Box(50, 0, 50);
+
+#endif
+
+static SM_Object sm_ground(ground_shape, &g_materialProps, 0, 0);
+static Object ground(&gl_ground, sm_ground);
+
+static SM_Object sm_sphere(DT_Sphere(0.0), &g_materialProps, &g_shapeProps, 0);
+static Object object(&gl_sphere, sm_sphere);
+
+
+static SM_Scene g_scene;
+
+
+bool g_hit = false;
+MT_Point3 g_spot;
+MT_Vector3 g_normal;
+
+
+void Callback::do_me()
+{
+ m_object.setMatrix();
+ m_object.print_reaction_force();
+}
+
+void myinit(void) {
+
+ GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
+ GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
+ GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
+
+ /* light_position is NOT default value */
+ GLfloat light_position0[] = { 1.0, 1.0, 1.0, 0.0 };
+ GLfloat light_position1[] = { -1.0, -1.0, -1.0, 0.0 };
+
+ glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
+ glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
+
+ glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
+ glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
+ glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
+
+
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_LIGHT1);
+
+ glShadeModel(GL_SMOOTH);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+
+ // glEnable(GL_CULL_FACE);
+ // glCullFace(GL_BACK);
+
+ ground.setPosition(MT_Point3(0, -10, 0));
+ ground.setOrientation(MT_Quaternion(0, 0, 0, 1));
+ ground.setMatrix();
+ center.setValue(0.0, 0.0, 0.0);
+ sm_ground.setMargin(ground_margin);
+
+ g_scene.setForceField(gravity);
+ g_scene.add(sm_ground);
+
+ object.setMargin(sphere_radius);
+
+ g_scene.add(sm_sphere);
+
+
+ newRandom();
+}
+
+
+//MT_Point3 cp1, cp2;
+//bool intersection;
+
+void display(void) {
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ ground.paint();
+ object.paint();
+
+ if (g_hit) {
+ glDisable(GL_LIGHTING);
+ glColor3f(1, 0, 0);
+
+ glPointSize(5);
+ glBegin(GL_POINTS);
+ glVertex3d(g_spot[0], g_spot[1], g_spot[2]);
+ glEnd();
+ glPointSize(1);
+
+ glColor3f(1, 1, 0);
+ glBegin(GL_LINES);
+ glVertex3d(g_spot[0], g_spot[1], g_spot[2]);
+ glVertex3d(g_spot[0] + g_normal[0],
+ g_spot[1] + g_normal[1],
+ g_spot[2] + g_normal[2]);
+ glEnd();
+ glEnable(GL_LIGHTING);
+ }
+
+
+
+#ifdef COLLISION
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glColor3f(1, 1, 0);
+ if (intersection) {
+ glPointSize(5);
+ glBegin(GL_POINTS);
+ glVertex3d(cp1[0], cp1[1], cp1[2]);
+ glEnd();
+ glPointSize(1);
+ }
+ else {
+ glBegin(GL_LINES);
+ glVertex3d(cp1[0], cp1[1], cp1[2]);
+ glVertex3d(cp2[0], cp2[1], cp2[2]);
+ glEnd();
+ }
+ glEnable(GL_LIGHTING);
+ glEnable(GL_DEPTH_TEST);
+#endif
+
+ glFlush();
+ glutSwapBuffers();
+}
+
+
+
+
+
+void newRandom() {
+ object.setPosition(MT_Point3(0, 0, 0));
+ object.setOrientation(MT_Quaternion::random());
+ object.clearMomentum();
+ object.setMatrix();
+
+ display();
+}
+
+void moveAndDisplay() {
+ g_scene.proceed(timeStep, 0.01);
+
+ display();
+ g_hit = false;
+}
+
+
+void turn_left() {
+ object.applyTorque(5.0 * object.getUp());
+}
+
+void turn_right() {
+ object.applyTorque(-5.0 * object.getUp());
+}
+
+void forward() {
+ object.applyCenterForce(10.0 * object.getAhead());
+}
+
+void backward() {
+ object.applyCenterForce(-10.0 * object.getAhead());
+}
+
+void jump() {
+ object.applyCenterForce(MT_Vector3(0.0, 200.0, 0.0));
+}
+
+
+void toggleIdle() {
+ static bool idle = true;
+ if (idle) {
+ glutIdleFunc(moveAndDisplay);
+ idle = false;
+ }
+ else {
+ glutIdleFunc(NULL);
+ idle = true;
+ }
+}
+
+
+void setCamera() {
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 200.0);
+ MT_Scalar rele = MT_radians(ele);
+ MT_Scalar razi = MT_radians(azi);
+ eye.setValue(DISTANCE * sin(razi) * cos(rele),
+ DISTANCE * sin(rele),
+ DISTANCE * cos(razi) * cos(rele));
+ gluLookAt(eye[0], eye[1], eye[2],
+ center[0], center[1], center[2],
+ 0, 1, 0);
+ glMatrixMode(GL_MODELVIEW);
+ display();
+}
+
+const MT_Scalar STEPSIZE = 5;
+
+void stepLeft() { azi -= STEPSIZE; if (azi < 0) azi += 360; setCamera(); }
+void stepRight() { azi += STEPSIZE; if (azi >= 360) azi -= 360; setCamera(); }
+void stepFront() { ele += STEPSIZE; if (azi >= 360) azi -= 360; setCamera(); }
+void stepBack() { ele -= STEPSIZE; if (azi < 0) azi += 360; setCamera(); }
+void zoomIn() { DISTANCE -= 1; setCamera(); }
+void zoomOut() { DISTANCE += 1; setCamera(); }
+
+
+void myReshape(int w, int h) {
+ glViewport(0, 0, w, h);
+ setCamera();
+}
+
+void myKeyboard(unsigned char key, int x, int y)
+{
+ switch (key)
+ {
+ case 'w': forward(); break;
+ case 's': backward(); break;
+ case 'a': turn_left(); break;
+ case 'd': turn_right(); break;
+ case 'e': jump(); break;
+ case 'l' : stepLeft(); break;
+ case 'r' : stepRight(); break;
+ case 'f' : stepFront(); break;
+ case 'b' : stepBack(); break;
+ case 'z' : zoomIn(); break;
+ case 'x' : zoomOut(); break;
+ case 'i' : toggleIdle(); break;
+ case ' ' : newRandom(); break;
+ default:
+// std::cout << "unused key : " << key << std::endl;
+ break;
+ }
+}
+
+void mySpecial(int key, int x, int y)
+{
+ switch (key)
+ {
+ case GLUT_KEY_LEFT : stepLeft(); break;
+ case GLUT_KEY_RIGHT : stepRight(); break;
+ case GLUT_KEY_UP : stepFront(); break;
+ case GLUT_KEY_DOWN : stepBack(); break;
+ case GLUT_KEY_PAGE_UP : zoomIn(); break;
+ case GLUT_KEY_PAGE_DOWN : zoomOut(); break;
+ case GLUT_KEY_HOME : toggleIdle(); break;
+ default:
+// std::cout << "unused (special) key : " << key << std::endl;
+ break;
+ }
+}
+
+void goodbye( void)
+{
+ g_scene.remove(sm_ground);
+ g_scene.remove(sm_sphere);
+
+ std::cout << "goodbye ..." << std::endl;
+ exit(0);
+}
+
+void menu(int choice)
+{
+
+ static int fullScreen = 0;
+ static int px, py, sx, sy;
+
+ switch(choice) {
+ case 1:
+ if (fullScreen == 1) {
+ glutPositionWindow(px,py);
+ glutReshapeWindow(sx,sy);
+ glutChangeToMenuEntry(1,"Full Screen",1);
+ fullScreen = 0;
+ } else {
+ px=glutGet((GLenum)GLUT_WINDOW_X);
+ py=glutGet((GLenum)GLUT_WINDOW_Y);
+ sx=glutGet((GLenum)GLUT_WINDOW_WIDTH);
+ sy=glutGet((GLenum)GLUT_WINDOW_HEIGHT);
+ glutFullScreen();
+ glutChangeToMenuEntry(1,"Close Full Screen",1);
+ fullScreen = 1;
+ }
+ break;
+ case 2:
+ toggleIdle();
+ break;
+ case 3:
+ goodbye();
+ break;
+ default:
+ break;
+ }
+}
+
+void createMenu()
+{
+ glutCreateMenu(menu);
+ glutAddMenuEntry("Full Screen", 1);
+ glutAddMenuEntry("Toggle Idle (Start/Stop)", 2);
+ glutAddMenuEntry("Quit", 3);
+ glutAttachMenu(GLUT_RIGHT_BUTTON);
+}
+
+int main(int argc, char **argv) {
+ glutInit(&argc, argv);
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
+ glutInitWindowPosition(0, 0);
+ glutInitWindowSize(500, 500);
+ glutCreateWindow("Physics demo");
+
+ myinit();
+ glutKeyboardFunc(myKeyboard);
+ glutSpecialFunc(mySpecial);
+ glutReshapeFunc(myReshape);
+ createMenu();
+ glutIdleFunc(NULL);
+
+ glutDisplayFunc(display);
+ glutMainLoop();
+ return 0;
+}
+
+
+
+
+
+
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/sample/particle0.cpp b/source/gameengine/Physics/Sumo/Fuzzics/sample/particle0.cpp
new file mode 100644
index 00000000000..1c03621f530
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/sample/particle0.cpp
@@ -0,0 +1,691 @@
+//#define FAKE_IT
+#define USE_COMPLEX
+#define QUADS
+
+#include <algorithm>
+#include <new>
+#include <GL/glut.h>
+
+#include "MT_MinMax.h"
+#include "MT_Point3.h"
+#include "MT_Vector3.h"
+#include "MT_Quaternion.h"
+#include "MT_Matrix3x3.h"
+#include "MT_Transform.h"
+
+#include "SM_Object.h"
+#include "SM_Scene.h"
+
+#include "solid.h"
+
+const MT_Scalar bowl_curv = 0.10;
+const MT_Scalar timeStep = 0.04;
+const MT_Scalar ground_margin = 0.0;
+const MT_Scalar sphere_radius = 0.5;
+
+const MT_Vector3 gravity(0, -9.8, 0);
+
+static MT_Scalar DISTANCE = 5;
+
+static MT_Scalar ele = 0, azi = 0;
+static MT_Point3 eye(0, 0, DISTANCE);
+static MT_Point3 center(0, 0, 0);
+
+inline double irnd() { return 2 * MT_random() - 1; }
+
+static const double SCALE_BOTTOM = 0.5;
+static const double SCALE_FACTOR = 2.0;
+
+SM_ShapeProps g_shapeProps = {
+ 1.0, // mass
+ 1.0, // inertia
+ 0.9, // linear drag
+ 0.9 // angular drag
+};
+
+SM_MaterialProps g_materialProps = {
+ 0.7, // restitution
+ 0.0, // friction
+ 0.0, // spring constant
+ 0.0 // damping
+};
+
+
+void toggleIdle();
+
+
+void newRandom();
+
+void coordSystem() {
+ glDisable(GL_LIGHTING);
+ glBegin(GL_LINES);
+ glColor3f(1, 0, 0);
+ glVertex3d(0, 0, 0);
+ glVertex3d(10, 0, 0);
+ glColor3f(0, 1, 0);
+ glVertex3d(0, 0, 0);
+ glVertex3d(0, 10, 0);
+ glColor3f(0, 0, 1);
+ glVertex3d(0, 0, 0);
+ glVertex3d(0, 0, 10);
+ glEnd();
+ glEnable(GL_LIGHTING);
+}
+
+
+void display_bbox(const MT_Point3& min, const MT_Point3& max) {
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glColor3f(0, 1, 1);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glBegin(GL_QUAD_STRIP);
+ glVertex3d(min[0], min[1], min[2]);
+ glVertex3d(min[0], min[1], max[2]);
+ glVertex3d(max[0], min[1], min[2]);
+ glVertex3d(max[0], min[1], max[2]);
+ glVertex3d(max[0], max[1], min[2]);
+ glVertex3d(max[0], max[1], max[2]);
+ glVertex3d(min[0], max[1], min[2]);
+ glVertex3d(min[0], max[1], max[2]);
+ glVertex3d(min[0], min[1], min[2]);
+ glVertex3d(min[0], min[1], max[2]);
+ glEnd();
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_DEPTH_TEST);
+}
+
+
+
+
+class GLShape {
+public:
+ virtual void paint(GLdouble *m) const = 0;
+};
+
+
+class GLSphere : public GLShape {
+ MT_Scalar radius;
+public:
+ GLSphere(MT_Scalar r) : radius(r) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ glutSolidSphere(radius, 20, 20);
+ glPopMatrix();
+ }
+};
+
+
+class GLBox : public GLShape {
+ MT_Vector3 extent;
+public:
+ GLBox(MT_Scalar x, MT_Scalar y, MT_Scalar z) :
+ extent(x, y, z) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ glPushMatrix();
+ glScaled(extent[0], extent[1], extent[2]);
+ glutSolidCube(1.0);
+ glPopMatrix();
+ glPopMatrix();
+ }
+};
+
+
+class GLCone : public GLShape {
+ MT_Scalar bottomRadius;
+ MT_Scalar height;
+ mutable GLuint displayList;
+
+public:
+ GLCone(MT_Scalar r, MT_Scalar h) :
+ bottomRadius(r),
+ height(h),
+ displayList(0) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ if (displayList) glCallList(displayList);
+ else {
+ GLUquadricObj *quadObj = gluNewQuadric();
+ displayList = glGenLists(1);
+ glNewList(displayList, GL_COMPILE_AND_EXECUTE);
+ glPushMatrix();
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ glTranslatef(0.0, 0.0, -1.0);
+ gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL);
+ gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH);
+ gluCylinder(quadObj, bottomRadius, 0, height, 15, 10);
+ glPopMatrix();
+ glEndList();
+ }
+ glPopMatrix();
+ }
+};
+
+class GLCylinder : public GLShape {
+ MT_Scalar radius;
+ MT_Scalar height;
+ mutable GLuint displayList;
+
+public:
+ GLCylinder(MT_Scalar r, MT_Scalar h) :
+ radius(r),
+ height(h),
+ displayList(0) {}
+
+ void paint(GLdouble *m) const {
+ glPushMatrix();
+ glLoadMatrixd(m);
+ coordSystem();
+ if (displayList) glCallList(displayList);
+ else {
+ GLUquadricObj *quadObj = gluNewQuadric();
+ displayList = glGenLists(1);
+ glNewList(displayList, GL_COMPILE_AND_EXECUTE);
+ glPushMatrix();
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ glTranslatef(0.0, 0.0, -1.0);
+ gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL);
+ gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH);
+ gluCylinder(quadObj, radius, radius, height, 15, 10);
+ glPopMatrix ();
+ glEndList();
+ }
+ glPopMatrix();
+ }
+};
+
+class Object;
+
+class Callback : public SM_Callback {
+public:
+ Callback(Object& object) : m_object(object) {}
+
+ virtual void do_me();
+
+private:
+ Object& m_object;
+};
+
+
+class Object {
+public:
+ Object(GLShape *gl_shape, SM_Object& object) :
+ m_gl_shape(gl_shape),
+ m_object(object),
+ m_callback(*this)
+ {
+ m_object.registerCallback(m_callback);
+ }
+
+ ~Object() {}
+
+ void paint() {
+ m_gl_shape->paint(m);
+ // display_bbox(m_bbox.lower(), m_bbox.upper());
+ }
+
+ MT_Vector3 getAhead() {
+ return MT_Vector3(-m[8], -m[9], -m[10]);
+ }
+
+ void clearMomentum() {
+ m_object.clearMomentum();
+ }
+
+ void setMargin(MT_Scalar margin) {
+ m_object.setMargin(margin);
+ }
+
+ void setScaling(const MT_Vector3& scaling) {
+ m_object.setScaling(scaling);
+ }
+
+ void setPosition(const MT_Point3& pos) {
+ m_object.setPosition(pos);
+ }
+
+ void setOrientation(const MT_Quaternion& orn) {
+ m_object.setOrientation(orn);
+ }
+
+ void applyCenterForce(const MT_Vector3& force) {
+ m_object.applyCenterForce(force);
+ }
+
+ void applyTorque(const MT_Vector3& torque) {
+ m_object.applyTorque(torque);
+ }
+
+ MT_Point3 getWorldCoord(const MT_Point3& local) const {
+ return m_object.getWorldCoord(local);
+ }
+
+ MT_Vector3 getLinearVelocity() const {
+ return m_object.getLinearVelocity();
+ }
+
+ void setMatrix() {
+ m_object.getMatrix(m);
+ }
+
+private:
+ GLShape *m_gl_shape;
+ SM_Object& m_object;
+ DT_Scalar m[16];
+ Callback m_callback;
+};
+
+
+void Callback::do_me()
+{
+ m_object.setMatrix();
+}
+
+
+const MT_Scalar SPACE_SIZE = 2;
+
+static GLSphere gl_sphere(sphere_radius);
+static GLBox gl_ground(50.0, 0.0, 50.0);
+
+
+
+#ifdef USE_COMPLEX
+
+const int GRID_SCALE = 10;
+const MT_Scalar GRID_UNIT = 25.0 / GRID_SCALE;
+
+DT_ShapeHandle createComplex() {
+ DT_ShapeHandle shape = DT_NewComplexShape();
+ for (int i0 = -GRID_SCALE; i0 != GRID_SCALE; ++i0) {
+ for (int j0 = -GRID_SCALE; j0 != GRID_SCALE; ++j0) {
+ int i1 = i0 + 1;
+ int j1 = j0 + 1;
+#ifdef QUADS
+ DT_Begin();
+ DT_Vertex(GRID_UNIT * i0, bowl_curv * i0*i0, GRID_UNIT * j0);
+ DT_Vertex(GRID_UNIT * i0, bowl_curv * i0*i0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, bowl_curv * i1*i1, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, bowl_curv * i1*i1, GRID_UNIT * j0);
+ DT_End();
+#else
+ DT_Begin();
+ DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j0);
+ DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j1);
+ DT_End();
+
+ DT_Begin();
+ DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j1);
+ DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j0);
+ DT_End();
+#endif
+
+ }
+ }
+ DT_EndComplexShape();
+ return shape;
+}
+
+
+static DT_ShapeHandle ground_shape = createComplex();
+
+#else
+
+static DT_ShapeHandle ground_shape = DT_Box(50, 0, 50);
+
+#endif
+
+static SM_Object sm_ground(ground_shape, &g_materialProps, 0, 0);
+static Object ground(&gl_ground, sm_ground);
+
+static SM_Object sm_sphere(DT_Sphere(0.0), &g_materialProps, &g_shapeProps, 0);
+static Object object(&gl_sphere, sm_sphere);
+
+
+static SM_Object sm_ray(DT_Ray(0.0, -1.0, 0.0), 0, 0, 0);
+
+static SM_Scene g_scene;
+
+
+void myinit(void) {
+
+ GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
+ GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
+ GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
+
+ /* light_position is NOT default value */
+ GLfloat light_position0[] = { 1.0, 1.0, 1.0, 0.0 };
+ GLfloat light_position1[] = { -1.0, -1.0, -1.0, 0.0 };
+
+ glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
+ glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
+
+ glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
+ glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
+ glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
+
+
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_LIGHT1);
+
+ glShadeModel(GL_SMOOTH);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+
+ // glEnable(GL_CULL_FACE);
+ // glCullFace(GL_BACK);
+
+ g_scene.setForceField(gravity);
+ g_scene.add(sm_ground);
+ sm_ground.setMargin(ground_margin);
+
+ new(&object) Object(&gl_sphere, sm_sphere);
+
+
+ object.setMargin(sphere_radius);
+
+ g_scene.add(sm_sphere);
+
+ ground.setPosition(MT_Point3(0, -10, 0));
+ ground.setOrientation(MT_Quaternion(0, 0, 0, 1));
+ ground.setMatrix();
+ center.setValue(0.0, 0.0, 0.0);
+
+ newRandom();
+}
+
+
+//MT_Point3 cp1, cp2;
+//bool intersection;
+
+bool g_hit = false;
+MT_Point3 g_spot;
+MT_Vector3 g_normal;
+
+
+void display(void) {
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ ground.paint();
+ object.paint();
+
+ if (g_hit) {
+ glPointSize(5);
+ glBegin(GL_POINTS);
+ glVertex3d(g_spot[0], g_spot[1], g_spot[2]);
+ glEnd();
+ glPointSize(1);
+ }
+
+
+
+#ifdef COLLISION
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glColor3f(1, 1, 0);
+ if (intersection) {
+ glPointSize(5);
+ glBegin(GL_POINTS);
+ glVertex3d(cp1[0], cp1[1], cp1[2]);
+ glEnd();
+ glPointSize(1);
+ }
+ else {
+ glBegin(GL_LINES);
+ glVertex3d(cp1[0], cp1[1], cp1[2]);
+ glVertex3d(cp2[0], cp2[1], cp2[2]);
+ glEnd();
+ }
+ glEnable(GL_LIGHTING);
+ glEnable(GL_DEPTH_TEST);
+#endif
+
+ glFlush();
+ glutSwapBuffers();
+}
+
+
+
+
+
+void newRandom() {
+ object.setPosition(MT_Point3(0, 0, 0));
+ object.clearMomentum();
+ object.setMatrix();
+
+ display();
+}
+
+void moveAndDisplay() {
+ g_scene.proceed(timeStep, 0.01);
+
+ MT_Vector3 normal(0, 1, 0);
+
+ MT_Point3 from = object.getWorldCoord(MT_Point3(0, 0, 0));
+ MT_Point3 to = from - normal * 10.0;
+
+ g_hit = DT_ObjectRayTest(sm_ground.getObjectHandle(),
+ from.getValue(),
+ to.getValue(), g_spot.getValue(),
+ g_normal.getValue());
+
+ // Scrap
+#define DO_FH
+#ifdef DO_FH
+ MT_Scalar dist = MT_distance(from, g_spot);
+ if (dist < 5.0) {
+ MT_Vector3 lin_vel = object.getLinearVelocity();
+ MT_Scalar lin_vel_normal = lin_vel.dot(normal);
+
+ MT_Scalar spring_extent = dist + lin_vel_normal * (timeStep * 0.5);
+
+ MT_Scalar f_spring = (5.0 - spring_extent) * 3.0;
+ object.applyCenterForce(normal * f_spring);
+ object.applyCenterForce(-lin_vel_normal * normal);
+ }
+
+#endif
+
+
+ display();
+}
+
+
+void turn_left() {
+ object.applyTorque(MT_Vector3(0.0, 10.0, 0.0));
+}
+
+void turn_right() {
+ object.applyTorque(MT_Vector3(0.0, -10.0, 0.0));
+}
+
+void forward() {
+ object.applyCenterForce(20.0 * object.getAhead());
+}
+
+void backward() {
+ object.applyCenterForce(-20.0 * object.getAhead());
+}
+
+void jump() {
+ object.applyCenterForce(MT_Vector3(0.0, 200.0, 0.0));
+}
+
+
+void toggleIdle() {
+ static bool idle = true;
+ if (idle) {
+ glutIdleFunc(moveAndDisplay);
+ idle = false;
+ }
+ else {
+ glutIdleFunc(NULL);
+ idle = true;
+ }
+}
+
+
+void setCamera() {
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 200.0);
+ MT_Scalar rele = MT_radians(ele);
+ MT_Scalar razi = MT_radians(azi);
+ eye.setValue(DISTANCE * sin(razi) * cos(rele),
+ DISTANCE * sin(rele),
+ DISTANCE * cos(razi) * cos(rele));
+ gluLookAt(eye[0], eye[1], eye[2],
+ center[0], center[1], center[2],
+ 0, 1, 0);
+ glMatrixMode(GL_MODELVIEW);
+ display();
+}
+
+const MT_Scalar STEPSIZE = 5;
+
+void stepLeft() { azi -= STEPSIZE; if (azi < 0) azi += 360; setCamera(); }
+void stepRight() { azi += STEPSIZE; if (azi >= 360) azi -= 360; setCamera(); }
+void stepFront() { ele += STEPSIZE; if (azi >= 360) azi -= 360; setCamera(); }
+void stepBack() { ele -= STEPSIZE; if (azi < 0) azi += 360; setCamera(); }
+void zoomIn() { DISTANCE -= 1; setCamera(); }
+void zoomOut() { DISTANCE += 1; setCamera(); }
+
+
+void myReshape(int w, int h) {
+ glViewport(0, 0, w, h);
+ setCamera();
+}
+
+void myKeyboard(unsigned char key, int x, int y)
+{
+ switch (key)
+ {
+ case 'w': forward(); break;
+ case 's': backward(); break;
+ case 'a': turn_left(); break;
+ case 'd': turn_right(); break;
+ case 'e': jump(); break;
+ case 'l' : stepLeft(); break;
+ case 'r' : stepRight(); break;
+ case 'f' : stepFront(); break;
+ case 'b' : stepBack(); break;
+ case 'z' : zoomIn(); break;
+ case 'x' : zoomOut(); break;
+ case 'i' : toggleIdle(); break;
+ case ' ' : newRandom(); break;
+ default:
+// std::cout << "unused key : " << key << std::endl;
+ break;
+ }
+}
+
+void mySpecial(int key, int x, int y)
+{
+ switch (key)
+ {
+ case GLUT_KEY_LEFT : stepLeft(); break;
+ case GLUT_KEY_RIGHT : stepRight(); break;
+ case GLUT_KEY_UP : stepFront(); break;
+ case GLUT_KEY_DOWN : stepBack(); break;
+ case GLUT_KEY_PAGE_UP : zoomIn(); break;
+ case GLUT_KEY_PAGE_DOWN : zoomOut(); break;
+ case GLUT_KEY_HOME : toggleIdle(); break;
+ default:
+// std::cout << "unused (special) key : " << key << std::endl;
+ break;
+ }
+}
+
+void goodbye( void)
+{
+ g_scene.remove(sm_ground);
+ g_scene.remove(sm_sphere);
+
+ std::cout << "goodbye ..." << std::endl;
+ exit(0);
+}
+
+void menu(int choice)
+{
+
+ static int fullScreen = 0;
+ static int px, py, sx, sy;
+
+ switch(choice) {
+ case 1:
+ if (fullScreen == 1) {
+ glutPositionWindow(px,py);
+ glutReshapeWindow(sx,sy);
+ glutChangeToMenuEntry(1,"Full Screen",1);
+ fullScreen = 0;
+ } else {
+ px=glutGet((GLenum)GLUT_WINDOW_X);
+ py=glutGet((GLenum)GLUT_WINDOW_Y);
+ sx=glutGet((GLenum)GLUT_WINDOW_WIDTH);
+ sy=glutGet((GLenum)GLUT_WINDOW_HEIGHT);
+ glutFullScreen();
+ glutChangeToMenuEntry(1,"Close Full Screen",1);
+ fullScreen = 1;
+ }
+ break;
+ case 2:
+ toggleIdle();
+ break;
+ case 3:
+ goodbye();
+ break;
+ default:
+ break;
+ }
+}
+
+void createMenu()
+{
+ glutCreateMenu(menu);
+ glutAddMenuEntry("Full Screen", 1);
+ glutAddMenuEntry("Toggle Idle (Start/Stop)", 2);
+ glutAddMenuEntry("Quit", 3);
+ glutAttachMenu(GLUT_RIGHT_BUTTON);
+}
+
+int main(int argc, char **argv) {
+ glutInit(&argc, argv);
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
+ glutInitWindowPosition(0, 0);
+ glutInitWindowSize(500, 500);
+ glutCreateWindow("Physics demo");
+
+ myinit();
+ glutKeyboardFunc(myKeyboard);
+ glutSpecialFunc(mySpecial);
+ glutReshapeFunc(myReshape);
+ createMenu();
+ glutIdleFunc(NULL);
+
+ glutDisplayFunc(display);
+ glutMainLoop();
+ return 0;
+}
+
+
+
+
+
+
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/Makefile b/source/gameengine/Physics/Sumo/Fuzzics/src/Makefile
new file mode 100644
index 00000000000..5e3b35f6cf4
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/src/Makefile
@@ -0,0 +1,13 @@
+#
+# $Id$
+# Copyright (C) 2001 NaN Technologies B.V.
+
+LIBNAME = fuzzics
+DIR = $(OCGDIR)/sumo
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I../include -I$(NAN_MOTO)/include -I../../include
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_FhObject.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_FhObject.cpp
new file mode 100644
index 00000000000..f8be49aa126
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_FhObject.cpp
@@ -0,0 +1,115 @@
+#include "SM_FhObject.h"
+#include "MT_MinMax.h"
+
+void SM_FhObject::ray_hit(void *client_data,
+ void *client_object1,
+ void *client_object2,
+ const DT_CollData *coll_data) {
+
+ SM_Object *hit_object = (SM_Object *)client_object1;
+ const SM_MaterialProps *matProps = hit_object->getMaterialProps();
+
+ if ((matProps == 0) || (matProps->m_fh_distance < MT_EPSILON)) {
+ return;
+ }
+
+ SM_FhObject *fh_object = (SM_FhObject *)client_object2;
+ SM_Object *cl_object = fh_object->getClientObject();
+
+ if (hit_object == cl_object) {
+ // Shot myself in the foot...
+ return;
+ }
+
+ const SM_ShapeProps *shapeProps = cl_object->getShapeProps();
+
+ // Exit if the client object is not dynamic.
+ if (shapeProps == 0) {
+ return;
+ }
+
+ MT_Point3 lspot;
+ MT_Vector3 normal;
+
+ if (DT_ObjectRayTest(hit_object->getObjectHandle(),
+ fh_object->getPosition().getValue(),
+ fh_object->getSpot().getValue(),
+ lspot.getValue(), normal.getValue())) {
+
+ const MT_Vector3& ray_dir = fh_object->getRayDirection();
+ MT_Scalar dist = MT_distance(fh_object->getPosition(),
+ hit_object->getWorldCoord(lspot)) -
+ cl_object->getMargin();
+
+ normal.normalize();
+
+ if (dist < matProps->m_fh_distance) {
+
+ if (shapeProps->m_do_fh) {
+ MT_Vector3 rel_vel = cl_object->getLinearVelocity() - hit_object->getVelocity(lspot);
+ MT_Scalar rel_vel_ray = ray_dir.dot(rel_vel);
+ MT_Scalar spring_extent = 1.0 - dist / matProps->m_fh_distance;
+
+ MT_Scalar i_spring = spring_extent * matProps->m_fh_spring;
+ MT_Scalar i_damp = rel_vel_ray * matProps->m_fh_damping;
+
+ cl_object->addLinearVelocity(-(i_spring + i_damp) * ray_dir);
+ if (matProps->m_fh_normal) {
+ cl_object->addLinearVelocity(
+ (i_spring + i_damp) *
+ (normal - normal.dot(ray_dir) * ray_dir));
+ }
+
+ MT_Vector3 lateral = rel_vel - rel_vel_ray * ray_dir;
+ const SM_ShapeProps *shapeProps = cl_object->getShapeProps();
+
+ if (shapeProps->m_do_anisotropic) {
+ MT_Matrix3x3 lcs(cl_object->getOrientation());
+ MT_Vector3 loc_lateral = lateral * lcs;
+ const MT_Vector3& friction_scaling =
+ shapeProps->m_friction_scaling;
+
+ loc_lateral.scale(friction_scaling[0],
+ friction_scaling[1],
+ friction_scaling[2]);
+ lateral = lcs * loc_lateral;
+ }
+
+
+ MT_Scalar rel_vel_lateral = lateral.length();
+
+ if (rel_vel_lateral > MT_EPSILON) {
+ MT_Scalar friction_factor = matProps->m_friction;
+ MT_Scalar max_friction = friction_factor * MT_max(0.0, i_spring);
+
+ MT_Scalar rel_mom_lateral = rel_vel_lateral /
+ cl_object->getInvMass();
+
+ MT_Vector3 friction =
+ (rel_mom_lateral > max_friction) ?
+ -lateral * (max_friction / rel_vel_lateral) :
+ -lateral;
+
+ cl_object->applyCenterImpulse(friction);
+ }
+ }
+
+ if (shapeProps->m_do_rot_fh) {
+ const double *ogl_mat = cl_object->getMatrix();
+ MT_Vector3 up(&ogl_mat[8]);
+ MT_Vector3 t_spring = up.cross(normal) * matProps->m_fh_spring;
+ MT_Vector3 ang_vel = cl_object->getAngularVelocity();
+
+ // only rotations that tilt relative to the normal are damped
+ ang_vel -= ang_vel.dot(normal) * normal;
+
+ MT_Vector3 t_damp = ang_vel * matProps->m_fh_damping;
+
+ cl_object->addAngularVelocity(t_spring - t_damp);
+ }
+ }
+ }
+}
+
+
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp
new file mode 100644
index 00000000000..655590c2086
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp
@@ -0,0 +1,953 @@
+/**
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * The basic physics object.
+ */
+
+#ifdef WIN32
+// This warning tells us about truncation of __long__ stl-generated names.
+// It can occasionally cause DevStudio to have internal compiler warnings.
+#pragma warning( disable : 4786 )
+#endif
+
+#include "SM_Object.h"
+#include "SM_Scene.h"
+#include "SM_FhObject.h"
+
+#include "MT_MinMax.h"
+
+
+// Tweak parameters
+static MT_Scalar ImpulseThreshold = 0.5;
+
+SM_Object::SM_Object(
+ DT_ShapeHandle shape,
+ const SM_MaterialProps *materialProps,
+ const SM_ShapeProps *shapeProps,
+ SM_Object *dynamicParent
+) :
+ m_shape(shape),
+ m_materialProps(materialProps),
+ m_materialPropsBackup(0),
+ m_shapeProps(shapeProps),
+ m_shapePropsBackup(0),
+ m_dynamicParent(dynamicParent),
+ m_object(DT_CreateObject(this, shape)),
+ m_margin(0.0),
+ m_scaling(1.0, 1.0, 1.0),
+ m_reaction_impulse(0.0, 0.0, 0.0),
+ m_reaction_force(0.0, 0.0, 0.0),
+ m_kinematic(false),
+ m_prev_kinematic(false),
+ m_is_rigid_body(false),
+ m_lin_mom(0.0, 0.0, 0.0),
+ m_ang_mom(0.0, 0.0, 0.0),
+ m_force(0.0, 0.0, 0.0),
+ m_torque(0.0, 0.0, 0.0),
+ m_client_object(0),
+ m_fh_object(0),
+
+ m_combined_lin_vel (0.0, 0.0, 0.0),
+ m_combined_ang_vel (0.0, 0.0, 0.0)
+{
+ m_xform.setIdentity();
+ m_xform.getValue(m_ogl_matrix);
+ if (shapeProps &&
+ (shapeProps->m_do_fh || shapeProps->m_do_rot_fh)) {
+ MT_Vector3 ray(0.0, 0.0, -10.0);
+ m_fh_object = new SM_FhObject(ray, this);
+ }
+ m_suspended = false;
+}
+
+
+ void
+SM_Object::
+integrateForces(
+ MT_Scalar timeStep
+){
+ if (!m_suspended) {
+ m_prev_state = *this;
+ m_prev_state.setLinearVelocity(actualLinVelocity());
+ m_prev_state.setAngularVelocity(actualAngVelocity());
+ if (isDynamic()) {
+ // Integrate momentum (forward Euler)
+ m_lin_mom += m_force * timeStep;
+ m_ang_mom += m_torque * timeStep;
+ // Drain momentum because of air/water resistance
+ m_lin_mom *= pow(m_shapeProps->m_lin_drag, timeStep);
+ m_ang_mom *= pow(m_shapeProps->m_ang_drag, timeStep);
+ // Set velocities according momentum
+ m_lin_vel = m_lin_mom / m_shapeProps->m_mass;
+ m_ang_vel = m_ang_mom / m_shapeProps->m_inertia;
+ }
+ }
+
+};
+
+ void
+SM_Object::
+integrateMomentum(
+ MT_Scalar timeStep
+){
+ // Integrate position and orientation
+
+ // only do it for objects with linear and/or angular velocity
+ // else clients with hierarchies may get into trouble
+ if (!actualLinVelocity().fuzzyZero() || !actualAngVelocity().fuzzyZero())
+ {
+
+ // those MIDPOINT and BACKWARD integration methods are
+ // in this form not ok with some testfiles !
+ // For a release build please use forward euler unless completely tested
+[
+//#define MIDPOINT
+//#define BACKWARD
+#ifdef MIDPOINT
+// Midpoint rule
+ m_pos += (m_prev_state.getLinearVelocity() + actualLinVelocity()) * (timeStep * 0.5);
+ m_orn += (m_prev_state.getAngularVelocity() * m_prev_state.getOrientation() + actualAngVelocity() * m_orn) * (timeStep * 0.25);
+#elif defined BACKWARD
+// Backward Euler
+ m_pos += actualLinVelocity() * timeStep;
+ m_orn += actualAngVelocity() * m_orn * (timeStep * 0.5);
+#else
+// Forward Euler
+
+ m_pos += m_prev_state.getLinearVelocity() * timeStep;
+ m_orn += m_prev_state.getAngularVelocity() * m_orn * (timeStep * 0.5);
+#endif
+ m_orn.normalize(); // I might not be necessary to do this every call
+
+ calcXform();
+ notifyClient();
+
+ }
+}
+
+
+void SM_Object::boing(
+ void *client_data,
+ void *object1,
+ void *object2,
+ const DT_CollData *coll_data
+){
+ SM_Scene *scene = (SM_Scene *)client_data;
+ SM_Object *obj1 = (SM_Object *)object1;
+ SM_Object *obj2 = (SM_Object *)object2;
+
+ scene->addPair(obj1, obj2); // Record this collision for client callbacks
+
+
+ // If one of the objects is a ghost then ignore it for the dynamics
+ if (obj1->isGhost() || obj2->isGhost()) {
+ return;
+ }
+
+
+ if (!obj2->isDynamic()) {
+ std::swap(obj1, obj2);
+ }
+
+ if (!obj2->isDynamic()) {
+ return;
+ }
+
+ // obj1 points to a dynamic object
+
+
+ // This distinction between dynamic and non-dynamic objects should not be
+ // necessary. Non-dynamic objects are assumed to have infinite mass.
+
+ if (obj1->isDynamic()) {
+ // normal to the contact plane
+ MT_Vector3 normal = obj2->m_pos - obj1->m_pos;
+ MT_Scalar dist = normal.length();
+
+ if (MT_EPSILON < dist && dist <= obj1->getMargin() + obj2->getMargin())
+ {
+ normal /= dist;
+ // relative velocity of the contact points
+ MT_Vector3 rel_vel = obj2->actualLinVelocity() - obj1->actualLinVelocity();
+ // relative velocity projected onto the normal
+ MT_Scalar rel_vel_normal = normal.dot(rel_vel);
+
+ // if the objects are approaching eachother...
+ if (rel_vel_normal < 0.0) {
+ MT_Scalar restitution;
+ // ...and the approaching velocity is large enough...
+ if (-rel_vel_normal > ImpulseThreshold) {
+ // ...this must be a true collision.
+ restitution =
+ MT_min(obj1->getMaterialProps()->m_restitution,
+ obj2->getMaterialProps()->m_restitution);
+ }
+ else {
+ // otherwise, it is a resting contact, and thus the
+ // relative velocity must be made zero
+ restitution = 0.0;
+ // We also need to interfere with the positions of the
+ // objects, otherwise they might drift into eachother.
+ MT_Vector3 penalty = normal *
+ (0.5 * (obj1->getMargin() + obj2->getMargin() - dist));
+ obj1->m_pos -= penalty;
+ obj2->m_pos += penalty;
+ }
+
+ // Compute the impulse necessary to yield the desired relative velocity...
+ MT_Scalar impulse = -(1.0 + restitution) * rel_vel_normal /
+ (obj1->getInvMass() + obj2->getInvMass());
+
+ // ... and apply it.
+ obj1->applyCenterImpulse(-impulse * normal);
+ obj2->applyCenterImpulse( impulse * normal);
+ }
+ }
+ }
+ else {
+ // Same again but now obj1 is non-dynamic
+
+ // Compute the point on obj1 closest to obj2 (= sphere with radius = 0)
+ MT_Point3 local1, local2;
+ MT_Scalar dist = DT_GetClosestPair(obj1->m_object, obj2->m_object,
+ local1.getValue(), local2.getValue());
+
+ // local1 is th point closest to obj2
+ // local2 is the local origin of obj2
+
+ if (MT_EPSILON < dist && dist <= obj2->getMargin()) {
+ MT_Point3 world1 = obj1->getWorldCoord(local1);
+ MT_Point3 world2 = obj2->getWorldCoord(local2);
+ MT_Vector3 vel1 = obj1->getVelocity(local1) + obj1->m_combined_lin_vel;
+ MT_Vector3 vel2 = obj2->getVelocity(local2) + obj2->m_combined_lin_vel;
+
+ // the normal to the contact plane
+ MT_Vector3 normal = world2 - world1;
+ normal /= dist;
+
+ // wr2 points from obj2's origin to the global contact point
+ // wr2 is only needed for rigid bodies (objects for which the
+ // friction can change the angular momentum).
+ // vel2 is adapted to denote the velocity of the contact point
+ MT_Vector3 wr2;
+ if (obj2->isRigidBody()) {
+ wr2 = -obj2->getMargin() * normal;
+ vel2 += obj2->actualAngVelocity().cross(wr2);
+ }
+
+
+ // This should look familiar....
+ MT_Vector3 rel_vel = vel2 - vel1;
+ MT_Scalar rel_vel_normal = normal.dot(rel_vel);
+
+ if (rel_vel_normal < 0.0) {
+ MT_Scalar restitution;
+ if (-rel_vel_normal > ImpulseThreshold) {
+ restitution =
+ MT_min(obj1->getMaterialProps()->m_restitution,
+ obj2->getMaterialProps()->m_restitution);
+ }
+ else {
+ restitution = 0.0;
+ // We fix drift by moving obj2 only, since obj1 was
+ // non-dynamic.
+ obj2->m_pos += normal * (obj2->getMargin() - dist);
+
+ }
+
+ MT_Scalar impulse = -(1.0 + restitution) * rel_vel_normal /
+ (obj1->getInvMass() + obj2->getInvMass());
+
+
+ obj2->applyCenterImpulse( impulse * normal);
+
+// The friction part starts here!!!!!!!!
+
+ // Compute the lateral component of the relative velocity
+ // lateral actually points in the opposite direction, i.e.,
+ // into the direction of the friction force.
+
+#if 1
+ // test - only do friction on the physics part of the
+ // velocity.
+ vel1 -= obj1->m_combined_lin_vel;
+ vel2 -= obj2->m_combined_lin_vel;
+
+ // This should look familiar....
+ rel_vel = vel2 - vel1;
+ rel_vel_normal = normal.dot(rel_vel);
+#endif
+
+ MT_Vector3 lateral = normal * rel_vel_normal - rel_vel;
+
+ const SM_ShapeProps *shapeProps = obj2->getShapeProps();
+
+ if (shapeProps->m_do_anisotropic) {
+
+ // For anisotropic friction we scale the lateral component,
+ // rather than compute a direction-dependent fricition
+ // factor. For this the lateral component is transformed to
+ // local coordinates.
+
+ MT_Matrix3x3 lcs(obj2->m_orn);
+ // We cannot use m_xform.getBasis() for the matrix, since
+ // it might contain a non-uniform scaling.
+ // OPT: it's a bit daft to compute the matrix since the
+ // quaternion itself can be used to do the transformation.
+
+ MT_Vector3 loc_lateral = lateral * lcs;
+ // lcs is orthogonal so lcs.inversed() == lcs.transposed(),
+ // and lcs.transposed() * lateral == lateral * lcs.
+
+ const MT_Vector3& friction_scaling =
+ shapeProps->m_friction_scaling;
+
+ // Scale the local lateral...
+ loc_lateral.scale(friction_scaling[0],
+ friction_scaling[1],
+ friction_scaling[2]);
+ // ... and transform it back to global coordinates
+ lateral = lcs * loc_lateral;
+ }
+
+ // A tiny Coulomb friction primer:
+ // The Coulomb friction law states that the magnitude of the
+ // maximum possible friction force depends linearly on the
+ // magnitude of the normal force.
+ //
+ // F_max_friction = friction_factor * F_normal
+ //
+ // (NB: independent of the contact area!!)
+ //
+ // The friction factor depends on the material.
+ // We use impulses rather than forces but let us not be
+ // bothered by this.
+
+
+ MT_Scalar rel_vel_lateral = lateral.length();
+
+ if (rel_vel_lateral > MT_EPSILON) {
+ lateral /= rel_vel_lateral;
+
+ MT_Scalar friction_factor =
+ MT_min(obj1->getMaterialProps()->m_friction,
+ obj2->getMaterialProps()->m_friction);
+
+ // Compute the maximum friction impulse
+
+ MT_Scalar max_friction =
+ friction_factor * MT_max(0.0, impulse);
+
+ // I guess the GEN_max is not necessary, so let's check it
+
+ assert(impulse >= 0.0);
+
+ // Here's the trick. We compute the impulse to make the
+ // lateral velocity zero. (Make the objects stick together
+ // at the contact point. If this impulse is larger than
+ // the maximum possible friction impulse, then shrink its
+ // magnitude to the maximum friction.
+
+ if (obj2->isRigidBody()) {
+
+ // For rigid bodies we take the inertia into account,
+ // since the friciton impulse is going to change the
+ // angular momentum as well.
+ MT_Scalar impulse_lateral = rel_vel_lateral /
+ (obj1->getInvMass() + obj2->getInvMass() +
+ ((obj2->getInvInertia() * wr2.cross(lateral)).cross(wr2)).dot(lateral));
+ MT_Scalar friction = MT_min(impulse_lateral, max_friction);
+ obj2->applyImpulse(world2 + wr2, friction * lateral);
+ }
+ else {
+ MT_Scalar impulse_lateral = rel_vel_lateral /
+ (obj1->getInvMass() + obj2->getInvMass());
+
+ MT_Scalar friction = MT_min(impulse_lateral, max_friction);
+ obj2->applyCenterImpulse( friction * lateral);
+ }
+ }
+
+ obj2->calcXform();
+ obj2->notifyClient();
+ }
+ }
+ }
+}
+
+
+
+SM_Object::SM_Object(
+) {
+ // warning no initialization of variables done by moto.
+}
+
+SM_Object::
+~SM_Object() {
+ delete m_fh_object;
+ DT_DeleteObject(m_object);
+}
+
+ bool
+SM_Object::
+isDynamic(
+) const {
+ return m_shapeProps != 0;
+}
+
+/* nzc experimental. There seem to be two places where kinematics
+ * are evaluated: proceedKinematic (called from SM_Scene) and
+ * proceed() in this object. I'll just try and bunge these out for
+ * now. */
+ void
+SM_Object::
+suspend(
+){
+ if (!m_suspended) {
+ m_suspended = true;
+ suspendDynamics();
+ }
+}
+
+ void
+SM_Object::
+resume(
+) {
+ if (m_suspended) {
+ m_suspended = false;
+ restoreDynamics();
+ }
+}
+
+ void
+SM_Object::
+suspendDynamics(
+) {
+ if (m_shapeProps) {
+ m_shapePropsBackup = m_shapeProps;
+ m_shapeProps = 0;
+ }
+}
+
+ void
+SM_Object::
+restoreDynamics(
+) {
+ if (m_shapePropsBackup) {
+ m_shapeProps = m_shapePropsBackup;
+ m_shapePropsBackup = 0;
+ }
+}
+
+ bool
+SM_Object::
+isGhost(
+) const {
+ return m_materialProps == 0;
+}
+
+ void
+SM_Object::
+suspendMaterial(
+) {
+ if (m_materialProps) {
+ m_materialPropsBackup = m_materialProps;
+ m_materialProps = 0;
+ }
+}
+
+ void
+SM_Object::
+restoreMaterial(
+) {
+ if (m_materialPropsBackup) {
+ m_materialProps = m_materialPropsBackup;
+ m_materialPropsBackup = 0;
+ }
+}
+
+ SM_FhObject *
+SM_Object::
+getFhObject(
+) const {
+ return m_fh_object;
+}
+
+ void
+SM_Object::
+registerCallback(
+ SM_Callback& callback
+) {
+ m_callbackList.push_back(&callback);
+}
+
+// Set the local coordinate system according to the current state
+ void
+SM_Object::
+calcXform() {
+ m_xform.setOrigin(m_pos);
+ m_xform.setBasis(MT_Matrix3x3(m_orn, m_scaling));
+ m_xform.getValue(m_ogl_matrix);
+ DT_SetMatrixd(m_object, m_ogl_matrix);
+ if (m_fh_object) {
+ m_fh_object->setPosition(m_pos);
+ m_fh_object->calcXform();
+ }
+}
+
+// Call callbacks to notify the client of a change of placement
+ void
+SM_Object::
+notifyClient() {
+ T_CallbackList::iterator i;
+ for (i = m_callbackList.begin(); i != m_callbackList.end(); ++i) {
+ (*i)->do_me();
+ }
+}
+
+
+// Save the current state information for use in the velocity computation in the next frame.
+ void
+SM_Object::
+proceedKinematic(
+ MT_Scalar timeStep
+) {
+ /* nzc: need to bunge this for the logic bubbling as well? */
+ if (!m_suspended) {
+ m_prev_kinematic = m_kinematic;
+ if (m_kinematic) {
+ m_prev_xform = m_xform;
+ m_timeStep = timeStep;
+ calcXform();
+ m_kinematic = false;
+ }
+ }
+}
+
+ void
+SM_Object::
+saveReactionForce(
+ MT_Scalar timeStep
+) {
+ if (isDynamic()) {
+ m_reaction_force = m_reaction_impulse / timeStep;
+ m_reaction_impulse.setValue(0.0, 0.0, 0.0);
+ }
+}
+
+ void
+SM_Object::
+clearForce(
+) {
+ m_force.setValue(0.0, 0.0, 0.0);
+ m_torque.setValue(0.0, 0.0, 0.0);
+}
+
+ void
+SM_Object::
+clearMomentum(
+) {
+ m_lin_mom.setValue(0.0, 0.0, 0.0);
+ m_ang_mom.setValue(0.0, 0.0, 0.0);
+}
+
+ void
+SM_Object::
+setMargin(
+ MT_Scalar margin
+) {
+ m_margin = margin;
+ DT_SetMargin(m_object, margin);
+}
+
+ MT_Scalar
+SM_Object::
+getMargin(
+) const {
+ return m_margin;
+}
+
+const
+ SM_MaterialProps *
+SM_Object::
+getMaterialProps(
+) const {
+ return m_materialProps;
+}
+
+const
+ SM_ShapeProps *
+SM_Object::
+getShapeProps(
+) const {
+ return m_shapeProps;
+}
+
+ void
+SM_Object::
+setPosition(
+ const MT_Point3& pos
+){
+ m_kinematic = true;
+ m_pos = pos;
+}
+
+ void
+SM_Object::
+setOrientation(
+ const MT_Quaternion& orn
+){
+ assert(!orn.fuzzyZero());
+ m_kinematic = true;
+ m_orn = orn;
+}
+
+ void
+SM_Object::
+setScaling(
+ const MT_Vector3& scaling
+){
+ m_kinematic = true;
+ m_scaling = scaling;
+}
+
+/**
+ * Functions to handle linear velocity
+ */
+
+ void
+SM_Object::
+setExternalLinearVelocity(
+ const MT_Vector3& lin_vel
+) {
+ m_combined_lin_vel=lin_vel;
+}
+
+ void
+SM_Object::
+addExternalLinearVelocity(
+ const MT_Vector3& lin_vel
+) {
+ m_combined_lin_vel+=lin_vel;
+}
+
+ void
+SM_Object::
+addLinearVelocity(
+ const MT_Vector3& lin_vel
+){
+ m_lin_vel += lin_vel;
+ if (m_shapeProps) {
+ m_lin_mom = m_lin_vel * m_shapeProps->m_mass;
+ }
+}
+
+ void
+SM_Object::
+setLinearVelocity(
+ const MT_Vector3& lin_vel
+){
+ m_lin_vel = lin_vel;
+ if (m_shapeProps) {
+ m_lin_mom = m_lin_vel * m_shapeProps->m_mass;
+ }
+}
+
+/**
+ * Functions to handle angular velocity
+ */
+
+ void
+SM_Object::
+setExternalAngularVelocity(
+ const MT_Vector3& ang_vel
+) {
+ m_combined_ang_vel = ang_vel;
+}
+
+ void
+SM_Object::
+addExternalAngularVelocity(
+ const MT_Vector3& ang_vel
+) {
+ m_combined_ang_vel += ang_vel;
+}
+
+ void
+SM_Object::
+setAngularVelocity(
+ const MT_Vector3& ang_vel
+) {
+ m_ang_vel = ang_vel;
+ if (m_shapeProps) {
+ m_ang_mom = m_ang_vel * m_shapeProps->m_inertia;
+ }
+}
+
+ void
+SM_Object::
+addAngularVelocity(
+ const MT_Vector3& ang_vel
+) {
+ m_ang_vel += ang_vel;
+ if (m_shapeProps) {
+ m_ang_mom = m_ang_vel * m_shapeProps->m_inertia;
+ }
+}
+
+
+ void
+SM_Object::
+clearCombinedVelocities(
+) {
+ m_combined_lin_vel = MT_Vector3(0,0,0);
+ m_combined_ang_vel = MT_Vector3(0,0,0);
+}
+
+ void
+SM_Object::
+resolveCombinedVelocities(
+ const MT_Vector3 & lin_vel,
+ const MT_Vector3 & ang_vel
+) {
+
+ // Different behaviours for dynamic and non-dynamic
+ // objects. For non-dynamic we just set the velocity to
+ // zero. For dynmic the physics velocity has to be
+ // taken into account. We must make an arbitrary decision
+ // on how to resolve the 2 velocities. Choices are
+ // Add the physics velocity to the linear velocity. Objects
+ // will just keep on moving in the direction they were
+ // last set in - untill external forces affect them.
+ // Set the combinbed linear and physics velocity to zero.
+ // Set the physics velocity in the direction of the set velocity
+ // zero.
+ if (isDynamic()) {
+
+#if 1
+ m_lin_vel += lin_vel;
+ m_ang_vel += ang_vel;
+#else
+
+ //compute the component of the physics velocity in the
+ // direction of the set velocity and set it to zero.
+ MT_Vector3 lin_vel_norm = lin_vel.normalized();
+
+ m_lin_vel -= (m_lin_vel.dot(lin_vel_norm) * lin_vel_norm);
+#endif
+ m_lin_mom = m_lin_vel * m_shapeProps->m_mass;
+ m_ang_mom = m_ang_vel * m_shapeProps->m_inertia;
+ clearCombinedVelocities();
+
+ }
+
+}
+
+
+ MT_Scalar
+SM_Object::
+getInvMass(
+) const {
+ return m_shapeProps ? 1.0 / m_shapeProps->m_mass : 0.0;
+ // OPT: cache the result of this division rather than compute it each call
+}
+
+ MT_Scalar
+SM_Object::
+getInvInertia(
+) const {
+ return m_shapeProps ? 1.0 / m_shapeProps->m_inertia : 0.0;
+ // OPT: cache the result of this division rather than compute it each call
+}
+
+ void
+SM_Object::
+applyForceField(
+ const MT_Vector3& accel
+) {
+ if (m_shapeProps) {
+ m_force += m_shapeProps->m_mass * accel; // F = m * a
+ }
+}
+
+ void
+SM_Object::
+applyCenterForce(
+ const MT_Vector3& force
+) {
+ m_force += force;
+}
+
+ void
+SM_Object::
+applyTorque(
+ const MT_Vector3& torque
+) {
+ m_torque += torque;
+}
+
+ void
+SM_Object::
+applyImpulse(
+ const MT_Point3& attach, const MT_Vector3& impulse
+) {
+ applyCenterImpulse(impulse); // Change in linear momentum
+ applyAngularImpulse((attach - m_pos).cross(impulse)); // Change in angular momentump
+}
+
+ void
+SM_Object::
+applyCenterImpulse(
+ const MT_Vector3& impulse
+) {
+ if (m_shapeProps) {
+ m_lin_mom += impulse;
+ m_reaction_impulse += impulse;
+ m_lin_vel = m_lin_mom / m_shapeProps->m_mass;
+
+ // The linear velocity is immedialtely updated since otherwise
+ // simultaneous collisions will get a double impulse.
+ }
+}
+
+ void
+SM_Object::
+applyAngularImpulse(
+ const MT_Vector3& impulse
+) {
+ if (m_shapeProps) {
+ m_ang_mom += impulse;
+ m_ang_vel = m_ang_mom / m_shapeProps->m_inertia;
+ }
+}
+
+ MT_Point3
+SM_Object::
+getWorldCoord(
+ const MT_Point3& local
+) const {
+ return m_xform(local);
+}
+
+ MT_Vector3
+SM_Object::
+getVelocity(
+ const MT_Point3& local
+) const {
+ // For displaced objects the velocity is faked using the previous state.
+ // Dynamic objects get their own velocity, not the faked velocity.
+ // (Dynamic objects shouldn't be displaced in the first place!!)
+
+ return m_prev_kinematic && !isDynamic() ?
+ (m_xform(local) - m_prev_xform(local)) / m_timeStep :
+ m_lin_vel + m_ang_vel.cross(m_xform.getBasis() * local);
+
+ // NB: m_xform.getBasis() * local == m_xform(local) - m_xform.getOrigin()
+
+}
+
+
+const
+ MT_Vector3&
+SM_Object::
+getReactionForce(
+) const {
+ return m_reaction_force;
+}
+
+ void
+SM_Object::
+getMatrix(
+ double *m
+) const {
+ std::copy(&m_ogl_matrix[0], &m_ogl_matrix[16], &m[0]);
+}
+
+const
+ double *
+SM_Object::
+getMatrix(
+) const {
+ return m_ogl_matrix;
+}
+
+// Still need this???
+const
+ MT_Transform&
+SM_Object::
+getScaledTransform(
+) const {
+ return m_xform;
+}
+
+ DT_ObjectHandle
+SM_Object::
+getObjectHandle(
+) const {
+ return m_object;
+}
+
+ DT_ShapeHandle
+SM_Object::
+getShapeHandle(
+) const {
+ return m_shape;
+}
+
+ void
+SM_Object::
+setClientObject(
+ void *clientobj
+) {
+ m_client_object = clientobj;
+}
+
+ void *
+SM_Object::
+getClientObject(
+){
+ return m_client_object;
+}
+
+ SM_Object *
+SM_Object::
+getDynamicParent(
+) {
+ return m_dynamicParent;
+}
+
+ void
+SM_Object::
+setRigidBody(
+ bool is_rigid_body
+) {
+ m_is_rigid_body = is_rigid_body;
+}
+
+ bool
+SM_Object::
+isRigidBody(
+) const {
+ return m_is_rigid_body;
+}
+
+const
+ MT_Vector3
+SM_Object::
+actualLinVelocity(
+) const {
+ return m_combined_lin_vel + m_lin_vel;
+};
+
+const
+ MT_Vector3
+SM_Object::
+actualAngVelocity(
+) const {
+ return m_combined_ang_vel + m_ang_vel;
+};
+
+
+
+
+
diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp
new file mode 100644
index 00000000000..e3eb7e5c5ea
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp
@@ -0,0 +1,179 @@
+/**
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * The physics scene.
+ */
+
+#ifdef WIN32
+#pragma warning(disable : 4786) // shut off 255 char limit debug template warning
+#endif
+
+#include "SM_Scene.h"
+#include "SM_Object.h"
+#include "SM_FhObject.h"
+
+#include <algorithm>
+
+void SM_Scene::add(SM_Object& object) {
+ object.calcXform();
+ m_objectList.push_back(&object);
+ DT_AddObject(m_scene, object.getObjectHandle());
+ if (object.isDynamic()) {
+ DT_SetObjectResponse(m_respTable, object.getObjectHandle(),
+ SM_Object::boing, DT_SIMPLE_RESPONSE, this);
+ }
+
+ if (object.getDynamicParent()) {
+ DT_SetPairResponse(m_respTable, object.getObjectHandle(),
+ object.getDynamicParent()->getObjectHandle(),
+ 0, DT_NO_RESPONSE, 0);
+ }
+ SM_FhObject *fh_object = object.getFhObject();
+
+ if (fh_object) {
+ DT_AddObject(m_scene, fh_object->getObjectHandle());
+ DT_SetObjectResponse(m_respTable, fh_object->getObjectHandle(),
+ SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this);
+ }
+}
+
+void SM_Scene::remove(SM_Object& object) {
+ T_ObjectList::iterator i =
+ std::find(m_objectList.begin(), m_objectList.end(), &object);
+ if (!(i == m_objectList.end()))
+ {
+ std::swap(*i, m_objectList.back());
+ m_objectList.pop_back();
+ DT_RemoveObject(m_scene, object.getObjectHandle());
+ if (object.isDynamic()) {
+ DT_ClearObjectResponse(m_respTable, object.getObjectHandle());
+ }
+
+ if (object.getDynamicParent()) {
+ DT_ClearPairResponse(m_respTable, object.getObjectHandle(),
+ object.getDynamicParent()->getObjectHandle());
+ }
+
+ SM_FhObject *fh_object = object.getFhObject();
+
+ if (fh_object) {
+ DT_RemoveObject(m_scene, fh_object->getObjectHandle());
+ DT_ClearObjectResponse(m_respTable,
+ fh_object->getObjectHandle());
+ }
+ }
+ else {
+ // tried to remove an object that is not in the scene
+ //assert(false);
+ }
+}
+
+void SM_Scene::proceed(MT_Scalar timeStep, MT_Scalar subSampling) {
+ // Don't waste time...but it's OK to spill a little.
+ if (timeStep < 0.001)
+ return;
+
+ // Divide the timeStep into a number of subsamples of size roughly
+ // equal to subSampling (might be a little smaller).
+ int num_samples = (int)ceil(timeStep / subSampling);
+
+
+ MT_Scalar subStep = timeStep / num_samples;
+ T_ObjectList::iterator i;
+
+ // Apply a forcefield (such as gravity)
+ for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
+ (*i)->applyForceField(m_forceField);
+ }
+
+ // Do the integration steps per object.
+ int step;
+ for (step = 0; step != num_samples; ++step) {
+
+ for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
+ (*i)->integrateForces(subStep);
+ }
+
+ // And second we update the object positions by performing
+ // an integration step for each object
+ for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
+ (*i)->integrateMomentum(subStep);
+ }
+#if 0
+ // I changed the order of the next 2 statements.
+ // Originally objects were first integrated with a call
+ // to proceed(). However if external objects were
+ // directly manipulating the velocities etc of physics
+ // objects then the physics environment would not be able
+ // to react before object positions were updated. --- Laurence.
+
+ // So now first we let the physics scene respond to
+ // new forces, velocities set externally.
+#endif
+ // The collsion and friction impulses are computed here.
+ DT_Test(m_scene, m_respTable);
+
+ }
+
+
+ // clear the user set velocities.
+#if 0
+ clearObjectCombinedVelocities();
+#endif
+ // Finish this timestep by saving al state information for the next
+ // timestep and clearing the accumulated forces.
+
+ for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
+ (*i)->proceedKinematic(timeStep);
+ (*i)->saveReactionForce(timeStep);
+ (*i)->clearForce();
+ }
+
+ // For each pair of object that collided, call the corresponding callback.
+ // Additional collisions of a pair within the same time step are ignored.
+
+ if (m_secondaryRespTable) {
+ T_PairList::iterator p;
+ for (p = m_pairList.begin(); p != m_pairList.end(); ++p) {
+ DT_CallResponse(m_secondaryRespTable,
+ (*p).first->getObjectHandle(),
+ (*p).second->getObjectHandle(),
+ 0);
+ }
+ }
+
+ clearPairs();
+}
+
+SM_Object *SM_Scene::rayTest(void *ignore_client,
+ const MT_Point3& from, const MT_Point3& to,
+ MT_Point3& result, MT_Vector3& normal) const {
+ MT_Point3 local;
+
+ SM_Object *hit_object = (SM_Object *)
+ DT_RayTest(m_scene, ignore_client, from.getValue(), to.getValue(),
+ local.getValue(), normal.getValue());
+
+ if (hit_object) {
+ result = hit_object->getWorldCoord(local);
+ }
+
+ return hit_object;
+}
+
+void SM_Scene::clearObjectCombinedVelocities() {
+
+ T_ObjectList::iterator i;
+
+ for (i = m_objectList.begin(); i != m_objectList.end(); ++i) {
+
+ (*i)->clearCombinedVelocities();
+
+ }
+
+}
+
+
+
+
+
diff --git a/source/gameengine/Physics/Sumo/Makefile b/source/gameengine/Physics/Sumo/Makefile
new file mode 100644
index 00000000000..3e5aca1d577
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/Makefile
@@ -0,0 +1,47 @@
+#
+# $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 = sumo
+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_GUARDEDALLOC)/include
+CPPFLAGS += -I../../Physics/common
+CPPFLAGS += -I../../Physics/Dummy
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsController.cpp b/source/gameengine/Physics/Sumo/SumoPhysicsController.cpp
new file mode 100644
index 00000000000..2b2c5b81856
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsController.cpp
@@ -0,0 +1,462 @@
+/**
+ * $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 *****
+ */
+
+#include "SumoPhysicsController.h"
+#include "PHY_IMotionState.h"
+#include "SM_Object.h"
+#include "MT_Quaternion.h"
+
+
+SumoPhysicsController::SumoPhysicsController(
+ class SM_Scene* sumoScene,
+ DT_SceneHandle solidscene,
+ class SM_Object* sumoObj,
+ class PHY_IMotionState* motionstate,
+
+ bool dyna)
+ :
+ m_sumoScene(sumoScene),
+ m_solidscene(solidscene),
+ m_sumoObj(sumoObj) ,
+ m_bFirstTime(true),
+ m_MotionState(motionstate),
+ m_bDyna(dyna)
+{
+ if (m_sumoObj)
+ {
+ m_sumoObj->setClientObject(this);
+ //if it is a dyna, register for a callback
+ m_sumoObj->registerCallback(*this);
+ }
+};
+
+
+
+SumoPhysicsController::~SumoPhysicsController()
+{
+ if (m_sumoObj)
+ {
+ m_sumoScene->remove(*m_sumoObj);
+
+
+ DT_ObjectHandle objhandle = (DT_ObjectHandle) m_sumoObj->getObjectHandle();
+ if (objhandle)
+ {
+ DT_RemoveObject(m_solidscene,objhandle);
+ }
+ delete m_sumoObj;
+ }
+}
+
+float SumoPhysicsController::getMass()
+{
+ if (m_sumoObj)
+ {
+ const SM_ShapeProps *shapeprops = m_sumoObj->getShapeProps();
+ return shapeprops->m_mass;
+ }
+ return 0.f;
+}
+
+bool SumoPhysicsController::SynchronizeMotionStates(float time)
+{
+
+ if (m_bFirstTime)
+ {
+ setSumoTransform(false);
+ m_bFirstTime = false;
+ }
+
+ if (!m_bDyna)
+ {
+ if (m_sumoObj)
+ {
+ MT_Point3 pos;
+ GetWorldPosition(pos);
+
+ m_sumoObj->setPosition(pos);
+ if (m_bDyna)
+ {
+ m_sumoObj->setScaling(MT_Vector3(1,1,1));
+ } else
+ {
+ MT_Vector3 scaling;
+ GetWorldScaling(scaling);
+ m_sumoObj->setScaling(scaling);
+ }
+ MT_Matrix3x3 orn;
+ GetWorldOrientation(orn);
+ m_sumoObj->setOrientation(orn.getRotation());
+ m_sumoObj->calcXform();
+ }
+ }
+ return false; // physics object are not part of
+ // hierarchy, or ignore it ??
+}
+
+
+
+
+void SumoPhysicsController::GetWorldOrientation(MT_Matrix3x3& mat)
+{
+ float orn[4];
+ m_MotionState->getWorldOrientation(orn[0],orn[1],orn[2],orn[3]);
+ MT_Quaternion quat(orn);
+ mat.setRotation(quat);
+
+}
+
+void SumoPhysicsController::GetWorldPosition(MT_Point3& pos)
+{
+ float worldpos[3];
+ m_MotionState->getWorldPosition(worldpos[0],worldpos[1],worldpos[2]);
+ pos[0]=worldpos[0];
+ pos[1]=worldpos[1];
+ pos[2]=worldpos[2];
+}
+
+void SumoPhysicsController::GetWorldScaling(MT_Vector3& scale)
+{
+ float worldscale[3];
+ m_MotionState->getWorldScaling(worldscale[0],worldscale[1],worldscale[2]);
+ scale[0]=worldscale[0];
+ scale[1]=worldscale[1];
+ scale[2]=worldscale[2];
+}
+
+
+ // kinematic methods
+void SumoPhysicsController::RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local)
+{
+
+
+ if (m_sumoObj)
+ {
+ MT_Matrix3x3 mat;
+ GetWorldOrientation(mat);
+ MT_Vector3 dloc(dlocX,dlocY,dlocZ);
+
+ MT_Point3 newpos = m_sumoObj->getPosition();
+ newpos += (local ? mat * dloc : dloc);
+ m_sumoObj->setPosition(newpos);
+ }
+
+}
+void SumoPhysicsController::RelativeRotate(const float drot[9],bool local)
+{
+
+ if (m_sumoObj )
+ {
+ MT_Matrix3x3 drotmat(drot);
+ MT_Matrix3x3 currentOrn;
+ GetWorldOrientation(currentOrn);
+
+ m_sumoObj->setOrientation(m_sumoObj->getOrientation()*(local ?
+ drotmat.getRotation() : (currentOrn.inverse() * drotmat * currentOrn)).getRotation());
+ }
+
+}
+void SumoPhysicsController::setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal)
+{
+ float orn [4]={quatImag0,quatImag1,quatImag2,quatReal};
+ MT_Quaternion quat(orn);
+ m_sumoObj->setOrientation(orn);
+}
+
+void SumoPhysicsController::getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal)
+{
+ const MT_Quaternion& q = m_sumoObj->getOrientation();
+ quatImag0 = q[0];
+ quatImag1 = q[1];
+ quatImag2 = q[2];
+ quatReal = q[3];
+}
+
+void SumoPhysicsController::setPosition(float posX,float posY,float posZ)
+{
+ m_sumoObj->setPosition(MT_Point3(posX,posY,posZ));
+}
+void SumoPhysicsController::setScaling(float scaleX,float scaleY,float scaleZ)
+{
+ m_sumoObj->setScaling(MT_Vector3(scaleX,scaleY,scaleZ));
+}
+
+ // physics methods
+void SumoPhysicsController::ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local)
+{
+ if (m_sumoObj)
+ {
+ MT_Vector3 torque(torqueX,torqueY,torqueZ);
+
+ MT_Matrix3x3 orn;
+ GetWorldOrientation(orn);
+ m_sumoObj->applyTorque(local ?
+ orn * torque :
+ torque);
+ }
+
+}
+
+void SumoPhysicsController::ApplyForce(float forceX,float forceY,float forceZ,bool local)
+{
+ if (m_sumoObj)
+ {
+ MT_Vector3 force(forceX,forceY,forceZ);
+
+ MT_Matrix3x3 orn;
+ GetWorldOrientation(orn);
+
+ m_sumoObj->applyCenterForce(local ?
+ orn * force :
+ force);
+
+ }
+
+}
+
+void SumoPhysicsController::SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local)
+{
+ if (m_sumoObj)
+ {
+ MT_Vector3 ang_vel(ang_velX,ang_velY,ang_velZ);
+
+ MT_Matrix3x3 orn;
+ GetWorldOrientation(orn);
+
+ m_sumoObj->setAngularVelocity(local ?
+ orn * ang_vel :
+ ang_vel);
+
+ }
+}
+
+void SumoPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local)
+{
+ if (m_sumoObj )
+ {
+ MT_Matrix3x3 orn;
+ GetWorldOrientation(orn);
+
+ MT_Vector3 lin_vel(lin_velX,lin_velY,lin_velZ);
+ m_sumoObj->setLinearVelocity(local ?
+ orn * lin_vel :
+ lin_vel);
+ }
+}
+
+void SumoPhysicsController::applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ)
+{
+ if (m_sumoObj)
+ {
+ MT_Point3 attach(attachX,attachY,attachZ);
+ MT_Vector3 impulse(impulseX,impulseY,impulseZ);
+ m_sumoObj->applyImpulse(attach,impulse);
+ }
+
+}
+
+void SumoPhysicsController::SuspendDynamics()
+{
+ m_suspendDynamics=true;
+
+ if (m_sumoObj)
+ {
+ m_sumoObj->suspendDynamics();
+ m_sumoObj->setLinearVelocity(MT_Vector3(0,0,0));
+ m_sumoObj->setAngularVelocity(MT_Vector3(0,0,0));
+ m_sumoObj->calcXform();
+ }
+}
+
+void SumoPhysicsController::RestoreDynamics()
+{
+ m_suspendDynamics=false;
+
+ if (m_sumoObj)
+ {
+ m_sumoObj->restoreDynamics();
+ }
+
+
+}
+
+
+ /**
+ reading out information from physics
+ */
+void SumoPhysicsController::GetLinearVelocity(float& linvX,float& linvY,float& linvZ)
+{
+ if (m_sumoObj)
+ {
+ // get velocity from the physics object (m_sumoObj)
+ const MT_Vector3& vel = m_sumoObj->getLinearVelocity();
+ 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 SumoPhysicsController::GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ)
+{
+ if (m_sumoObj)
+ {
+ MT_Point3 pos(posX,posY,posZ);
+ // get velocity from the physics object (m_sumoObj)
+ const MT_Vector3& vel = m_sumoObj->getVelocity(pos);
+ linvX = vel[0];
+ linvY = vel[1];
+ linvZ = vel[2];
+ }
+ else
+ {
+ linvX = 0.f;
+ linvY = 0.f;
+ linvZ = 0.f;
+
+ }
+}
+
+
+void SumoPhysicsController::getReactionForce(float& forceX,float& forceY,float& forceZ)
+{
+ const MT_Vector3& force = m_sumoObj->getReactionForce();
+ forceX = force[0];
+ forceY = force[1];
+ forceZ = force[2];
+
+
+}
+void SumoPhysicsController::setRigidBody(bool rigid)
+{
+ m_sumoObj->setRigidBody(rigid);
+}
+
+
+void SumoPhysicsController::PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl)
+{
+ m_MotionState = motionstate;
+
+ SM_Object* dynaparent=0;
+ SumoPhysicsController* sumoparentctrl = (SumoPhysicsController* )parentctrl;
+
+ if (sumoparentctrl)
+ {
+ dynaparent = sumoparentctrl->GetSumoObject();
+ }
+
+ SM_Object* orgsumoobject = m_sumoObj;
+
+
+ m_sumoObj = new SM_Object(
+ orgsumoobject->getShapeHandle(),
+ orgsumoobject->getMaterialProps(),
+ orgsumoobject->getShapeProps(),
+ dynaparent);
+
+ m_sumoObj->setRigidBody(orgsumoobject->isRigidBody());
+
+ double radius = orgsumoobject->getMargin();
+ m_sumoObj->setMargin(orgsumoobject->getMargin());
+ m_sumoObj->setPosition(orgsumoobject->getPosition());
+ m_sumoObj->setOrientation(orgsumoobject->getOrientation());
+ m_sumoScene->add(* (m_sumoObj));
+
+ if (m_sumoObj)
+ {
+ m_sumoObj->setClientObject(this);
+ //if it is a dyna, register for a callback
+ m_sumoObj->registerCallback(*this);
+ }
+
+
+ DT_AddObject(m_solidscene,m_sumoObj->getObjectHandle());
+
+}
+
+void SumoPhysicsController::SetSimulatedTime(float time)
+{
+}
+
+
+void SumoPhysicsController::WriteMotionStateToDynamics(bool nondynaonly)
+{
+
+}
+// this is the actual callback from sumo, and the position/orientation
+//is written to the scenegraph, using the motionstate abstraction
+
+void SumoPhysicsController::do_me()
+{
+
+ const MT_Point3& pos = m_sumoObj->getPosition();
+ const MT_Quaternion& orn = m_sumoObj->getOrientation();
+
+ m_MotionState->setWorldPosition(pos[0],pos[1],pos[2]);
+ m_MotionState->setWorldOrientation(orn[0],orn[1],orn[2],orn[3]);
+
+}
+
+
+void SumoPhysicsController::setSumoTransform(bool nondynaonly)
+{
+ if (!nondynaonly || !m_bDyna)
+ {
+ if (m_sumoObj)
+ {
+ MT_Point3 pos;
+ GetWorldPosition(pos);
+
+ m_sumoObj->setPosition(pos);
+ if (m_bDyna)
+ {
+ m_sumoObj->setScaling(MT_Vector3(1,1,1));
+ } else
+ {
+ MT_Vector3 scale;
+ GetWorldScaling(scale);
+ m_sumoObj->setScaling(scale);
+ }
+ MT_Matrix3x3 orn;
+ GetWorldOrientation(orn);
+ m_sumoObj->setOrientation(orn.getRotation());
+ m_sumoObj->calcXform();
+ }
+ }
+}
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsController.h b/source/gameengine/Physics/Sumo/SumoPhysicsController.h
new file mode 100644
index 00000000000..d78c21dbd1b
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsController.h
@@ -0,0 +1,171 @@
+/**
+ * $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 *****
+ */
+#ifndef __SUMO_PHYSICSCONTROLLER_H
+#define __SUMO_PHYSICSCONTROLLER_H
+
+
+#include "PHY_IPhysicsController.h"
+#include "SM_Scene.h"
+#include "SM_Callback.h"
+
+
+/**
+ Sumo 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 SumoPhysicsController : public PHY_IPhysicsController , public SM_Callback
+
+
+{
+
+ class SM_Object* m_sumoObj;
+ class SM_Scene* m_sumoScene; // needed for replication
+ DT_SceneHandle m_solidscene;
+ bool m_bFirstTime;
+ bool m_bDyna;
+
+ float m_friction;
+ float m_restitution;
+
+
+ bool m_suspendDynamics;
+
+public:
+ SumoPhysicsController(
+ class SM_Scene* sumoScene,
+ DT_SceneHandle solidscene,
+ class SM_Object* sumoObj,
+ class PHY_IMotionState* motionstate,
+ bool dyna);
+
+ virtual ~SumoPhysicsController();
+
+ // 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;
+
+
+ float getFriction() { return m_friction;}
+ float getRestitution() { return m_restitution;}
+
+ // sumo callback
+ virtual void do_me();
+
+ class SM_Object* GetSumoObject ()
+ {
+ return m_sumoObj;
+ };
+
+ void GetWorldOrientation(class MT_Matrix3x3& mat);
+ void GetWorldPosition(MT_Point3& pos);
+ void GetWorldScaling(MT_Vector3& scale);
+
+
+// void SetSumoObject(class SM_Object* sumoObj) {
+// m_sumoObj = sumoObj;
+// }
+// void SetSumoScene(class SM_Scene* sumoScene) {
+// m_sumoScene = sumoScene;
+// }
+
+ void setSumoTransform(bool nondynaonly);
+
+
+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;
+
+ class PHY_IMotionState* m_MotionState;
+
+};
+
+#endif //__SUMO_PHYSICSCONTROLLER_H
+
+
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp
new file mode 100644
index 00000000000..05b88fcb06b
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp
@@ -0,0 +1,103 @@
+/**
+ * $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 *****
+ */
+#include "SumoPhysicsEnvironment.h"
+#include "PHY_IMotionState.h"
+#include "SumoPhysicsController.h"
+#include "SM_Scene.h"
+
+
+const MT_Scalar UpperBoundForFuzzicsIntegrator = 0.01;
+// At least 100Hz (isn't this CPU hungry ?)
+
+
+SumoPhysicsEnvironment::SumoPhysicsEnvironment()
+{
+ // seperate collision scene for events
+ m_solidScene = DT_CreateScene();
+ m_respTable = DT_CreateRespTable();
+
+ m_sumoScene = new SM_Scene();
+ m_sumoScene->setSecondaryRespTable(m_respTable);
+
+}
+
+
+
+SumoPhysicsEnvironment::~SumoPhysicsEnvironment()
+{
+ delete m_sumoScene;
+
+ DT_DeleteScene(m_solidScene);
+ DT_DeleteRespTable(m_respTable);
+}
+
+void SumoPhysicsEnvironment::proceed(double timeStep)
+{
+ m_sumoScene->proceed(timeStep,UpperBoundForFuzzicsIntegrator);
+}
+
+void SumoPhysicsEnvironment::setGravity(float x,float y,float z)
+{
+ m_sumoScene->setForceField(MT_Vector3(x,y,z));
+
+}
+
+
+
+
+
+int SumoPhysicsEnvironment::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;
+ return constraintid;
+
+}
+
+void SumoPhysicsEnvironment::removeConstraint(int constraintid)
+{
+ if (constraintid)
+ {
+ }
+}
+
+PHY_IPhysicsController* SumoPhysicsEnvironment::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
+ //m_sumoScene->rayTest(ignoreclient,from,to,result,normal);
+
+ return NULL;
+}
+
+
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
new file mode 100644
index 00000000000..0e28b855833
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
@@ -0,0 +1,88 @@
+/**
+ * $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 *****
+ */
+#ifndef _SUMOPhysicsEnvironment
+#define _SUMOPhysicsEnvironment
+
+
+#include "PHY_IPhysicsEnvironment.h"
+
+#include "solid.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 SumoPhysicsEnvironment : public PHY_IPhysicsEnvironment
+{
+
+ class SM_Scene* m_sumoScene;
+
+ DT_SceneHandle m_solidScene;
+ DT_RespTableHandle m_respTable;
+
+public:
+ SumoPhysicsEnvironment();
+ virtual ~SumoPhysicsEnvironment();
+// 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);
+
+
+ // sumo specific
+ SM_Scene* GetSumoScene()
+ {
+ return m_sumoScene;
+ }
+
+ DT_SceneHandle GetSolidScene()
+ {
+ return m_solidScene;
+ }
+
+private:
+
+
+
+
+};
+
+#endif //_SUMOPhysicsEnvironment
+
+
+
diff --git a/source/gameengine/Physics/Sumo/convert.txt b/source/gameengine/Physics/Sumo/convert.txt
new file mode 100644
index 00000000000..81f8f602cde
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/convert.txt
@@ -0,0 +1,35 @@
+static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj)
+{
+ DT_ShapeHandle shape = DT_NewComplexShape();
+ int numpolys = meshobj->NumPolygons();
+ int numvalidpolys = 0;
+
+ for (int p=0; p<numpolys; p++)
+ {
+ RAS_Polygon* poly = meshobj->GetPolygon(p);
+
+ // only add polygons that have the collisionflag set
+ if (poly->IsCollider())
+ {
+ DT_Begin();
+ for (int v=0; v<poly->VertexCount(); v++) {
+ MT_Point3 pt = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
+ poly->GetVertexIndexBase().m_indexarray[v],
+ poly->GetMaterial()->GetPolyMaterial())->xyz();
+ DT_Vertex(pt[0],pt[1],pt[2]);
+ }
+ DT_End();
+
+ numvalidpolys++;
+ }
+ }
+
+ DT_EndComplexShape();
+
+ if (numvalidpolys==0) {
+ delete shape;
+ return NULL;
+ } else {
+ return shape;
+ }
+}
diff --git a/source/gameengine/Physics/Sumo/include/interpolator.h b/source/gameengine/Physics/Sumo/include/interpolator.h
new file mode 100644
index 00000000000..055c242edc7
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/include/interpolator.h
@@ -0,0 +1,27 @@
+#ifndef INTERPOLATOR_H
+#define INTERPOLATOR_H
+
+#include "solid_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DT_DECLARE_HANDLE(IP_IpoHandle);
+
+typedef struct IP_ControlPoint {
+ DT_Scalar m_key;
+ DT_Scalar m_keyValue;
+} IP_ControlPoint;
+
+IP_IpoHandle IP_CreateLinear(const IP_ControlPoint *cpoints, int num_cpoints);
+
+void IP_DeleteInterpolator(IP_IpoHandle ipo);
+
+DT_Scalar IP_GetValue(IP_IpoHandle ipo, DT_Scalar key);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/gameengine/Physics/Sumo/include/solid.h b/source/gameengine/Physics/Sumo/include/solid.h
new file mode 100644
index 00000000000..985014a2a46
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/include/solid.h
@@ -0,0 +1,195 @@
+#ifndef SOLID_H
+#define SOLID_H
+
+#include "solid_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DT_DECLARE_HANDLE(DT_ObjectHandle);
+DT_DECLARE_HANDLE(DT_SceneHandle);
+DT_DECLARE_HANDLE(DT_ShapeHandle);
+DT_DECLARE_HANDLE(DT_RespTableHandle);
+
+typedef enum DT_ScalarType {
+ DT_FLOAT,
+ DT_DOUBLE
+} DT_ScalarType;
+
+typedef enum DT_ResponseType {
+ DT_NO_RESPONSE,
+ DT_SIMPLE_RESPONSE,
+ DT_WITNESSED_RESPONSE,
+ DT_DEPTH_RESPONSE,
+} DT_ResponseType;
+
+typedef struct DT_CollData {
+ DT_Vector3 point1;
+ DT_Vector3 point2;
+ DT_Vector3 normal;
+} DT_CollData;
+
+typedef void (*DT_ResponseCallback)(
+ void *client_data,
+ void *client_object1,
+ void *client_object2,
+ const DT_CollData *coll_data);
+
+/* Shape definition, similar to OpenGL */
+
+extern DT_ShapeHandle DT_Box(DT_Scalar x, DT_Scalar y, DT_Scalar z);
+extern DT_ShapeHandle DT_Cone(DT_Scalar radius, DT_Scalar height);
+extern DT_ShapeHandle DT_Cylinder(DT_Scalar radius, DT_Scalar height);
+extern DT_ShapeHandle DT_Sphere(DT_Scalar radius);
+extern DT_ShapeHandle DT_Ray(DT_Scalar x, DT_Scalar y, DT_Scalar z);
+
+extern DT_ShapeHandle DT_NewComplexShape();
+extern void DT_EndComplexShape();
+
+extern DT_ShapeHandle DT_NewPolyhedron();
+extern void DT_EndPolyhedron();
+
+extern void DT_Begin();
+extern void DT_End();
+
+extern void DT_Vertex(DT_Scalar x, DT_Scalar y, DT_Scalar z);
+
+/* Vertex arrays maintained by the client application can be accessed directly
+ by SUMO. For instance, you have a vertex struct in the client of the form:
+
+ struct Vertex {
+ float xyz[3];
+ float uv[2];
+ float normal[3];
+ };
+
+ And maintain vertex arrays e.g. as
+
+ struct Vertex vertices[328];
+
+ Within a Polyhedron or a ComplexShape you can use this data by specifying
+
+ DT_VertexBase(vertices, DT_FLOAT, sizeof(struct Vertex));
+
+ and refer to vertices in the array using
+
+ DT_VertexIndex(10);
+
+ or
+
+ DT_Index indices[5] = { 6, 4, 8, 1, 3 };
+ DT_VertexIndices(5, indices);
+
+ or even
+
+ DT_VertexRange(8, 4);
+
+ for the range 8, 9, 10, 11.
+*/
+
+
+extern void DT_SetVertexBase(const void *base, DT_ScalarType type,
+ DT_Size stride);
+extern void DT_VertexIndex(DT_Index index);
+extern void DT_VertexIndices(DT_Count count, const DT_Index *indices);
+extern void DT_VertexRange(DT_Index first, DT_Count count);
+
+
+/* currently not implemented */
+extern void DT_ChangeVertexBase(DT_ShapeHandle shape, const void *base);
+
+extern void DT_DeleteShape(DT_ShapeHandle shape);
+
+/* Scene */
+
+extern DT_SceneHandle DT_CreateScene();
+extern void DT_DeleteScene(DT_SceneHandle scene);
+
+extern void DT_AddObject(DT_SceneHandle scene, DT_ObjectHandle object);
+extern void DT_RemoveObject(DT_SceneHandle scene, DT_ObjectHandle object);
+
+
+
+/* Object */
+
+extern DT_ObjectHandle DT_CreateObject(
+ void *client_object, /* pointer to object in client memory */
+ DT_ShapeHandle shape /* the shape or geometry of the object */
+ );
+
+extern void DT_DeleteObject(DT_ObjectHandle object);
+
+extern void DT_SetScaling(DT_ObjectHandle object, const DT_Vector3 scaling);
+extern void DT_SetPosition(DT_ObjectHandle object, const DT_Vector3 position);
+extern void DT_SetOrientation(DT_ObjectHandle object, const DT_Quaternion orientation);
+
+extern void DT_SetMargin(DT_ObjectHandle object, DT_Scalar margin);
+
+extern void DT_SetMatrixf(DT_ObjectHandle object, const float *m);
+extern void DT_GetMatrixf(DT_ObjectHandle object, float *m);
+
+extern void DT_SetMatrixd(DT_ObjectHandle object, const double *m);
+extern void DT_GetMatrixd(DT_ObjectHandle object, double *m);
+
+extern void DT_GetWorldCoord(DT_ObjectHandle object,
+ const DT_Vector3 local,
+ DT_Vector3 world);
+
+extern DT_Scalar DT_GetClosestPair(DT_ObjectHandle object1, DT_ObjectHandle object2,
+ DT_Vector3 point1, DT_Vector3 point2);
+
+
+/* Response, see SOLID user manual */
+
+extern DT_RespTableHandle DT_CreateRespTable();
+extern void DT_DeleteRespTable(DT_RespTableHandle respTable);
+
+extern void DT_CallResponse(DT_RespTableHandle respTable,
+ DT_ObjectHandle object1,
+ DT_ObjectHandle object2,
+ const DT_CollData *coll_data);
+
+extern void DT_SetDefaultResponse(DT_RespTableHandle respTable,
+ DT_ResponseCallback response,
+ DT_ResponseType type,
+ void *client_data);
+
+extern void DT_ClearDefaultResponse(DT_RespTableHandle respTable);
+
+extern void DT_SetObjectResponse(DT_RespTableHandle respTable,
+ DT_ObjectHandle object,
+ DT_ResponseCallback response,
+ DT_ResponseType type, void *client_data);
+extern void DT_ClearObjectResponse(DT_RespTableHandle respTable,
+ DT_ObjectHandle object);
+
+extern void DT_SetPairResponse(DT_RespTableHandle respTable,
+ DT_ObjectHandle object1,
+ DT_ObjectHandle object2,
+ DT_ResponseCallback response,
+ DT_ResponseType type,
+ void *client_data);
+extern void DT_ClearPairResponse(DT_RespTableHandle respTable,
+ DT_ObjectHandle object1,
+ DT_ObjectHandle object2);
+
+
+
+/* Perform a collision test for a given scene, using a response table */
+
+extern DT_Count DT_Test(DT_SceneHandle scene, DT_RespTableHandle respTable);
+
+extern void *DT_RayTest(DT_SceneHandle scene, void *ignore_client,
+ const DT_Vector3 from, const DT_Vector3 to,
+ DT_Vector3 spot, DT_Vector3 normal);
+
+extern int DT_ObjectRayTest(DT_ObjectHandle object,
+ const DT_Vector3 from, const DT_Vector3 to,
+ DT_Vector3 spot, DT_Vector3 normal);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/gameengine/Physics/Sumo/include/solid_broadphase.h b/source/gameengine/Physics/Sumo/include/solid_broadphase.h
new file mode 100644
index 00000000000..d5d05e8a243
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/include/solid_broadphase.h
@@ -0,0 +1,38 @@
+#ifndef SOLID_BROADPHASE_H
+#define SOLID_BROADPHASE_H
+
+#include "solid_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DT_DECLARE_HANDLE(BP_SceneHandle);
+DT_DECLARE_HANDLE(BP_ProxyHandle);
+
+typedef void (*BP_Callback)(void *client_data,
+ void *object1,
+ void *object2);
+
+extern BP_SceneHandle BP_CreateScene(void *client_data,
+ BP_Callback beginOverlap,
+ BP_Callback endOverlap);
+
+extern void BP_DeleteScene(BP_SceneHandle scene);
+
+extern BP_ProxyHandle BP_CreateProxy(BP_SceneHandle scene, void *object,
+ const DT_Vector3 lower,
+ const DT_Vector3 upper);
+
+extern void BP_DeleteProxy(BP_SceneHandle scene,
+ BP_ProxyHandle proxy);
+
+extern void BP_SetBBox(BP_ProxyHandle proxy,
+ const DT_Vector3 lower,
+ const DT_Vector3 upper);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/gameengine/Physics/Sumo/include/solid_types.h b/source/gameengine/Physics/Sumo/include/solid_types.h
new file mode 100644
index 00000000000..537bbcb5826
--- /dev/null
+++ b/source/gameengine/Physics/Sumo/include/solid_types.h
@@ -0,0 +1,14 @@
+#ifndef SOLID_TYPES_H
+#define SOLID_TYPES_H
+
+#define DT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+typedef double DT_Scalar;
+typedef unsigned int DT_Count;
+typedef unsigned int DT_Index;
+typedef unsigned int DT_Size;
+
+typedef DT_Scalar DT_Vector3[3];
+typedef DT_Scalar DT_Quaternion[4];
+
+#endif
diff --git a/source/gameengine/Physics/common/Makefile b/source/gameengine/Physics/common/Makefile
new file mode 100644
index 00000000000..3783d959e14
--- /dev/null
+++ b/source/gameengine/Physics/common/Makefile
@@ -0,0 +1,59 @@
+#
+# $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 = common
+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../../blender
+# these two needed because of blenkernel
+CPPFLAGS += -I../../blender/makesdna
+CPPFLAGS += -I../../blender/include
+CPPFLAGS += -I../../blender/blenlib
+CPPFLAGS += -I../../blender/blenkernel
+CPPFLAGS += -I../../blender/render/extern/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I../Expressions -I../Rasterizer -I../GameLogic -I../SoundSystem
+CPPFLAGS += -I../Ketsji -I../BlenderRoutines -I../SceneGraph
+CPPFLAGS += -I../../kernel/gen_system
+CPPFLAGS += -I../Rasterizer/RAS_OpenGLRasterizer
+CPPFLAGS += -I../Network -I../Ketsji/KXNetwork
+CPPFLAGS += -I../Physics
+CPPFLAGS += -I../Physics/Dummy
diff --git a/source/gameengine/Physics/common/PHY_DynamicTypes.h b/source/gameengine/Physics/common/PHY_DynamicTypes.h
new file mode 100644
index 00000000000..4b10a29e1e7
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_DynamicTypes.h
@@ -0,0 +1,68 @@
+/**
+ * $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 *****
+ */
+#ifndef __PHY_DYNAMIC_TYPES
+#define __PHY_DYNAMIC_TYPES
+
+/// PHY_ScalarType enumerates possible scalar types.
+/// See the PHY_IMeshInterface for its use
+typedef enum PHY_ScalarType {
+ PHY_FLOAT,
+ PHY_DOUBLE,
+ PHY_INTEGER,
+ PHY_SHORT,
+ PHY_FIXEDPOINT88
+} PHY_ScalarType;
+
+/// PHY_PhysicsType enumerates all possible Physics Entities.
+/// It is mainly used to create/add Physics Objects
+
+typedef enum PHY_PhysicsType {
+ PHY_CONVEX_RIGIDBODY=16386,
+ PHY_CONCAVE_RIGIDBODY=16399,
+ PHY_CONVEX_FIXEDBODY=16388,//'collision object'
+ PHY_CONCAVE_FIXEDBODY=16401,
+ PHY_CONVEX_KINEMATICBODY=16387,//
+ PHY_CONCAVE_KINEMATICBODY=16400,
+ PHY_CONVEX_PHANTOMBODY=16398,
+ PHY_CONCAVE_PHANTOMBODY=16402
+} PHY_PhysicsType;
+
+/// PHY_ConstraintType enumerates all supported Constraint Types
+typedef enum PHY_ConstraintType {
+ PHY_POINT2POINT_CONSTRAINT=1,
+ PHY_LINEHINGE_CONSTRAINT,
+
+} PHY_ConstraintType;
+
+typedef float PHY_Vector3[3];
+
+#endif //__PHY_DYNAMIC_TYPES
diff --git a/source/gameengine/Physics/common/PHY_IMotionState.cpp b/source/gameengine/Physics/common/PHY_IMotionState.cpp
new file mode 100644
index 00000000000..106f453424d
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IMotionState.cpp
@@ -0,0 +1,37 @@
+/**
+ * $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 *****
+ */
+#include "PHY_IMotionState.h"
+
+PHY_IMotionState::~PHY_IMotionState()
+{
+
+}
diff --git a/source/gameengine/Physics/common/PHY_IMotionState.h b/source/gameengine/Physics/common/PHY_IMotionState.h
new file mode 100644
index 00000000000..6dd97427b59
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IMotionState.h
@@ -0,0 +1,57 @@
+/**
+ * $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 *****
+ */
+#ifndef PHY__MOTIONSTATE_H
+#define PHY__MOTIONSTATE_H
+
+
+/**
+ PHY_IMotionState is the Interface to explicitly synchronize the world transformation.
+ Default implementations for mayor graphics libraries like OpenGL and DirectX can be provided.
+*/
+class PHY_IMotionState
+
+{
+ public:
+
+ virtual ~PHY_IMotionState();
+
+ virtual void getWorldPosition(float& posX,float& posY,float& posZ)=0;
+ virtual void getWorldScaling(float& scaleX,float& scaleY,float& scaleZ)=0;
+ virtual void getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal)=0;
+
+ virtual void setWorldPosition(float posX,float posY,float posZ)=0;
+ virtual void setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal)=0;
+
+ virtual void calculateWorldTransformations()=0;
+};
+
+#endif //PHY__MOTIONSTATE_H
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.cpp b/source/gameengine/Physics/common/PHY_IPhysicsController.cpp
new file mode 100644
index 00000000000..ec0f7b9df3e
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IPhysicsController.cpp
@@ -0,0 +1,39 @@
+/**
+ * $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 *****
+ */
+#include "PHY_IPhysicsController.h"
+
+
+PHY_IPhysicsController::~PHY_IPhysicsController()
+{
+
+}
+
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h
new file mode 100644
index 00000000000..e8309c0ca40
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h
@@ -0,0 +1,89 @@
+/**
+ * $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 *****
+ */
+#ifndef PHY_IPHYSICSCONTROLLER_H
+#define PHY_IPHYSICSCONTROLLER_H
+
+/**
+ PHY_IPhysicsController is the abstract simplified Interface to a physical object.
+ It contains the IMotionState and IDeformableMesh Interfaces.
+*/
+
+
+class PHY_IPhysicsController
+{
+
+ public:
+
+ virtual ~PHY_IPhysicsController();
+ /**
+ SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
+ */
+ virtual bool SynchronizeMotionStates(float time)=0;
+ /**
+ WriteMotionStateToDynamics ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
+ */
+
+ virtual void WriteMotionStateToDynamics(bool nondynaonly)=0;
+ virtual void WriteDynamicsToMotionState()=0;
+ // controller replication
+ virtual void PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl)=0;
+
+ // kinematic methods
+ virtual void RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local)=0;
+ virtual void RelativeRotate(const float drot[9],bool local)=0;
+ virtual void getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal)=0;
+ virtual void setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal)=0;
+ virtual void setPosition(float posX,float posY,float posZ)=0;
+ virtual void setScaling(float scaleX,float scaleY,float scaleZ)=0;
+
+ // physics methods
+ virtual void ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local)=0;
+ virtual void ApplyForce(float forceX,float forceY,float forceZ,bool local)=0;
+ virtual void SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local)=0;
+ virtual void SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local)=0;
+ virtual void applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ)=0;
+ virtual void SetActive(bool active)=0;
+
+ // reading out information from physics
+ virtual void GetLinearVelocity(float& linvX,float& linvY,float& linvZ)=0;
+ virtual void GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ)=0;
+ virtual void getReactionForce(float& forceX,float& forceY,float& forceZ)=0;
+
+ // dyna's that are rigidbody are free in orientation, dyna's with non-rigidbody are restricted
+ virtual void setRigidBody(bool rigid)=0;
+
+ // clientinfo for raycasts for example
+ virtual void* getClientInfo()=0;
+ virtual void setClientInfo(void* clientinfo)=0;
+};
+
+#endif //PHY_IPHYSICSCONTROLLER_H
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.cpp b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.cpp
new file mode 100644
index 00000000000..7c0660976fb
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.cpp
@@ -0,0 +1,45 @@
+/**
+ * $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 *****
+ */
+
+#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
+*/
+
+
+
+PHY_IPhysicsEnvironment::~PHY_IPhysicsEnvironment()
+{
+
+}
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
new file mode 100644
index 00000000000..5867e27ce42
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
@@ -0,0 +1,60 @@
+/**
+ * $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 *****
+ */
+#ifndef _IPHYSICSENVIRONMENT
+#define _IPHYSICSENVIRONMENT
+
+#include <vector>
+#include "PHY_DynamicTypes.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 PHY_IPhysicsEnvironment
+{
+ public:
+ virtual ~PHY_IPhysicsEnvironment();
+ /// Perform an integration step of duration 'timeStep'.
+ virtual void proceed(double timeStep)=0;
+ virtual void setGravity(float x,float y,float z)=0;
+
+ 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)=0;
+ virtual void removeConstraint(int constraintid)=0;
+
+ 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)=0;
+};
+
+#endif //_IPHYSICSENVIRONMENT
diff --git a/source/gameengine/Physics/common/PHY_Pro.h b/source/gameengine/Physics/common/PHY_Pro.h
new file mode 100644
index 00000000000..58f3badaff6
--- /dev/null
+++ b/source/gameengine/Physics/common/PHY_Pro.h
@@ -0,0 +1,60 @@
+/**
+ * $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 *****
+ */
+#ifndef PHY_PROPSH
+#define PHY_PROPSH
+
+#include <MT_Scalar.h>
+
+// Properties of dynamic objects
+struct PHY_ShapeProps {
+ MT_Scalar m_mass; // Total mass
+ MT_Scalar m_inertia; // Inertia, should be a tensor some time
+ MT_Scalar m_lin_drag; // Linear drag (air, water) 0 = concrete, 1 = vacuum
+ MT_Scalar m_ang_drag; // Angular drag
+ MT_Scalar m_friction_scaling[3]; // Scaling for anisotropic friction. Component in range [0, 1]
+ bool m_do_anisotropic; // Should I do anisotropic friction?
+ bool m_do_fh; // Should the object have a linear Fh spring?
+ bool m_do_rot_fh; // Should the object have an angular Fh spring?
+};
+
+
+// Properties of collidable objects (non-ghost objects)
+struct PHY_MaterialProps {
+ MT_Scalar m_restitution; // restitution of energie after a collision 0 = inelastic, 1 = elastic
+ MT_Scalar m_friction; // Coulomb friction (= ratio between the normal en maximum friction force)
+ MT_Scalar m_fh_spring; // Spring constant (both linear and angular)
+ MT_Scalar m_fh_damping; // Damping factor (linear and angular) in range [0, 1]
+ MT_Scalar m_fh_distance; // The range above the surface where Fh is active.
+ bool m_fh_normal; // Should the object slide off slopes?
+};
+
+#endif //PHY_PROPSH