ソースを参照

Removed CCD Radius parameter for now as continuous collision detection is not supported for all collision shapes.
Changed the way RigidBody attributes are applied to reduce unnecessary re-adding of the body to the simulation world during deserialization.

Lasse Öörni 13 年 前
コミット
51c9160eae

+ 0 - 1
Bin/Data/Objects/Ninja.xml

@@ -43,7 +43,6 @@
 		<attribute name="Angular Damping" value="0" />
 		<attribute name="Linear Rest Threshold" value="0.8" />
 		<attribute name="Angular Rest Threshold" value="1" />
-		<attribute name="CCD Radius" value="35" />
 		<attribute name="Collision Layer" value="1" />
 		<attribute name="Collision Mask" value="3" />
 		<attribute name="Collision Event Mode" value="Always" />

+ 0 - 1
Bin/Data/Objects/Potion.xml

@@ -60,7 +60,6 @@
 		<attribute name="Angular Damping" value="0" />
 		<attribute name="Linear Rest Threshold" value="0.8" />
 		<attribute name="Angular Rest Threshold" value="1" />
-		<attribute name="CCD Radius" value="10" />
 		<attribute name="Collision Layer" value="1" />
 		<attribute name="Collision Mask" value="3" />
 		<attribute name="Collision Event Mode" value="When Active" />

+ 0 - 1
Bin/Data/Objects/SnowBall.xml

@@ -60,7 +60,6 @@
 		<attribute name="Angular Damping" value="0" />
 		<attribute name="Linear Rest Threshold" value="0.8" />
 		<attribute name="Angular Rest Threshold" value="1" />
-		<attribute name="CCD Radius" value="7" />
 		<attribute name="Collision Layer" value="1" />
 		<attribute name="Collision Mask" value="3" />
 		<attribute name="Collision Event Mode" value="When Active" />

+ 0 - 1
Bin/Data/Objects/SnowCrate.xml

@@ -60,7 +60,6 @@
 		<attribute name="Angular Damping" value="0" />
 		<attribute name="Linear Rest Threshold" value="0.8" />
 		<attribute name="Angular Rest Threshold" value="1" />
-		<attribute name="CCD Radius" value="40" />
 		<attribute name="Collision Layer" value="2" />
 		<attribute name="Collision Mask" value="3" />
 		<attribute name="Collision Event Mode" value="When Active" />

+ 0 - 1
Bin/Data/Scenes/NinjaSnowWar.xml

@@ -131,7 +131,6 @@
 			<attribute name="Angular Damping" value="0" />
 			<attribute name="Linear Rest Threshold" value="0.8" />
 			<attribute name="Angular Rest Threshold" value="1" />
-			<attribute name="CCD Radius" value="0" />
 			<attribute name="Collision Layer" value="2" />
 			<attribute name="Collision Mask" value="3" />
 			<attribute name="Collision Event Mode" value="When Active" />

+ 0 - 2
Docs/Reference.dox

@@ -833,8 +833,6 @@ RigidBodies can be either static or moving. A body is static if its mass is 0, a
 
 The collision behaviour of a rigid body is controlled by several variables. First, the collision layer and mask define which other objects to collide with: see \ref RigidBody::SetCollisionLayer "SetCollisionLayer()" and \ref RigidBody::SetCollisionMask "SetCollisionMask()". By default a rigid body is on layer 1; the layer will be ANDed with the other body's collision mask to see if the collision should be reported. A rigid body can also be set to \ref RigidBody::SetPhantom "phantom mode" to only report collisions without actually applying collision forces. Finally, the \ref RigidBody::SetFriction "friction" and \ref RigidBody::SetRestitution "restitution" coefficients (between 0 - 1) control how kinetic energy is transferred in the collisions.
 
-For continuous collision detection of fast moving bodies, the Bullet library approximates them as swept spheres; use \ref RigidBody::SetCcdRadius "SetCcdRadius()" to control the size. The swept sphere should not be larger than the collision geometries attached to the rigid body. By default the radius is 0.
-
 By default rigid bodies can move and rotate about all 3 coordinate axes when forces are applied. To limit the movement, use \ref RigidBody::SetLinearFactor "SetLinearFactor()" and \ref RigidBody::SetAngularFactor "SetAngularFactor()" and set the axes you wish to use to 1 and those you do not wish to use to 0. For example moving humanoid characters are often represented by a capsule shape: to ensure they stay upright and only rotate when you explicitly set the rotation in code, set the angular factor to 0, 0, 0.
 
 The physics simulation does all calculations in world space. Nodes containing a RigidBody component should be parented to the Scene (root node) to ensure correct operation.

+ 0 - 2
Engine/Engine/PhysicsAPI.cpp

@@ -161,8 +161,6 @@ static void RegisterRigidBody(asIScriptEngine* engine)
     engine->RegisterObjectMethod("RigidBody", "void set_kinematic(bool)", asMETHOD(RigidBody, SetKinematic), asCALL_THISCALL);
     engine->RegisterObjectMethod("RigidBody", "bool get_kinematic() const", asMETHOD(RigidBody, IsKinematic), asCALL_THISCALL);
     engine->RegisterObjectMethod("RigidBody", "bool get_active() const", asMETHOD(RigidBody, IsActive), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RigidBody", "void set_ccdRadius(float)", asMETHOD(RigidBody, SetCcdRadius), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RigidBody", "float get_ccdRadius() const", asMETHOD(RigidBody, GetCcdRadius), asCALL_THISCALL);
     engine->RegisterObjectMethod("RigidBody", "void set_collisionLayer(uint)", asMETHOD(RigidBody, SetCollisionLayer), asCALL_THISCALL);
     engine->RegisterObjectMethod("RigidBody", "uint get_collisionLayer() const", asMETHOD(RigidBody, GetCollisionLayer), asCALL_THISCALL);
     engine->RegisterObjectMethod("RigidBody", "void set_collisionMask(uint)", asMETHOD(RigidBody, SetCollisionMask), asCALL_THISCALL);

+ 0 - 1
Engine/Physics/PhysicsWorld.cpp

@@ -89,7 +89,6 @@ PhysicsWorld::PhysicsWorld(Context* context) :
     world_->setDebugDrawer(this);
     world_->setInternalTickCallback(InternalPreTickCallback, static_cast<void*>(this), true);
     world_->setInternalTickCallback(InternalTickCallback, static_cast<void*>(this), false);
-    world_->getDispatchInfo().m_useContinuous = true;
 }
 
 PhysicsWorld::~PhysicsWorld()

+ 53 - 63
Engine/Physics/RigidBody.cpp

@@ -69,8 +69,11 @@ RigidBody::RigidBody(Context* context) :
     collisionEventMode_(COLLISION_ACTIVE),
     lastPosition_(Vector3::ZERO),
     lastRotation_(Quaternion::IDENTITY),
+    kinematic_(false),
+    phantom_(false),
     inSetTransform_(false),
-    hasSmoothedTransform_(false)
+    hasSmoothedTransform_(false),
+    dirty_(false)
 {
     compoundShape_ = new btCompoundShape();
 }
@@ -92,7 +95,7 @@ void RigidBody::RegisterObject(Context* context)
     
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_VECTOR3, "Physics Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_FILE | AM_NOEDIT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_QUATERNION, "Physics Rotation", GetRotation, SetRotation, Quaternion, Quaternion::IDENTITY, AM_FILE | AM_NOEDIT);
-    ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Mass", GetMass, SetMass, float, DEFAULT_MASS, AM_DEFAULT);
+    ATTRIBUTE(RigidBody, VAR_FLOAT, "Mass", mass_, DEFAULT_MASS, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Friction", GetFriction, SetFriction, float, DEFAULT_FRICTION, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Restitution", GetRestitution, SetRestitution, float, DEFAULT_RESTITUTION, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_VECTOR3, "Linear Velocity", GetLinearVelocity, SetLinearVelocity, Vector3, Vector3::ZERO, AM_DEFAULT | AM_LATESTDATA);
@@ -103,14 +106,28 @@ void RigidBody::RegisterObject(Context* context)
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Angular Damping", GetAngularDamping, SetAngularDamping, float, 0.01f, AM_DEFAULT);
     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_FLOAT, "CCD Radius", GetCcdRadius, SetCcdRadius, float, 0.0f, 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_MASK, AM_DEFAULT);
+    ATTRIBUTE(RigidBody, VAR_INT, "Collision Layer", collisionLayer_, DEFAULT_COLLISION_LAYER, AM_DEFAULT);
+    ATTRIBUTE(RigidBody, VAR_INT, "Collision Mask", collisionMask_, 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);
+    ATTRIBUTE(RigidBody, VAR_BOOL, "Is Kinematic", kinematic_, false, AM_DEFAULT);
+    ATTRIBUTE(RigidBody, VAR_BOOL, "Is Phantom", phantom_, false, AM_DEFAULT);
+}
+
+void RigidBody::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
+{
+    Serializable::OnSetAttribute(attr, src);
+    dirty_ = true;
+}
+
+void RigidBody::ApplyAttributes()
+{
+    if (dirty_)
+    {
+        AddBodyToWorld();
+        dirty_ = false;
+    }
 }
 
 void RigidBody::getWorldTransform(btTransform &worldTrans) const
@@ -154,14 +171,6 @@ void RigidBody::SetMass(float mass)
     {
         mass_ = mass;
         AddBodyToWorld();
-        
-        if (mass > 0.0f)
-            Activate();
-        else
-        {
-            SetLinearVelocity(Vector3::ZERO);
-            SetAngularVelocity(Vector3::ZERO);
-        }
     }
 }
 
@@ -279,7 +288,7 @@ void RigidBody::SetRestitution(float restitution)
 
 void RigidBody::SetUseGravity(bool enable)
 {
-    if (physicsWorld_ && body_)
+    if (physicsWorld_ && body_ && enable != GetUseGravity())
     {
         btDiscreteDynamicsWorld* world = physicsWorld_->GetWorld();
         
@@ -299,41 +308,22 @@ void RigidBody::SetUseGravity(bool enable)
 
 void RigidBody::SetKinematic(bool enable)
 {
-    if (body_)
+    if (enable != kinematic_)
     {
-        int flags = body_->getCollisionFlags();
-        if (enable)
-            flags |= btCollisionObject::CF_KINEMATIC_OBJECT;
-        else
-            flags &= ~btCollisionObject::CF_KINEMATIC_OBJECT;
-        body_->setCollisionFlags(flags),
-        
+        kinematic_ = enable;
         AddBodyToWorld();
     }
 }
 
 void RigidBody::SetPhantom(bool enable)
 {
-    if (body_)
+    if (enable != phantom_)
     {
-        int flags = body_->getCollisionFlags();
-        if (enable)
-            flags |= btCollisionObject::CF_NO_CONTACT_RESPONSE;
-        else
-            flags &= ~btCollisionObject::CF_NO_CONTACT_RESPONSE;
-        body_->setCollisionFlags(flags);
-        
+        phantom_ = enable;
         AddBodyToWorld();
     }
 }
 
-void RigidBody::SetCcdRadius(float radius)
-{
-    radius = Max(radius, 0.0f);
-    if (body_)
-        body_->setCcdSweptSphereRadius(radius);
-}
-
 void RigidBody::SetCollisionLayer(unsigned layer)
 {
     if (layer != collisionLayer_)
@@ -537,22 +527,6 @@ bool RigidBody::GetUseGravity() const
         return true;
 }
 
-bool RigidBody::IsKinematic() const
-{
-    if (body_)
-        return (body_->getCollisionFlags() & btCollisionObject::CF_KINEMATIC_OBJECT) != 0;
-    else
-        return false;
-}
-
-bool RigidBody::IsPhantom() const
-{
-    if (body_)
-        return (body_->getCollisionFlags() & btCollisionObject::CF_NO_CONTACT_RESPONSE) != 0;
-    else
-        return false;
-}
-
 bool RigidBody::IsActive() const
 {
     if (body_)
@@ -561,14 +535,6 @@ bool RigidBody::IsActive() const
         return false;
 }
 
-float RigidBody::GetCcdRadius() const
-{
-    if (body_)
-        return body_->getCcdSweptSphereRadius();
-    else
-        return 0.0f;
-}
-
 void RigidBody::ApplyWorldTransform(const Vector3& newWorldPosition, const Quaternion& newWorldRotation)
 {
     inSetTransform_ = true;
@@ -693,6 +659,11 @@ void RigidBody::AddBodyToWorld()
     if (!physicsWorld_)
         return;
     
+    PROFILE(AddBodyToWorld);
+    
+    if (mass_ < 0.0f)
+        mass_ = 0.0f;
+    
     bool massUpdated = false;
     
     btDiscreteDynamicsWorld* world = physicsWorld_->GetWorld();
@@ -729,7 +700,26 @@ void RigidBody::AddBodyToWorld()
     if (!massUpdated)
         UpdateMass();
     
+    int flags = body_->getCollisionFlags();
+    if (phantom_)
+        flags |= btCollisionObject::CF_NO_CONTACT_RESPONSE;
+    else
+        flags &= ~btCollisionObject::CF_NO_CONTACT_RESPONSE;
+    if (kinematic_)
+        flags |= btCollisionObject::CF_KINEMATIC_OBJECT;
+    else
+        flags &= ~btCollisionObject::CF_KINEMATIC_OBJECT;
+    body_->setCollisionFlags(flags);
+    
     world->addRigidBody(body_, collisionLayer_, collisionMask_);
+    
+    if (mass_ > 0.0f)
+        Activate();
+    else
+    {
+        SetLinearVelocity(Vector3::ZERO);
+        SetAngularVelocity(Vector3::ZERO);
+    }
 }
 
 void RigidBody::ReleaseBody()

+ 12 - 6
Engine/Physics/RigidBody.h

@@ -58,6 +58,10 @@ public:
     /// Register object factory.
     static void RegisterObject(Context* context);
     
+    /// Handle attribute write access.
+    virtual void OnSetAttribute(const AttributeInfo& attr, const Variant& src);
+    /// Apply attribute changes that can not be applied immediately. Called after scene load or a network update.
+    virtual void ApplyAttributes();
     /// Return initial world transform to Bullet.
     virtual void getWorldTransform(btTransform &worldTrans) const;
     /// Update world transform from Bullet.
@@ -97,8 +101,6 @@ public:
     void SetKinematic(bool enable);
     /// %Set rigid body phantom mode. In phantom mode collisions are reported but do not apply forces.
     void SetPhantom(bool enable);
-    /// %Set continuous collision detection radius.
-    void SetCcdRadius(float radius);
     /// %Set collision layer.
     void SetCollisionLayer(unsigned layer);
     /// %Set collision mask.
@@ -163,13 +165,11 @@ public:
     /// Return whether rigid body uses gravity.
     bool GetUseGravity() const;
     /// Return kinematic mode flag.
-    bool IsKinematic() const;
+    bool IsKinematic() const { return kinematic_; }
     /// Return phantom mode flag.
-    bool IsPhantom() const;
+    bool IsPhantom() const { return phantom_; }
     /// Return whether rigid body is active.
     bool IsActive() const;
-    /// Return continuous collision detection radius.
-    float GetCcdRadius() const;
     /// Return collision layer.
     unsigned GetCollisionLayer() const { return collisionLayer_; }
     /// Return collision mask.
@@ -224,8 +224,14 @@ private:
     mutable Vector3 lastPosition_;
     /// Last interpolated rotation from the simulation.
     mutable Quaternion lastRotation_;
+    /// Kinematic flag.
+    bool kinematic_;
+    /// Phantom flag.
+    bool phantom_;
     /// Whether is in Bullet's transform update. Node dirtying is ignored at this point to prevent endless recursion.
     bool inSetTransform_;
     /// Smoothed transform mode.
     bool hasSmoothedTransform_;
+    /// Dirty flag.
+    bool dirty_;
 };