Browse Source

Further refactoring of the Joint API. Now position & axis are specified in the local space of the own rigid body.

Lasse Öörni 13 years ago
parent
commit
8a5274b596

+ 9 - 9
Engine/Audio/Sound.cpp

@@ -318,32 +318,32 @@ void* Sound::AllocateDecoder()
     return vorbis;
 }
 
-unsigned Sound::Decode(void* Decoder, signed char* dest, unsigned bytes)
+unsigned Sound::Decode(void* decoder, signed char* dest, unsigned bytes)
 {
-    if (!Decoder)
+    if (!decoder)
         return 0;
     
     unsigned soundSources = stereo_ ? 2 : 1;
-    stb_vorbis* vorbis = static_cast<stb_vorbis*>(Decoder);
+    stb_vorbis* vorbis = static_cast<stb_vorbis*>(decoder);
     unsigned outSamples = stb_vorbis_get_samples_short_interleaved(vorbis, soundSources, (short*)dest, bytes >> 1);
     return (outSamples * soundSources) << 1;
 }
 
-void Sound::RewindDecoder(void* Decoder)
+void Sound::RewindDecoder(void* decoder)
 {
-    if (!Decoder)
+    if (!decoder)
         return;
     
-    stb_vorbis* vorbis = static_cast<stb_vorbis*>(Decoder);
+    stb_vorbis* vorbis = static_cast<stb_vorbis*>(decoder);
     stb_vorbis_seek_start(vorbis);
 }
 
-void Sound::FreeDecoder(void* Decoder)
+void Sound::FreeDecoder(void* decoder)
 {
-    if (!Decoder)
+    if (!decoder)
         return;
     
-    stb_vorbis* vorbis = static_cast<stb_vorbis*>(Decoder);
+    stb_vorbis* vorbis = static_cast<stb_vorbis*>(decoder);
     stb_vorbis_close(vorbis);
 }
 

+ 5 - 5
Engine/Audio/Sound.h

@@ -61,14 +61,14 @@ public:
     /// Fix interpolation by copying data from loop start to loop end (looped), or adding silence (oneshot.)
     void FixInterpolation();
     
-    /// Create and return a Decoder. Return null if fails.
+    /// Create and return a compressed audio decoder instance. Return null if fails.
     void* AllocateDecoder();
     /// Decode compressed audio data. Return number of actually decoded bytes.
-    unsigned Decode(void* Decoder, signed char* dest, unsigned bytes);
+    unsigned Decode(void* decoder, signed char* dest, unsigned bytes);
     /// Rewind the decoder to beginning of audio data.
-    void RewindDecoder(void* Decoder);
-    /// Free the decoder.
-    void FreeDecoder(void* Decoder);
+    void RewindDecoder(void* decoder);
+    /// Free the decoder instance.
+    void FreeDecoder(void* decoder);
     
     /// Return sound data start.
     signed char* GetStart() const { return data_.Get(); }

+ 4 - 2
Engine/Engine/PhysicsAPI.cpp

@@ -157,14 +157,16 @@ static void RegisterJoint(asIScriptEngine* engine)
     
     RegisterComponent<Joint>(engine, "Joint");
     engine->RegisterObjectMethod("Joint", "void Clear()", asMETHOD(Joint, Clear), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Joint", "bool SetBall(const Vector3&in, RigidBody@+)", asMETHOD(Joint, SetBall), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Joint", "bool SetHinge(const Vector3&in, const Vector3&in, RigidBody@+)", asMETHOD(Joint, SetHinge), asCALL_THISCALL);
     engine->RegisterObjectMethod("Joint", "void set_position(Vector3)", asMETHOD(Joint, SetPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod("Joint", "Vector3 get_position() const", asMETHOD(Joint, GetPosition), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Joint", "Vector3 get_worldPosition() const", asMETHOD(Joint, GetWorldPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod("Joint", "void set_axis(Vector3)", asMETHOD(Joint, SetAxis), asCALL_THISCALL);
     engine->RegisterObjectMethod("Joint", "Vector3 get_axis() const", asMETHOD(Joint, GetAxis), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Joint", "Vector3 get_worldAxis() const", asMETHOD(Joint, GetWorldAxis), asCALL_THISCALL);
     engine->RegisterObjectMethod("Joint", "RigidBody@+ get_ownBody() const", asMETHOD(Joint, GetOwnBody), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Joint", "void set_otherBody(RigidBody@+)", asMETHOD(Joint, SetOtherBody), asCALL_THISCALL);
     engine->RegisterObjectMethod("Joint", "RigidBody@+ get_otherBody() const", asMETHOD(Joint, GetOtherBody), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Joint", "bool set_jointType(JointType)", asMETHOD(Joint, SetJointType), asCALL_THISCALL);
     engine->RegisterObjectMethod("Joint", "JointType get_jointType() const", asMETHOD(Joint, GetJointType), asCALL_THISCALL);
 }
 

+ 1 - 1
Engine/Graphics/AnimationState.cpp

@@ -177,7 +177,7 @@ void AnimationState::Apply()
         return;
     
     // Check first if full weight or blending
-    if (weight_ == 1.0f)
+    if (Equals(weight_, 1.0f))
     {
         for (HashMap<unsigned, Bone*>::ConstIterator i = trackToBoneMap_.Begin(); i != trackToBoneMap_.End(); ++i)
         {

+ 63 - 78
Engine/Physics/Joint.cpp

@@ -49,6 +49,7 @@ Joint::Joint(Context* context) :
     joint_(0),
     position_(Vector3::ZERO),
     axis_(Vector3::ZERO),
+    jointScale_(Vector3::ONE),
     otherBodyNodeID_(0),
     recreateJoint_(false)
 {
@@ -69,19 +70,16 @@ void Joint::RegisterObject(Context* context)
     ENUM_ATTRIBUTE(Joint, "Joint Type", type_, typeNames, JOINT_NONE, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Joint, VAR_VECTOR3, "Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_DEFAULT | AM_LATESTDATA);
     ACCESSOR_ATTRIBUTE(Joint, VAR_VECTOR3, "Axis", GetAxis, SetAxis, Vector3, Vector3::ZERO, AM_DEFAULT | AM_LATESTDATA);
-    ACCESSOR_ATTRIBUTE(Joint, VAR_INT, "Other Body NodeID", GetOtherBodyAttr, SetOtherBodyAttr, int, 0, AM_DEFAULT | AM_NODEID);
+    ATTRIBUTE(Joint, VAR_INT, "Other Body NodeID", otherBodyNodeID_, 0, AM_DEFAULT | AM_NODEID);
 }
 
 void Joint::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
 {
     Serializable::OnSetAttribute(attr, src);
     
-    // Change of the joint type requires the joint to be recreated
-    if (attr.offset_ == offsetof(Joint, type_))
-    {
-        otherBodyNodeID_ = GetOtherBodyAttr();
+    // Change of the joint type or connected body requires the joint to be recreated
+    if (attr.offset_ == offsetof(Joint, type_) || attr.offset_ == offsetof(Joint, otherBodyNodeID_))
         recreateJoint_ = true;
-    }
 }
 
 void Joint::ApplyAttributes()
@@ -98,21 +96,7 @@ void Joint::ApplyAttributes()
                 otherBody_ = otherNode->GetComponent<RigidBody>();
         }
         
-        switch (type_)
-        {
-        case JOINT_NONE:
-            Clear();
-            break;
-            
-        case JOINT_BALL:
-            SetBall(position_, otherBody_);
-            break;
-            
-        case JOINT_HINGE:
-            SetHinge(position_, axis_, otherBody_);
-            break;
-        }
-        
+        SetJointType(type_);
         recreateJoint_ = false;
     }
 }
@@ -129,15 +113,17 @@ void Joint::Clear()
     {
         dJointDestroy(joint_);
         joint_ = 0;
+        type_ = JOINT_NONE;
     }
-    
-    type_ = JOINT_NONE;
 }
 
-bool Joint::SetBall(const Vector3& position, RigidBody* otherBody)
+bool Joint::SetJointType(JointType type)
 {
     Clear();
     
+    if (type == JOINT_NONE)
+        return true;
+    
     if (!physicsWorld_)
     {
         LOGERROR("Null physics world, can not set joint type");
@@ -151,62 +137,65 @@ bool Joint::SetBall(const Vector3& position, RigidBody* otherBody)
         return false;
     }
     
-    otherBody_ = otherBody;
-    type_ = JOINT_BALL;
+    type_ = type;
     
-    joint_ = dJointCreateBall(physicsWorld_->GetWorld(), 0);
-    dJointSetData(joint_, this);
-    dJointSetBallAnchor(joint_, position.x_, position.y_, position.z_);
-    dJointAttach(joint_, ownBody_->GetBody(), otherBody_ ? otherBody_->GetBody() : 0);
+    switch (type)
+    {
+    case JOINT_NONE:
+        break;
+        
+    case JOINT_BALL:
+        joint_ = dJointCreateBall(physicsWorld_->GetWorld(), 0);
+        dJointSetData(joint_, this);
+        dJointAttach(joint_, ownBody_->GetBody(), otherBody_ ? otherBody_->GetBody() : 0);
+        SetPosition(position_);
+        break;
+        
+    case JOINT_HINGE:
+        joint_ = dJointCreateHinge(physicsWorld_->GetWorld(), 0);
+        dJointSetData(joint_, this);
+        dJointAttach(joint_, ownBody_->GetBody(), otherBody_ ? otherBody_->GetBody() : 0);
+        SetPosition(position_);
+        SetAxis(axis_);
+        break;
+    }
     
     return true;
 }
 
-bool Joint::SetHinge(const Vector3& position, const Vector3& axis, RigidBody* otherBody)
+void Joint::SetOtherBody(RigidBody* body)
 {
-    Clear();
-    
-    if (!physicsWorld_)
-    {
-        LOGERROR("Null physics world, can not set joint type");
-        return false;
-    }
-    
-    ownBody_ = static_cast<RigidBody*>(GetComponent(RigidBody::GetTypeStatic()));
-    if (!ownBody_)
+    if (otherBody_ != body)
     {
-        LOGERROR("No rigid body in node, can not set joint type");
-        return false;
+        otherBody_ = body;
+        
+        // Update the connected body attribute
+        Node* otherNode = otherBody_ ? otherBody_->GetNode() : 0;
+        otherBodyNodeID_ = otherNode ? otherNode->GetID() : 0;
+        
+        if (joint_)
+            dJointAttach(joint_, ownBody_->GetBody(), otherBody_ ? otherBody_->GetBody() : 0);
     }
-    
-    otherBody_ = otherBody;
-    type_ = JOINT_HINGE;
-    
-    Vector3 normalizedAxis = axis.Normalized();
-    
-    joint_ = dJointCreateHinge(physicsWorld_->GetWorld(), 0);
-    dJointSetData(joint_, this);
-    dJointSetHingeAnchor(joint_, position.x_, position.y_, position.z_);
-    dJointSetHingeAxis(joint_, normalizedAxis.x_, normalizedAxis.y_, normalizedAxis.z_);
-    dJointAttach(joint_, ownBody_->GetBody(), otherBody_ ? otherBody_->GetBody() : 0);
-    
-    return true;
 }
 
 void Joint::SetPosition(Vector3 position)
 {
-    if (joint_)
+    position_ = position;
+   
+    if (joint_ && node_ && ownBody_)
     {
+        jointScale_ = node_->GetWorldScale();
+        Vector3 worldPosition = ownBody_->GetRotation() * (jointScale_ * position) + ownBody_->GetPosition();
         dJointType type = dJointGetType(joint_);
         
         switch (type)
         {
         case dJointTypeBall:
-            dJointSetBallAnchor(joint_, position.x_, position.y_, position.z_);
+            dJointSetBallAnchor(joint_, worldPosition.x_, worldPosition.y_, worldPosition.z_);
             break;
             
         case dJointTypeHinge:
-            dJointSetHingeAnchor(joint_, position.x_, position.y_, position.z_);
+            dJointSetHingeAnchor(joint_, worldPosition.x_, worldPosition.y_, worldPosition.z_);
             break;
         }
     }
@@ -214,20 +203,23 @@ void Joint::SetPosition(Vector3 position)
 
 void Joint::SetAxis(Vector3 axis)
 {
-    if (joint_)
+    axis_ = axis.Normalized();
+    
+    if (joint_ && node_ && ownBody_)
     {
+        Vector3 worldAxis = ownBody_->GetRotation() * axis_;
         dJointType type = dJointGetType(joint_);
         
         switch (type)
         {
         case dJointTypeHinge:
-            dJointSetHingeAxis(joint_, axis.x_, axis.y_, axis.z_);
+            dJointSetHingeAxis(joint_, worldAxis.x_, worldAxis.y_, worldAxis.z_);
             break;
         }
     }
 }
 
-Vector3 Joint::GetPosition() const
+Vector3 Joint::GetWorldPosition() const
 {
     dVector3 pos;
     
@@ -250,7 +242,7 @@ Vector3 Joint::GetPosition() const
     return Vector3::ZERO;
 }
 
-Vector3 Joint::GetAxis() const
+Vector3 Joint::GetWorldAxis() const
 {
     dVector3 axis;
     
@@ -269,21 +261,6 @@ Vector3 Joint::GetAxis() const
     return Vector3::ZERO;
 }
 
-void Joint::SetOtherBodyAttr(int value)
-{
-    otherBodyNodeID_ = value;
-    recreateJoint_ = true;
-}
-
-int Joint::GetOtherBodyAttr() const
-{
-    if (!otherBody_)
-        return 0;
-    
-    Node* otherNode = otherBody_->GetNode();
-    return otherNode ? otherNode->GetID() : 0;
-}
-
 void Joint::OnNodeSet(Node* node)
 {
     if (node)
@@ -295,5 +272,13 @@ void Joint::OnNodeSet(Node* node)
             if (physicsWorld_)
                 physicsWorld_->AddJoint(this);
         }
+        node->AddListener(this);
     }
 }
+
+void Joint::OnMarkedDirty(Node* node)
+{
+    // Reapply position if scale changed
+    if (node_->GetWorldScale() != jointScale_)
+        SetPosition(position_);
+}

+ 22 - 19
Engine/Physics/Joint.h

@@ -60,38 +60,39 @@ public:
     
     /// Remove the joint.
     void Clear();
-    /// %Set a ball joint.
-    bool SetBall(const Vector3& position, RigidBody* otherBody = 0);
-    /// %Set a hinge joint.
-    bool SetHinge(const Vector3& position, const Vector3& axis, RigidBody* otherBody = 0);
-    /// %Set joint world position.
+    /// %Set joint type and recreate the joint. Return true if successful.
+    bool SetJointType(JointType type);
+    /// %Set other body to connect to.
+    void SetOtherBody(RigidBody* body);
+    /// %Set joint local-space position.
     void SetPosition(Vector3 position);
-    /// %Set joint world axis if applicable.
+    /// %Set joint local-space axis.
     void SetAxis(Vector3 axis);
     
     /// Return physics world.
     PhysicsWorld* GetPhysicsWorld() const { return physicsWorld_; }
+    /// Return joint type.
+    JointType GetJointType() const { return type_; }
     /// Return rigid body in own scene node.
     RigidBody* GetOwnBody() const { return ownBody_; }
     /// Return the other rigid body. May be null if connected to the static world.
     RigidBody* GetOtherBody() const { return otherBody_; }
-    /// Return joint type.
-    JointType GetJointType() const { return type_; }
     /// Return the ODE joint ID.
     dJointID GetJoint() const { return joint_; }
-    /// Return joint world position.
-    Vector3 GetPosition() const;
-    /// Return joint world axis.
-    Vector3 GetAxis() const;
-    
-    /// %Set other body attribute.
-    void SetOtherBodyAttr(int value);
-    /// Return other body attribute.
-    int GetOtherBodyAttr() const;
+    /// Return joint local-space position.
+    Vector3 GetPosition() const { return position_; }
+    /// Return joint local-space axis.
+    Vector3 GetAxis() const { return axis_; }
+    /// Return joint world-space position.
+    Vector3 GetWorldPosition() const;
+    /// Return joint world-space axis.
+    Vector3 GetWorldAxis() const;
     
 protected:
     /// Handle node being assigned.
     virtual void OnNodeSet(Node* node);
+    /// Handle node transform being dirtied.
+    virtual void OnMarkedDirty(Node* node);
     
 private:
     /// Physics world.
@@ -104,10 +105,12 @@ private:
     JointType type_;
     /// ODE joint ID.
     dJointID joint_;
-    /// Joint position for creation during post-load.
+    /// Joint local-space position.
     Vector3 position_;
-    /// Joint axis for creation during post-load.
+    /// Joint local-space axis.
     Vector3 axis_;
+    /// Cached world scale of node.
+    Vector3 jointScale_;
     /// Other body node ID for pending joint recreation.
     int otherBodyNodeID_;
     /// Recreate joint flag.