DOTY

DirectX11. 7) 3D Model Rendering 본문

DirectX

DirectX11. 7) 3D Model Rendering

증식세포 2023. 6. 16. 15:35
728x90
반응형

이전의 코드에서는 3D 공간에서 평면인 모델만 렌더링 했지만 이번에는 입체를 렌더링 한다.

따라서 이전의 코드와 큰 차이가 없지만 3D 모델을 처리하기 위한 Vertex(x, y, z), Texture(tu, tv), Normal(nx, ny, nz)가 포함된 텍스쳐 파일을 읽어와 이를 처리하여 렌더링 하는 것을 익힐 수 있었다.

추가로 Rotate, Translate, Scale 관련 코드도 추가되었다.

 

> Cube.txt <


Vertex Count: 36

Data:

-1.0  1.0 -1.0 0.0 0.0  0.0  0.0 -1.0
 1.0  1.0 -1.0 1.0 0.0  0.0  0.0 -1.0
-1.0 -1.0 -1.0 0.0 1.0  0.0  0.0 -1.0
-1.0 -1.0 -1.0 0.0 1.0  0.0  0.0 -1.0
 1.0  1.0 -1.0 1.0 0.0  0.0  0.0 -1.0
 1.0 -1.0 -1.0 1.0 1.0  0.0  0.0 -1.0
 1.0  1.0 -1.0 0.0 0.0  1.0  0.0  0.0
 1.0  1.0  1.0 1.0 0.0  1.0  0.0  0.0
 1.0 -1.0 -1.0 0.0 1.0  1.0  0.0  0.0
 1.0 -1.0 -1.0 0.0 1.0  1.0  0.0  0.0
 1.0  1.0  1.0 1.0 0.0  1.0  0.0  0.0
 1.0 -1.0  1.0 1.0 1.0  1.0  0.0  0.0
 1.0  1.0  1.0 0.0 0.0  0.0  0.0  1.0
-1.0  1.0  1.0 1.0 0.0  0.0  0.0  1.0
 1.0 -1.0  1.0 0.0 1.0  0.0  0.0  1.0
 1.0 -1.0  1.0 0.0 1.0  0.0  0.0  1.0
-1.0  1.0  1.0 1.0 0.0  0.0  0.0  1.0
-1.0 -1.0  1.0 1.0 1.0  0.0  0.0  1.0
-1.0  1.0  1.0 0.0 0.0 -1.0  0.0  0.0
-1.0  1.0 -1.0 1.0 0.0 -1.0  0.0  0.0
-1.0 -1.0  1.0 0.0 1.0 -1.0  0.0  0.0
-1.0 -1.0  1.0 0.0 1.0 -1.0  0.0  0.0
-1.0  1.0 -1.0 1.0 0.0 -1.0  0.0  0.0
-1.0 -1.0 -1.0 1.0 1.0 -1.0  0.0  0.0
-1.0  1.0  1.0 0.0 0.0  0.0  1.0  0.0
 1.0  1.0  1.0 1.0 0.0  0.0  1.0  0.0
-1.0  1.0 -1.0 0.0 1.0  0.0  1.0  0.0
-1.0  1.0 -1.0 0.0 1.0  0.0  1.0  0.0
 1.0  1.0  1.0 1.0 0.0  0.0  1.0  0.0
 1.0  1.0 -1.0 1.0 1.0  0.0  1.0  0.0
-1.0 -1.0 -1.0 0.0 0.0  0.0 -1.0  0.0
 1.0 -1.0 -1.0 1.0 0.0  0.0 -1.0  0.0
-1.0 -1.0  1.0 0.0 1.0  0.0 -1.0  0.0
-1.0 -1.0  1.0 0.0 1.0  0.0 -1.0  0.0
 1.0 -1.0 -1.0 1.0 0.0  0.0 -1.0  0.0
 1.0 -1.0  1.0 1.0 1.0  0.0 -1.0  0.0
 
 
 

 

1. ModelClass.h

#pragma once
#ifndef _MODELCLASS_H_
#define _MODELCLASS_H_

#include "TextureClass.h"

#include <d3d11.h>
#include <directxmath.h>
#include <fstream>
using namespace DirectX;
using namespace std;

class ModelClass
{
private:
	struct VertexType
	{
		XMFLOAT3 position;
		XMFLOAT2 texture;
		XMFLOAT3 normal;
	};

	struct ModelType
	{
		float x, y, z;
		float tu, tv;
		float nx, ny, nz;
	};

public:
	ModelClass();
	ModelClass(const ModelClass&);
	~ModelClass();

	bool Initialize(ID3D11Device*, ID3D11DeviceContext*, char*, char*, HWND);
	void Shutdown();
	void Render(ID3D11DeviceContext*);

	int GetIndexCount();
	ID3D11ShaderResourceView* GetTexture();

private:
	bool InitializeBuffers(ID3D11Device*);
	void ShutdownBuffers();
	void RenderBuffers(ID3D11DeviceContext*);

	bool LoadTexture(ID3D11Device*, ID3D11DeviceContext*, char*);
	void ReleaseTexture();

	bool LoadModel(char*);
	void ReleaseModel();

private:
	ID3D11Buffer* m_vertexBuffer, * m_indexBuffer;
	int m_vertexCount, m_indexCount;
	TextureClass* m_Texture;

	ModelType* m_model;
};

#endif

※Initialize의 매개변수 HWND는 어디서 오류가 났는지 확인하기 위함이다. 필요하면 지워도 무방하다.

 

1-1. ModelType

3D모델을 처리하기 위한 세 타입의 변수 총 8가지를 선언.  Vertex(x, y, z), Texture(tu, tv), Normal(nx, ny, nz)

정점을 처리하기 위한 Vertex, 텍스쳐를 적용하기 위한 Texture, 정점으로 만들어진 면이 어느 방향을 보고 있는지에 대한 Normal 세 타입의 변수를 선언한다.

 

1-2. Initialize

filename을 얻기 위한 char* 형식의 매개변수가 추가되었다. 이를 이용해 텍스트 파일을 읽어온다.

for(i=0; i<m_vertexCount; i++)
{
    vertices[i].position = XMFLOAT3(m_model[i].x, m_model[i].y, m_model[i].z);
    vertices[i].texture = XMFLOAT2(m_model[i].tu, m_model[i].tv);
    vertices[i].normal = XMFLOAT3(m_model[i].nx, m_model[i].ny, m_model[i].nz);

    indices[i] = i;
}

이전의 Vertex와 Index들을 일일이 썼다면 이번에는 가공을 한 후에 m_model에 저장했기 때문에 그 데이터들을 직접 불러오면 된다.

 

1-3. LoadModel

bool ModelClass::LoadModel(char* filename)
{
	ifstream fin;
	char input;
	int i;


	// Open the model file.
	fin.open(filename);

	// If it could not open the file then exit.
	if (fin.fail())
	{
		return false;
	}

	// Read up to the value of vertex count.
	fin.get(input);
	while (input != ':')
	{
		fin.get(input);
	}

	// Read in the vertex count.
	fin >> m_vertexCount;

	// Set the number of indices to be the same as the vertex count.
	m_indexCount = m_vertexCount;

	// Create the model using the vertex count that was read in.
	m_model = new ModelType[m_vertexCount];

	// Read up to the beginning of the data.
	fin.get(input);
	while (input != ':')
	{
		fin.get(input);
	}
	fin.get(input);
	fin.get(input);

	// Read in the vertex data.
	for (i = 0; i < m_vertexCount; i++)
	{
		fin >> m_model[i].x >> m_model[i].y >> m_model[i].z;
		fin >> m_model[i].tu >> m_model[i].tv;
		fin >> m_model[i].nx >> m_model[i].ny >> m_model[i].nz;
	}

	// Close the model file.
	fin.close();

	return true;
}

텍스트 파일의 데이터들을 그대로 쓰기는 어려워 가공해야 한다. txt파일의 첫 줄을 m_vertexCount를 얻을 수 있다.

따라서 InitializeBuffers에서 Vertex

그다음줄부터는 큐브를 그리기 위한 12개의 삼각형 즉, 36개의 점들이 적혀있다.

(x, y, z, tu, tv, nx, ny, nz) 순으로 적혀있고 이를 m_model 구조체 배열에 하나씩 저장해 준다.

 

2. ApplicationClass - Render

bool ApplicationClass::Render(float rotation)
{
	XMMATRIX worldMatrix, viewMatrix, projectionMatrix;
	// new Matrix for Rotate, Translate, Scale
	XMMATRIX rotateMatrix, translateMatrix, scaleMatrix, srMatrix;
	bool result;


	// Clear the buffers to begin the scene.
	m_Direct3D->BeginScene(1.0f, 1.0f, 1.0f, 1.0f);

	// Generate the view matrix based on the camera's position.
	m_Camera->Render();

	// Get the world, view, and projection matrices from the camera and d3d objects.
	m_Direct3D->GetWorldMatrix(worldMatrix);
	m_Camera->GetViewMatrix(viewMatrix);
	m_Direct3D->GetProjectionMatrix(projectionMatrix);

	rotateMatrix = XMMatrixRotationY(rotation);  // Build the rotation matrix.
	translateMatrix = XMMatrixTranslation(-2.0f, 0.0f, 0.0f);  // Build the translation matrix.

	// Multiply them together to create the final world transformation matrix.
	worldMatrix = XMMatrixMultiply(rotateMatrix, translateMatrix);

	// Put the model vertex and index buffers on the graphics pipeline to prepare them for drawing.
	m_Model->Render(m_Direct3D->GetDeviceContext());

	// Render the model using the light shader.
	result = m_LightShader->Render(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture(),
		m_Light->GetDirection(), m_Light->GetDiffuseColor());
	if (!result)
	{
		return false;
	}

	scaleMatrix = XMMatrixScaling(0.5f, 0.5f, 0.5f);  // Build the scaling matrix.
	rotateMatrix = XMMatrixRotationY(-rotation);  // Build the rotation matrix.
	translateMatrix = XMMatrixTranslation(2.0f, 0.0f, 0.0f);  // Build the translation matrix.

	// Multiply the scale, rotation, and translation matrices together to create the final world transformation matrix.
	srMatrix = XMMatrixMultiply(scaleMatrix, rotateMatrix);
	worldMatrix = XMMatrixMultiply(srMatrix, translateMatrix);

	// Put the model vertex and index buffers on the graphics pipeline to prepare them for drawing.
	m_Model->Render(m_Direct3D->GetDeviceContext());

	// Render the model using the light shader.
	result = m_LightShader->Render(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture(),
		m_Light->GetDirection(), m_Light->GetDiffuseColor());
	if (!result)
	{
		return false;
	}

	m_Direct3D->EndScene();
	return true;
}

Rotate, Translate, Scale의 Matrix를 추가해서 이들을 곱한 최종 Matrix를 적용하여 렌더링 한다. 

 

translateMatrix = XMMatrixTranslation(2.0f + sin(rotation * 2), 0.0f + cos(rotation), 0.0f);

이런식으로 삼각함수를 섞어서 쓴다면 한 점을 중심으로 원의 둘레를 따라 원운동하는 오브젝트도 만들 수 있다.


 rastertek Tutorial chapter 7과 8의 내용이 포함되어있다.

728x90
반응형

'DirectX' 카테고리의 다른 글

DirectX11. 8) Ambient Light, Specular Lighting  (0) 2023.06.19
DirectX11. check 1) Back-Face culling  (0) 2023.06.14
DirectX11. 6) Light  (0) 2023.06.14
DirectX11. 5) Texture  (0) 2023.06.13
DirectX11. 4) Buffer, Shader II  (0) 2023.06.12
Comments