Browse Source

Fixing build on windows, fixing segfault in release builds

TheComet 8 years ago
parent
commit
327965a40c

+ 1 - 1
Source/Samples/45_InverseKinematics/InverseKinematics.cpp

@@ -138,7 +138,7 @@ void InverseKinematics::CreateScene()
     // possible to the effectors for optimal performance. Since in this case
     // we're solving the legs only, we can place the solver at the spine.
     Node* spine = jackNode_->GetChild("Bip01_Spine", true);
-    solver_ = spine->CreateComponent<IKSolver>();
+    solver_ = jackNode_->CreateComponent<IKSolver>();
 
     // Disable auto-solving, which means we need to call Solve() manually
     solver_->EnableAutoSolve(false);

+ 5 - 2
Source/ThirdParty/ik/cmake/Urho3D/CMakeLists.txt

@@ -19,6 +19,11 @@
 # THE SOFTWARE.
 #
 
+include (CheckIncludeFiles)
+
+set (IK_BUILD_TYPE "STATIC")
+check_include_files ("stdint.h" HAVE_STDINT_H)
+
 # memory debugging
 if (CMAKE_BUILD_TYPE MATCHES Debug)
     option (IK_MEMORY_DEBUGGING "Global switch for memory options. Keeps track of the number of allocations and de-allocations and prints a report when the program shuts down" ON)
@@ -38,8 +43,6 @@ endif ()
 set (IK_REAL "float" CACHE STRING "Type to use for real numbers")
 option (IK_DOT_OUTPUT "When enabled, the generated chains are dumped to DOT for debug purposes" OFF)
 
-set (EXPORT_H_TEMPLATE )
-
 configure_file ("../../ik/include/ik/export.h.in"
                 "../../include/ik/gen/export.h")
 configure_file ("../../ik/include/ik/config.h.in"

+ 15 - 14
Source/ThirdParty/ik/ik/CMakeLists.txt

@@ -1,5 +1,7 @@
-set (PROJECT_NAME "IK")
-set (BUILD_TYPE "STATIC")
+include (CheckIncludeFiles)
+
+set (IK_BUILD_TYPE "STATIC")
+check_include_files ("stdint.h" HAVE_STDINT_H)
 
 # memory debugging
 if (CMAKE_BUILD_TYPE MATCHES Debug)
@@ -65,7 +67,7 @@ list (APPEND IK_SOURCES ${IK_PLATFORM_SOURCES})
 
 include_directories ("include")
 
-add_library (ik ${BUILD_TYPE}
+add_library (ik ${IK_BUILD_TYPE}
     ${IK_HEADERS}
     ${IK_SOURCES}
 )
@@ -77,14 +79,13 @@ add_definitions (-DIK_BUILDING)
 # install targets
 ###############################################################################
 
-# only install if shared library
-if (${BUILD_TYPE} STREQUAL "SHARED")
-    install (
-        TARGETS
-            ik
-        LIBRARY DESTINATION
-            "lib"
-        RUNTIME DESTINATION
-            "bin"
-    )
-endif ()
+install (
+    TARGETS
+        ik
+    LIBRARY DESTINATION
+        "lib"
+    RUNTIME DESTINATION
+        "bin"
+    ARCHIVE DESTINATION
+        "lib"
+)

+ 0 - 1
Source/ThirdParty/ik/ik/include/ik/backtrace.h

@@ -4,7 +4,6 @@
 #define BACKTRACE_SIZE 64
 
 #include "ik/gen/config.h"
-#include "ik/pstdint.h"
 
 C_HEADER_BEGIN
 

+ 0 - 1
Source/ThirdParty/ik/ik/include/ik/bst_vector.h

@@ -8,7 +8,6 @@
 #ifndef IK_BST_VECTOR_H
 #define IK_BST_VECTOR_H
 
-#include "ik/pstdint.h"
 #include "ik/gen/config.h"
 #include "ik/ordered_vector.h"
 

+ 14 - 5
Source/ThirdParty/ik/ik/include/ik/config.h.in

@@ -5,18 +5,14 @@
 #ifndef IK_CONFIG_HPP
 #   define IK_CONFIG_HPP
 
-#   include "ik/gen/export.h"
-
     /* --------------------------------------------------------------
      * build settings
      * --------------------------------------------------------------*/
 
 #   define OFF    0
 #   define ON     1
-#   define SHARED 2
-#   define STATIC 3
 
-#   define IK_BUILD_TYPE STATIC
+#   define HAVE_STDINT_H @HAVE_STDINT_H@
 #   define ik_real @IK_REAL@
 #   define IK_MEMORY_DEBUGGING @IK_MEMORY_DEBUGGING@
 #   if IK_MEMORY_DEBUGGING == ON
@@ -24,4 +20,17 @@
 #   endif
 #   define IK_DOT_OUTPUT @IK_DOT_OUTPUT@
 
+    /* --------------------------------------------------------------
+     * common include files
+     * --------------------------------------------------------------*/
+
+#   include "ik/gen/export.h"
+#   include <stddef.h>
+
+#   if HAVE_STDINT_H == ON
+#       include <stdint.h>
+#   else
+#       include "ik/pstdint.h"
+#   endif
+
 #endif /* IK_CONFIG_HPP */

+ 0 - 1
Source/ThirdParty/ik/ik/include/ik/effector.h

@@ -2,7 +2,6 @@
 #define EFFECTOR_H
 
 #include "ik/gen/config.h"
-#include "ik/pstdint.h"
 #include "ik/vec3.h"
 #include "ik/quat.h"
 

+ 1 - 1
Source/ThirdParty/ik/ik/include/ik/export.h.in

@@ -14,7 +14,7 @@
 #   define IK_EXPORT_H
 
     /* set @BUILD_TYPE@ to SHARED or STATIC */
-#   define IK_STATIC
+#   define IK_@IK_BUILD_TYPE@
 
     /* --------------------------------------------------------------
      * define visibility macros

+ 0 - 1
Source/ThirdParty/ik/ik/include/ik/memory.h

@@ -2,7 +2,6 @@
 #define MEMORY_H
 
 #include "ik/gen/config.h"
-#include "ik/pstdint.h"
 
 #if IK_MEMORY_DEBUGGING == ON
 #   define MALLOC malloc_wrapper

+ 0 - 1
Source/ThirdParty/ik/ik/include/ik/node.h

@@ -2,7 +2,6 @@
 #define IK_NODE_H
 
 #include "ik/gen/config.h"
-#include "ik/pstdint.h"
 #include "ik/bst_vector.h"
 #include "ik/vec3.h"
 #include "ik/quat.h"

+ 0 - 1
Source/ThirdParty/ik/ik/include/ik/ordered_vector.h

@@ -12,7 +12,6 @@
 #define ORDERED_VECTOR_H
 
 #include "ik/gen/config.h"
-#include "ik/pstdint.h"
 
 C_HEADER_BEGIN
 

+ 0 - 1
Source/ThirdParty/ik/ik/include/ik/solver.h

@@ -2,7 +2,6 @@
 #define IK_SOLVER_H
 
 #include "ik/gen/config.h"
-#include "ik/pstdint.h"
 #include "ik/ordered_vector.h"
 #include "ik/vec3.h"
 #include "ik/quat.h"

+ 1 - 1
Source/ThirdParty/ik/ik/src/node.c

@@ -87,7 +87,7 @@ ik_node_unlink(struct ik_node_t* node)
     if(node->parent == NULL)
         return;
 
-    assert(node == bstv_erase(&node->parent->children, node->guid));
+    bstv_erase(&node->parent->children, node->guid);
     node->parent = NULL;
 }
 

+ 0 - 4
Source/Urho3D/Core/Context.cpp

@@ -33,10 +33,6 @@
 #endif
 
 #ifdef URHO3D_IK
-// Hopefully fixes issue on windows where ik/pstdint.h redefines int32_t
-#if defined(HAVE_STDINT_H)
-#define _PSTDINT_H_INCLUDED
-#endif
 #include <ik/memory.h>
 #include <ik/log.h>
 #endif

+ 1 - 0
Source/Urho3D/IK/IKEffector.h

@@ -75,6 +75,7 @@ public:
      * @brief Sets the name of the target node. The node doesn't necessarily
      * have to exist in the scene graph. When a node is created that matches
      * this name, it is selected as the target.
+     * @note This clears the existing target node.
      */
     void SetTargetName(const String& nodeName);
 

+ 10 - 7
Source/Urho3D/IK/IKSolver.cpp

@@ -39,6 +39,7 @@
 #include <ik/solver.h>
 #include <ik/node.h>
 #include <ik/effector.h>
+#include <ik/log.h>
 
 namespace Urho3D
 {
@@ -319,7 +320,7 @@ void IKSolver::OnNodeSet(Node* node)
     DestroyTree();
 
     if (node != NULL)
-        BuildTree();
+        RebuildTree();
 }
 
 // ----------------------------------------------------------------------------
@@ -348,7 +349,7 @@ void IKSolver::DestroyTree()
 }
 
 // ----------------------------------------------------------------------------
-void IKSolver::BuildTree()
+void IKSolver::RebuildTree()
 {
     assert(node_ != NULL);
 
@@ -434,6 +435,7 @@ void IKSolver::HandleComponentRemoved(StringHash eventType, VariantMap& eventDat
         IKEffector* effector = static_cast<IKEffector*>(component);
         Node* node = static_cast<Node*>(eventData[P_NODE].GetPtr());
         ik_node_t* ikNode = ik_node_find_child(solver_->tree, node->GetID());
+        assert(ikNode != NULL);
         ik_node_destroy_effector(ikNode);
         effector->SetIKEffector(NULL);
         effectorList_.RemoveSwap(effector);
@@ -484,7 +486,9 @@ void IKSolver::HandleNodeRemoved(StringHash eventType, VariantMap& eventData)
     node->GetChildrenWithComponent<IKEffector>(nodes, true);
     for (PODVector<Node*>::ConstIterator it = nodes.Begin(); it != nodes.End(); ++it)
     {
-        effectorList_.Remove((*it)->GetComponent<IKEffector>());
+        IKEffector* effector = (*it)->GetComponent<IKEffector>();
+        effector->SetIKEffector(NULL);
+        effectorList_.RemoveSwap(effector);
     }
 
     // Special case, if the node being destroyed is the root node, destroy the
@@ -493,14 +497,13 @@ void IKSolver::HandleNodeRemoved(StringHash eventType, VariantMap& eventData)
     ik_node_t* ikNode = ik_node_find_child(solver_->tree, node->GetID());
     if (ikNode != NULL)
     {
-        if(ikNode == solver_->tree)
+        if (ikNode == solver_->tree)
             ik_solver_destroy_tree(solver_);
         else
             ik_node_destroy(ikNode);
-    }
 
-    ResetToInitialPose();
-    MarkSolverTreeDirty();
+        MarkSolverTreeDirty();
+    }
 }
 
 // ----------------------------------------------------------------------------

+ 2 - 2
Source/Urho3D/IK/IKSolver.h

@@ -231,8 +231,8 @@ private:
 
     /// Destroys the solver's tree
     void DestroyTree();
-    /// Builds the solver's tree to match the scene graph's tree
-    void BuildTree();
+    /// Builds the solver's tree to match the scene graph's tree. If a tree already exists, it is first destroyed
+    void RebuildTree();
     /// Builds a chain of nodes up to the specified node and adds an effector. Thus, the specified node must have an IKEffector attached.
     void BuildTreeToEffector(const Node* node);
 

+ 6 - 0
Source/Urho3D/LuaScript/LuaScript.cpp

@@ -63,6 +63,9 @@ extern int tolua_NetworkLuaAPI_open(lua_State*);
 #ifdef URHO3D_DATABASE
 extern int tolua_DatabaseLuaAPI_open(lua_State*);
 #endif
+#ifdef URHO3D_IK
+extern int tolua_IKLuaAPI_open(lua_State*);
+#endif
 #ifdef URHO3D_PHYSICS
 extern int tolua_PhysicsLuaAPI_open(lua_State*);
 #endif
@@ -115,6 +118,9 @@ LuaScript::LuaScript(Context* context) :
 #ifdef URHO3D_DATABASE
     tolua_DatabaseLuaAPI_open(luaState_);
 #endif
+#ifdef URHO3D_IK
+    tolua_IKLuaAPI_open(luaState_);
+#endif
 #ifdef URHO3D_PHYSICS
     tolua_PhysicsLuaAPI_open(luaState_);
 #endif

+ 9 - 3
Source/Urho3D/LuaScript/pkgs/IK/IKEffector.pkg

@@ -14,9 +14,6 @@ class IKEffector : public Component
     const Quaternion& GetTargetRotation() const;
     void SetTargetRotation(const Quaternion& targetRotation);
 
-    Vector3 GetTargetRotationEuler() const;
-    void SetTargetRotationEuler(const Vector3& targetRotation);
-
     unsigned GetChainLength() const;
     void SetChainLength(unsigned chainLength);
 
@@ -34,4 +31,13 @@ class IKEffector : public Component
 
     bool InheritParentRotationEnabled() const;
     void EnableInheritParentRotation(bool enable);
+
+    tolua_property__get_set Node* targetNode;
+    tolua_property__get_set String targetName;
+    tolua_property__get_set Vector3 targetPosition;
+    tolua_property__get_set Quaternion targetRotation;
+    tolua_property__get_set unsigned chainLength;
+    tolua_property__get_set float weight;
+    tolua_property__get_set float rotationWeight;
+    tolua_property__get_set float rotationDecay;
 };

+ 4 - 0
Source/Urho3D/LuaScript/pkgs/IK/IKSolver.pkg

@@ -32,5 +32,9 @@ class IKSolver : public Component
     void Solve();
     void ResetToInitialPose();
     void UpdateInitialPose();
+
+    tolua_property__get_set Algorithm algorithm;
+    tolua_property__get_set unsigned maximumIterations;
+    tolua_property__get_set float tolerance;
 };
 

+ 79 - 30
bin/Data/LuaScripts/45_InverseKinematics.lua

@@ -83,24 +83,21 @@ function CreateScene()
     -- control the grounding.
     leftFoot_  = jackNode_:GetChild("Bip01_L_Foot", true);
     rightFoot_ = jackNode_:GetChild("Bip01_R_Foot", true);
-
-    -- NOTE: Crashes here for some reason
     leftEffector_  = leftFoot_:CreateComponent("IKEffector")
-
-    --rightEffector_ = rightFoot_:CreateComponent("IKEffector")
+    rightEffector_ = rightFoot_:CreateComponent("IKEffector")
     -- Control 2 segments up to the hips
-    --leftEffector_.chainLength = 2;
-    --rightEffector_.chainLength = 2;
+    leftEffector_.chainLength = 2;
+    rightEffector_.chainLength = 2;
 
     -- For the effectors to work, an IKSolver needs to be attached to one of
     -- the parent nodes. Typically, you want to place the solver as close as
     -- possible to the effectors for optimal performance. Since in this case
     -- we're solving the legs only, we can place the solver at the spine.
-    --local spine = jackNode_:GetChild("Bip01_Spine", true);
-    --solver_ = spine:CreateComponent("IKSolver");
+    local spine = jackNode_:GetChild("Bip01_Spine", true);
+    solver_ = spine:CreateComponent("IKSolver");
 
     -- Disable auto-solving, which means we can call Solve() manually.
-    --solver_.autoSolve = false;
+    solver_:EnableAutoSolve(false);
 
     -- When this is enabled, the solver will use the current positions of the
     -- nodes in the skeleton as its basis every frame. If you disable this, then
@@ -108,20 +105,24 @@ function CreateScene()
     -- use those positions for calculating solutions.
     -- With animated characters you generally want to continuously update the
     -- initial positions.
-    --solver_.updatePose = true;
+    solver_:EnableUpdatePose(true);
 
     -- Create the camera.
-    cameraNode = scene_:CreateChild("Camera")
+    cameraRotateNode_ = scene_:CreateChild("CameraRotate")
+    cameraNode = cameraRotateNode_:CreateChild("Camera")
     cameraNode:CreateComponent("Camera")
 
     -- Set an initial position for the camera scene node above the plane
-    cameraNode.position = Vector3(0.0, 2.0, -14.0)
+    cameraNode.position = Vector3(0.0, 0.0, -4.0)
+    cameraRotateNode_.position = Vector3(0.0, 0.4, 0.0)
+    pitch = 20.0
+    yaw = 50.0
 end
 
 function CreateInstructions()
     -- Construct new Text object, set string to display and font to use
     local instructionText = ui.root:CreateChild("Text")
-    instructionText:SetText("Use WASD keys and mouse to move")
+    instructionText:SetText("Left-Click and drag to look around\nRight-Click and drag to change incline\nPress space to reset floor\nPress D to draw debug geometry")
     instructionText:SetFont(cache:GetResource("Font", "Fonts/Anonymous Pro.ttf"), 15)
 
     -- Position the text relative to the screen center
@@ -150,33 +151,43 @@ function UpdateCameraAndFloor(timeStep)
     local MOUSE_SENSITIVITY = 0.1
 
     -- Use this frame's mouse motion to adjust camera node yaw and pitch. Clamp the pitch between -90 and 90 degrees
-    local mouseMove = input.mouseMove
-    yaw = yaw +MOUSE_SENSITIVITY * mouseMove.x
-    pitch = pitch + MOUSE_SENSITIVITY * mouseMove.y
-    pitch = Clamp(pitch, -90.0, 90.0)
+    if input:GetMouseButtonDown(MOUSEB_LEFT) then
+        local mouseMove = input.mouseMove
+        yaw = yaw +MOUSE_SENSITIVITY * mouseMove.x
+        pitch = pitch + MOUSE_SENSITIVITY * mouseMove.y
+        pitch = Clamp(pitch, -90.0, 90.0)
+    end
 
-    -- Construct new orientation for the camera scene node from yaw and pitch. Roll is fixed to zero
-    cameraNode.rotation = Quaternion(pitch, yaw, 0.0)
+    if input:GetMouseButtonDown(MOUSEB_RIGHT) then
+        local mouseMoveInt = input.mouseMove
+        local mouseMove = Vector2()
+        mouseMove.x = -Cos(yaw) * mouseMoveInt.y - Sin(yaw) * mouseMoveInt.x
+        mouseMove.y = Sin(yaw) * mouseMoveInt.y - Cos(yaw) * mouseMoveInt.x
 
-    -- Read WASD keys and move the camera scene node to the corresponding direction if they are pressed
-    -- Use the Translate() function (default local space) to move relative to the node's orientation.
-    if input:GetKeyDown(KEY_W) then
-        cameraNode:Translate(Vector3(0.0, 0.0, 1.0) * MOVE_SPEED * timeStep)
-    end
-    if input:GetKeyDown(KEY_S) then
-        cameraNode:Translate(Vector3(0.0, 0.0, -1.0) * MOVE_SPEED * timeStep)
+        floorPitch_ = floorPitch_ + MOUSE_SENSITIVITY * mouseMove.x
+        floorPitch_ = Clamp(floorPitch_, -90.0, 90.0)
+        floorRoll_ = floorRoll_ + MOUSE_SENSITIVITY * mouseMove.y
     end
-    if input:GetKeyDown(KEY_A) then
-        cameraNode:Translate(Vector3(-1.0, 0.0, 0.0) * MOVE_SPEED * timeStep)
+
+    if input:GetKeyPress(KEY_SPACE) then
+        floorPitch_ = 0.0
+        floorRoll_ = 0.0
     end
-    if input:GetKeyDown(KEY_D) then
-        cameraNode:Translate(Vector3(1.0, 0.0, 0.0) * MOVE_SPEED * timeStep)
+
+    if input:GetKeyPress(KEY_D) then
+        drawDebug_ = not drawDebug_
     end
+
+    -- Construct new orientation for the camera scene node from yaw and pitch. Roll is fixed to zero
+    cameraRotateNode_.rotation = Quaternion(pitch, yaw, 0.0)
+    floorNode_.rotation = Quaternion(floorPitch_, 0.0, floorRoll_)
 end
 
 function SubscribeToEvents()
     -- Subscribe HandleUpdate() function for processing update events
     SubscribeToEvent("Update", "HandleUpdate")
+    SubscribeToEvent("PostRenderUpdate", "HandlePostRenderUpdate")
+    SubscribeToEvent("SceneDrawableUpdateFinished", "HandleSceneDrawableUpdateFinished")
 end
 
 function HandleUpdate(eventType, eventData)
@@ -186,3 +197,41 @@ function HandleUpdate(eventType, eventData)
     -- Move the camera, scale movement with time step
     UpdateCameraAndFloor(timeStep)
 end
+
+function HandlePostRenderUpdate(eventType, eventData)
+    if drawDebug_ then
+        solver_:DrawDebugGeometry(false)
+    end
+end
+
+function HandleSceneDrawableUpdateFinished(eventType, eventData)
+    local physicsWorld = scene_:GetComponent("PhysicsWorld")
+    local leftFootPosition = leftFoot_.worldPosition
+    local rightFootPosition = rightFoot_.worldPosition
+
+    -- Cast ray down to get the normal of the underlying surface
+    local result = physicsWorld:RaycastSingle(Ray(leftFootPosition + Vector3(0, 1, 0), Vector3(0, -1, 0)), 2)
+    if result.body then
+        -- Cast again, but this time along the normal. Set the target position
+        -- to the ray intersection
+        local oppositeNormal = result.normal * -1
+        result = physicsWorld:RaycastSingle(Ray(leftFootPosition + result.normal, oppositeNormal), 2)
+        -- The foot node has an offset relative to the root node
+        footOffset = jackNode_.worldPosition.y + leftFoot_.worldPosition.y
+        leftEffector_.targetPosition = result.position + result.normal * footOffset
+        -- Rotate foot according to normal
+        leftFoot_:Rotate(Quaternion(Vector3(0, 1, 0), result.normal), TS_WORLD)
+    end
+
+    -- Same deal with the right foot
+    result = physicsWorld:RaycastSingle(Ray(rightFootPosition + Vector3(0, 1, 0), Vector3(0, -1, 0)), 2)
+    if result.body then
+        local oppositeNormal = result.normal * -1
+        result = physicsWorld:RaycastSingle(Ray(rightFootPosition + result.normal, oppositeNormal), 2)
+        footOffset = jackNode_.worldPosition.y + rightFoot_.worldPosition.y
+        rightEffector_.targetPosition = result.position + result.normal * footOffset
+        rightFoot_:Rotate(Quaternion(Vector3(0, 1, 0), result.normal), TS_WORLD)
+    end
+
+    solver_:Solve()
+end

+ 4 - 5
bin/Data/Scripts/45_InverseKinematics.as

@@ -167,11 +167,10 @@ void UpdateCameraAndFloor(float timeStep)
     if (input.mouseButtonDown[MOUSEB_RIGHT])
     {
         IntVector2 mouseMoveInt = input.mouseMove;
-        Vector3 mouseMove = Matrix3(
-            -Cos(yaw), Sin(yaw), 0,
-            Sin(yaw),  Cos(yaw), 0,
-            0,         0,        1
-        ) * Vector3(mouseMoveInt.y, -mouseMoveInt.x, 0);
+        Vector2 mouseMove = Matrix2(
+            -Cos(yaw), Sin(yaw),
+            Sin(yaw),  Cos(yaw)
+        ) * Vector2(mouseMoveInt.y, -mouseMoveInt.x);
         floorPitch_ += MOUSE_SENSITIVITY * mouseMove.x;
         floorPitch_ = Clamp(floorPitch_, -90.0f, 90.0f);
         floorRoll_ += MOUSE_SENSITIVITY * mouseMove.y;