From 4e2f7baff2ef86a6104f9cb17ea09088875454c5 Mon Sep 17 00:00:00 2001 From: Kester Maddock Date: Fri, 16 Apr 2004 06:26:33 +0000 Subject: [PATCH] Improved rigid body handling for non spherical bounds type. Polyheder dynamic objects are now converted properly. --- .../Converter/BL_BlenderDataConversion.cpp | 7 +++- .../Ketsji/KX_ConvertPhysicsObjects.cpp | 25 +++++++++++--- .../Sumo/Fuzzics/include/SM_MotionState.h | 10 +++--- .../Physics/Sumo/Fuzzics/src/SM_Object.cpp | 34 ++++++------------- 4 files changed, 42 insertions(+), 34 deletions(-) diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index ac66bfba4b8..6f58198c75f 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -496,7 +496,7 @@ static PHY_ShapeProps *CreateShapePropsFromBlenderObject(struct Object* blendero // in Blender, inertia stands for the size value which is equivalent to // the sphere radius - shapeProps->m_inertia = blenderobject->formfactor * blenderobject->mass * blenderobject->inertia * blenderobject->inertia; + shapeProps->m_inertia = blenderobject->formfactor; assert(0.0f <= blenderobject->damping && blenderobject->damping <= 1.0f); assert(0.0f <= blenderobject->rdamping && blenderobject->rdamping <= 1.0f); @@ -734,6 +734,11 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, objprop.m_boundobject.c.m_height = 2.f*bb.m_extends[2]; break; } + case OB_BOUND_POLYH: + { + objprop.m_boundclass = KX_BOUNDMESH; + break; + } } } diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 11a97d680bb..dd886dcf322 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -130,27 +130,42 @@ void KX_ConvertSumoObject( KX_GameObject* gameobj, switch (objprop->m_boundclass) { case KX_BOUNDBOX: - shape = DT_NewBox(objprop->m_boundobject.box.m_extends[0], objprop->m_boundobject.box.m_extends[1], objprop->m_boundobject.box.m_extends[2]); - smprop->m_inertia.scale(objprop->m_boundobject.box.m_extends[0], objprop->m_boundobject.box.m_extends[1], objprop->m_boundobject.box.m_extends[2]); - smprop->m_inertia /= (objprop->m_boundobject.box.m_extends[0] + objprop->m_boundobject.box.m_extends[1] + objprop->m_boundobject.box.m_extends[2]) / 3.; + shape = DT_NewBox(objprop->m_boundobject.box.m_extends[0], + objprop->m_boundobject.box.m_extends[1], + objprop->m_boundobject.box.m_extends[2]); + smprop->m_inertia.scale(objprop->m_boundobject.box.m_extends[0]*objprop->m_boundobject.box.m_extends[0], + objprop->m_boundobject.box.m_extends[1]*objprop->m_boundobject.box.m_extends[1], + objprop->m_boundobject.box.m_extends[2]*objprop->m_boundobject.box.m_extends[2]); + smprop->m_inertia *= smprop->m_mass/MT_Vector3(objprop->m_boundobject.box.m_extends).length(); break; case KX_BOUNDCYLINDER: - shape = DT_NewCylinder(objprop->m_radius, objprop->m_boundobject.c.m_height); + shape = DT_NewCylinder(smprop->m_radius, objprop->m_boundobject.c.m_height); + smprop->m_inertia.scale(smprop->m_mass*smprop->m_radius*smprop->m_radius, + smprop->m_mass*smprop->m_radius*smprop->m_radius, + smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height); break; case KX_BOUNDCONE: shape = DT_NewCone(objprop->m_radius, objprop->m_boundobject.c.m_height); + smprop->m_inertia.scale(smprop->m_mass*smprop->m_radius*smprop->m_radius, + smprop->m_mass*smprop->m_radius*smprop->m_radius, + smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height); break; -/* Enabling this allows you to use dynamic mesh objects. It's disabled 'cause it's really slow. */ + /* Dynamic mesh objects. WARNING! slow. */ case KX_BOUNDMESH: if (meshobj && meshobj->NumPolygons() > 0) { if ((shape = CreateShapeFromMesh(meshobj))) + { + // TODO: calculate proper inertia + smprop->m_inertia *= smprop->m_mass*smprop->m_radius*smprop->m_radius; break; + } } /* If CreateShapeFromMesh fails, fall through and use sphere */ default: case KX_BOUNDSPHERE: shape = DT_NewSphere(objprop->m_radius); + smprop->m_inertia *= smprop->m_mass*smprop->m_radius*smprop->m_radius; break; } diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h index 92cecbdebaa..e7fbf3cdacc 100644 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h +++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h @@ -14,14 +14,14 @@ public: 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 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; } - + 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); } diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp index d0d52934768..f6b0f50219e 100644 --- a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp +++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp @@ -51,7 +51,7 @@ // Tweak parameters -static const MT_Scalar ImpulseThreshold = 0.5; +static const MT_Scalar ImpulseThreshold = -10.; static const MT_Scalar FixThreshold = 0.01; static const MT_Scalar FixVelocity = 0.01; SM_Object::SM_Object( @@ -177,27 +177,22 @@ void SM_Object::dynamicCollision(const MT_Point3 &local2, MT_Scalar invMass ) { - // Same again but now obj1 is non-dynamic - // Compute the point on obj1 closest to obj2 (= sphere with radius = 0) - // local1 is th point closest to obj2 - // local2 is the local origin of obj2 - // This should look familiar.... MT_Scalar rel_vel_normal = normal.dot(rel_vel); - if (rel_vel_normal <= 0.0) { - if (-rel_vel_normal < ImpulseThreshold) { - restitution = 0.0; - } + if (rel_vel_normal < -MT_EPSILON) { + restitution *= MT_min(MT_Scalar(1.0), rel_vel_normal/ImpulseThreshold); MT_Scalar impulse = -(1.0 + restitution) * rel_vel_normal; if (isRigidBody()) { - MT_Vector3 temp = getInvInertiaTensor() * local2.cross(normal); - applyImpulse(local2 + m_pos, (impulse / (invMass + normal.dot(temp.cross(local2)))) * normal); + MT_Vector3 temp = getInvInertiaTensor() * local2.cross(normal); + impulse /= invMass + normal.dot(temp.cross(local2)); + applyImpulse(local2 + m_pos, impulse * normal); } else { - applyCenterImpulse( ( impulse / invMass ) * normal ); + impulse /= invMass; + applyCenterImpulse( impulse * normal ); } // The friction part starts here!!!!!!!! @@ -361,15 +356,8 @@ DT_Bool SM_Object::boing( local1 -= obj1->m_pos, local2 -= obj2->m_pos; // Calculate collision parameters - MT_Vector3 rel_vel = obj1->getVelocity(local1) + obj1->m_combined_lin_vel - - obj2->getVelocity(local2) - obj2->m_combined_lin_vel; + MT_Vector3 rel_vel = obj1->getVelocity(local1) - obj2->getVelocity(local2); - if (obj1->isRigidBody()) - rel_vel += obj1->actualAngVelocity().cross(local1); - - if (obj2->isRigidBody()) - rel_vel -= obj2->actualAngVelocity().cross(local2); - MT_Scalar restitution = MT_min(obj1->getMaterialProps()->m_restitution, obj2->getMaterialProps()->m_restitution); @@ -1013,9 +1001,9 @@ getVelocity( */ return m_prev_kinematic && !isDynamic() ? (m_xform(local) - m_prev_xform(local)) / m_timeStep : - m_lin_vel + m_ang_vel.cross(local); + actualLinVelocity() + actualAngVelocity().cross(local); - // m_lin_vel + m_ang_vel.cross(m_xform.getBasis() * local); + //m_lin_vel + m_ang_vel.cross(m_xform.getBasis() * local); // NB: m_xform.getBasis() * local == m_xform(local) - m_xform.getOrigin() }