글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자입니다

 

목차

     

     


     

     

    Model Animator

     

    bone->Transform = bone->Transform * matParent;
    • Global = Relative(=local로 봐도 무방) * Global
    • Global = Relative * Global이다

     

     

    R8G8B8A8  4Byte

     

    R32G32B32A32 16Byte(픽셀 하나 당 쓸 수 있는 최대값)

     

     

    Texture1D - Array

    Texture2D - Array  >> Dynamic으로 쓸 수 없다. 

    Texture3D - Array

     


     

     

    Model.fx

     

    Model.fx

    더보기
    #include "00_Global.fx"
    
    float3 Direction = float3(-1, -1, +1);
    
    struct VertexModel
    {
        float4 Position : Position;
        float2 Uv : Uv;
        float3 Normal : Normal;
        float3 Tangent : Tangent;
        float4 BlendIndices : BlendIndices;
        float4 BlendWeights : BlendWeights;
    };
    
    #define MAX_MODEL_TRANSFORMS 250
    
    cbuffer CB_Bone
    {
        matrix BoneTransforms[MAX_MODEL_TRANSFORMS];
        
        uint BoneIndex;
    };
    
    struct VertexOutput
    {
        float4 Position : SV_Position;
        float3 Normal : Normal;
        float2 Uv : Uv;
    };
    
    VertexOutput VS(VertexModel input)
    {
        VertexOutput output;
        
        World = mul(BoneTransforms[BoneIndex], World);
        
        output.Position = WorldPosition(input.Position);
        output.Position = ViewProjection(output.Position);
        
        output.Normal = WorldNormal(input.Normal);
        output.Uv = input.Uv;
        
        return output;
    }
    
    float4 PS(VertexOutput input) : SV_Target
    {
        float NdotL = dot(normalize(input.Normal), -Direction);
        
        return DiffuseMap.Sample(LinearSampler, input.Uv) * NdotL;
    }
    
    technique11 T0
    {
        P_VP(P0, VS, PS)
        P_RS_VP(P1, FillMode_WireFrame, VS, PS)
    }

     


     

     

    Model Animator

     

    Model Animator.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();
    
    	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);
    
    private:
    	void CreateTexture();
    	void CreateClipTransform(UINT index);
    
    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;
    
    	ConstantBuffer* frameBuffer;
    	ID3DX11EffectConstantBuffer* sFrameBuffer;
    
    	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];
    
    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;
    };

     

     

     

    Model Animator.cpp

    더보기
    #include "Framework.h"
    #include "ModelAnimator.h"
    
    ModelAnimator::ModelAnimator(Shader * shader)
    	: shader(shader)
    {
    	model = new Model();
    
    	frameBuffer = new ConstantBuffer(&tweenDesc, sizeof(TweenDesc) * MAX_MODEL_INSTANCE);
    	sFrameBuffer = 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);
    }
    
    ModelAnimator::~ModelAnimator()
    {
    	SafeDelete(model);
    
    	SafeDeleteArray(clipTransforms);
    	SafeRelease(texture);
    	SafeRelease(srv);
    
    	SafeDelete(frameBuffer);
    	SafeDelete(blendBuffer);
    
    	SafeDelete(instanceBuffer);
    }
    
    void ModelAnimator::Update()
    {
    	for (UINT i = 0; i < transforms.size(); i++)
    	{
    		if (blendDesc[i].Mode == 0)
    			UpdateTweenMode(i);
    		else
    			UpdateBlendMode(i);
    	}
    	
    	
    
    	if (texture == NULL)
    	{
    		for (ModelMesh* mesh : model->Meshes())
    			mesh->SetShader(shader);
    
    		CreateTexture();
    	}
    
    	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()
    {
    	frameBuffer->Render();
    	sFrameBuffer->SetConstantBuffer(frameBuffer->Buffer());
    
    	blendBuffer->Render();
    	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::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)
    }
    
    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);
    }

     

     

    bones[b] = animation * parent;

    • Global = Relative * Global

     

     

     

    clipTransforms[index].Transform[f][b] = invGlobal * bones[b]

     

    • Global = Global의 역행렬(=Relative) * Global = Relative * Global