[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