루리코딩 세상

Assimp Lib 활용 및 정리 본문

이론/DirectX

Assimp Lib 활용 및 정리

루리딩 2025. 6. 11. 13:20

https://github.com/assimp/assimp

 

GitHub - assimp/assimp: The official Open-Asset-Importer-Library Repository. Loads 40+ 3D-file-formats into one unified and clea

The official Open-Asset-Importer-Library Repository. Loads 40+ 3D-file-formats into one unified and clean data structure. - GitHub - assimp/assimp: The official Open-Asset-Importer-Library Reposit...

github.com


https://assimp.org/

 

The Asset-Importer Library Home

The Open Asset Importer Library Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory imediate format. It supports more than 40 file formats for import and a growing selection of file formats for export. Please che

assimp.org


다양한 3D 라이브러리가 존재하는 Assimp 라이브러리는(Open Asset Import Library)는 다양한 3D 모델 파일 형식을 가져오기 위한 공통 인터페이스를 제공해준다. 다양한 소스 모델을 로드하는 프로세스를 표준화시켜, 개발자가 3D 데이터로 작업하기 위한 환경을 목표로 하는 라이브러리이다.

오픈 지엘에서 만들었다고 한다.


_Assats

- 모델링된 파일을 모아둘 공간

- FBX 익스포트 옵션//FBX 임포트 옵션 -> 바탕화면으로 Unreal Engine에서 Mash 파일을 꺼내올 수 있다.

https://dev.epicgames.com/documentation/ko-kr/unreal-engine/importing-static-meshes-in-unreal-engine?application_version=5.3

 

 

 

생성하기
void CMain::Cube()
{
	CConverter


}

Meshes[0] = new CMeshRenderer(Shader);
Meshes[0]->ReadMesh(L"Cube");

Meshes[1] = new CMeshRenderer(Shader);
Meshes[1]->ReadMesh(L"Cube");

Meshes[2] = new CMeshRenderer(Shader);
Meshes[2]->ReadMesh(L"Cube");

Meshes[4] = new CMeshRenderer(Shader);
Meshes[3]->ReadMesh(L"Cube");

MeshRenderer = Meshes[MeshIndex];

ModelEditor (ReadFile, Main, PCH, Converter(변환기), Scene)

- bGameLoop

- Initialize

- Framwork - 빌드 후 이벤트 - ModleEditor

- Assimp에서 사용하는 자료형에는 ai가 붙는다 (ex, aiVector)

- Converter 변환기 생성과 사용 방법에 대한 이해한다. // converter.h & cpp 파일 생성과 문법 작성

- dll File은 항상 Project 파일에 함께 있어야한다. (exe + dll 함께 넣기)


#pragma once

#include "Framework.h"
#pragme comment(lib, "Framework.lib")

//Assimp
MSG msg;
ZeroMemory() // 메모리 초기화 시키기

 

종속시키기
void CMain::Initialize
MessgeBox(CD3D::Get()->GetHandle()L"변환 완료", L"Message", MB_OK);
converter.h

#pragma once

class CConverter
{
public:
	CConverter();
    ~CConverter();
    
public:
	void ReadFile(wstring InFaile, float In GlobalScale)
    
public:
    void ExportMesh(wstring InSaveFileName)
    
public:
	void ReadFile(wstring InFile, float InGlobalScale = 1.0f);
    //InGlobalScale 모델을 부르는 순간에 서로 다른 파일 모델간의 비율이 맞지 않는 것을 조절해주는 것임.

private:
	Assimp::Importer* Loader

private:
	wstring File;
    const aiScene* Scene;
    
private:
	vector<struct FMeshData*> Meshes;
};
Converter.cpp

CConverter::CConverter()
{
	Loader = new Assimp::Importer();
}

CConverter::~CConverter()
{
	Delete(Loader); //생성자의 소멸자 꼭 필수임
}

////////////////////////////////////////////////////////////////////////////////////////////

void CConReadFile::ReadFile(Wstring InFile) //void 정의 내려진 식별자 형식임
{
	File = L"../../_Assets/" + InFile;
    
    string file = CString::ToString(File);
    Scene = Loader->ReadFile
    (
    	file,
        aiProcess_ConvertToLeftHanded
        \ aiProcess_Triangulate // 삼각형 단위로 변경하는 기능
        \ aiProcess_GenUVCoords // 
        \ aiProcess_GenNormals  // 
        \ aiProcess_CalcTangentSpace // 탄젠트 벡터와 공간을 정보를 제공
        \ aiProcess_GenBoundingBoxes // 충돌 박스를 불러온다, 없으면 생성
        \ aiProcess_GlobalScale // 스케일을 맞춘다?
    )
    
    assert(Scene != nullptr && "모델 정상 로드 않됨");
    
    int a = 0;
    
void CConverter::ExportMesh(wstring InSaveFileName)
{
	InSaveFileName = L"../../_Models" + InSaveFileName + "L.mesh";
    
    ReadMeshData();
}
void CConverter::ReadMeshData()
{
	for(UINT i = 0; i < Scene->mNumMeshes; i++)
   	{
    	FMeshData* data = new FMeshData();
        
        aiMesh* mesh = Scene->mMeshes[i];
        data->Name = mesh->mName.C_Str();
        
        for(UINT v = 0; v < mesh ->mNumVertices; v++) //정점의 갯수를 불러올 차례
        {
        	FVertexModel vertex;
            
            memcpy_s(&vertex.Position, sizeof(FVector), &mesh->mVertices[v], sizeof(FVector)); // 메모리카피
            
            if(mesh->HasTextureCoords(0))
            	memcpy_s(&vertex.Uv, sizeof(FVector2D, &mesh->mTextureCoords[0][v], sizeof(aiVertor2D));)
                
 			if(mesh->HasTextureCoords(0))
            	memcpy_s(&vertex.Color, sizeof(FColor), &mesh->mColor[0][v], sizeof(aiColor4D));
                
            if(mesh->HasTextureCoords(0))
            	memcpy_s(&vertex.Normal, sizeof(FVector), &mesh->mNormal[v], sizeof(aiVector3D));
                
            if(mesh->HasTextureCoords(0))
            	memcpy_s(&vertex.Tangent, sizeof(FVector), &mesh->mTangents[v], sizeof(aiVector3D));
                
            data->Vertices.push_back(vertex);     
                
            mseh->mVertices[v];     //aiVerctor3t? 멤버 확인하기 F12로 진입
        }
        
        for (UINT f = 0; f < mesh->mNumFaces; f++)
        {
        	aiFace& face = mesh->mFaces[f];
            
            for(UINT k = 0; k < face.mNumIndices; k++)
            	data->Indices.push_back(face.mIndices[k]);
        }
       
    }
}// 나온 데이터를 변수로 저장해둘 것이다.
//Converter Object 생성
void CMain::Cube()
{
	CConverter* converter = new CConverter();
    converter->ReadFile(L"Cube.fbx", )
	Delete(converter);
};

Types

- 변수 타입을 파일에 알맞게 변환하는 Assimp


#pragma once
#include "PCH.h"

struct FMeshData
{
	string Name;
    string MaterialName;
    
    verctor<FVertexMode1> Vertices;
    vector<UINT> Indices;    
};


///////////////////////////////////////

struct FVertexModel
{
	FVector Position;
    FVector2D Uv;
    FColor Color;
	FVector Normal;
    FVector Tangent;
    FVector4 Indices; // int4 - Skinning
    FVector4 Weights; // float 
}


BinaryFile

- 바이널리 형식으로 저장하는 파일 형식 만들기


#pragma once

class CBinaryWriter
{
public:
	CBinaryWriter(wstring InFile);
	~CBinaryWriter();
	
    void Close(); //파일닫기
    void ToInt(Int InValue);
    void ToUInt(UINT InValue);
  	void ToString(const string& InValue);
    void ToByte(void* InValue, UINT InDataSize);

private:
	HANDLE FileHandle = nullptr;


}
.cpp

#include "BinaryFile.h"

생성
	assert(InFile.length() > 0);
    
    FileHandle = CreateFile // 만든다는 의미 x 연다는 의미
    (
    	InFile.c_str(),
        GENRIC_WRITE,
        0,
        nullptr,
        CREATE_ALLWAYS,
        FILE_ATRIBUTE_NORMAL,
		nullptr
    );
    assert(FileHandle != INVALID_HANDLE_VALUE);

소멸
{
	Close();
}

void CBinaryWriter::Close() // 닫는 역할
{
	CheckNu11(FileHandle);
    
    CloseHandle(FileHandle);
    FileHandle = nullptr;
}

void CBinaryWriter::ToInt(int InValue)
{
	DWORD size = 0; // UINT 파일의 용량을 결정해주는ㄷㅔ
	WriteFile(FileHandle, &InValue, sizeof(int), &size, nullptr);
}

void CBinaryWriter::ToUINT(UINT InValue)
{
	DWORD size = 0; // UINT 파일의 용량을 결정해주는ㄷㅔ
	WriteFile(FileHandle, &InValue, sizeof(UINT), &size, nullptr);
}

void CBinaryWriter::ToString(const string& InValue)
{	//바이트는 무조건 사용할 메모리의 크기를 작성해줘야한다.
	ToUINT(InValue.size());
    
    DWORD size = 0;
    
    const char* str = InValue.c_str();
    WriteFile(FileHandle, str, InValue.size(), &size, nullptr);

}
void CBinaryWriter::ToByte(void* InValue, UINT InDataSize); // 대량의 데이터를 사용할 예정입니다.
{
	DWORD size = 0;
    WriteFile(FileHandle, InValue, InDataSize, &size, nullptr);
	assert(InDataSize == size);
}
Converter.h

vector<FVertexModel> Vertices;
vector<UINT> Indices;

///////////////////////////////////////////////////////////////
Converter.cpp



WriteMeshData(InSaveFileName);

void CConverter::WriteMeshData(wstring InSaveFileName)
{
	CPath::CreateFolders(CPath::GetDirectoryName(InSaveFileName));
    
    CBinaryWriter* w = new CBinaryWriter(InSaveFileName);
    
    w->ToUINT(Meshes.size());
    for(FMeshData* data : Meshes)
    {
    	w->ToString(data->Name);
        w->ToString(data->MaterialName);
        
        w->ToUINT(data->Verticse.size());
        w->ToUINT(&data->Vertices.size());
        
        w->ToUINT(data->Indices.size());
        w->ToByte(&data0>Vertices[0], sizeof(UINT) * data->Indices.size());
    }
    
    w->Close();
    Delete(w);
}

ModelMesh - Reader (ReadMashData, CreateBuffer, Tick, Render)

-


meshes[0]->Vertices, 144
펼쳐진 주소의 데이터 값

디버깅 중단점을 통한 조사식에서 불러와진 Data가 정상적으로 생성되었다.

MashRender.cpp

//call 해주는 로직

void CMeshRenderer::Tick()
{
	for (CModelMesh* mesh : Meshes)
    	mesh->Tick();
}


void CMeshRenderer::Render()
{
	for (CModelMesh* mesh : Meshes)
    	mesh->Render();
}

CModeMesh::CreateBuffer(CShader* InShader)
{
	Shader = InShader;
    
    Transform = new CTransform(Shader);
    Frame = new CFrame(Shader);
    
    VBuffer = new 
    IBuffer = new
}

void CModelMesh::Render()
{
	Fream->Render();
    
    

	Shader->DrawIndex()

}

mesh->CreateBuffer(InShader);

Shader (VertexModel, Definitions.fx)

- 08_Landscape.fx 활용하기


Position
Uv
Color
Normal
Tangent
Indices
Weights

// 텍스쳐 없음
//항상 맨위에 추가할 lib

#ifndef FX_DEFINITIONS
#define FX_DEFINITIONS

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Vertex / Pixel
///////////////////////////////////////////////////////////////////////////////
#define P_VP(name, vs, ps) \
pass name \
{ \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_RS_VP(name, rs, vs, ps) \
pass name \
{ \
    SetRasterizerState(rs); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_BS_VP(name, bs, vs, ps) \
pass name \
{ \
    SetBlendState(bs, float4(0, 0, 0, 0), 0xFF); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_DSS_VP(name, dss, vs, ps) \
pass name \
{ \
    SetDepthStencilState(dss, 1); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_RS_DSS_VP(name, rs, dss, vs, ps) \
pass name \
{ \
    SetRasterizerState(rs); \
    SetDepthStencilState(dss, 1); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_RS_BS_VP(name, rs, bs, vs, ps) \
pass name \
{ \
    SetRasterizerState(rs); \
    SetBlendState(bs, float4(0, 0, 0, 0), 0xFF); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_DSS_BS_VP(name, dss, bs, vs, ps) \
pass name \
{ \
    SetDepthStencilState(dss, 1); \
    SetBlendState(bs, float4(0, 0, 0, 0), 0xFF); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

///////////////////////////////////////////////////////////////////////////////
// Vertex / Geometry / Pixel
///////////////////////////////////////////////////////////////////////////////
#define P_VGP(name, vs, gs, ps) \
pass name \
{ \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetGeometryShader(CompileShader(gs_5_0, gs())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_RS_VGP(name, rs, vs, gs, ps) \
pass name \
{ \
    SetRasterizerState(rs); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetGeometryShader(CompileShader(gs_5_0, gs())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_BS_VGP(name, bs, vs, gs, ps) \
pass name \
{ \
    SetBlendState(bs, float4(0, 0, 0, 0), 0xFF); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetGeometryShader(CompileShader(gs_5_0, gs())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_DSS_VGP(name, dss, vs, gs, ps) \
pass name \
{ \
    SetDepthStencilState(dss, 1); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetGeometryShader(CompileShader(gs_5_0, gs())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_RS_DSS_VGP(name, rs, dss, vs, gs, ps) \
pass name \
{ \
    SetRasterizerState(rs); \
    SetDepthStencilState(dss, 1); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetGeometryShader(CompileShader(gs_5_0, gs())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_RS_BS_VGP(name, rs, bs, vs, gs, ps) \
pass name \
{ \
    SetRasterizerState(rs); \
    SetBlendState(bs, float4(0, 0, 0, 0), 0xFF); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetGeometryShader(CompileShader(gs_5_0, gs())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_DSS_BS_VGP(name, dss, bs, vs, gs, ps) \
pass name \
{ \
    SetDepthStencilState(dss, 1); \
    SetBlendState(bs, float4(0, 0, 0, 0), 0xFF); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetGeometryShader(CompileShader(gs_5_0, gs())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_RS_DSS_BS_VGP(name, rs, dss, bs, vs, gs, ps) \
pass name \
{ \
    SetRasterizerState(rs); \
    SetDepthStencilState(dss, 1); \
    SetBlendState(bs, float4(0, 0, 0, 0), 0xFF); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetGeometryShader(CompileShader(gs_5_0, gs())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}


///////////////////////////////////////////////////////////////////////////////
// Vertex / Tessellation / Pixel
///////////////////////////////////////////////////////////////////////////////
#define P_VTP(name, vs, hs, ds, ps) \
pass name \
{ \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetHullShader(CompileShader(hs_5_0, hs())); \
    SetDomainShader(CompileShader(ds_5_0, ds())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_RS_VTP(name, rs, vs, hs, ds, ps) \
pass name \
{ \
    SetRasterizerState(rs); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetHullShader(CompileShader(hs_5_0, hs())); \
    SetDomainShader(CompileShader(ds_5_0, ds())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_BS_VTP(name, bs, vs, hs, ds, ps) \
pass name \
{ \
    SetBlendState(bs, float4(0, 0, 0, 0), 0xFF); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetHullShader(CompileShader(hs_5_0, hs())); \
    SetDomainShader(CompileShader(ds_5_0, ds())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_DSS_VTP(name, dss, vs, hs, ds, ps) \
pass name \
{ \
    SetDepthStencilState(dss, 1); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetHullShader(CompileShader(hs_5_0, hs())); \
    SetDomainShader(CompileShader(ds_5_0, ds())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_RS_DSS_VTP(name, rs, dss, vs, hs, ds, ps) \
pass name \
{ \
    SetRasterizerState(rs); \
    SetDepthStencilState(dss, 1); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetHullShader(CompileShader(hs_5_0, hs())); \
    SetDomainShader(CompileShader(ds_5_0, ds())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_RS_BS_VTP(name, rs, bs, vs, hs, ds, ps) \
pass name \
{ \
    SetRasterizerState(rs); \
    SetBlendState(bs, float4(0, 0, 0, 0), 0xFF); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetHullShader(CompileShader(hs_5_0, hs())); \
    SetDomainShader(CompileShader(ds_5_0, ds())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_DSS_BS_VTP(name, dss, bs, vs, hs, ds, ps) \
pass name \
{ \
    SetDepthStencilState(dss, 1); \
    SetBlendState(bs, float4(0, 0, 0, 0), 0xFF); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetHullShader(CompileShader(hs_5_0, hs())); \
    SetDomainShader(CompileShader(ds_5_0, ds())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#define P_RS_DSS_BS_VTP(name, rs, dss, bs, vs, hs, ds, ps) \
pass name \
{ \
    SetRasterizerState(rs); \
    SetDepthStencilState(dss, 1); \
    SetBlendState(bs, float4(0, 0, 0, 0), 0xFF); \
    SetVertexShader(CompileShader(vs_5_0, vs())); \
    SetHullShader(CompileShader(hs_5_0, hs())); \
    SetDomainShader(CompileShader(ds_5_0, ds())); \
    SetPixelShader(CompileShader(ps_5_0, ps())); \
}

#endif //FX_DEFINITIONS
technique11 T_Render
{
	P_VP(P0, VS, PS)
}

technique11 T_Render_Wireframe
{
	P_RS_VP(P0, FillMode_Wireframe, VS, PS)
}

Demo::


void CDemo::Initialize()
{
	CContext::Get()->GetCamera()->SetPosition


}
/////////////////////////////////////////////////////////////////////////////////////////////

float4 PS_Wireframe(VertexOutput input) : SV_Target // 생성된 음영이 없어진 온전한 형태로 등장
{
	return float(1, 1, 1, 1);
}

/////////////////////////////////////////////////////////////////////////////////////////////
void CDemo::Render()
{
	ImGui::Separator();
    ImGui::SeparatorText("Mesh")l
    ImGui::InputInt("Technique", (int*)&Technique);
    Technique = FMath::Clamp<UINT>(Technique, 0, 1);
    Shader->SetTechniqueNumber(Technique);
    
}