Jump to content
  • Advertisement
Sign in to follow this  
  • entry
    1
  • comments
    0
  • views
    15836

Assimp model loader code (C++)

Sign in to follow this  
newtechnology

2119 views

Here is the newly written code of my assimp model loader. It's much cleaner than what I wrote earlier.

iAJ3MU8.jpg

Model.h#ifndef _MODEL_H_#define _MODEL_H_ #include "BasicIncludes.h"#include "VertexBuffer.h"#include "IndexBuffer.h"#include "Vertex.h" #include #include #include #include namespace NTEngine{struct Subset{Subset(){ZeroMemory(this, sizeof(Subset));} UINT ID;UINT VertexStart;UINT VertexCount;UINT FaceStart;UINT FaceCount;}; class Model{public:DLLEXPORT Model();virtual DLLEXPORT ~Model(); DLLEXPORT virtual VOID LoadFromFile(ID3D11Device* dev, const std::string& file) = 0; protected:DLLEXPORT VOID ExtractIndices(ID3D11Device* dev, const aiScene* scene);DLLEXPORT VOID LoadIndices(ID3D11Device* dev, std::vector& indices);VOID inline LoadDiffuseMap(aiMaterial* mat); protected:VertexBuffer* m_VertexBuffer;IndexBuffer* m_IndexBuffer; UINT m_NumVertices;UINT m_NumFaces;UINT m_Flags; bool m_HasNormalMaps; std::vector m_Subsets; std::vector m_DiffuseMaps; }; class BasicModel : public Model{public:BasicModel() {};~BasicModel() {}; DLLEXPORT VOID LoadFromFile(ID3D11Device* dev, const std::string& file); DLLEXPORT VOID inline Render(ID3D11DeviceContext* devcon); }; class NormalMappedModel : public Model{public:NormalMappedModel() {}~NormalMappedModel() {} DLLEXPORT VOID LoadFromFile(ID3D11Device* dev, const std::string& file); DLLEXPORT VOID inline Render(ID3D11DeviceContext* devcon); private:VOID inline LoadNormalMap(aiMaterial* mat); private:std::vector m_NormalMaps;}; } #endif
Model.cpp#include "Model.h"#include "TextureManager.h"#include "Shaders.h" namespace NTEngine{ #pragma region BaseModelModel::Model(){m_VertexBuffer = new VertexBuffer();m_IndexBuffer = new IndexBuffer(); m_Flags = aiProcess_CalcTangentSpace |aiProcess_JoinIdenticalVertices |aiProcess_Triangulate |aiProcess_GenSmoothNormals |aiProcess_OptimizeMeshes |aiProcess_OptimizeGraph |aiProcess_RemoveRedundantMaterials |aiProcess_ConvertToLeftHanded |aiProcess_SortByPType;} Model::~Model(){SafeDelete(m_VertexBuffer);SafeDelete(m_IndexBuffer); #if defined(DEBUG) | defined(_DEBUG)OutputDebugString("Model released.\n");#endif} void Model::LoadIndices(ID3D11Device* dev, std::vector& indices){std::vector Indices16(indices.size()); bool UseIndices16 = false; //use USHORT for indices if we canif (indices.size() < USHRT_MAX){//convert to USHORT indicesfor (UINT k = 0; k < indices.size(); ++k){Indices16[k] = static_cast(indices[k]);} UseIndices16 = true;} if (UseIndices16)m_IndexBuffer->SetIndices(dev, &Indices16[0], Indices16.size(), DXGI_FORMAT_R16_UINT);elsem_IndexBuffer->SetIndices(dev, &indices[0], indices.size(), DXGI_FORMAT_R32_UINT);} void Model::ExtractIndices(ID3D11Device* dev, const aiScene* pScene){ #if defined(DEBUG) | defined(_DEBUG)assert(!m_Subsets.empty()); #endif std::vector indices; for (UINT i = 0; i < pScene->mNumMeshes; ++i){m_Subsets.FaceStart = indices.size() / 3; aiMesh* CurrentMesh = pScene->mMeshes; //for each triangle in this subsetfor (UINT j = 0; j < CurrentMesh->mNumFaces; ++j){//for each index in this trianglefor (UINT index = 0; index < CurrentMesh->mFaces[j].mNumIndices; ++index){indices.push_back(m_Subsets.VertexStart + CurrentMesh->mFaces[j].mIndices[index]);}} } LoadIndices(dev, indices); } void Model::LoadDiffuseMap(aiMaterial* mat){aiString path; ID3D11ShaderResourceView* SRV = nullptr; if (mat->GetTextureCount(aiTextureType_DIFFUSE) > 0 && mat->GetTexture(aiTextureType_DIFFUSE, 0, &path) == AI_SUCCESS){std::string FileName = path.C_Str(); FileName = removeExtension(FileName);FileName = "Textures\\" + FileName + ".dds"; if (!FileExists(FileName)){#if defined(DEBUG) | defined(_DEBUG)char s[200];sprintf_s(s, "File does not exists: %s\n", FileName.c_str()); OutputDebugString(s);#endif m_DiffuseMaps.push_back(SRV); return;} SRV = TextureManager::Instance()->Create(FileName); m_DiffuseMaps.push_back(SRV);}else{m_DiffuseMaps.push_back(SRV);}} #pragma endregion #pragma region BasicModel void BasicModel::LoadFromFile(ID3D11Device* dev, const std::string& file){ Assimp::Importer imp; const aiScene* pScene = imp.ReadFile(file, m_Flags); if (pScene == NULL)ShowError(imp.GetErrorString()); std::vector vertices; for (UINT i = 0; i < pScene->mNumMeshes; ++i){aiMesh* CurrentMesh = pScene->mMeshes; Subset subset; subset.VertexCount = CurrentMesh->mNumVertices;subset.VertexStart = vertices.size();subset.FaceCount = CurrentMesh->mNumFaces;subset.ID = CurrentMesh->mMaterialIndex; m_NumVertices += subset.VertexCount;m_NumFaces += subset.FaceCount; for (UINT j = 0; j < subset.VertexCount; ++j){Vertex::Basic32 vertex; vertex.Pos.x = CurrentMesh->mVertices[j].x;vertex.Pos.y = CurrentMesh->mVertices[j].y;vertex.Pos.z = CurrentMesh->mVertices[j].z; vertex.Normal.x = CurrentMesh->mNormals[j].x;vertex.Normal.y = CurrentMesh->mNormals[j].y;vertex.Normal.z = CurrentMesh->mNormals[j].z; if (CurrentMesh->HasTextureCoords(0)){vertex.Tex.x = CurrentMesh->mTextureCoords[0][j].x;vertex.Tex.y = CurrentMesh->mTextureCoords[0][j].y;} vertices.push_back(vertex);} aiMaterial* CurrentMeshMaterial = pScene->mMaterials[subset.ID]; //Extract diffuse mapsLoadDiffuseMap(CurrentMeshMaterial); m_Subsets.push_back(subset);} ExtractIndices(dev, pScene); m_VertexBuffer->SetVertices(dev, &vertices[0], vertices.size());} void BasicModel::Render(ID3D11DeviceContext* devcon){UINT offset = 0; const UINT& VertexStride = m_VertexBuffer->GetVertexStride(); ID3D11Buffer* VB = m_VertexBuffer->GetVertexBuffer();ID3D11Buffer* IB = m_IndexBuffer->GetIndexBuffer(); devcon->IASetVertexBuffers(0, 1, &VB, &VertexStride, &offset);devcon->IASetIndexBuffer(IB, m_IndexBuffer->GetIndexBufferFormat(), 0); devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); for (UINT i = 0; i < m_Subsets.size(); ++i){if (m_DiffuseMaps == nullptr)continue; Shaders::Basic->SetDiffuseMap(m_DiffuseMaps); devcon->DrawIndexed(m_Subsets.FaceCount * 3, m_Subsets.FaceStart * 3, 0);}} #pragma endregion #pragma region NormalMappedModel void NormalMappedModel::LoadFromFile(ID3D11Device* dev, const std::string& file){Assimp::Importer imp; const aiScene* pScene = imp.ReadFile(file, m_Flags); if (pScene == NULL)ShowError(imp.GetErrorString()); std::vector vertices; for (UINT i = 0; i < pScene->mNumMeshes; ++i){aiMesh* CurrentMesh = pScene->mMeshes; Subset subset; subset.VertexCount = CurrentMesh->mNumVertices;subset.VertexStart = vertices.size();subset.FaceCount = CurrentMesh->mNumFaces;subset.ID = CurrentMesh->mMaterialIndex; m_NumVertices += subset.VertexCount;m_NumFaces += subset.FaceCount; for (UINT j = 0; j < subset.VertexCount; ++j){Vertex::NormalMap vertex; vertex.Pos.x = CurrentMesh->mVertices[j].x;vertex.Pos.y = CurrentMesh->mVertices[j].y;vertex.Pos.z = CurrentMesh->mVertices[j].z; vertex.Normal.x = CurrentMesh->mNormals[j].x;vertex.Normal.y = CurrentMesh->mNormals[j].y;vertex.Normal.z = CurrentMesh->mNormals[j].z; if (CurrentMesh->HasTangentsAndBitangents()){vertex.Tangent.x = CurrentMesh->mTangents[j].x;vertex.Tangent.y = CurrentMesh->mTangents[j].y;vertex.Tangent.z = CurrentMesh->mTangents[j].z;} if (CurrentMesh->HasTextureCoords(0)){vertex.Tex.x = CurrentMesh->mTextureCoords[0][j].x;vertex.Tex.y = CurrentMesh->mTextureCoords[0][j].y;} vertices.push_back(vertex);} aiMaterial* CurrentMeshMaterial = pScene->mMaterials[subset.ID]; //Extract diffuse mapsLoadDiffuseMap(CurrentMeshMaterial); //Extract normal mapsLoadNormalMap(CurrentMeshMaterial); m_Subsets.push_back(subset);} ExtractIndices(dev, pScene); m_VertexBuffer->SetVertices(dev, &vertices[0], vertices.size());} void NormalMappedModel::LoadNormalMap(aiMaterial* mat){aiString path; ID3D11ShaderResourceView* SRV = nullptr; if (mat->GetTextureCount(aiTextureType_DIFFUSE) > 0 && mat->GetTexture(aiTextureType_DIFFUSE, 0, &path) == AI_SUCCESS){std::string FileName = path.C_Str(); FileName = removeExtension(FileName);FileName = "Textures\\" + FileName + "_nrm" + ".dds"; if (!FileExists(FileName)){#if defined(DEBUG) | defined(_DEBUG)char s[200];sprintf_s(s, "File does not exists: %s\n", FileName.c_str()); OutputDebugString(s);#endif m_NormalMaps.push_back(SRV); return;} SRV = TextureManager::Instance()->Create(FileName); m_NormalMaps.push_back(SRV);}else{m_NormalMaps.push_back(SRV);}} void NormalMappedModel::Render(ID3D11DeviceContext* devcon){UINT offset = 0; const UINT& VertexStride = m_VertexBuffer->GetVertexStride(); ID3D11Buffer* VB = m_VertexBuffer->GetVertexBuffer();ID3D11Buffer* IB = m_IndexBuffer->GetIndexBuffer(); devcon->IASetVertexBuffers(0, 1, &VB, &VertexStride, &offset);devcon->IASetIndexBuffer(IB, m_IndexBuffer->GetIndexBufferFormat(), 0); devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); for (UINT i = 0; i < m_Subsets.size(); ++i){//skip this mesh subset if diffuse map or normal map is missing//this is just a temporary hack and it's going to be removed soon if (m_DiffuseMaps == nullptr)continue; if (m_NormalMaps == nullptr)continue; Shaders::NormalMap->SetDiffuseAndNormalMap(m_DiffuseMaps, m_NormalMaps); devcon->DrawIndexed(m_Subsets.FaceCount * 3, m_Subsets.FaceStart * 3, 0);}} #pragma endregion }
Full source code with usage can be found here:
https://github.com/newtechnology/NT-Engine

For better reading, I suggest using the above github link.
Sign in to follow this  


0 Comments


Recommended Comments

There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!