[DirectX11] 064~65 Bone 위치에 충돌체 삽입하기
컴퓨팅 셰이더(Compute Shader)는 그래픽 렌더링에 주로 사용되는 정점 및 픽셀 셰이더와 같은 다른 유형의 셰이더와 달리, Compute Shader는 더 유연하고 다용도적으로 설계되어 있다.
Animation Instancing
Shader | |
RawBuffer.fx GetAnimationBone.fx |
|
Framework | |
Model | |
ModeAnimator.h .cpp | |
Objects | |
Collider.h .cpp | |
Renders | |
Buffer.h .cpp Render2D.h .cpp |
|
UnitTest | |
DirectCompute | |
RawBufferDemo.h .cpp GetAnimationBoneDemo.h .cpp |
|
Instancing | |
InstancingFrameworkDemo.h .cpp | |
Main.h .cpp |
fx
어제만든 GetAnimationBone.fx 사용
Instancing Framework Demo
InstancingFrameworkDemo.h
더보기
#pragma once #include "Systems/IExecute.h" class InstancingFrameworkDemo : public IExecute { public: virtual void Initialize() override; virtual void Ready() override {} virtual void Destroy() override {} virtual void Update() override; virtual void PreRender() override {} virtual void Render() override; virtual void PostRender() override {} virtual void ResizeScreen() override {} private: void Mesh(); void Airplane(); void Kachujin(); void Pass(UINT mesh, UINT model, UINT anim); private: Shader* shader; CubeSky* sky; Material* floor; Material* stone; Material* brick; Material* wall; MeshRender* cube; MeshRender* cylinder; MeshRender* sphere; MeshRender* grid; ModelRender* airplane = NULL; ModelAnimator* kachujin = NULL; vector<MeshRender *> meshes; vector<ModelRender *> models; vector<ModelAnimator *> animators; };
InstancingFrameworkDemo.cpp
더보기
#include "stdafx.h" #include "InstancingFrameworkDemo.h" void InstancingFrameworkDemo::Initialize() { Context::Get()->GetCamera()->RotationDegree(20, 0, 0); Context::Get()->GetCamera()->Position(1, 36, -85); shader = new Shader(L"55_Render.fx"); sky = new CubeSky(L"Environment/GrassCube1024.dds"); Mesh(); Airplane(); Kachujin(); } void InstancingFrameworkDemo::Update() { sky->Update(); cube->Update(); grid->Update(); cylinder->Update(); sphere->Update(); airplane->Update(); kachujin->Update(); } void InstancingFrameworkDemo::Render() { sky->Render(); Pass(0, 1, 2); wall->Render(); sphere->Render(); brick->Render(); cylinder->Render(); stone->Render(); cube->Render(); floor->Render(); grid->Render(); airplane->Render(); kachujin->Render(); } void InstancingFrameworkDemo::Mesh() { //Create Material { floor = new Material(shader); floor->DiffuseMap("Floor.png"); //floor->SpecularMap("Floor_Specular.png"); //floor->NormalMap("Floor_Normal.png"); //floor->Specular(1, 1, 1, 20); stone = new Material(shader); stone->DiffuseMap("Stones.png"); //stone->SpecularMap("Stones_Specular.png"); //stone->NormalMap("Stones_Normal.png"); //stone->Specular(1, 1, 1, 20); brick = new Material(shader); brick->DiffuseMap("Bricks.png"); //brick->SpecularMap("Bricks_Specular.png"); //brick->NormalMap("Bricks_Normal.png"); //brick->Specular(1, 0.3f, 0.3f, 20); wall = new Material(shader); wall->DiffuseMap("Wall.png"); //wall->SpecularMap("Wall_Specular.png"); //wall->NormalMap("Wall_Normal.png"); //wall->Specular(1, 1, 1, 20); } //Create Mesh { Transform* transform = NULL; cube = new MeshRender(shader, new MeshCube()); transform = cube->AddTransform(); transform->Position(0, 5, 0); transform->Scale(20, 10, 20); grid = new MeshRender(shader, new MeshGrid(5, 5)); transform = grid->AddTransform(); transform->Position(0, 0, 0); transform->Scale(12, 1, 12); cylinder = new MeshRender(shader, new MeshCylinder(0.5f, 3.0f, 20, 20)); sphere = new MeshRender(shader, new MeshSphere(0.5f, 20, 20)); for (UINT i = 0; i < 5; i++) { transform = cylinder->AddTransform(); transform->Position(-30, 6, -15.0f + (float)i * 15.0f); transform->Scale(5, 5, 5); transform = cylinder->AddTransform(); transform->Position(30, 6, -15.0f + (float)i * 15.0f); transform->Scale(5, 5, 5); transform = sphere->AddTransform(); transform->Position(-30, 15.5f, -15.0f + (float)i * 15.0f); transform->Scale(5, 5, 5); transform = sphere->AddTransform(); transform->Position(30, 15.5f, -15.0f + (float)i * 15.0f); transform->Scale(5, 5, 5); } } sphere->UpdateTransforms(); cylinder->UpdateTransforms(); cube->UpdateTransforms(); grid->UpdateTransforms(); meshes.push_back(sphere); meshes.push_back(cylinder); meshes.push_back(cube); meshes.push_back(grid); } void InstancingFrameworkDemo::Airplane() { airplane = new ModelRender(shader); airplane->ReadMesh(L"B787/Airplane"); airplane->ReadMaterial(L"B787/Airplane"); Transform* transform = airplane->AddTransform(); transform->Position(2.0f, 9.91f, 2.0f); transform->Scale(0.004f, 0.004f, 0.004f); airplane->UpdateTransforms(); models.push_back(airplane); } void InstancingFrameworkDemo::Kachujin() { kachujin = new ModelAnimator(shader); kachujin->ReadMesh(L"Kachujin/Mesh"); kachujin->ReadMaterial(L"Kachujin/Mesh"); kachujin->ReadClip(L"Kachujin/Sword And Shield Idle"); kachujin->ReadClip(L"Kachujin/Sword And Shield Walk"); kachujin->ReadClip(L"Kachujin/Sword And Shield Run"); kachujin->ReadClip(L"Kachujin/Sword And Shield Slash"); kachujin->ReadClip(L"Kachujin/Salsa Dancing"); Transform* transform = NULL; transform = kachujin->AddTransform(); transform->Position(0, 0, -30); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayTweenMode(0, 0, 1.0f); transform = kachujin->AddTransform(); transform->Position(-15, 0, -30); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayTweenMode(1, 1, 1.0f); transform = kachujin->AddTransform(); transform->Position(-30, 0, -30); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayTweenMode(2, 2, 0.75f); transform = kachujin->AddTransform(); transform->Position(15, 0, -30); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayBlendMode(3, 0, 1, 2); kachujin->SetBlendAlpha(3, 1.5f); transform = kachujin->AddTransform(); transform->Position(30, 0, -32.5f); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayTweenMode(4, 4, 0.75f); kachujin->UpdateTransforms(); animators.push_back(kachujin); } void InstancingFrameworkDemo::Pass(UINT mesh, UINT model, UINT anim) { for (MeshRender* temp : meshes) temp->Pass(mesh); for (ModelRender* temp : models) temp->Pass(model); for (ModelAnimator* temp : animators) temp->Pass(anim); }
Get Animation Bone Demo
GetAnimationBoneDemo.h
더보기
#pragma once #include "Systems/IExecute.h" class GetAnimationBoneDemo : public IExecute { public: virtual void Initialize() override; virtual void Ready() override {} virtual void Destroy() override {} virtual void Update() override; virtual void PreRender() override {} virtual void Render() override; virtual void PostRender() override {} virtual void ResizeScreen() override {} private: void Mesh(); void Airplane(); void Kachujin(); void KachujinCollider();//Kachujin 충돌체 void Pass(UINT mesh, UINT model, UINT anim); private: Shader* shader; CubeSky* sky; Material* floor; Material* stone; Material* brick; Material* wall; MeshRender* cube; MeshRender* cylinder; MeshRender* sphere; MeshRender* grid; ModelRender* airplane = NULL; ModelAnimator* kachujin = NULL; ColliderObject** colliders; //충돌체를 몇개 쓸지 모르니 2차 포인터 사용 vector<MeshRender *> meshes; vector<ModelRender *> models; vector<ModelAnimator *> animators; };
GetAnimationBoneDemo.cpp
더보기
#include "stdafx.h" #include "GetAnimationBoneDemo.h" void GetAnimationBoneDemo::Initialize() { Context::Get()->GetCamera()->RotationDegree(20, 0, 0); Context::Get()->GetCamera()->Position(1, 36, -85); shader = new Shader(L"55_Render.fx"); sky = new CubeSky(L"Environment/GrassCube1024.dds"); Mesh(); Airplane(); Kachujin(); KachujinCollider(); } void GetAnimationBoneDemo::Update() { sky->Update(); cube->Update(); grid->Update(); cylinder->Update(); sphere->Update(); airplane->Update(); kachujin->Update(); //collider 계산 for (UINT i = 0; i < kachujin->GetTransformCount(); i++) { Matrix attach; kachujin->GetAttachTransform(i, &attach); colliders[i]->Collider->GetTransform()->World(attach); colliders[i]->Collider->Update(); } } void GetAnimationBoneDemo::Render() { sky->Render(); Pass(0, 1, 2); wall->Render(); sphere->Render(); brick->Render(); cylinder->Render(); stone->Render(); cube->Render(); floor->Render(); grid->Render(); airplane->Render(); kachujin->Render(); for (UINT i = 0; i < kachujin->GetTransformCount(); i++) colliders[i]->Collider->Render(); } void GetAnimationBoneDemo::Mesh() { //Create Material { floor = new Material(shader); floor->DiffuseMap("Floor.png"); //floor->SpecularMap("Floor_Specular.png"); //floor->NormalMap("Floor_Normal.png"); //floor->Specular(1, 1, 1, 20); stone = new Material(shader); stone->DiffuseMap("Stones.png"); //stone->SpecularMap("Stones_Specular.png"); //stone->NormalMap("Stones_Normal.png"); //stone->Specular(1, 1, 1, 20); brick = new Material(shader); brick->DiffuseMap("Bricks.png"); //brick->SpecularMap("Bricks_Specular.png"); //brick->NormalMap("Bricks_Normal.png"); //brick->Specular(1, 0.3f, 0.3f, 20); wall = new Material(shader); wall->DiffuseMap("Wall.png"); //wall->SpecularMap("Wall_Specular.png"); //wall->NormalMap("Wall_Normal.png"); //wall->Specular(1, 1, 1, 20); } //Create Mesh { Transform* transform = NULL; cube = new MeshRender(shader, new MeshCube()); transform = cube->AddTransform(); transform->Position(0, 5, 0); transform->Scale(20, 10, 20); grid = new MeshRender(shader, new MeshGrid(5, 5)); transform = grid->AddTransform(); transform->Position(0, 0, 0); transform->Scale(12, 1, 12); cylinder = new MeshRender(shader, new MeshCylinder(0.5f, 3.0f, 20, 20)); sphere = new MeshRender(shader, new MeshSphere(0.5f, 20, 20)); for (UINT i = 0; i < 5; i++) { transform = cylinder->AddTransform(); transform->Position(-30, 6, -15.0f + (float)i * 15.0f); transform->Scale(5, 5, 5); transform = cylinder->AddTransform(); transform->Position(30, 6, -15.0f + (float)i * 15.0f); transform->Scale(5, 5, 5); transform = sphere->AddTransform(); transform->Position(-30, 15.5f, -15.0f + (float)i * 15.0f); transform->Scale(5, 5, 5); transform = sphere->AddTransform(); transform->Position(30, 15.5f, -15.0f + (float)i * 15.0f); transform->Scale(5, 5, 5); } } sphere->UpdateTransforms(); cylinder->UpdateTransforms(); cube->UpdateTransforms(); grid->UpdateTransforms(); meshes.push_back(sphere); meshes.push_back(cylinder); meshes.push_back(cube); meshes.push_back(grid); } void GetAnimationBoneDemo::Airplane() { airplane = new ModelRender(shader); airplane->ReadMesh(L"B787/Airplane"); airplane->ReadMaterial(L"B787/Airplane"); Transform* transform = airplane->AddTransform(); transform->Position(2.0f, 9.91f, 2.0f); transform->Scale(0.004f, 0.004f, 0.004f); airplane->UpdateTransforms(); models.push_back(airplane); } void GetAnimationBoneDemo::Kachujin() { kachujin = new ModelAnimator(shader); kachujin->ReadMesh(L"Kachujin/Mesh"); kachujin->ReadMaterial(L"Kachujin/Mesh"); kachujin->ReadClip(L"Kachujin/Sword And Shield Idle"); kachujin->ReadClip(L"Kachujin/Sword And Shield Walk"); kachujin->ReadClip(L"Kachujin/Sword And Shield Run"); kachujin->ReadClip(L"Kachujin/Sword And Shield Slash"); kachujin->ReadClip(L"Kachujin/Salsa Dancing"); Transform* transform = NULL; transform = kachujin->AddTransform(); transform->Position(0, 0, -30); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayTweenMode(0, 0, 1.0f); transform = kachujin->AddTransform(); transform->Position(-15, 0, -30); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayTweenMode(1, 1, 1.0f); transform = kachujin->AddTransform(); transform->Position(-30, 0, -30); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayTweenMode(2, 2, 0.75f); transform = kachujin->AddTransform(); transform->Position(15, 0, -30); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayBlendMode(3, 0, 1, 2); kachujin->SetBlendAlpha(3, 1.5f); transform = kachujin->AddTransform(); transform->Position(30, 0, -32.5f); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayTweenMode(4, 4, 0.75f); kachujin->UpdateTransforms(); kachujin->SetAttachTransform(40);//kachujin 오른손 Bone animators.push_back(kachujin); } void GetAnimationBoneDemo::KachujinCollider() { UINT count = kachujin->GetTransformCount(); //Instancing 개수 가져옴. colliders = new ColliderObject*[count]; //collider 할당. 2차 포인터로 생성해서 포인터 하나 들어간다. for (UINT i = 0; i < count; i++) { colliders[i] = new ColliderObject(); colliders[i]->Init = new Transform(); colliders[i]->Init->Position(0, 0, 0); colliders[i]->Init->Scale(10, 30, 10); colliders[i]->Transform = new Transform(); colliders[i]->Collider = new Collider(colliders[i]->Transform, colliders[i]->Init); } } void GetAnimationBoneDemo::Pass(UINT mesh, UINT model, UINT anim) { for (MeshRender* temp : meshes) temp->Pass(mesh); for (ModelRender* temp : models) temp->Pass(model); for (ModelAnimator* temp : animators) temp->Pass(anim); }
Model Animator
ModelAnimator.h
더보기
#pragma once class ModelAnimator { public: ModelAnimator(Shader* shader); ~ModelAnimator(); void Update(); private: void UpdateTweenMode(UINT index); void UpdateBlendMode(UINT index); public: void Render(); public: void ReadMesh(wstring file); void ReadMaterial(wstring file); void ReadClip(wstring file); Model* GetModel() { return model; } void Pass(UINT pass); Transform* AddTransform(); Transform* GetTransform(UINT index) { return transforms[index]; } void UpdateTransforms(); UINT GetTransformCount() { return transforms.size(); }//Instancing 개수 가져옴. void PlayTweenMode(UINT index, UINT clip, float speed = 1.0f, float takeTime = 1.0f); void PlayBlendMode(UINT index, UINT clip, UINT clip1, UINT clip2); void SetBlendAlpha(UINT index, float alpha); void SetAttachTransform(UINT boneIndex); void GetAttachTransform(UINT instance, Matrix* outResult); private: void CreateTexture(); void CreateClipTransform(UINT index); void CreateComputeBuffer(); private: struct ClipTransform { Matrix** Transform; ClipTransform() { Transform = new Matrix*[MAX_MODEL_KEYFRAMES]; for (UINT i = 0; i < MAX_MODEL_KEYFRAMES; i++) Transform[i] = new Matrix[MAX_MODEL_TRANSFORMS]; } ~ClipTransform() { for (UINT i = 0; i < MAX_MODEL_KEYFRAMES; i++) SafeDeleteArray(Transform[i]); SafeDeleteArray(Transform); } }; ClipTransform* clipTransforms = NULL; ID3D11Texture2D* texture = NULL; ID3D11ShaderResourceView* srv = NULL; private: struct KeyframeDesc { int Clip = 0; UINT CurrFrame = 0; UINT NextFrame = 0; float Time = 0.0f; float RunningTime = 0.0f; float Speed = 1.0f; Vector2 Padding; }; // keyframeDesc; struct TweenDesc { float TakeTime = 1.0f; float TweenTime = 0.0f; float ChangeTime = 0.0f; float Padding; KeyframeDesc Curr; KeyframeDesc Next; TweenDesc() { Curr.Clip = 0; Next.Clip = -1; } } tweenDesc[MAX_MODEL_INSTANCE]; ConstantBuffer* tweenBuffer; ID3DX11EffectConstantBuffer* sTweenBuffer; private: struct BlendDesc { UINT Mode = 0; float Alpha = 0; Vector2 Padding; KeyframeDesc Clip[3]; } blendDesc[MAX_MODEL_INSTANCE]; ConstantBuffer* blendBuffer; ID3DX11EffectConstantBuffer* sBlendBuffer; private: Shader* shader; Model* model; vector<Transform *> transforms; Matrix worlds[MAX_MODEL_INSTANCE]; VertexBuffer* instanceBuffer; private: struct CS_InputDesc { Matrix Bone; }; struct CS_OutputDesc { Matrix Result; }; struct AttachDesc { UINT BoneIndex = 0; float Padding[3]; } attachDesc; private: Shader* computeShader; StructuredBuffer* computeBuffer = NULL; CS_InputDesc* csInput = NULL; CS_OutputDesc* csOutput = NULL; ID3DX11EffectShaderResourceVariable* sInputSRV; ID3DX11EffectUnorderedAccessViewVariable* sOutputUAV; ConstantBuffer* computeAttachBuffer; ID3DX11EffectConstantBuffer* sComputeAttachBuffer; ID3DX11EffectConstantBuffer* sComputeTweenBuffer; ID3DX11EffectConstantBuffer* sComputeBlendBuffer; };
ModelAnimator.cpp
더보기
#include "Framework.h" #include "ModelAnimator.h" ModelAnimator::ModelAnimator(Shader * shader) : shader(shader) { model = new Model(); tweenBuffer = new ConstantBuffer(&tweenDesc, sizeof(TweenDesc) * MAX_MODEL_INSTANCE); sTweenBuffer = shader->AsConstantBuffer("CB_TweenFrame"); blendBuffer = new ConstantBuffer(&blendDesc, sizeof(BlendDesc) * MAX_MODEL_INSTANCE); sBlendBuffer = shader->AsConstantBuffer("CB_BlendFrame"); instanceBuffer = new VertexBuffer(worlds, MAX_MODEL_INSTANCE, sizeof(Matrix), 1, true); computeShader = new Shader(L"63_GetAnimationBone.fx"); computeAttachBuffer = new ConstantBuffer(&attachDesc, sizeof(AttachDesc)); sInputSRV = computeShader->AsSRV("Input"); sOutputUAV = computeShader->AsUAV("Output"); sComputeAttachBuffer = computeShader->AsConstantBuffer("CB_AttachBone"); sComputeTweenBuffer = computeShader->AsConstantBuffer("CB_TweenFrame"); sComputeBlendBuffer = computeShader->AsConstantBuffer("CB_BlendFrame"); } ModelAnimator::~ModelAnimator() { SafeDelete(model); SafeDeleteArray(clipTransforms); SafeRelease(texture); SafeRelease(srv); SafeDelete(tweenBuffer); SafeDelete(blendBuffer); SafeDelete(instanceBuffer); SafeDelete(computeShader); SafeDelete(computeBuffer); SafeDeleteArray(csInput); SafeDeleteArray(csOutput); SafeDelete(computeAttachBuffer); } void ModelAnimator::Update() { if (texture == NULL) { for (ModelMesh* mesh : model->Meshes()) mesh->SetShader(shader); CreateTexture(); CreateComputeBuffer(); } for (UINT i = 0; i < transforms.size(); i++) blendDesc[i].Mode == 0 ? UpdateTweenMode(i) : UpdateBlendMode(i); tweenBuffer->Render(); blendBuffer->Render(); //computeBuffer 정보를 넘긴다. if (computeBuffer != NULL) { computeAttachBuffer->Render(); sComputeAttachBuffer->SetConstantBuffer(computeAttachBuffer->Buffer()); sComputeTweenBuffer->SetConstantBuffer(tweenBuffer->Buffer()); sComputeBlendBuffer->SetConstantBuffer(blendBuffer->Buffer()); sInputSRV->SetResource(computeBuffer->SRV()); sOutputUAV->SetUnorderedAccessView(computeBuffer->UAV()); computeShader->Dispatch(0, 0, 1, 1, 1); computeBuffer->CopyFromOutput(csOutput); } for (ModelMesh* mesh : model->Meshes()) mesh->Update(); } void ModelAnimator::UpdateTweenMode(UINT index) { TweenDesc& desc = tweenDesc[index]; //현재 애니메이션 { ModelClip* clip = model->ClipByIndex(desc.Curr.Clip); desc.Curr.RunningTime += Time::Delta(); float time = 1.0f / clip->FrameRate() / desc.Curr.Speed; if (desc.Curr.Time >= 1.0f) { desc.Curr.RunningTime = 0; desc.Curr.CurrFrame = (desc.Curr.CurrFrame + 1) % clip->FrameCount(); desc.Curr.NextFrame = (desc.Curr.CurrFrame + 1) % clip->FrameCount(); } desc.Curr.Time = desc.Curr.RunningTime / time; } if (desc.Next.Clip > -1) { desc.ChangeTime += Time::Delta(); desc.TweenTime = desc.ChangeTime / desc.TakeTime; if (desc.TweenTime >= 1.0f) { desc.Curr = desc.Next; desc.Next.Clip = -1; desc.Next.CurrFrame = 0; desc.Next.NextFrame = 0; desc.Next.Time = 0; desc.Next.RunningTime = 0.0f; desc.ChangeTime = 0.0f; desc.TweenTime = 0.0f; } else { ModelClip* clip = model->ClipByIndex(desc.Next.Clip); desc.Next.RunningTime += Time::Delta(); float time = 1.0f / clip->FrameRate() / desc.Next.Speed; if (desc.Next.Time >= 1.0f) { desc.Next.RunningTime = 0; desc.Next.CurrFrame = (desc.Next.CurrFrame + 1) % clip->FrameCount(); desc.Next.NextFrame = (desc.Next.CurrFrame + 1) % clip->FrameCount(); } desc.Next.Time = desc.Next.RunningTime / time; } } } void ModelAnimator::UpdateBlendMode(UINT index) { BlendDesc& desc = blendDesc[index]; for (UINT i = 0; i < 3; i++) { ModelClip* clip = model->ClipByIndex(desc.Clip[i].Clip); desc.Clip[i].RunningTime += Time::Delta(); float time = 1.0f / clip->FrameRate() / desc.Clip[i].Speed; if (desc.Clip[i].Time >= 1.0f) { desc.Clip[i].RunningTime = 0; desc.Clip[i].CurrFrame = (desc.Clip[i].CurrFrame + 1) % clip->FrameCount(); desc.Clip[i].NextFrame = (desc.Clip[i].CurrFrame + 1) % clip->FrameCount(); } desc.Clip[i].Time = desc.Clip[i].RunningTime / time; } } void ModelAnimator::Render() { sTweenBuffer->SetConstantBuffer(tweenBuffer->Buffer()); sBlendBuffer->SetConstantBuffer(blendBuffer->Buffer()); instanceBuffer->Render(); for (ModelMesh* mesh : model->Meshes()) mesh->Render(transforms.size()); } void ModelAnimator::ReadMesh(wstring file) { model->ReadMesh(file); } void ModelAnimator::ReadMaterial(wstring file) { model->ReadMaterial(file); } void ModelAnimator::ReadClip(wstring file) { model->ReadClip(file); } void ModelAnimator::Pass(UINT pass) { for (ModelMesh* mesh : model->Meshes()) mesh->Pass(pass); } void ModelAnimator::PlayTweenMode(UINT index, UINT clip, float speed, float takeTime) { blendDesc[index].Mode = 0; tweenDesc[index].TakeTime = takeTime; tweenDesc[index].Next.Clip = clip; tweenDesc[index].Next.Speed = speed; } void ModelAnimator::PlayBlendMode(UINT index, UINT clip, UINT clip1, UINT clip2) { blendDesc[index].Mode = 1; blendDesc[index].Clip[0].Clip = clip; blendDesc[index].Clip[1].Clip = clip1; blendDesc[index].Clip[2].Clip = clip2; } void ModelAnimator::SetBlendAlpha(UINT index, float alpha) { alpha = Math::Clamp(alpha, 0.0f, 2.0f); blendDesc[index].Alpha = alpha; } void ModelAnimator::SetAttachTransform(UINT boneIndex) { attachDesc.BoneIndex = boneIndex; } void ModelAnimator::GetAttachTransform(UINT instance, Matrix * outResult) { if (csOutput == NULL) { D3DXMatrixIdentity(outResult); return; } Matrix transform = model->BoneByIndex(attachDesc.BoneIndex)->Transform(); //기준 본 행렬 Matrix result = csOutput[instance].Result; //애니메이션 행렬 Matrix world = GetTransform(instance)->World(); *outResult = transform * result * world; //기준에서 애니메이션이 얼마나 됬는지 모델이 얼마나 움직였는지 } void ModelAnimator::CreateTexture() { //Matrix matrix[MAX_MODEL_KEYFRAMES][MAX_MODEL_TRANSFORMS]; clipTransforms = new ClipTransform[model->ClipCount()]; for (UINT i = 0; i < model->ClipCount(); i++) CreateClipTransform(i); //Create Texture { D3D11_TEXTURE2D_DESC desc; ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC)); desc.Width = MAX_MODEL_TRANSFORMS * 4; desc.Height = MAX_MODEL_KEYFRAMES; desc.ArraySize = model->ClipCount(); desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; //16Byte * 4 = 64Byte desc.Usage = D3D11_USAGE_IMMUTABLE; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.MipLevels = 1; desc.SampleDesc.Count = 1; UINT pageSize = MAX_MODEL_TRANSFORMS * 4 * 16 * MAX_MODEL_KEYFRAMES; //void* p = malloc(pageSize * model->ClipCount()); void* p = VirtualAlloc(NULL, pageSize * model->ClipCount(), MEM_RESERVE, PAGE_READWRITE); //MEMORY_BASIC_INFORMATION, VirtualQuery for (UINT c = 0; c < model->ClipCount(); c++) { UINT start = c * pageSize; for (UINT k = 0; k < MAX_MODEL_KEYFRAMES; k++) { void* temp = (BYTE *)p + MAX_MODEL_TRANSFORMS * k * sizeof(Matrix) + start; VirtualAlloc(temp, MAX_MODEL_TRANSFORMS * sizeof(Matrix), MEM_COMMIT, PAGE_READWRITE); memcpy(temp, clipTransforms[c].Transform[k], MAX_MODEL_TRANSFORMS * sizeof(Matrix)); } }//for(c) D3D11_SUBRESOURCE_DATA* subResources = new D3D11_SUBRESOURCE_DATA[model->ClipCount()]; for (UINT c = 0; c < model->ClipCount(); c++) { void* temp = (BYTE *)p + c * pageSize; subResources[c].pSysMem = temp; subResources[c].SysMemPitch = MAX_MODEL_TRANSFORMS * sizeof(Matrix); subResources[c].SysMemSlicePitch = pageSize; } Check(D3D::GetDevice()->CreateTexture2D(&desc, subResources, &texture)); SafeDeleteArray(subResources); VirtualFree(p, 0, MEM_RELEASE); } //Create SRV { D3D11_SHADER_RESOURCE_VIEW_DESC desc; ZeroMemory(&desc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC)); desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; desc.Texture2DArray.MipLevels = 1; desc.Texture2DArray.ArraySize = model->ClipCount(); Check(D3D::GetDevice()->CreateShaderResourceView(texture, &desc, &srv)); } for (ModelMesh* mesh : model->Meshes()) mesh->TransformsSRV(srv); } void ModelAnimator::CreateClipTransform(UINT index) { Matrix* bones = new Matrix[MAX_MODEL_TRANSFORMS]; ModelClip* clip = model->ClipByIndex(index); for (UINT f = 0; f < clip->FrameCount(); f++) { for (UINT b = 0; b < model->BoneCount(); b++) { ModelBone* bone = model->BoneByIndex(b); Matrix parent; Matrix invGlobal = bone->Transform(); D3DXMatrixInverse(&invGlobal, NULL, &invGlobal); int parentIndex = bone->ParentIndex(); if (parentIndex < 0) D3DXMatrixIdentity(&parent); else parent = bones[parentIndex]; Matrix animation; ModelKeyframe* frame = clip->Keyframe(bone->Name()); if (frame != NULL) { ModelKeyframeData& data = frame->Transforms[f]; Matrix S, R, T; D3DXMatrixScaling(&S, data.Scale.x, data.Scale.y, data.Scale.z); D3DXMatrixRotationQuaternion(&R, &data.Rotation); D3DXMatrixTranslation(&T, data.Translation.x, data.Translation.y, data.Translation.z); animation = S * R * T; } else { D3DXMatrixIdentity(&animation); } bones[b] = animation * parent; clipTransforms[index].Transform[f][b] = invGlobal * bones[b]; }//for(b) }//for(f) } void ModelAnimator::CreateComputeBuffer() { UINT clipCount = model->ClipCount(); UINT inSize = clipCount * MAX_MODEL_KEYFRAMES * MAX_MODEL_TRANSFORMS; UINT outSize = MAX_MODEL_INSTANCE; csInput = new CS_InputDesc[inSize]; UINT count = 0; for (UINT clipIndex = 0; clipIndex < clipCount; clipIndex++) { for (UINT frameIndex = 0; frameIndex < MAX_MODEL_KEYFRAMES; frameIndex++) { for (UINT boneIndex = 0; boneIndex < MAX_MODEL_TRANSFORMS; boneIndex++) { csInput[count].Bone = clipTransforms[clipIndex].Transform[frameIndex][boneIndex]; count++; } }//for(frameIndex) }//for(clipIndex) computeBuffer = new StructuredBuffer(csInput, sizeof(CS_InputDesc), inSize, sizeof(CS_OutputDesc), outSize); csOutput = new CS_OutputDesc[outSize]; //초기값이 없어서 Identity 시켜준다. for (UINT i = 0; i < outSize; i++) D3DXMatrixIdentity(&csOutput[i].Result); } Transform * ModelAnimator::AddTransform() { Transform* transform = new Transform(); transforms.push_back(transform); return transform; } void ModelAnimator::UpdateTransforms() { for (UINT i = 0; i < transforms.size(); i++) memcpy(worlds[i], transforms[i]->World(), sizeof(Matrix)); D3D11_MAPPED_SUBRESOURCE subResource; D3D::GetDC()->Map(instanceBuffer->Buffer(), 0, D3D11_MAP_WRITE_DISCARD, 0, &subResource); { memcpy(subResource.pData, worlds, sizeof(Matrix) * MAX_MESH_INSTANCE); } D3D::GetDC()->Unmap(instanceBuffer->Buffer(), 0); }
- computeShader
- computeBuffer
- csInput
- csOutput
- computeAttachBuffer
void CreateTexture();
void CreateClipTransform(UINT index);
void CreateComputeBuffer();
Collider
Collider.h
더보기
#pragma once struct ColliderObject { class Transform* Init = NULL; class Transform* Transform = NULL; class Collider* Collider = NULL; }; class Collider //충돌체 { public: Collider(Transform* transform, Transform* init = NULL); ~Collider(); void Update(); void Render(Color color = Color(0, 1, 0, 1)); //충돌체 녹색 설정 Transform* GetTransform() { return transform; } //transform을 리턴하는 함수 private: Transform* init = NULL; //기준 Transform* transform; //기준에서 얼마나 움직였는지 Vector3 lines[8]; };
Collider.cpp
더보기
#include "Framework.h" #include "Collider.h" Collider::Collider(Transform * transform, Transform * init) : transform(transform), init(init) { //육면체 //충돌작업에 0번과 7번을 사용할 것이다. lines[0] = Vector3(-0.5f, -0.5f, -0.5f); lines[1] = Vector3(-0.5f, +0.5f, -0.5f); lines[2] = Vector3(+0.5f, -0.5f, -0.5f); lines[3] = Vector3(+0.5f, +0.5f, -0.5f); lines[4] = Vector3(-0.5f, -0.5f, +0.5f); lines[5] = Vector3(-0.5f, +0.5f, +0.5f); lines[6] = Vector3(+0.5f, -0.5f, +0.5f); lines[7] = Vector3(+0.5f, +0.5f, +0.5f); } Collider::~Collider() { } void Collider::Update() { } void Collider::Render(Color color) { Transform temp; temp.World(transform->World()); if (init != NULL) temp.World(init->World() * transform->World()); Matrix world = temp.World(); Vector3 dest[8]; //선 8개 선언 for (UINT i = 0; i < 8; i++) D3DXVec3TransformCoord(&dest[i], &lines[i], &world); //선의 위치를 그려준다. //Front DebugLine::Get()->RenderLine(dest[0], dest[1], color); DebugLine::Get()->RenderLine(dest[1], dest[3], color); DebugLine::Get()->RenderLine(dest[3], dest[2], color); DebugLine::Get()->RenderLine(dest[2], dest[0], color); //Backward DebugLine::Get()->RenderLine(dest[4], dest[5], color); DebugLine::Get()->RenderLine(dest[5], dest[7], color); DebugLine::Get()->RenderLine(dest[7], dest[6], color); DebugLine::Get()->RenderLine(dest[6], dest[4], color); //Side DebugLine::Get()->RenderLine(dest[0], dest[4], color); DebugLine::Get()->RenderLine(dest[1], dest[5], color); DebugLine::Get()->RenderLine(dest[2], dest[6], color); DebugLine::Get()->RenderLine(dest[3], dest[7], color); }
Get Animation Bone Demo

'⭐ DirectX > DirectX11 3D' 카테고리의 다른 글
[DirectX11] 067 Projection (0) | 2023.03.09 |
---|---|
[DirectX11] 066 3D 공간에서 충돌체 선택하기 (0) | 2023.03.08 |
[DirectX11] 063 Compute Shader - GetAnimationBone 구현하기 (0) | 2023.03.06 |
[DirectX11] 062 Texture Buffer (0) | 2023.03.03 |
[DirectX11] 061 Thread Group, SV_GroupID (0) | 2023.03.02 |
댓글
이 글 공유하기
다른 글
-
[DirectX11] 067 Projection
[DirectX11] 067 Projection
2023.03.09 -
[DirectX11] 066 3D 공간에서 충돌체 선택하기
[DirectX11] 066 3D 공간에서 충돌체 선택하기
2023.03.08 -
[DirectX11] 063 Compute Shader - GetAnimationBone 구현하기
[DirectX11] 063 Compute Shader - GetAnimationBone 구현하기
2023.03.06 -
[DirectX11] 062 Texture Buffer
[DirectX11] 062 Texture Buffer
2023.03.03
댓글을 사용할 수 없습니다.