Browse Source

Exposed missing physics enums to script.
Added collision event mode to RigidBody, which allows to filter out unneeded collision events.

Lasse Öörni 13 years ago
parent
commit
187f179af6

+ 21 - 2
Engine/Engine/PhysicsAPI.cpp

@@ -71,6 +71,16 @@ static PhysicsRaycastResult PhysicsWorldRaycastSingle(const Ray& ray, float maxD
 
 static void RegisterCollisionShape(asIScriptEngine* engine)
 {
+    engine->RegisterEnum("ShapeType");
+    engine->RegisterEnumValue("ShapeType", "SHAPE_BOX", SHAPE_BOX);
+    engine->RegisterEnumValue("ShapeType", "SHAPE_SPHERE", SHAPE_SPHERE);
+    engine->RegisterEnumValue("ShapeType", "SHAPE_CYLINDER", SHAPE_CYLINDER);
+    engine->RegisterEnumValue("ShapeType", "SHAPE_CAPSULE", SHAPE_CAPSULE);
+    engine->RegisterEnumValue("ShapeType", "SHAPE_CONE", SHAPE_CONE);
+    engine->RegisterEnumValue("ShapeType", "SHAPE_TRIANGLEMESH", SHAPE_TRIANGLEMESH);
+    engine->RegisterEnumValue("ShapeType", "SHAPE_CONVEXHULL", SHAPE_CONVEXHULL);
+    engine->RegisterEnumValue("ShapeType", "SHAPE_HEIGHTFIELD", SHAPE_HEIGHTFIELD);
+    
     RegisterComponent<CollisionShape>(engine, "CollisionShape");
     engine->RegisterObjectMethod("CollisionShape", "void SetSphere(float, const Vector3&in pos = Vector3(), const Quaternion&in rot = Quaternion())", asMETHOD(CollisionShape, SetSphere), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "void SetBox(const Vector3&in, const Vector3&in pos = Vector3(), const Quaternion&in rot = Quaternion())", asMETHOD(CollisionShape, SetBox), asCALL_THISCALL);
@@ -82,12 +92,14 @@ static void RegisterCollisionShape(asIScriptEngine* engine)
     engine->RegisterObjectMethod("CollisionShape", "void SetConvexHull(Model@+, uint, float, const Vector3&in scale = Vector3(1, 1, 1), const Vector3&in pos = Vector3(), const Quaternion&in rot = Quaternion())", asMETHOD(CollisionShape, SetConvexHull), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "void SetTransform(const Vector3&in, const Quaternion&in)", asMETHOD(CollisionShape, SetTransform), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "void DrawDebugGeometry(DebugRenderer@+, bool)", asMETHOD(CollisionShape, DrawDebugGeometry), asCALL_THISCALL);
+    engine->RegisterObjectMethod("CollisionShape", "void set_shapeType(ShapeType)", asMETHOD(CollisionShape, SetShapeType), asCALL_THISCALL);
+    engine->RegisterObjectMethod("CollisionShape", "ShapeType get_shapeType() const", asMETHOD(CollisionShape, GetShapeType), asCALL_THISCALL);
+    engine->RegisterObjectMethod("CollisionShape", "void set_size(const Vector3&in)", asMETHOD(CollisionShape, SetSize), asCALL_THISCALL);
+    engine->RegisterObjectMethod("CollisionShape", "const Vector3& get_size() const", asMETHOD(CollisionShape, GetSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "void set_position(const Vector3&in)", asMETHOD(CollisionShape, SetPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "const Vector3& get_position() const", asMETHOD(CollisionShape, GetPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "void set_rotation(const Quaternion&in)", asMETHOD(CollisionShape, SetRotation), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "const Quaternion& get_rotation() const", asMETHOD(CollisionShape, GetRotation), asCALL_THISCALL);
-    engine->RegisterObjectMethod("CollisionShape", "void set_size(const Vector3&in)", asMETHOD(CollisionShape, SetSize), asCALL_THISCALL);
-    engine->RegisterObjectMethod("CollisionShape", "const Vector3& get_size() const", asMETHOD(CollisionShape, GetSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "void set_model(Model@+)", asMETHOD(CollisionShape, SetModel), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "Model@+ get_model() const", asMETHOD(CollisionShape, GetModel), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "void set_lodLevel(uint)", asMETHOD(CollisionShape, SetLodLevel), asCALL_THISCALL);
@@ -105,6 +117,11 @@ static void RegisterCollisionShape(asIScriptEngine* engine)
 
 static void RegisterRigidBody(asIScriptEngine* engine)
 {
+    engine->RegisterEnum("CollisionEventMode");
+    engine->RegisterEnumValue("CollisionEventMode", "COLLISION_NEVER", COLLISION_NEVER);
+    engine->RegisterEnumValue("CollisionEventMode", "COLLISION_ACTIVE", COLLISION_ACTIVE);
+    engine->RegisterEnumValue("CollisionEventMode", "COLLISION_ALWAYS", COLLISION_ALWAYS);
+    
     RegisterComponent<RigidBody>(engine, "RigidBody");
     engine->RegisterObjectMethod("RigidBody", "void SetTransform(const Vector3&in, const Quaternion&in)", asMETHOD(RigidBody, SetTransform), asCALL_THISCALL);
     engine->RegisterObjectMethod("RigidBody", "void SetCollisionLayerAndMask(uint, uint)", asMETHOD(RigidBody, SetCollisionLayerAndMask), asCALL_THISCALL);
@@ -154,6 +171,8 @@ static void RegisterRigidBody(asIScriptEngine* engine)
     engine->RegisterObjectMethod("RigidBody", "uint get_collisionLayer() const", asMETHOD(RigidBody, GetCollisionLayer), asCALL_THISCALL);
     engine->RegisterObjectMethod("RigidBody", "void set_collisionMask(uint)", asMETHOD(RigidBody, SetCollisionMask), asCALL_THISCALL);
     engine->RegisterObjectMethod("RigidBody", "uint get_collisionMask() const", asMETHOD(RigidBody, GetCollisionMask), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RigidBody", "void set_collisionEventMode(CollisionEventMode)", asMETHOD(RigidBody, SetCollisionEventMode), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RigidBody", "CollisionEventMode get_collisionEventMode() const", asMETHOD(RigidBody, GetCollisionEventMode), asCALL_THISCALL);
     
     // Register Variant GetPtr() for RigidBody
     engine->RegisterObjectMethod("Variant", "RigidBody@+ GetRigidBody() const", asFUNCTION(GetVariantPtr<RigidBody>), asCALL_CDECL_OBJLAST);

+ 13 - 14
Engine/Physics/CollisionShape.cpp

@@ -299,10 +299,10 @@ void CollisionShape::RegisterObject(Context* context)
     context->RegisterFactory<CollisionShape>();
     
     ENUM_ATTRIBUTE(CollisionShape, "Shape Type", shapeType_, typeNames, SHAPE_BOX, AM_DEFAULT);
-    ACCESSOR_ATTRIBUTE(CollisionShape, VAR_RESOURCEREF, "Model", GetModelAttr, SetModelAttr, ResourceRef, ResourceRef(Model::GetTypeStatic()), AM_DEFAULT);
+    ATTRIBUTE(CollisionShape, VAR_VECTOR3, "Size", size_, Vector3::ONE, AM_DEFAULT);
     ATTRIBUTE(CollisionShape, VAR_VECTOR3, "Offset Position", position_, Vector3::ZERO, AM_DEFAULT);
     ATTRIBUTE(CollisionShape, VAR_QUATERNION, "Offset Rotation", rotation_, Quaternion::IDENTITY, AM_DEFAULT);
-    ATTRIBUTE(CollisionShape, VAR_VECTOR3, "Size", size_, Vector3::ONE, AM_DEFAULT);
+    ACCESSOR_ATTRIBUTE(CollisionShape, VAR_RESOURCEREF, "Model", GetModelAttr, SetModelAttr, ResourceRef, ResourceRef(Model::GetTypeStatic()), AM_DEFAULT);
     ATTRIBUTE(CollisionShape, VAR_INT, "LOD Level", lodLevel_, 0, AM_DEFAULT);
     ATTRIBUTE(CollisionShape, VAR_FLOAT, "Hull Thickness", thickness_, 0.0f, AM_DEFAULT);
     ATTRIBUTE(CollisionShape, VAR_INT, "Heightfield Points X", numPoints_.x_, 0, AM_DEFAULT);
@@ -322,6 +322,7 @@ void CollisionShape::ApplyAttributes()
     {
         UpdateShape();
         NotifyRigidBody();
+        dirty_ = false;
     }
 }
 
@@ -454,6 +455,16 @@ void CollisionShape::SetShapeType(ShapeType type)
     }
 }
 
+void CollisionShape::SetSize(const Vector3& size)
+{
+    if (size != size_)
+    {
+        size_ = size;
+        UpdateShape();
+        NotifyRigidBody();
+    }
+}
+
 void CollisionShape::SetPosition(const Vector3& position)
 {
     if (position != position_)
@@ -482,16 +493,6 @@ void CollisionShape::SetTransform(const Vector3& position, const Quaternion& rot
     }
 }
 
-void CollisionShape::SetSize(const Vector3& size)
-{
-    if (size != size_)
-    {
-        size_ = size;
-        UpdateShape();
-        NotifyRigidBody();
-    }
-}
-
 void CollisionShape::SetModel(Model* model)
 {
     if (model != model_)
@@ -576,8 +577,6 @@ void CollisionShape::NotifyRigidBody()
         // Finally tell the rigid body to update its mass
         rigidBody_->UpdateMass();
     }
-    
-    dirty_ = false;
 }
 
 void CollisionShape::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)

+ 4 - 4
Engine/Physics/CollisionShape.h

@@ -143,14 +143,14 @@ public:
     void SetConvexHull(Model* model, unsigned lodLevel, float thickness, const Vector3& size = Vector3::ONE, const Vector3& position = Vector3::ZERO, const Quaternion& rotation = Quaternion::IDENTITY);
     /// %Set shape type.
     void SetShapeType(ShapeType type);
+    /// %Set shape size.
+    void SetSize(const Vector3& size);
     /// %Set offset position.
     void SetPosition(const Vector3& position);
     /// %Set offset rotation.
     void SetRotation(const Quaternion& rotation);
     /// %Set offset transform.
     void SetTransform(const Vector3& position, const Quaternion& rotation);
-    /// %Set shape size.
-    void SetSize(const Vector3& size);
     /// %Set triangle mesh / convex hull / heightfield model.
     void SetModel(Model* model);
     /// %Set model LOD level.
@@ -168,12 +168,12 @@ public:
     PhysicsWorld* GetPhysicsWorld() const { return physicsWorld_; }
     /// Return shape type.
     ShapeType GetShapeType() const { return shapeType_; }
+    /// Return shape size.
+    const Vector3& GetSize() const { return size_; }
     /// Return offset position.
     const Vector3& GetPosition() const { return position_; }
     /// Return offset rotation.
     const Quaternion& GetRotation() const { return rotation_; }
-    /// Return shape size
-    const Vector3& GetSize() const { return size_; }
     /// Return triangle mesh / convex hull / heightfield model.
     Model* GetModel() const { return model_; }
     /// Return model LOD level.

+ 2 - 2
Engine/Physics/PhysicsEvents.h

@@ -48,7 +48,7 @@ EVENT(E_PHYSICSCOLLISION, PhysicsCollision)
     PARAM(P_BODYA, BodyA);                  // RigidBody pointer
     PARAM(P_BODYB, BodyB);                  // RigidBody pointer
     PARAM(P_NEWCOLLISION, NewCollision);    // bool
-    PARAM(P_CONTACTS, Contacts);            // Buffer containing position, normal, distance for each contact
+    PARAM(P_CONTACTS, Contacts);            // Buffer containing position (Vector3), normal (Vector3), distance (float), impulse (float) for each contact
 }
 
 /// Physics collision occurred (sent to the participating scene nodes.)
@@ -58,5 +58,5 @@ EVENT(E_NODECOLLISION, NodeCollision)
     PARAM(P_OTHERNODE, OtherNode);          // Node pointer
     PARAM(P_OTHERBODY, OtherBody);          // RigidBody pointer
     PARAM(P_NEWCOLLISION, NewCollision);    // bool
-    PARAM(P_CONTACTS, Contacts);            // Buffer containing position, normal, distance for each contact
+    PARAM(P_CONTACTS, Contacts);            // Buffer containing position (Vector3), normal (Vector3), distance (float), impulse (float) for each contact
 }

+ 11 - 4
Engine/Physics/PhysicsWorld.cpp

@@ -370,9 +370,14 @@ void PhysicsWorld::SendCollisionEvents()
             RigidBody* bodyA = static_cast<RigidBody*>(objectA->getUserPointer());
             RigidBody* bodyB = static_cast<RigidBody*>(objectB->getUserPointer());
             
-            // Skip collision if both objects are static or inactive
-            if ((bodyA->GetMass() == 0.0f && bodyB->GetMass() == 0.0f) || (!bodyA->IsActive() && !bodyB->IsActive()))
+            // Skip collision event signaling if both objects are static, or if collision event mode does not match
+            if (bodyA->GetMass() == 0.0f && bodyB->GetMass() == 0.0f)
                 continue;
+            if (bodyA->GetCollisionEventMode() == COLLISION_NEVER || bodyB->GetCollisionEventMode() == COLLISION_NEVER)
+                return;
+            if (bodyA->GetCollisionEventMode() == COLLISION_ACTIVE && bodyB->GetCollisionEventMode() == COLLISION_ACTIVE &&
+                !bodyA->IsActive() && !bodyB->IsActive())
+                return;
             
             Node* nodeA = bodyA->GetNode();
             Node* nodeB = bodyB->GetNode();
@@ -401,7 +406,8 @@ void PhysicsWorld::SendCollisionEvents()
                 btManifoldPoint& point = contactManifold->getContactPoint(j);
                 contacts.WriteVector3(ToVector3(point.m_positionWorldOnB));
                 contacts.WriteVector3(ToVector3(point.m_normalWorldOnB));
-                contacts.WriteFloat(point.getDistance());
+                contacts.WriteFloat(point.m_distance1);
+                contacts.WriteFloat(point.m_appliedImpulse);
             }
             
             physicsCollisionData[PhysicsCollision::P_CONTACTS] = contacts.GetBuffer();
@@ -430,7 +436,8 @@ void PhysicsWorld::SendCollisionEvents()
                 btManifoldPoint& point = contactManifold->getContactPoint(j);
                 contacts.WriteVector3(ToVector3(point.m_positionWorldOnB));
                 contacts.WriteVector3(-ToVector3(point.m_normalWorldOnB));
-                contacts.WriteFloat(point.getDistance());
+                contacts.WriteFloat(point.m_distance1);
+                contacts.WriteFloat(point.m_appliedImpulse);
             }
             
             nodeCollisionData[NodeCollision::P_BODY] = (void*)bodyB;

+ 19 - 10
Engine/Physics/RigidBody.cpp

@@ -44,7 +44,16 @@ static const float DEFAULT_FRICTION = 0.5f;
 static const float DEFAULT_RESTITUTION = 0.0f;
 static const float DEFAULT_LINEAR_REST_THRESHOLD = 0.8f;
 static const float DEFAULT_ANGULAR_REST_THRESHOLD = 1.0f;
-static const unsigned DEFAULT_COLLISION_LAYER = 0xffff;
+static const unsigned DEFAULT_COLLISION_LAYER = 0x1;
+static const unsigned DEFAULT_COLLISION_MASK = M_MAX_UNSIGNED;
+
+static const String collisionEventModeNames[] = 
+{
+    "Never",
+    "When Active",
+    "Always",
+    ""
+};
 
 OBJECTTYPESTATIC(RigidBody);
 
@@ -54,7 +63,8 @@ RigidBody::RigidBody(Context* context) :
     compoundShape_(0),
     mass_(DEFAULT_MASS),
     collisionLayer_(DEFAULT_COLLISION_LAYER),
-    collisionMask_(DEFAULT_COLLISION_LAYER),
+    collisionMask_(DEFAULT_COLLISION_MASK),
+    collisionEventMode_(COLLISION_ACTIVE),
     inSetTransform_(false)
 {
     compoundShape_ = new btCompoundShape();
@@ -89,8 +99,9 @@ void RigidBody::RegisterObject(Context* context)
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Linear Rest Threshold", GetLinearRestThreshold, SetLinearRestThreshold, float, 0.01f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Angular Rest Threshold", GetAngularRestThreshold, SetAngularRestThreshold, float, 0.01f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_INT, "Collision Layer", GetCollisionLayer, SetCollisionLayer, unsigned, DEFAULT_COLLISION_LAYER, AM_DEFAULT);
-    ACCESSOR_ATTRIBUTE(RigidBody, VAR_INT, "Collision Mask", GetCollisionMask, SetCollisionMask, unsigned, DEFAULT_COLLISION_LAYER, AM_DEFAULT);
+    ACCESSOR_ATTRIBUTE(RigidBody, VAR_INT, "Collision Mask", GetCollisionMask, SetCollisionMask, unsigned, DEFAULT_COLLISION_MASK, AM_DEFAULT);
     REF_ACCESSOR_ATTRIBUTE(RigidBody, VAR_BUFFER, "Network Angular Velocity", GetNetAngularVelocityAttr, SetNetAngularVelocityAttr, PODVector<unsigned char>, PODVector<unsigned char>(), AM_NET | AM_LATESTDATA | AM_NOEDIT);
+    ENUM_ATTRIBUTE(RigidBody, "Collision Event Mode", collisionEventMode_, collisionEventModeNames, COLLISION_ACTIVE, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_BOOL, "Use Gravity", GetUseGravity, SetUseGravity, bool, true, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_BOOL, "Is Kinematic", IsKinematic, SetKinematic, bool, false, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_BOOL, "Is Phantom", IsPhantom, SetPhantom, bool, false, AM_DEFAULT);
@@ -300,8 +311,6 @@ void RigidBody::SetPhantom(bool enable)
 
 void RigidBody::SetCollisionLayer(unsigned layer)
 {
-    layer &= 0xffff;
-    
     if (layer != collisionLayer_)
     {
         collisionLayer_ = layer;
@@ -311,8 +320,6 @@ void RigidBody::SetCollisionLayer(unsigned layer)
 
 void RigidBody::SetCollisionMask(unsigned mask)
 {
-    mask &= 0xffff;
-    
     if (mask != collisionMask_)
     {
         collisionMask_ = mask;
@@ -322,9 +329,6 @@ void RigidBody::SetCollisionMask(unsigned mask)
 
 void RigidBody::SetCollisionLayerAndMask(unsigned layer, unsigned mask)
 {
-    layer &= 0xffff;
-    mask &= 0xffff;
-    
     if (layer != collisionLayer_ || mask != collisionMask_)
     {
         collisionLayer_ = layer;
@@ -333,6 +337,11 @@ void RigidBody::SetCollisionLayerAndMask(unsigned layer, unsigned mask)
     }
 }
 
+void RigidBody::SetCollisionEventMode(CollisionEventMode mode)
+{
+    collisionEventMode_ = mode;
+}
+
 void RigidBody::ApplyForce(const Vector3& force)
 {
     if (body_ && force != Vector3::ZERO)

+ 16 - 6
Engine/Physics/RigidBody.h

@@ -34,6 +34,14 @@ class PhysicsWorld;
 class btCompoundShape;
 class btRigidBody;
 
+/// Rigid body collision event signaling mode.
+enum CollisionEventMode
+{
+    COLLISION_NEVER = 0,
+    COLLISION_ACTIVE,
+    COLLISION_ALWAYS
+};
+
 /// Physics rigid body component.
 class RigidBody : public Component, public btMotionState
 {
@@ -94,6 +102,8 @@ public:
     void SetCollisionMask(unsigned mask);
     /// %Set collision group and mask.
     void SetCollisionLayerAndMask(unsigned layer, unsigned mask);
+    /// %Set collision event signaling mode. Default is to signal when active.
+    void SetCollisionEventMode(CollisionEventMode mode);
     /// Apply force to center of mass.
     void ApplyForce(const Vector3& force);
     /// Apply force at position.
@@ -153,6 +163,8 @@ public:
     unsigned GetCollisionLayer() const { return collisionLayer_; }
     /// Return collision mask.
     unsigned GetCollisionMask() const { return collisionMask_; }
+    /// Return collision event signaling mode.
+    CollisionEventMode GetCollisionEventMode() const { return collisionEventMode_; }
     
     /// Return physics world.
     PhysicsWorld* GetPhysicsWorld() const { return physicsWorld_; }
@@ -190,16 +202,14 @@ private:
     WeakPtr<PhysicsWorld> physicsWorld_;
     /// Mass.
     float mass_;
-    /// Last interpolated position set during PostStep.
-    Vector3 lastInterpolatedPosition_;
-    /// Last interpolated rotation set during PostStep.
-    Quaternion lastInterpolatedRotation_;
     /// Attribute buffer for network replication.
     mutable VectorBuffer attrBuffer_;
-    /// Whether is in Bullet's transform update. Node dirtying is ignored at this point to prevent endless recursion.
-    bool inSetTransform_;
     /// Collision layer.
     unsigned collisionLayer_;
     /// Collision mask.
     unsigned collisionMask_;
+    /// Collision event signaling mode.
+    CollisionEventMode collisionEventMode_;
+    /// Whether is in Bullet's transform update. Node dirtying is ignored at this point to prevent endless recursion.
+    bool inSetTransform_;
 };