Explorar o código

Reverted to joint world space positioning for reliability.
Added debug geometry visualization for joints.
Added nullchecks to prevent crash by calling DrawDebugGeometry() from script with a null debug renderer pointer.

Lasse Öörni %!s(int64=13) %!d(string=hai) anos
pai
achega
a85817a355

+ 6 - 0
Bin/Data/Scripts/Editor/EditorView.as

@@ -343,6 +343,12 @@ void HandlePostRenderUpdate()
             CollisionShape@ shape = cast<CollisionShape>(selectedComponents[i]);
             CollisionShape@ shape = cast<CollisionShape>(selectedComponents[i]);
             if (shape !is null)
             if (shape !is null)
                 shape.DrawDebugGeometry(debug, false);
                 shape.DrawDebugGeometry(debug, false);
+            else
+            {
+                Joint@ joint = cast<Joint>(selectedComponents[i]);
+                if (joint !is null)
+                    joint.DrawDebugGeometry(debug, false);
+            }
         }
         }
     }
     }
 
 

+ 3 - 4
Docs/ScriptAPI.dox

@@ -4003,6 +4003,7 @@ Methods:<br>
 - Variant GetAttribute(const String&)
 - Variant GetAttribute(const String&)
 - void Remove()
 - void Remove()
 - void Clear()
 - void Clear()
+- void DrawDebugGeometry(DebugRenderer@, bool)
 
 
 Properties:<br>
 Properties:<br>
 - ShortStringHash type (readonly)
 - ShortStringHash type (readonly)
@@ -4012,10 +4013,8 @@ Properties:<br>
 - AttributeInfo&[] attributeInfos (readonly)
 - AttributeInfo&[] attributeInfos (readonly)
 - uint id (readonly)
 - uint id (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
-- Vector3 position
-- Vector3 worldPosition (readonly)
-- Vector3 axis
-- Vector3 worldAxis (readonly)
+- Vector3& position
+- Vector3& axis
 - RigidBody@ ownBody (readonly)
 - RigidBody@ ownBody (readonly)
 - RigidBody@ otherBody
 - RigidBody@ otherBody
 - JointType jointType
 - JointType jointType

+ 2 - 0
Engine/Core/Attribute.h

@@ -26,6 +26,8 @@
 #include "Ptr.h"
 #include "Ptr.h"
 #include "Variant.h"
 #include "Variant.h"
 
 
+/// Attribute shown only in the editor, but not serialized.
+static const unsigned AM_EDIT = 0x0;
 /// Attribute used for file serialization.
 /// Attribute used for file serialization.
 static const unsigned AM_FILE = 0x1;
 static const unsigned AM_FILE = 0x1;
 /// Attribute used for network replication.
 /// Attribute used for network replication.

+ 5 - 6
Engine/Engine/PhysicsAPI.cpp

@@ -157,12 +157,11 @@ static void RegisterJoint(asIScriptEngine* engine)
     
     
     RegisterComponent<Joint>(engine, "Joint");
     RegisterComponent<Joint>(engine, "Joint");
     engine->RegisterObjectMethod("Joint", "void Clear()", asMETHOD(Joint, Clear), asCALL_THISCALL);
     engine->RegisterObjectMethod("Joint", "void Clear()", asMETHOD(Joint, Clear), 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", "void DrawDebugGeometry(DebugRenderer@+, bool)", asMETHOD(Joint, DrawDebugGeometry), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Joint", "void set_position(const Vector3&in)", asMETHOD(Joint, SetPosition), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Joint", "const Vector3& get_position() const", asMETHOD(Joint, GetPosition), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Joint", "void set_axis(const Vector3&in)", asMETHOD(Joint, SetAxis), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Joint", "const Vector3& get_axis() const", asMETHOD(Joint, GetAxis), asCALL_THISCALL);
     engine->RegisterObjectMethod("Joint", "RigidBody@+ get_ownBody() const", asMETHOD(Joint, GetOwnBody), 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", "void set_otherBody(RigidBody@+)", asMETHOD(Joint, SetOtherBody), asCALL_THISCALL);
     engine->RegisterObjectMethod("Joint", "RigidBody@+ get_otherBody() const", asMETHOD(Joint, GetOtherBody), asCALL_THISCALL);
     engine->RegisterObjectMethod("Joint", "RigidBody@+ get_otherBody() const", asMETHOD(Joint, GetOtherBody), asCALL_THISCALL);

+ 5 - 2
Engine/Graphics/AnimatedModel.cpp

@@ -280,8 +280,11 @@ void AnimatedModel::GetBatch(Batch& batch, const FrameInfo& frame, unsigned batc
 
 
 void AnimatedModel::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 void AnimatedModel::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 {
 {
-    debug->AddBoundingBox(GetWorldBoundingBox(), Color(0.0f, 1.0f, 0.0f), depthTest);
-    debug->AddSkeleton(skeleton_, Color(0.75f, 0.75f, 0.75f), depthTest);
+    if (debug)
+    {
+        debug->AddBoundingBox(GetWorldBoundingBox(), Color(0.0f, 1.0f, 0.0f), depthTest);
+        debug->AddSkeleton(skeleton_, Color(0.75f, 0.75f, 0.75f), depthTest);
+    }
 }
 }
 
 
 void AnimatedModel::SetModel(Model* model, bool createBones)
 void AnimatedModel::SetModel(Model* model, bool createBones)

+ 2 - 1
Engine/Graphics/Drawable.cpp

@@ -108,7 +108,8 @@ void Drawable::UpdateDistance(const FrameInfo& frame)
 
 
 void Drawable::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 void Drawable::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 {
 {
-    debug->AddBoundingBox(GetWorldBoundingBox(), Color(0.0f, 1.0f, 0.0f), depthTest);
+    if (debug)
+        debug->AddBoundingBox(GetWorldBoundingBox(), Color(0.0f, 1.0f, 0.0f), depthTest);
 }
 }
 
 
 void Drawable::SetDrawDistance(float distance)
 void Drawable::SetDrawDistance(float distance)

+ 11 - 8
Engine/Graphics/Light.cpp

@@ -247,15 +247,18 @@ void Light::UpdateDistance(const FrameInfo& frame)
 
 
 void Light::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 void Light::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 {
 {
-    switch (lightType_)
+    if (debug)
     {
     {
-    case LIGHT_SPOT:
-        debug->AddFrustum(GetFrustum(), color_, depthTest);
-        break;
-        
-    case LIGHT_POINT:
-        debug->AddSphere(Sphere(GetWorldPosition(), range_), GetColor(), depthTest);
-        break;
+        switch (lightType_)
+        {
+        case LIGHT_SPOT:
+            debug->AddFrustum(GetFrustum(), color_, depthTest);
+            break;
+            
+        case LIGHT_POINT:
+            debug->AddSphere(Sphere(GetWorldPosition(), range_), GetColor(), depthTest);
+            break;
+        }
     }
     }
 }
 }
 
 

+ 10 - 12
Engine/Graphics/Octree.cpp

@@ -190,15 +190,15 @@ void Octant::ResetRoot()
 
 
 void Octant::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 void Octant::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 {
 {
-    if (!debug->IsInside(worldBoundingBox_))
-        return;
-    
-    debug->AddBoundingBox(worldBoundingBox_, Color(0.25f, 0.25f, 0.25f), depthTest);
-    
-    for (unsigned i = 0; i < NUM_OCTANTS; ++i)
+    if (debug && debug->IsInside(worldBoundingBox_))
     {
     {
-        if (children_[i])
-            children_[i]->DrawDebugGeometry(debug, depthTest);
+        debug->AddBoundingBox(worldBoundingBox_, Color(0.25f, 0.25f, 0.25f), depthTest);
+        
+        for (unsigned i = 0; i < NUM_OCTANTS; ++i)
+        {
+            if (children_[i])
+                children_[i]->DrawDebugGeometry(debug, depthTest);
+        }
     }
     }
 }
 }
 
 
@@ -519,10 +519,8 @@ void Octree::DrawDebugGeometry(bool depthTest)
     PROFILE(OctreeDrawDebug);
     PROFILE(OctreeDrawDebug);
     
     
     DebugRenderer* debug = GetComponent<DebugRenderer>();
     DebugRenderer* debug = GetComponent<DebugRenderer>();
-    if (!debug)
-        return;
-    
-    Octant::DrawDebugGeometry(debug, depthTest);
+    if (debug)
+        Octant::DrawDebugGeometry(debug, depthTest);
 }
 }
 
 
 void Octree::OnNodeSet(Node* node)
 void Octree::OnNodeSet(Node* node)

+ 2 - 1
Engine/Graphics/Zone.cpp

@@ -92,7 +92,8 @@ void Zone::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
 
 
 void Zone::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 void Zone::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 {
 {
-    debug->AddBoundingBox(boundingBox_, GetWorldTransform(), Color::GREEN, depthTest);
+    if (debug)
+        debug->AddBoundingBox(boundingBox_, GetWorldTransform(), Color::GREEN, depthTest);
 }
 }
 
 
 void Zone::SetBoundingBox(const BoundingBox& box)
 void Zone::SetBoundingBox(const BoundingBox& box)

+ 146 - 149
Engine/Physics/CollisionShape.cpp

@@ -614,188 +614,185 @@ void CollisionShape::UpdateTransform(bool nodeUpdate)
 
 
 void CollisionShape::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 void CollisionShape::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 {
 {
-    if (!geometry_)
-        return;
-    
-    const Color* color;
-    RigidBody* rigidBody = GetComponent<RigidBody>();
-    if (rigidBody && rigidBody->IsActive())
-        color = &Color::WHITE;
-    else
-        color = &Color::GREEN;
-    unsigned uintColor = color->ToUInt();
-    
     // Drawing all the debug geometries of a large world may be expensive (especially triangle meshes)
     // Drawing all the debug geometries of a large world may be expensive (especially triangle meshes)
     // so cull the geometry AABB against the debug geometry frustum first
     // so cull the geometry AABB against the debug geometry frustum first
-    if (!debug->IsInside(GetWorldBoundingBox()))
-        return;
-    
-    const Vector3& position = *reinterpret_cast<const Vector3*>(dGeomGetPosition(geometry_));
-    Quaternion rotation;
-    dGeomGetQuaternion(geometry_, const_cast<float*>(rotation.Data()));
-    Matrix3x4 transform(position, rotation, 1.0f);
-    
-    switch (dGeomGetClass(geometry_))
+    if (debug && geometry_ && debug->IsInside(GetWorldBoundingBox()))
     {
     {
-    case dSphereClass:
+        const Color* color;
+        RigidBody* rigidBody = GetComponent<RigidBody>();
+        if (rigidBody && rigidBody->IsActive())
+            color = &Color::WHITE;
+        else
+            color = &Color::GREEN;
+        unsigned uintColor = color->ToUInt();
+        
+        const Vector3& position = *reinterpret_cast<const Vector3*>(dGeomGetPosition(geometry_));
+        Quaternion rotation;
+        dGeomGetQuaternion(geometry_, const_cast<float*>(rotation.Data()));
+        Matrix3x4 transform(position, rotation, 1.0f);
+        
+        switch (dGeomGetClass(geometry_))
         {
         {
-            float radius = dGeomSphereGetRadius(geometry_);
-            
-            for (unsigned i = 0; i < 360; i += 45)
+        case dSphereClass:
             {
             {
-                unsigned j = i + 45;
-                float a = radius * sinf(i * M_DEGTORAD);
-                float b = radius * cosf(i * M_DEGTORAD);
-                float c = radius * sinf(j * M_DEGTORAD);
-                float d = radius * cosf(j * M_DEGTORAD);
-                Vector3 start, end;
+                float radius = dGeomSphereGetRadius(geometry_);
                 
                 
-                start = transform * Vector3(a, b, 0.0f);
-                end = transform * Vector3(c, d, 0.0f);
-                debug->AddLine(start, end, uintColor, depthTest);
-                start = transform * Vector3(a, 0.0f, b);
-                end = transform * Vector3(c, 0.0f, d);
-                debug->AddLine(start, end, uintColor, depthTest);
-                start = transform * Vector3(0.0f, a, b);
-                end = transform * Vector3(0.0f, c, d);
-                debug->AddLine(start, end, uintColor, depthTest);
+                for (unsigned i = 0; i < 360; i += 45)
+                {
+                    unsigned j = i + 45;
+                    float a = radius * sinf(i * M_DEGTORAD);
+                    float b = radius * cosf(i * M_DEGTORAD);
+                    float c = radius * sinf(j * M_DEGTORAD);
+                    float d = radius * cosf(j * M_DEGTORAD);
+                    Vector3 start, end;
+                    
+                    start = transform * Vector3(a, b, 0.0f);
+                    end = transform * Vector3(c, d, 0.0f);
+                    debug->AddLine(start, end, uintColor, depthTest);
+                    start = transform * Vector3(a, 0.0f, b);
+                    end = transform * Vector3(c, 0.0f, d);
+                    debug->AddLine(start, end, uintColor, depthTest);
+                    start = transform * Vector3(0.0f, a, b);
+                    end = transform * Vector3(0.0f, c, d);
+                    debug->AddLine(start, end, uintColor, depthTest);
+                }
             }
             }
-        }
-        break;
-        
-    case dBoxClass:
-        {
-            dVector3 size;
-            dGeomBoxGetLengths(geometry_, size);
-            BoundingBox box(0.5f * Vector3(size[0], size[1], size[2]), 0.5f * Vector3(-size[0], -size[1], -size[2]));
-            debug->AddBoundingBox(box, transform, *color, depthTest);
-        }
-        break;
-        
-    case dCapsuleClass:
-        {
-            float radius, length;
+            break;
             
             
-            dGeomCapsuleGetParams(geometry_, &radius, &length);
-            for (unsigned i = 0; i < 360; i += 45)
+        case dBoxClass:
             {
             {
-                unsigned j = i + 45;
-                
-                float a = radius * sinf(i * M_DEGTORAD);
-                float b = radius * cosf(i * M_DEGTORAD);
-                float c = radius * sinf(j * M_DEGTORAD);
-                float d = radius * cosf(j * M_DEGTORAD);
-                Vector3 start, end;
+                dVector3 size;
+                dGeomBoxGetLengths(geometry_, size);
+                BoundingBox box(0.5f * Vector3(size[0], size[1], size[2]), 0.5f * Vector3(-size[0], -size[1], -size[2]));
+                debug->AddBoundingBox(box, transform, *color, depthTest);
+            }
+            break;
+            
+        case dCapsuleClass:
+            {
+                float radius, length;
                 
                 
-                start = transform * Vector3(a, b, 0.5f * length);
-                end = transform * Vector3(c, d, 0.5f * length);
-                debug->AddLine(start, end, uintColor, depthTest);
-                start = transform * Vector3(a, b, -0.5f * length);
-                end = transform * Vector3(c, d, -0.5f * length);
-                debug->AddLine(start, end, uintColor, depthTest);
-                if (!(i & 1))
+                dGeomCapsuleGetParams(geometry_, &radius, &length);
+                for (unsigned i = 0; i < 360; i += 45)
                 {
                 {
+                    unsigned j = i + 45;
+                    
+                    float a = radius * sinf(i * M_DEGTORAD);
+                    float b = radius * cosf(i * M_DEGTORAD);
+                    float c = radius * sinf(j * M_DEGTORAD);
+                    float d = radius * cosf(j * M_DEGTORAD);
+                    Vector3 start, end;
+                    
                     start = transform * Vector3(a, b, 0.5f * length);
                     start = transform * Vector3(a, b, 0.5f * length);
-                    end = transform * Vector3(a, b, -0.5f * length);
+                    end = transform * Vector3(c, d, 0.5f * length);
+                    debug->AddLine(start, end, uintColor, depthTest);
+                    start = transform * Vector3(a, b, -0.5f * length);
+                    end = transform * Vector3(c, d, -0.5f * length);
                     debug->AddLine(start, end, uintColor, depthTest);
                     debug->AddLine(start, end, uintColor, depthTest);
+                    if (!(i & 1))
+                    {
+                        start = transform * Vector3(a, b, 0.5f * length);
+                        end = transform * Vector3(a, b, -0.5f * length);
+                        debug->AddLine(start, end, uintColor, depthTest);
+                    }
+                    if (b > -M_EPSILON)
+                    {
+                        start = transform * Vector3(a, 0.0f, b + 0.5f * length);
+                        end = transform * Vector3(c, 0.0f, d + 0.5f * length);
+                        debug->AddLine(start, end, uintColor, depthTest);
+                        start = transform * Vector3(0.0f, a, b + 0.5f * length);
+                        end = transform * Vector3(0.0f, c, d + 0.5f * length);
+                        debug->AddLine(start, end, uintColor, depthTest);
+                        start = transform * Vector3(a, 0.0f, -b - 0.5f * length);
+                        end = transform * Vector3(c, 0.0f, -d - 0.5f * length);
+                        debug->AddLine(start, end, uintColor, depthTest);
+                        start = transform * Vector3(0.0f, a, -b - 0.5f * length);
+                        end = transform * Vector3(0.0f, c, -d - 0.5f * length);
+                        debug->AddLine(start, end, uintColor, depthTest);
+                    }
                 }
                 }
-                if (b > -M_EPSILON)
+            }
+            break;
+            
+        case dCylinderClass:
+            {
+                float radius, length;
+                
+                dGeomCylinderGetParams(geometry_, &radius, &length);
+                for (unsigned i = 0; i < 360; i += 45)
                 {
                 {
-                    start = transform * Vector3(a, 0.0f, b + 0.5f * length);
-                    end = transform * Vector3(c, 0.0f, d + 0.5f * length);
-                    debug->AddLine(start, end, uintColor, depthTest);
-                    start = transform * Vector3(0.0f, a, b + 0.5f * length);
-                    end = transform * Vector3(0.0f, c, d + 0.5f * length);
+                    unsigned j = i + 45;
+                    float a = radius * sinf(i * M_DEGTORAD);
+                    float b = radius * cosf(i * M_DEGTORAD);
+                    float c = radius * sinf(j * M_DEGTORAD);
+                    float d = radius * cosf(j * M_DEGTORAD);
+                    Vector3 start, end;
+                    
+                    start = transform * Vector3(a, b, 0.5f * length);
+                    end = transform * Vector3(c, d, 0.5f * length);
                     debug->AddLine(start, end, uintColor, depthTest);
                     debug->AddLine(start, end, uintColor, depthTest);
-                    start = transform * Vector3(a, 0.0f, -b - 0.5f * length);
-                    end = transform * Vector3(c, 0.0f, -d - 0.5f * length);
+                    start = transform * Vector3(a, b, -0.5f * length);
+                    end = transform * Vector3(c, d, -0.5f * length);
                     debug->AddLine(start, end, uintColor, depthTest);
                     debug->AddLine(start, end, uintColor, depthTest);
-                    start = transform * Vector3(0.0f, a, -b - 0.5f * length);
-                    end = transform * Vector3(0.0f, c, -d - 0.5f * length);
+                    start = transform * Vector3(a, b, 0.5f * length);
+                    end = transform * Vector3(a, b, -0.5f * length);
                     debug->AddLine(start, end, uintColor, depthTest);
                     debug->AddLine(start, end, uintColor, depthTest);
                 }
                 }
             }
             }
-        }
-        break;
-        
-    case dCylinderClass:
-        {
-            float radius, length;
+            break;
             
             
-            dGeomCylinderGetParams(geometry_, &radius, &length);
-            for (unsigned i = 0; i < 360; i += 45)
+        case dTriMeshClass:
             {
             {
-                unsigned j = i + 45;
-                float a = radius * sinf(i * M_DEGTORAD);
-                float b = radius * cosf(i * M_DEGTORAD);
-                float c = radius * sinf(j * M_DEGTORAD);
-                float d = radius * cosf(j * M_DEGTORAD);
-                Vector3 start, end;
-                
-                start = transform * Vector3(a, b, 0.5f * length);
-                end = transform * Vector3(c, d, 0.5f * length);
-                debug->AddLine(start, end, uintColor, depthTest);
-                start = transform * Vector3(a, b, -0.5f * length);
-                end = transform * Vector3(c, d, -0.5f * length);
-                debug->AddLine(start, end, uintColor, depthTest);
-                start = transform * Vector3(a, b, 0.5f * length);
-                end = transform * Vector3(a, b, -0.5f * length);
-                debug->AddLine(start, end, uintColor, depthTest);
-            }
-        }
-        break;
-        
-    case dTriMeshClass:
-        {
-            TriangleMeshData* data = static_cast<TriangleMeshData*>(geometryData_.Get());
-            if (data)
-            {
-                debug->AddTriangleMesh(data->vertexData_.Get(), sizeof(Vector3), data->indexData_.Get(), sizeof(unsigned), 0,
-                    data->indexCount_, transform, *color, depthTest);
+                TriangleMeshData* data = static_cast<TriangleMeshData*>(geometryData_.Get());
+                if (data)
+                {
+                    debug->AddTriangleMesh(data->vertexData_.Get(), sizeof(Vector3), data->indexData_.Get(), sizeof(unsigned), 0,
+                        data->indexCount_, transform, *color, depthTest);
+                }
             }
             }
-        }
-        break;
-        
-    case dHeightfieldClass:
-        {
-            dHeightfieldDataID heightData = dGeomHeightfieldGetHeightfieldData(geometry_);
-            unsigned xPoints = heightData->m_nWidthSamples;
-            unsigned zPoints = heightData->m_nDepthSamples;
-            float xWidth = heightData->m_fWidth;
-            float zWidth = heightData->m_fDepth;
-            float xBase = -0.5f * xWidth;
-            float zBase = -0.5f * zWidth;
-            float xSpacing = xWidth / (xPoints - 1);
-            float zSpacing = zWidth / (zPoints - 1);
-            float* heights = (float*)heightData->m_pHeightData;
+            break;
             
             
-            for (unsigned z = 0; z < zPoints - 1; ++z)
+        case dHeightfieldClass:
             {
             {
+                dHeightfieldDataID heightData = dGeomHeightfieldGetHeightfieldData(geometry_);
+                unsigned xPoints = heightData->m_nWidthSamples;
+                unsigned zPoints = heightData->m_nDepthSamples;
+                float xWidth = heightData->m_fWidth;
+                float zWidth = heightData->m_fDepth;
+                float xBase = -0.5f * xWidth;
+                float zBase = -0.5f * zWidth;
+                float xSpacing = xWidth / (xPoints - 1);
+                float zSpacing = zWidth / (zPoints - 1);
+                float* heights = (float*)heightData->m_pHeightData;
+                
+                for (unsigned z = 0; z < zPoints - 1; ++z)
+                {
+                    for (unsigned x = 0; x < xPoints - 1; ++x)
+                    {
+                        Vector3 a = transform * Vector3(xBase + x * xSpacing, heights[z * xPoints + x], zBase + z * zSpacing);
+                        Vector3 b = transform * Vector3(xBase + (x + 1) * xSpacing, heights[z * xPoints + x + 1], zBase + z * zSpacing);
+                        Vector3 c = transform * Vector3(xBase + x * xSpacing, heights[(z + 1) * xPoints + x], zBase + (z + 1) * zSpacing);
+                        debug->AddLine(a, b, uintColor, depthTest);
+                        debug->AddLine(a, c, uintColor, depthTest);
+                    }
+                }
+                for (unsigned z = 0; z < zPoints - 1; ++z)
+                {
+                    unsigned x = xPoints - 1;
+                    Vector3 a = transform * Vector3(xBase + x * xSpacing, heights[z * xPoints + x], zBase + z * zSpacing);
+                    Vector3 b = transform * Vector3(xBase + x * xSpacing, heights[(z + 1) * xPoints + x], zBase + (z + 1) * zSpacing);
+                    debug->AddLine(a, b, uintColor, depthTest);
+                }
                 for (unsigned x = 0; x < xPoints - 1; ++x)
                 for (unsigned x = 0; x < xPoints - 1; ++x)
                 {
                 {
+                    unsigned z = zPoints - 1;
                     Vector3 a = transform * Vector3(xBase + x * xSpacing, heights[z * xPoints + x], zBase + z * zSpacing);
                     Vector3 a = transform * Vector3(xBase + x * xSpacing, heights[z * xPoints + x], zBase + z * zSpacing);
                     Vector3 b = transform * Vector3(xBase + (x + 1) * xSpacing, heights[z * xPoints + x + 1], zBase + z * zSpacing);
                     Vector3 b = transform * Vector3(xBase + (x + 1) * xSpacing, heights[z * xPoints + x + 1], zBase + z * zSpacing);
-                    Vector3 c = transform * Vector3(xBase + x * xSpacing, heights[(z + 1) * xPoints + x], zBase + (z + 1) * zSpacing);
                     debug->AddLine(a, b, uintColor, depthTest);
                     debug->AddLine(a, b, uintColor, depthTest);
-                    debug->AddLine(a, c, uintColor, depthTest);
                 }
                 }
             }
             }
-            for (unsigned z = 0; z < zPoints - 1; ++z)
-            {
-                unsigned x = xPoints - 1;
-                Vector3 a = transform * Vector3(xBase + x * xSpacing, heights[z * xPoints + x], zBase + z * zSpacing);
-                Vector3 b = transform * Vector3(xBase + x * xSpacing, heights[(z + 1) * xPoints + x], zBase + (z + 1) * zSpacing);
-                debug->AddLine(a, b, uintColor, depthTest);
-            }
-            for (unsigned x = 0; x < xPoints - 1; ++x)
-            {
-                unsigned z = zPoints - 1;
-                Vector3 a = transform * Vector3(xBase + x * xSpacing, heights[z * xPoints + x], zBase + z * zSpacing);
-                Vector3 b = transform * Vector3(xBase + (x + 1) * xSpacing, heights[z * xPoints + x + 1], zBase + z * zSpacing);
-                debug->AddLine(a, b, uintColor, depthTest);
-            }
+            break;
         }
         }
-        break;
     }
     }
 }
 }
 
 

+ 52 - 27
Engine/Physics/Joint.cpp

@@ -23,6 +23,7 @@
 
 
 #include "Precompiled.h"
 #include "Precompiled.h"
 #include "Context.h"
 #include "Context.h"
+#include "DebugRenderer.h"
 #include "Joint.h"
 #include "Joint.h"
 #include "Log.h"
 #include "Log.h"
 #include "PhysicsWorld.h"
 #include "PhysicsWorld.h"
@@ -49,7 +50,6 @@ Joint::Joint(Context* context) :
     joint_(0),
     joint_(0),
     position_(Vector3::ZERO),
     position_(Vector3::ZERO),
     axis_(Vector3::ZERO),
     axis_(Vector3::ZERO),
-    jointScale_(Vector3::ONE),
     otherBodyNodeID_(0),
     otherBodyNodeID_(0),
     recreateJoint_(false)
     recreateJoint_(false)
 {
 {
@@ -68,8 +68,8 @@ void Joint::RegisterObject(Context* context)
     context->RegisterFactory<Joint>();
     context->RegisterFactory<Joint>();
     
     
     ENUM_ATTRIBUTE(Joint, "Joint Type", type_, typeNames, JOINT_NONE, AM_DEFAULT);
     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);
+    REF_ACCESSOR_ATTRIBUTE(Joint, VAR_VECTOR3, "Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_DEFAULT | AM_LATESTDATA);
+    REF_ACCESSOR_ATTRIBUTE(Joint, VAR_VECTOR3, "Axis", GetAxis, SetAxis, Vector3, Vector3::ZERO, AM_DEFAULT | AM_LATESTDATA);
     ATTRIBUTE(Joint, VAR_INT, "Other Body NodeID", otherBodyNodeID_, 0, AM_DEFAULT | AM_NODEID);
     ATTRIBUTE(Joint, VAR_INT, "Other Body NodeID", otherBodyNodeID_, 0, AM_DEFAULT | AM_NODEID);
 }
 }
 
 
@@ -178,48 +178,45 @@ void Joint::SetOtherBody(RigidBody* body)
     }
     }
 }
 }
 
 
-void Joint::SetPosition(Vector3 position)
+void Joint::SetPosition(const Vector3& position)
 {
 {
     position_ = position;
     position_ = position;
    
    
-    if (joint_ && node_ && ownBody_)
+    if (joint_)
     {
     {
-        jointScale_ = node_->GetWorldScale();
-        Vector3 worldPosition = ownBody_->GetRotation() * (jointScale_ * position) + ownBody_->GetPosition();
         dJointType type = dJointGetType(joint_);
         dJointType type = dJointGetType(joint_);
         
         
         switch (type)
         switch (type)
         {
         {
         case dJointTypeBall:
         case dJointTypeBall:
-            dJointSetBallAnchor(joint_, worldPosition.x_, worldPosition.y_, worldPosition.z_);
+            dJointSetBallAnchor(joint_, position_.x_, position_.y_, position_.z_);
             break;
             break;
             
             
         case dJointTypeHinge:
         case dJointTypeHinge:
-            dJointSetHingeAnchor(joint_, worldPosition.x_, worldPosition.y_, worldPosition.z_);
+            dJointSetHingeAnchor(joint_, position_.x_, position_.y_, position_.z_);
             break;
             break;
         }
         }
     }
     }
 }
 }
 
 
-void Joint::SetAxis(Vector3 axis)
+void Joint::SetAxis(const Vector3& axis)
 {
 {
     axis_ = axis.Normalized();
     axis_ = axis.Normalized();
     
     
-    if (joint_ && node_ && ownBody_)
+    if (joint_)
     {
     {
-        Vector3 worldAxis = ownBody_->GetRotation() * axis_;
         dJointType type = dJointGetType(joint_);
         dJointType type = dJointGetType(joint_);
         
         
         switch (type)
         switch (type)
         {
         {
         case dJointTypeHinge:
         case dJointTypeHinge:
-            dJointSetHingeAxis(joint_, worldAxis.x_, worldAxis.y_, worldAxis.z_);
+            dJointSetHingeAxis(joint_, axis_.x_, axis_.y_, axis_.z_);
             break;
             break;
         }
         }
     }
     }
 }
 }
 
 
-Vector3 Joint::GetWorldPosition() const
+const Vector3& Joint::GetPosition() const
 {
 {
     dVector3 pos;
     dVector3 pos;
     
     
@@ -231,18 +228,20 @@ Vector3 Joint::GetWorldPosition() const
         {
         {
         case dJointTypeBall:
         case dJointTypeBall:
             dJointGetBallAnchor(joint_, pos);
             dJointGetBallAnchor(joint_, pos);
-            return Vector3(pos[0], pos[1], pos[2]);
+            position_ = Vector3(pos[0], pos[1], pos[2]);
+            break;
             
             
         case dJointTypeHinge:
         case dJointTypeHinge:
             dJointGetHingeAnchor(joint_, pos);
             dJointGetHingeAnchor(joint_, pos);
-            return Vector3(pos[0], pos[1], pos[2]);
+            position_ = Vector3(pos[0], pos[1], pos[2]);
+            break;
         }
         }
     }
     }
     
     
-    return Vector3::ZERO;
+    return position_;
 }
 }
 
 
-Vector3 Joint::GetWorldAxis() const
+const Vector3& Joint::GetAxis() const
 {
 {
     dVector3 axis;
     dVector3 axis;
     
     
@@ -254,11 +253,41 @@ Vector3 Joint::GetWorldAxis() const
         {
         {
         case dJointTypeHinge:
         case dJointTypeHinge:
             dJointGetHingeAxis(joint_, axis);
             dJointGetHingeAxis(joint_, axis);
-            return Vector3(axis[0], axis[1], axis[2]);
+            axis_ = Vector3(axis[0], axis[1], axis[2]);
+            break;
         }
         }
     }
     }
     
     
-    return Vector3::ZERO;
+    return axis_;
+}
+
+void Joint::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
+{
+    if (debug && joint_ && ownBody_)
+    {
+        const Vector3& jointPos = GetPosition();
+        const Vector3& ownBodyPos = ownBody_->GetPosition();
+        const Vector3& otherBodyPos = otherBody_ ? otherBody_->GetPosition() : Vector3::ZERO;
+        
+        BoundingBox jointBox;
+        jointBox.Merge(jointPos);
+        jointBox.Merge(ownBodyPos);
+        if (otherBody_)
+            jointBox.Merge(otherBodyPos);
+        
+        if (debug->IsInside(jointBox))
+        {
+            debug->AddLine(jointPos, ownBodyPos, Color::YELLOW, depthTest);
+            if (otherBody_)
+                debug->AddLine(jointPos, otherBodyPos, Color::YELLOW, depthTest);
+            
+            if (type_ == JOINT_HINGE)
+            {
+                const Vector3& axis = GetAxis();
+                debug->AddLine(jointPos + 0.1f * axis, jointPos - 0.1f * axis, Color::WHITE, depthTest);
+            }
+        }
+    }
 }
 }
 
 
 void Joint::OnNodeSet(Node* node)
 void Joint::OnNodeSet(Node* node)
@@ -273,12 +302,8 @@ void Joint::OnNodeSet(Node* node)
                 physicsWorld_->AddJoint(this);
                 physicsWorld_->AddJoint(this);
         }
         }
         node->AddListener(this);
         node->AddListener(this);
+        
+        // Set default position at the node
+        position_ = node->GetWorldPosition();
     }
     }
 }
 }
-
-void Joint::OnMarkedDirty(Node* node)
-{
-    // Reapply position if scale changed
-    if (node_->GetWorldScale() != jointScale_)
-        SetPosition(position_);
-}

+ 13 - 18
Engine/Physics/Joint.h

@@ -64,10 +64,10 @@ public:
     bool SetJointType(JointType type);
     bool SetJointType(JointType type);
     /// %Set other body to connect to.
     /// %Set other body to connect to.
     void SetOtherBody(RigidBody* body);
     void SetOtherBody(RigidBody* body);
-    /// %Set joint local-space position.
-    void SetPosition(Vector3 position);
-    /// %Set joint local-space axis.
-    void SetAxis(Vector3 axis);
+    /// %Set joint world-space position.
+    void SetPosition(const Vector3& position);
+    /// %Set joint world-space axis.
+    void SetAxis(const Vector3& axis);
     
     
     /// Return physics world.
     /// Return physics world.
     PhysicsWorld* GetPhysicsWorld() const { return physicsWorld_; }
     PhysicsWorld* GetPhysicsWorld() const { return physicsWorld_; }
@@ -79,20 +79,17 @@ public:
     RigidBody* GetOtherBody() const { return otherBody_; }
     RigidBody* GetOtherBody() const { return otherBody_; }
     /// Return the ODE joint ID.
     /// Return the ODE joint ID.
     dJointID GetJoint() const { return joint_; }
     dJointID GetJoint() const { return joint_; }
-    /// 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.
     /// Return joint world-space position.
-    Vector3 GetWorldPosition() const;
+    const Vector3& GetPosition() const;
     /// Return joint world-space axis.
     /// Return joint world-space axis.
-    Vector3 GetWorldAxis() const;
+    const Vector3& GetAxis() const;
+    
+    /// Add debug geometry to the debug renderer.
+    void DrawDebugGeometry(DebugRenderer* debug, bool depthTest);
     
     
 protected:
 protected:
     /// Handle node being assigned.
     /// Handle node being assigned.
     virtual void OnNodeSet(Node* node);
     virtual void OnNodeSet(Node* node);
-    /// Handle node transform being dirtied.
-    virtual void OnMarkedDirty(Node* node);
     
     
 private:
 private:
     /// Physics world.
     /// Physics world.
@@ -105,12 +102,10 @@ private:
     JointType type_;
     JointType type_;
     /// ODE joint ID.
     /// ODE joint ID.
     dJointID joint_;
     dJointID joint_;
-    /// Joint local-space position.
-    Vector3 position_;
-    /// Joint local-space axis.
-    Vector3 axis_;
-    /// Cached world scale of node.
-    Vector3 jointScale_;
+    /// Joint world-space position.
+    mutable Vector3 position_;
+    /// Joint world-space axis.
+    mutable Vector3 axis_;
     /// Other body node ID for pending joint recreation.
     /// Other body node ID for pending joint recreation.
     int otherBodyNodeID_;
     int otherBodyNodeID_;
     /// Recreate joint flag.
     /// Recreate joint flag.

+ 8 - 5
Engine/Physics/PhysicsWorld.cpp

@@ -491,11 +491,14 @@ void PhysicsWorld::DrawDebugGeometry(bool depthTest)
     PROFILE(PhysicsDrawDebug);
     PROFILE(PhysicsDrawDebug);
     
     
     DebugRenderer* debug = GetComponent<DebugRenderer>();
     DebugRenderer* debug = GetComponent<DebugRenderer>();
-    if (!debug)
-        return;
-    
-    for (PODVector<CollisionShape*>::Iterator i = collisionShapes_.Begin(); i != collisionShapes_.End(); ++i)
-        (*i)->DrawDebugGeometry(debug, depthTest);
+    if (debug)
+    {
+        for (PODVector<CollisionShape*>::Iterator i = collisionShapes_.Begin(); i != collisionShapes_.End(); ++i)
+            (*i)->DrawDebugGeometry(debug, depthTest);
+        
+        for (PODVector<Joint*>::Iterator i = joints_.Begin(); i != joints_.End(); ++i)
+            (*i)->DrawDebugGeometry(debug, depthTest);
+    }
 }
 }
 
 
 void PhysicsWorld::CleanupGeometryCache()
 void PhysicsWorld::CleanupGeometryCache()

+ 5 - 5
Engine/Physics/RigidBody.h

@@ -49,11 +49,11 @@ public:
     void SetMass(float mass);
     void SetMass(float mass);
     /// %Set mass axis for the cylinder and capsule shapes. By default 1 (Y-axis.)
     /// %Set mass axis for the cylinder and capsule shapes. By default 1 (Y-axis.)
     void SetMassAxis(int axis);
     void SetMassAxis(int axis);
-    /// %Set physics position.
+    /// %Set rigid body world-space position.
     void SetPosition(const Vector3& position);
     void SetPosition(const Vector3& position);
-    /// %Set physics rotation.
+    /// %Set rigid body world-space rotation.
     void SetRotation(const Quaternion& rotation);
     void SetRotation(const Quaternion& rotation);
-    /// %Set physics transform.
+    /// %Set rigid body world-space position and rotation.
     void SetTransform(const Vector3& position, const Quaternion& rotation);
     void SetTransform(const Vector3& position, const Quaternion& rotation);
     /// %Set linear velocity.
     /// %Set linear velocity.
     void SetLinearVelocity(const Vector3& velocity);
     void SetLinearVelocity(const Vector3& velocity);
@@ -94,9 +94,9 @@ public:
     int GetMassAxis() const { return massAxis_; }
     int GetMassAxis() const { return massAxis_; }
     /// Return ODE body ID.
     /// Return ODE body ID.
     dBodyID GetBody() const { return body_; }
     dBodyID GetBody() const { return body_; }
-    /// Return physics position.
+    /// Return rigid body world-space position.
     const Vector3& GetPosition() const;
     const Vector3& GetPosition() const;
-    /// Return physics rotation.
+    /// Return rigid body world-space rotation.
     const Quaternion& GetRotation() const;
     const Quaternion& GetRotation() const;
     /// Return linear velocity.
     /// Return linear velocity.
     const Vector3& GetLinearVelocity() const;
     const Vector3& GetLinearVelocity() const;