From ecfcd4b7bead84af5cafa0660f21a9079c512c0e Mon Sep 17 00:00:00 2001 From: turanszkij Date: Mon, 6 Feb 2017 23:32:16 +0100 Subject: [PATCH] updated skinning, gui and started animation editor --- WickedEngine/AnimationWindow.cpp | 80 +++++++++++++++++++ WickedEngine/AnimationWindow.h | 25 ++++++ WickedEngine/Editor.cpp | 14 ++++ WickedEngine/Editor.h | 2 + WickedEngine/WickedEngineEditor.vcxproj | 2 + .../WickedEngineEditor.vcxproj.filters | 2 + WickedEngine/skinningHF.hlsli | 6 +- WickedEngine/wiLoader.cpp | 10 +++ WickedEngine/wiRenderer.cpp | 66 +++++++-------- WickedEngine/wiVersion.cpp | 2 +- WickedEngine/wiWidget.cpp | 9 +++ WickedEngine/wiWidget.h | 2 + 12 files changed, 178 insertions(+), 42 deletions(-) create mode 100644 WickedEngine/AnimationWindow.cpp create mode 100644 WickedEngine/AnimationWindow.h diff --git a/WickedEngine/AnimationWindow.cpp b/WickedEngine/AnimationWindow.cpp new file mode 100644 index 000000000..a887501d4 --- /dev/null +++ b/WickedEngine/AnimationWindow.cpp @@ -0,0 +1,80 @@ +#include "stdafx.h" +#include "AnimationWindow.h" + + +AnimationWindow::AnimationWindow(wiGUI* gui) :GUI(gui) +{ + assert(GUI && "Invalid GUI!"); + + float screenW = (float)wiRenderer::GetDevice()->GetScreenWidth(); + float screenH = (float)wiRenderer::GetDevice()->GetScreenHeight(); + + + animWindow = new wiWindow(GUI, "Animation Window"); + animWindow->SetSize(XMFLOAT2(700, 300)); + GUI->AddWidget(animWindow); + + float x = 200; + float y = 0; + float step = 35; + + actionsComboBox = new wiComboBox("Actions: "); + actionsComboBox->SetSize(XMFLOAT2(400, 20)); + actionsComboBox->SetPos(XMFLOAT2(x, y += step)); + actionsComboBox->OnSelect([&](wiEventArgs args) { + if (armature != nullptr && args.iValue >= 0) + { + armature->ChangeAction(args.sValue, blendSlider->GetValue()); + } + }); + actionsComboBox->SetEnabled(false); + actionsComboBox->SetTooltip("Choose an animation clip..."); + animWindow->AddWidget(actionsComboBox); + + blendSlider = new wiSlider(0.0f, 60, 0, 100000, "Blend Frames: "); + blendSlider->SetSize(XMFLOAT2(100, 30)); + blendSlider->SetPos(XMFLOAT2(x, y += step)); + blendSlider->OnSlide([&](wiEventArgs args) { + // no operation, will only be queried + }); + blendSlider->SetEnabled(false); + blendSlider->SetTooltip("Adjust the blend length in frames when changing actions..."); + animWindow->AddWidget(blendSlider); + + + animWindow->Translate(XMFLOAT3(100, 50, 0)); + animWindow->SetVisible(false); + + SetArmature(nullptr); +} + + +AnimationWindow::~AnimationWindow() +{ + SAFE_DELETE(animWindow); + SAFE_DELETE(actionsComboBox); + SAFE_DELETE(blendSlider); +} + +void AnimationWindow::SetArmature(Armature* armature) +{ + this->armature = armature; + + if (armature != nullptr) + { + actionsComboBox->ClearItems(); + actionsComboBox->SetEnabled(true); + for (auto& x : armature->actions) + { + actionsComboBox->AddItem(x.name); + } + actionsComboBox->SetSelected(armature->GetPrimaryAnimation()->activeAction); + blendSlider->SetEnabled(true); + } + else + { + actionsComboBox->ClearItems(); + actionsComboBox->SetEnabled(false); + blendSlider->SetEnabled(false); + } +} diff --git a/WickedEngine/AnimationWindow.h b/WickedEngine/AnimationWindow.h new file mode 100644 index 000000000..5e7bddadf --- /dev/null +++ b/WickedEngine/AnimationWindow.h @@ -0,0 +1,25 @@ +#pragma once + +struct Armature; +class wiGUI; +class wiWindow; +class wiLabel; +class wiCheckBox; +class wiSlider; +class wiComboBox; + +class AnimationWindow +{ +public: + AnimationWindow(wiGUI* gui); + ~AnimationWindow(); + + wiGUI* GUI; + Armature* armature; + void SetArmature(Armature* armature); + + wiWindow* animWindow; + wiComboBox* actionsComboBox; + wiSlider* blendSlider; +}; + diff --git a/WickedEngine/Editor.cpp b/WickedEngine/Editor.cpp index bc9f7048a..d5d280ac9 100644 --- a/WickedEngine/Editor.cpp +++ b/WickedEngine/Editor.cpp @@ -12,6 +12,7 @@ #include "EnvProbeWindow.h" #include "DecalWindow.h" #include "LightWindow.h" +#include "AnimationWindow.h" #include // openfile #include @@ -240,6 +241,7 @@ void EditorComponent::Load() envProbeWnd = new EnvProbeWindow(&GetGUI()); decalWnd = new DecalWindow(&GetGUI()); lightWnd = new LightWindow(&GetGUI()); + animWnd = new AnimationWindow(&GetGUI()); float screenW = (float)wiRenderer::GetDevice()->GetScreenWidth(); float screenH = (float)wiRenderer::GetDevice()->GetScreenHeight(); @@ -336,6 +338,15 @@ void EditorComponent::Load() }); GetGUI().AddWidget(lightWnd_Toggle); + wiButton* animWnd_Toggle = new wiButton("Animation"); + animWnd_Toggle->SetTooltip("Animation inspector window"); + animWnd_Toggle->SetPos(XMFLOAT2(x += step, screenH - 40)); + animWnd_Toggle->SetSize(XMFLOAT2(100, 40)); + animWnd_Toggle->OnClick([=](wiEventArgs args) { + animWnd->animWindow->SetVisible(!animWnd->animWindow->IsVisible()); + }); + GetGUI().AddWidget(animWnd_Toggle); + //////////////////////////////////////////////////////////////////////////////////// @@ -840,12 +851,14 @@ void EditorComponent::FixedUpdate() savedParents.erase(picked->object); picked->transform = picked->object->mesh->armature; savedParents.insert(pair(picked->transform, picked->transform->parent)); + animWnd->SetArmature(picked->object->mesh->armature); } } else { meshWnd->SetMesh(nullptr); materialWnd->SetMaterial(nullptr); + animWnd->SetArmature(nullptr); } if (picked->light != nullptr) @@ -1183,6 +1196,7 @@ void EditorComponent::Unload() SAFE_DELETE(cameraWnd); SAFE_DELETE(decalWnd); SAFE_DELETE(lightWnd); + SAFE_DELETE(animWnd); SAFE_DELETE(translator); diff --git a/WickedEngine/Editor.h b/WickedEngine/Editor.h index 0802b791a..cb97f958d 100644 --- a/WickedEngine/Editor.h +++ b/WickedEngine/Editor.h @@ -11,6 +11,7 @@ class RendererWindow; class EnvProbeWindow; class DecalWindow; class LightWindow; +class AnimationWindow; class EditorLoadingScreen : public LoadingScreenComponent { @@ -41,6 +42,7 @@ public: EnvProbeWindow* envProbeWnd; DecalWindow* decalWnd; LightWindow* lightWnd; + AnimationWindow* animWnd; Editor* main; EditorLoadingScreen* loader; diff --git a/WickedEngine/WickedEngineEditor.vcxproj b/WickedEngine/WickedEngineEditor.vcxproj index 3f1bc1aaa..4cb704119 100644 --- a/WickedEngine/WickedEngineEditor.vcxproj +++ b/WickedEngine/WickedEngineEditor.vcxproj @@ -165,6 +165,7 @@ + @@ -182,6 +183,7 @@ + diff --git a/WickedEngine/WickedEngineEditor.vcxproj.filters b/WickedEngine/WickedEngineEditor.vcxproj.filters index a7cd38f93..3497b2c65 100644 --- a/WickedEngine/WickedEngineEditor.vcxproj.filters +++ b/WickedEngine/WickedEngineEditor.vcxproj.filters @@ -79,6 +79,7 @@ Code + @@ -120,6 +121,7 @@ Code + diff --git a/WickedEngine/skinningHF.hlsli b/WickedEngine/skinningHF.hlsli index d8e4ffe5d..4977434c1 100644 --- a/WickedEngine/skinningHF.hlsli +++ b/WickedEngine/skinningHF.hlsli @@ -17,16 +17,12 @@ inline void Skinning(inout float4 pos, inout float4 posPrev, inout float4 inNor, if(any(inWei)) { bonetype sump = 0, sumpPrev = 0; - float sumw = 0.0f; - inWei = normalize(inWei); + [unroll] for (uint i = 0; i < 4; i++) { - sumw += inWei[i]; sump += boneBuffer[(uint)inBon[i]].pose * inWei[i]; sumpPrev += boneBuffer[(uint)inBon[i]].prev * inWei[i]; } - sump /= sumw; - sumpPrev /= sumw; pos = mul(pos, sump); posPrev = mul(posPrev, sumpPrev); inNor.xyz = mul(inNor.xyz, (float3x3)sump); diff --git a/WickedEngine/wiLoader.cpp b/WickedEngine/wiLoader.cpp index a32c214d4..639a979e1 100644 --- a/WickedEngine/wiLoader.cpp +++ b/WickedEngine/wiLoader.cpp @@ -2243,6 +2243,16 @@ void Mesh::CreateVertexArrays() vertices_Complete.resize(vertices.size()); for (size_t i = 0; i < vertices.size(); ++i) { + // normalize bone weights: + float len = vertices[i].wei.x + vertices[i].wei.y + vertices[i].wei.z + vertices[i].wei.w; + if (len > 0) + { + vertices[i].wei.x /= len; + vertices[i].wei.y /= len; + vertices[i].wei.z /= len; + vertices[i].wei.w /= len; + } + // copy the vertex to the unskinned vertex array: vertices_Complete[i].pos = vertices[i].pos; vertices_Complete[i].nor = vertices[i].nor; vertices_Complete[i].tex = vertices[i].tex; diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 37c3d0d78..ee325f08e 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -1308,68 +1308,62 @@ Vertex wiRenderer::TransformVertex(const Mesh* mesh, const SkinnedVertex& vertex ,vertex.bon.z ,vertex.bon.w}; XMMATRIX sump; - if(inWei[0] || inWei[1] || inWei[2] || inWei[3]){ - sump = XMMATRIX(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - float sumw = 0; - for(unsigned int i=0;i<4;i++){ - sumw += inWei[i]; - sump += XMLoadFloat4x4( &mesh->armature->boneCollection[int(inBon[i])]->boneRelativity ) * inWei[i]; + if (inWei[0] || inWei[1] || inWei[2] || inWei[3]) + { + sump = XMMATRIX(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + for (unsigned int i = 0; i < 4; i++) + { + sump += XMLoadFloat4x4(&mesh->armature->boneCollection[int(inBon[i])]->boneRelativity) * inWei[i]; } - if(sumw) sump/=sumw; - - //sump = XMMatrixTranspose(sump); } else + { sump = XMMatrixIdentity(); + } - //sump*=mat; sump = XMMatrixMultiply(sump, mat); XMFLOAT3 transformedP,transformedN; - XMStoreFloat3( &transformedP,XMVector3Transform(pos,sump) ); + XMStoreFloat3(&transformedP, XMVector3Transform(pos, sump)); - sump.r[3]=XMVectorSetX(sump.r[3],0); - sump.r[3]=XMVectorSetY(sump.r[3],0); - sump.r[3]=XMVectorSetZ(sump.r[3],0); - //sump.r[3].m128_f32[0]=sump.r[3].m128_f32[1]=sump.r[3].m128_f32[2]=0; - XMStoreFloat3( &transformedN,XMVector3Normalize(XMVector3Transform(nor,sump))); + XMStoreFloat3(&transformedN, XMVector3Normalize(XMVector3TransformNormal(nor, sump))); Vertex retV(transformedP); - retV.nor = XMFLOAT4(transformedN.x, transformedN.y, transformedN.z,retV.nor.w); + retV.nor = XMFLOAT4(transformedN.x, transformedN.y, transformedN.z, retV.nor.w); retV.tex = vertex.tex; - retV.pre=XMFLOAT4(0,0,0,1); + retV.pre = XMFLOAT4(0, 0, 0, 1); return retV; } -XMFLOAT3 wiRenderer::VertexVelocity(const Mesh* mesh, const int& vertexI){ - XMVECTOR pos = XMLoadFloat4( &mesh->vertices[vertexI].pos ); - float inWei[4]={mesh->vertices[vertexI].wei.x +XMFLOAT3 wiRenderer::VertexVelocity(const Mesh* mesh, const int& vertexI) +{ + XMVECTOR pos = XMLoadFloat4(&mesh->vertices[vertexI].pos); + float inWei[4] = { mesh->vertices[vertexI].wei.x ,mesh->vertices[vertexI].wei.y ,mesh->vertices[vertexI].wei.z - ,mesh->vertices[vertexI].wei.w}; - float inBon[4]={mesh->vertices[vertexI].bon.x + ,mesh->vertices[vertexI].wei.w }; + float inBon[4] = { mesh->vertices[vertexI].bon.x ,mesh->vertices[vertexI].bon.y ,mesh->vertices[vertexI].bon.z - ,mesh->vertices[vertexI].bon.w}; + ,mesh->vertices[vertexI].bon.w }; XMMATRIX sump; XMMATRIX sumpPrev; - if(inWei[0] || inWei[1] || inWei[2] || inWei[3]){ - sump = sumpPrev = XMMATRIX(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); - float sumw = 0; - for(unsigned int i=0;i<4;i++){ - sumw += inWei[i]; - sump += XMLoadFloat4x4( &mesh->armature->boneCollection[int(inBon[i])]->boneRelativity ) * inWei[i]; - sumpPrev += XMLoadFloat4x4( &mesh->armature->boneCollection[int(inBon[i])]->boneRelativityPrev ) * inWei[i]; - } - if(sumw){ - sump/=sumw; - sumpPrev/=sumw; + if (inWei[0] || inWei[1] || inWei[2] || inWei[3]) + { + sump = sumpPrev = XMMATRIX(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + for (unsigned int i = 0; i < 4; i++) + { + sump += XMLoadFloat4x4(&mesh->armature->boneCollection[int(inBon[i])]->boneRelativity) * inWei[i]; + sumpPrev += XMLoadFloat4x4(&mesh->armature->boneCollection[int(inBon[i])]->boneRelativityPrev) * inWei[i]; } } else + { sump = sumpPrev = XMMatrixIdentity(); + } + XMFLOAT3 velocity; - XMStoreFloat3( &velocity,GetGameSpeed()*XMVectorSubtract(XMVector3Transform(pos,sump),XMVector3Transform(pos,sumpPrev)) ); + XMStoreFloat3(&velocity, GetGameSpeed()*XMVectorSubtract(XMVector3Transform(pos, sump), XMVector3Transform(pos, sumpPrev))); return velocity; } void wiRenderer::Update() diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index e88876682..adf1fb4ca 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -7,7 +7,7 @@ namespace wiVersion // minor features, major updates const int minor = 9; // minor bug fixes, alterations, refactors, updates - const int revision = 59; + const int revision = 60; long GetVersion() diff --git a/WickedEngine/wiWidget.cpp b/WickedEngine/wiWidget.cpp index 03daf0d56..220279ec3 100644 --- a/WickedEngine/wiWidget.cpp +++ b/WickedEngine/wiWidget.cpp @@ -892,8 +892,17 @@ void wiComboBox::SetSelected(int index) wiEventArgs args; args.iValue = selected; + args.sValue = GetItemText(selected); onSelect(args); } +string wiComboBox::GetItemText(int index) +{ + if (index >= 0) + { + return items[index]; + } + return ""; +} int wiComboBox::GetSelected() { return selected; diff --git a/WickedEngine/wiWidget.h b/WickedEngine/wiWidget.h index 39e87370e..b27782adf 100644 --- a/WickedEngine/wiWidget.h +++ b/WickedEngine/wiWidget.h @@ -18,6 +18,7 @@ struct wiEventArgs bool bValue; int iValue; XMFLOAT4 color; + string sValue; }; class wiWidget : public Transform @@ -195,6 +196,7 @@ public: void SetSelected(int index); int GetSelected(); + string GetItemText(int index); virtual void Update(wiGUI* gui) override; virtual void Render(wiGUI* gui) override;