Bläddra i källkod

Added constraint & collision shape type "none" as default value to avoid unnecessary creation of shapes on scene load, before proper attribute values are deserialized. Do not create shape/constraint in OnNodeSet(), as the type is always "none" at that time.
Reactivate a rigid body when any constraint is removed from it.

Lasse Öörni 13 år sedan
förälder
incheckning
9d82a32c9e

+ 3 - 1
Docs/ScriptAPI.dox

@@ -4753,8 +4753,9 @@ Methods:<br>
 - void Remove()
 - void MarkNetworkUpdate() const
 - void DrawDebugGeometry(DebugRenderer@, bool)
-- void SetSphere(float, const Vector3& arg1 = Vector3 ( ), const Quaternion& arg2 = Quaternion ( ))
+- void Clear()
 - void SetBox(const Vector3&, const Vector3& arg1 = Vector3 ( ), const Quaternion& arg2 = Quaternion ( ))
+- void SetSphere(float, const Vector3& arg1 = Vector3 ( ), const Quaternion& arg2 = Quaternion ( ))
 - void SetCylinder(float, float, const Vector3& arg2 = Vector3 ( ), const Quaternion& arg3 = Quaternion ( ))
 - void SetCapsule(float, float, const Vector3& arg2 = Vector3 ( ), const Quaternion& arg3 = Quaternion ( ))
 - void SetCone(float, float, const Vector3& arg2 = Vector3 ( ), const Quaternion& arg3 = Quaternion ( ))
@@ -4856,6 +4857,7 @@ Methods:<br>
 - void Remove()
 - void MarkNetworkUpdate() const
 - void DrawDebugGeometry(DebugRenderer@, bool)
+- void Clear()
 
 Properties:<br>
 - ShortStringHash type (readonly)

+ 5 - 1
Engine/Engine/PhysicsAPI.cpp

@@ -60,6 +60,7 @@ static RigidBody* PhysicsRaycastResultGetRigidBody(PhysicsRaycastResult* ptr)
 static void RegisterCollisionShape(asIScriptEngine* engine)
 {
     engine->RegisterEnum("ShapeType");
+    engine->RegisterEnumValue("ShapeType", "SHAPE_NONE", SHAPE_NONE);
     engine->RegisterEnumValue("ShapeType", "SHAPE_BOX", SHAPE_BOX);
     engine->RegisterEnumValue("ShapeType", "SHAPE_SPHERE", SHAPE_SPHERE);
     engine->RegisterEnumValue("ShapeType", "SHAPE_CYLINDER", SHAPE_CYLINDER);
@@ -70,8 +71,9 @@ static void RegisterCollisionShape(asIScriptEngine* engine)
     engine->RegisterEnumValue("ShapeType", "SHAPE_TERRAIN", SHAPE_TERRAIN);
     
     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 Clear()", asMETHOD(CollisionShape, Clear), 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);
+    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 SetCylinder(float, float, const Vector3&in pos = Vector3(), const Quaternion&in rot = Quaternion())", asMETHOD(CollisionShape, SetCylinder), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "void SetCapsule(float, float, const Vector3&in pos = Vector3(), const Quaternion&in rot = Quaternion())", asMETHOD(CollisionShape, SetCapsule), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "void SetCone(float, float, const Vector3&in pos = Vector3(), const Quaternion&in rot = Quaternion())", asMETHOD(CollisionShape, SetCone), asCALL_THISCALL);
@@ -175,12 +177,14 @@ static void RegisterRigidBody(asIScriptEngine* engine)
 static void RegisterConstraint(asIScriptEngine* engine)
 {
     engine->RegisterEnum("ConstraintType");
+    engine->RegisterEnumValue("ConstraintType", "CONSTRAINT_NONE", CONSTRAINT_NONE);
     engine->RegisterEnumValue("ConstraintType", "CONSTRAINT_POINT", CONSTRAINT_POINT);
     engine->RegisterEnumValue("ConstraintType", "CONSTRAINT_HINGE", CONSTRAINT_HINGE);
     engine->RegisterEnumValue("ConstraintType", "CONSTRAINT_SLIDER", CONSTRAINT_SLIDER);
     engine->RegisterEnumValue("ConstraintType", "CONSTRAINT_CONETWIST", CONSTRAINT_CONETWIST);
     
     RegisterComponent<Constraint>(engine, "Constraint");
+    engine->RegisterObjectMethod("Constraint", "void Clear()", asMETHOD(Constraint, Clear), asCALL_THISCALL);
     engine->RegisterObjectMethod("Constraint", "void set_constraintType(ConstraintType)", asMETHOD(Constraint, SetConstraintType), asCALL_THISCALL);
     engine->RegisterObjectMethod("Constraint", "ConstraintType get_constraintType() const", asMETHOD(Constraint, GetConstraintType), asCALL_THISCALL);
     engine->RegisterObjectMethod("Constraint", "void set_position(const Vector3&in)", asMETHOD(Constraint, SetPosition), asCALL_THISCALL);

+ 17 - 5
Engine/Physics/CollisionShape.cpp

@@ -56,6 +56,7 @@ static const float DEFAULT_COLLISION_MARGIN = 0.04f;
 
 static const char* typeNames[] = 
 {
+    "None",
     "Box",
     "Sphere",
     "Cylinder",
@@ -255,7 +256,7 @@ OBJECTTYPESTATIC(CollisionShape);
 CollisionShape::CollisionShape(Context* context) :
     Component(context),
     shape_(0),
-    shapeType_(SHAPE_BOX),
+    shapeType_(SHAPE_NONE),
     position_(Vector3::ZERO),
     rotation_(Quaternion::IDENTITY),
     size_(Vector3::ONE),
@@ -278,7 +279,7 @@ void CollisionShape::RegisterObject(Context* context)
 {
     context->RegisterFactory<CollisionShape>();
     
-    ENUM_ATTRIBUTE(CollisionShape, "Shape Type", shapeType_, typeNames, SHAPE_BOX, AM_DEFAULT);
+    ENUM_ATTRIBUTE(CollisionShape, "Shape Type", shapeType_, typeNames, SHAPE_NONE, AM_DEFAULT);
     ATTRIBUTE(CollisionShape, VAR_VECTOR3, "Size", size_, Vector3::ONE, AM_DEFAULT);
     REF_ACCESSOR_ATTRIBUTE(CollisionShape, VAR_VECTOR3, "Offset Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_DEFAULT);
     REF_ACCESSOR_ATTRIBUTE(CollisionShape, VAR_QUATERNION, "Offset Rotation", GetRotation, SetRotation, Quaternion, Quaternion::IDENTITY, AM_DEFAULT);
@@ -340,6 +341,15 @@ void CollisionShape::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
     }
 }
 
+void CollisionShape::Clear()
+{
+    shapeType_ = SHAPE_NONE;
+    
+    UpdateShape();
+    NotifyRigidBody();
+    MarkNetworkUpdate();
+}
+
 void CollisionShape::SetBox(const Vector3& size, const Vector3& position, const Quaternion& rotation)
 {
     shapeType_ = SHAPE_BOX;
@@ -626,13 +636,12 @@ void CollisionShape::OnNodeSet(Node* node)
             else
                 LOGERROR("No physics world component in scene, can not create collision shape");
         }
+        
         node->AddListener(this);
+        cachedWorldScale_ = node->GetWorldScale();
         
         // Terrain collision shape depends on the terrain component's geometry updates. Subscribe to them
         SubscribeToEvent(node, E_TERRAINCREATED, HANDLER(CollisionShape, HandleTerrainCreated));
-        
-        UpdateShape();
-        NotifyRigidBody();
     }
 }
 
@@ -788,6 +797,9 @@ void CollisionShape::UpdateShape()
                 }
             }
             break;
+            
+        default:
+            break;
         }
         
         if (shape_)

+ 6 - 3
Engine/Physics/CollisionShape.h

@@ -44,7 +44,8 @@ class Terrain;
 /// Collision shape type.
 enum ShapeType
 {
-    SHAPE_BOX = 0,
+    SHAPE_NONE = 0,
+    SHAPE_BOX,
     SHAPE_SPHERE,
     SHAPE_CYLINDER,
     SHAPE_CAPSULE,
@@ -129,10 +130,12 @@ public:
     /// Visualize the component as debug geometry.
     virtual void DrawDebugGeometry(DebugRenderer* debug, bool depthTest);
     
-    /// Set as a sphere.
-    void SetSphere(float diameter, const Vector3& position = Vector3::ZERO, const Quaternion& rotation = Quaternion::IDENTITY);
+    /// Remove collision geometry.
+    void Clear();
     /// Set as a box.
     void SetBox(const Vector3& size, const Vector3& position = Vector3::ZERO, const Quaternion& rotation = Quaternion::IDENTITY);
+    /// Set as a sphere.
+    void SetSphere(float diameter, const Vector3& position = Vector3::ZERO, const Quaternion& rotation = Quaternion::IDENTITY);
     /// Set as a cylinder.
     void SetCylinder(float diameter, float height, const Vector3& position = Vector3::ZERO, const Quaternion& rotation = Quaternion::IDENTITY);
     /// Set as a capsule.

+ 24 - 13
Engine/Physics/Constraint.cpp

@@ -44,6 +44,7 @@ namespace Urho3D
 
 static const char* typeNames[] =
 {
+    "None",
     "Point",
     "Hinge",
     "Slider",
@@ -56,7 +57,7 @@ OBJECTTYPESTATIC(Constraint);
 Constraint::Constraint(Context* context) :
     Component(context),
     constraint_(0),
-    constraintType_(CONSTRAINT_POINT),
+    constraintType_(CONSTRAINT_NONE),
     position_(Vector3::ZERO),
     rotation_(Quaternion::IDENTITY),
     otherPosition_(Vector3::ZERO),
@@ -82,7 +83,7 @@ void Constraint::RegisterObject(Context* context)
 {
     context->RegisterFactory<Constraint>();
     
-    ENUM_ATTRIBUTE(Constraint, "Constraint Type", constraintType_, typeNames, CONSTRAINT_POINT, AM_DEFAULT);
+    ENUM_ATTRIBUTE(Constraint, "Constraint Type", constraintType_, typeNames, CONSTRAINT_NONE, AM_DEFAULT);
     ATTRIBUTE(Constraint, VAR_VECTOR3, "Position", position_, Vector3::ZERO, AM_DEFAULT);
     ATTRIBUTE(Constraint, VAR_QUATERNION, "Rotation", rotation_, Quaternion::IDENTITY, AM_DEFAULT);
     ATTRIBUTE(Constraint, VAR_VECTOR3, "Other Body Position", otherPosition_, Vector3::ZERO, AM_DEFAULT);
@@ -163,6 +164,11 @@ void Constraint::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
     }
 }
 
+void Constraint::Clear()
+{
+    SetConstraintType(CONSTRAINT_NONE);
+}
+
 void Constraint::SetConstraintType(ConstraintType type)
 {
     if (type != constraintType_)
@@ -358,10 +364,9 @@ void Constraint::OnNodeSet(Node* node)
             else
                 LOGERROR("No physics world component in scene, can not create constraint");
         }
-        node->AddListener(this);
         
-        // Try to create constraint immediately, may fail if the rigid body component does not exist yet
-        CreateConstraint();
+        node->AddListener(this);
+        cachedWorldScale_ = node->GetWorldScale();
     }
 }
 
@@ -426,16 +431,22 @@ void Constraint::CreateConstraint()
             constraint_ = new btConeTwistConstraint(*ownBody, *otherBody, ownFrame, otherFrame);
         }
         break;
+        
+    default:
+        break;
     }
     
-    constraint_->setUserConstraintPtr(this);
-    ownBody_->AddConstraint(this);
-    if (otherBody_)
-        otherBody_->AddConstraint(this);
-    
-    ApplyLimits();
-    
-    physicsWorld_->GetWorld()->addConstraint(constraint_, disableCollision_);
+    if (constraint_)
+    {
+        constraint_->setUserConstraintPtr(this);
+        ownBody_->AddConstraint(this);
+        if (otherBody_)
+            otherBody_->AddConstraint(this);
+        
+        ApplyLimits();
+        
+        physicsWorld_->GetWorld()->addConstraint(constraint_, disableCollision_);
+    }
 }
 
 void Constraint::ApplyFrames()

+ 4 - 1
Engine/Physics/Constraint.h

@@ -33,7 +33,8 @@ namespace Urho3D
 /// Supported constraint types.
 enum ConstraintType
 {
-    CONSTRAINT_POINT = 0,
+    CONSTRAINT_NONE = 0,
+    CONSTRAINT_POINT,
     CONSTRAINT_HINGE,
     CONSTRAINT_SLIDER,
     CONSTRAINT_CONETWIST
@@ -66,6 +67,8 @@ public:
     /// Visualize the component as debug geometry.
     virtual void DrawDebugGeometry(DebugRenderer* debug, bool depthTest);
     
+    /// Remove constraint.
+    void Clear();
     /// Set constraint type and recreate the constraint.
     void SetConstraintType(ConstraintType type);
     /// Set other body to connect to. Set to null to connect to the static world.

+ 2 - 0
Engine/Physics/RigidBody.cpp

@@ -711,6 +711,8 @@ void RigidBody::AddConstraint(Constraint* constraint)
 void RigidBody::RemoveConstraint(Constraint* constraint)
 {
     constraints_.Remove(constraint);
+    // A constraint being removed should possibly cause the object to eg. start falling, so activate
+    Activate();
 }
 
 void RigidBody::ReleaseBody()