diff --git a/ScriptingAPI-Documentation.md b/ScriptingAPI-Documentation.md index aba556454..9cce7a2fe 100644 --- a/ScriptingAPI-Documentation.md +++ b/ScriptingAPI-Documentation.md @@ -115,6 +115,7 @@ You can use the Renderer with the following functions, all of which are in the g - SetPointLightShadowProps(int shadowMapCount, int resolution) - SetSpotLightShadowProps(int shadowMapCount, int resolution) - SetDebugBoxesEnabled(bool enabled) +- SetDebugBonesEnabled(bool enabled) - SetVSyncEnabled(opt bool enabled) - SetPhysicsParams(opt bool rigidBodyPhysicsEnabled, opt bool softBodyPhysicsEnabled, opt int softBodyIterationCount) - Pick(Ray ray, opt PICKTYPE pickType) : Object? object, Vector position,normal, float distance @@ -308,7 +309,7 @@ It inherits functions from Transform. - GetFrame() : float? result - GetFrameCount() : float? result - IsValid() : boolean result -- ChangeAction(String name) +- ChangeAction(String name, opt float blendFrames) - StopAction() - PauseAction() - PlayAction() diff --git a/WickedEngine/wiLoader.cpp b/WickedEngine/wiLoader.cpp index 6f6adbeb1..2258c316c 100644 --- a/WickedEngine/wiLoader.cpp +++ b/WickedEngine/wiLoader.cpp @@ -530,23 +530,9 @@ void LoadWiArmatures(const string& directory, const string& name, const string& file.close(); + //CREATE FAMILY for(Armature* armature : armatures){ - //for(int i=0;iboneCollection.size();i++){ - // string parent = armature->boneCollection[i]->parentName; - // if(parent.length()>0){ - // for(int j=0;jboneCollection.size();j++) - // if(!armature->boneCollection[j].name.compare(parent)){ - // armature->boneCollection[i].parentI=j; - // armature->boneCollection[j].children.push_back(armature->boneCollection[i].name); - // armature->boneCollection[j].childrenI.push_back(i); - // } - // } - // else{ - // armature->rootbones.push_back(i); - // } - //} - for(Bone* i : armature->boneCollection){ if(i->parentName.length()>0){ for(Bone* j : armature->boneCollection){ diff --git a/WickedEngine/wiLoader.h b/WickedEngine/wiLoader.h index 0db9f226a..9aef022f3 100644 --- a/WickedEngine/wiLoader.h +++ b/WickedEngine/wiLoader.h @@ -596,26 +596,10 @@ struct Bone : public Transform childrenI.resize(0); actionFrames.resize(0); length=1.0f; - //XMStoreFloat4x4( &world,XMMatrixIdentity() ); - //XMStoreFloat4x4( &worldPrev,XMMatrixIdentity() ); - //XMStoreFloat4x4( &recursivePose,XMMatrixIdentity() ); - //XMStoreFloat4x4( &recursiveRest,XMMatrixIdentity() ); - //XMStoreFloat4x4( &recursiveRestInv,XMMatrixIdentity() ); boneRelativity=new XMFLOAT4X4(); boneRelativityPrev=new XMFLOAT4X4(); connected = false; } - //XMFLOAT3 getTailPos(const XMMATRIX& world){ - // XMFLOAT3 pos = XMFLOAT3( 0,0,length ); - // XMVECTOR _pos = XMLoadFloat3( &pos ); - // XMVECTOR restedPos = XMVector3Transform( _pos,XMMatrixInverse( 0,XMMatrixTranspose(XMLoadFloat4x4(&rest) )) ); - // XMVECTOR posedPos = XMVector3Transform( restedPos,XMMatrixTranspose(XMLoadFloat4x4(&poseFrame)) ); - // XMVECTOR worldPos = XMVector3Transform( posedPos,world ); - // XMFLOAT3 finalPos; - // XMStoreFloat3( &finalPos, worldPos ); - - // return finalPos; - //} void CleanUp(){ childrenN.clear(); childrenI.clear(); @@ -635,11 +619,21 @@ public: vector rootbones; int activeAction, prevAction; - float currentFrame, prevActionResolveFrame; + float currentFrame; vector actions; bool playing; + + // for the calculation of the blendFact + float blendCurrentFrame; + // how many frames should the blend finish in + float blendFrames; + // [0,1] 0: prev; 1: current + float blendFact; + // animate prev action and blend with current bone set + float currentFramePrevAction; + Armature(){} Armature(string newName,string identifier):Transform(){ unidentified_name=newName; @@ -650,28 +644,39 @@ public: rootbones.resize(0); activeAction=prevAction=0; currentFrame=0; - prevActionResolveFrame=0; actions.resize(0); XMStoreFloat4x4(&world,XMMatrixIdentity()); playing = true; + blendCurrentFrame = 0.0f; + blendFrames = 0.0f; + blendFact = 0.0f; + currentFramePrevAction = 0.0f; } void CleanUp(){ actions.clear(); - for(Bone* b:boneCollection) + for (Bone* b : boneCollection) + { b->CleanUp(); + delete b; + } boneCollection.clear(); rootbones.clear(); } - bool ChangeAction(const string& actionName) + bool ChangeAction(const string& actionName, float blendFrames = 0.0f) { int i = 0; for (Action& x : actions) { if (!x.name.compare(actionName)) { + currentFramePrevAction = currentFrame; + ResetAction(); prevAction = activeAction; activeAction = i; + this->blendFrames = blendFrames; + blendFact = 0.0f; + blendCurrentFrame = 0.0f; return true; } i++; @@ -682,6 +687,10 @@ public: { currentFrame = 1; } + void ResetActionPrev() + { + currentFramePrevAction = 1; + } void PauseAction() { playing = false; @@ -1000,7 +1009,7 @@ static const int RESOLUTION = 36; - +// Create rest positions for bone tree void RecursiveRest(Armature* armature, Bone* bone); void LoadWiArmatures(const string& directory, const string& filename, const string& identifier, vector& armatures diff --git a/WickedEngine/wiLoader_BindLua.cpp b/WickedEngine/wiLoader_BindLua.cpp index 180d6d0e3..39d4fcb05 100644 --- a/WickedEngine/wiLoader_BindLua.cpp +++ b/WickedEngine/wiLoader_BindLua.cpp @@ -772,21 +772,26 @@ int Armature_BindLua::ChangeAction(lua_State* L) { if (armature == nullptr) { - wiLua::SError(L, "ChangeAction(String name) armature is null!"); + wiLua::SError(L, "ChangeAction(String name, opt float blendFrames=0) armature is null!"); return 0; } int argc = wiLua::SGetArgCount(L); if (argc > 0) { string armatureName = wiLua::SGetString(L, 1); - if (!armature->ChangeAction(armatureName)) + float blendFrames = 0.0f; + if (argc > 1) { - wiLua::SError(L, "ChangeAction(String name) action not found!"); + blendFrames = wiLua::SGetFloat(L, 2); + } + if (!armature->ChangeAction(armatureName,blendFrames)) + { + wiLua::SError(L, "ChangeAction(String name, opt float blendFrames=0) action not found!"); } } else { - wiLua::SError(L, "ChangeAction(String name) not enough arguments!"); + wiLua::SError(L, "ChangeAction(String name, opt float blendFrames=0) not enough arguments!"); } return 0; } diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index a9184d618..460fd77a9 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -1691,17 +1691,30 @@ Light* wiRenderer::getLightByName(const string& name) } void wiRenderer::RecursiveBoneTransform(Armature* armature, Bone* bone, const XMMATRIX& parentCombinedMat){ - float cf = armature->currentFrame; - float prevActionResolveFrame = armature->prevActionResolveFrame; - int maxCf = 0; - int activeAction = armature->activeAction; - int prevAction = armature->prevAction; - Bone* parent = (Bone*)bone->parent; - - XMVECTOR& finalTrans = InterPolateKeyFrames(cf,maxCf,bone->actionFrames[activeAction].keyframesPos,POSITIONKEYFRAMETYPE); - XMVECTOR& finalRotat = InterPolateKeyFrames(cf,maxCf,bone->actionFrames[activeAction].keyframesRot,ROTATIONKEYFRAMETYPE); - XMVECTOR& finalScala = InterPolateKeyFrames(cf,maxCf,bone->actionFrames[activeAction].keyframesSca,SCALARKEYFRAMETYPE); + float cf = armature->currentFrame, cfPrev = armature->currentFramePrevAction; + int activeAction = armature->activeAction, prevAction = armature->prevAction; + int maxCf = armature->actions[activeAction].frameCount, maxCfPrev = armature->actions[prevAction].frameCount; + Bone* parent = (Bone*)bone->parent; + +#if 1 + XMVECTOR& prevTrans = InterPolateKeyFrames(cfPrev, maxCfPrev, bone->actionFrames[prevAction].keyframesPos, POSITIONKEYFRAMETYPE); + XMVECTOR& prevRotat = InterPolateKeyFrames(cfPrev, maxCfPrev, bone->actionFrames[prevAction].keyframesRot, ROTATIONKEYFRAMETYPE); + XMVECTOR& prevScala = InterPolateKeyFrames(cfPrev, maxCfPrev, bone->actionFrames[prevAction].keyframesSca, SCALARKEYFRAMETYPE); + + XMVECTOR& currTrans = InterPolateKeyFrames(cf, maxCf, bone->actionFrames[activeAction].keyframesPos, POSITIONKEYFRAMETYPE); + XMVECTOR& currRotat = InterPolateKeyFrames(cf, maxCf, bone->actionFrames[activeAction].keyframesRot, ROTATIONKEYFRAMETYPE); + XMVECTOR& currScala = InterPolateKeyFrames(cf, maxCf, bone->actionFrames[activeAction].keyframesSca, SCALARKEYFRAMETYPE); + + float blendFact = armature->blendFact; + XMVECTOR& finalTrans = XMVectorLerp(prevTrans, currTrans, blendFact); + XMVECTOR& finalRotat = XMQuaternionSlerp(prevRotat, currRotat, blendFact); + XMVECTOR& finalScala = XMVectorLerp(prevScala, currScala, blendFact); +#else + XMVECTOR& finalTrans = InterPolateKeyFrames(cf, maxCf, bone->actionFrames[activeAction].keyframesPos, POSITIONKEYFRAMETYPE); + XMVECTOR& finalRotat = InterPolateKeyFrames(cf, maxCf, bone->actionFrames[activeAction].keyframesRot, ROTATIONKEYFRAMETYPE); + XMVECTOR& finalScala = InterPolateKeyFrames(cf, maxCf, bone->actionFrames[activeAction].keyframesSca, SCALARKEYFRAMETYPE); +#endif bone->worldPrev = bone->world; bone->translationPrev = bone->translation; @@ -1737,7 +1750,7 @@ void wiRenderer::RecursiveBoneTransform(Armature* armature, Bone* bone, const XM } } -XMVECTOR wiRenderer::InterPolateKeyFrames(float cf, const int& maxCf, const vector& keyframeList, KeyFrameType type) +XMVECTOR wiRenderer::InterPolateKeyFrames(float cf, const int maxCf, const vector& keyframeList, KeyFrameType type) { XMVECTOR result = XMVectorSet(0,0,0,0); @@ -1908,17 +1921,16 @@ void wiRenderer::Update(float amount) { for(Armature* armature : armatures){ if(armature->actions.size()){ - //XMMATRIX world = XMMatrixScalingFromVector(XMLoadFloat3(&armature->scale))*XMMatrixRotationQuaternion(XMLoadFloat4(&armature->rotation))*XMMatrixTranslationFromVector(XMLoadFloat3(&armature->translation)); - //XMStoreFloat4x4( &armature->world,world ); XMMATRIX world = armature->getTransform(); + // current action float cf = armature->currentFrame; - float prevActionResolveFrame = armature->prevActionResolveFrame; int maxCf = 0; int activeAction = armature->activeAction; int prevAction = armature->prevAction; + float frameInc = (armature->playing ? amount : 0.f); - cf = armature->currentFrame += (armature->playing ? amount : 0.f); + cf = armature->currentFrame += frameInc; maxCf = armature->actions[activeAction].frameCount; if ((int)cf > maxCf) { @@ -1926,11 +1938,27 @@ void wiRenderer::Update(float amount) cf = armature->currentFrame; } + + // prev action + float cfPrevAction = armature->currentFramePrevAction; + int maxCfPrevAction = armature->actions[prevAction].frameCount; + cfPrevAction = armature->currentFramePrevAction += frameInc; + if ((int)cfPrevAction > maxCfPrevAction) { - for (unsigned int j = 0; jrootbones.size(); ++j){ - RecursiveBoneTransform(armature,armature->rootbones[j],world); - } + armature->ResetActionPrev(); + cfPrevAction = armature->currentFramePrevAction; } + + // blending + armature->blendCurrentFrame += frameInc; + armature->blendFact = wiMath::Clamp(armature->blendCurrentFrame / armature->blendFrames, 0, 1); + + + // calculate frame + for (unsigned int j = 0; jrootbones.size(); ++j) { + RecursiveBoneTransform(armature, armature->rootbones[j], world); + } + } } diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index 41315a11d..4082299cb 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -357,7 +357,7 @@ protected: static void RecursiveBoneTransform(Armature* armature, Bone* bone, const XMMATRIX& parentCombinedMat); - static XMVECTOR InterPolateKeyFrames(float currentFrame, const int& frameCount,const std::vector& keyframes, KeyFrameType type); + static XMVECTOR InterPolateKeyFrames(float currentFrame, const int frameCount,const std::vector& keyframes, KeyFrameType type); static Vertex TransformVertex(const Mesh* mesh, int vertexI, const XMMATRIX& mat=XMMatrixIdentity()); static Vertex TransformVertex(const Mesh* mesh, const SkinnedVertex& vertex, const XMMATRIX& mat = XMMatrixIdentity()); static XMFLOAT3 VertexVelocity(const Mesh* mesh, const int& vertexI); diff --git a/WickedEngine/wiRenderer_BindLua.cpp b/WickedEngine/wiRenderer_BindLua.cpp index 2a9a97635..07e352f9d 100644 --- a/WickedEngine/wiRenderer_BindLua.cpp +++ b/WickedEngine/wiRenderer_BindLua.cpp @@ -385,6 +385,15 @@ namespace wiRenderer_BindLua } return 0; } + int SetDebugBonesEnabled(lua_State* L) + { + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + wiRenderer::SetToDrawDebugBoneLines(wiLua::SGetBool(L, 1)); + } + return 0; + } int SetVSyncEnabled(lua_State* L) { int argc = wiLua::SGetArgCount(L); @@ -534,6 +543,7 @@ namespace wiRenderer_BindLua wiLua::GetGlobal()->RegisterFunc("SetPointLightShadowProps", SetPointLightShadowProps); wiLua::GetGlobal()->RegisterFunc("SetSpotLightShadowProps", SetSpotLightShadowProps); wiLua::GetGlobal()->RegisterFunc("SetDebugBoxesEnabled", SetDebugBoxesEnabled); + wiLua::GetGlobal()->RegisterFunc("SetDebugBonesEnabled", SetDebugBonesEnabled); wiLua::GetGlobal()->RegisterFunc("SetVSyncEnabled", SetVSyncEnabled); wiLua::GetGlobal()->RegisterFunc("SetPhysicsParams", SetPhysicsParams); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 691e26d32..d13fed6d0 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -5,9 +5,9 @@ namespace wiVersion // major features const int major = 0; // minor features, major bug fixes - const int minor = 1; + const int minor = 2; // minor bug fixes, alterations - const int revision = 2; + const int revision = 0; long GetVersion()