summaryrefslogtreecommitdiff
path: root/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp')
-rw-r--r--libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp186
1 files changed, 186 insertions, 0 deletions
diff --git a/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp
new file mode 100644
index 0000000..18bb10f
--- /dev/null
+++ b/libs/assimp/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp
@@ -0,0 +1,186 @@
+#include "ModelLoader.h"
+
+ModelLoader::ModelLoader() :
+ dev_(nullptr),
+ devcon_(nullptr),
+ meshes_(),
+ directory_(),
+ textures_loaded_(),
+ hwnd_(nullptr) {
+ // empty
+}
+
+
+ModelLoader::~ModelLoader() {
+ // empty
+}
+
+bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devcon, std::string filename) {
+ Assimp::Importer importer;
+
+ const aiScene* pScene = importer.ReadFile(filename,
+ aiProcess_Triangulate |
+ aiProcess_ConvertToLeftHanded);
+
+ if (pScene == nullptr)
+ return false;
+
+ this->directory_ = filename.substr(0, filename.find_last_of("/\\"));
+
+ this->dev_ = dev;
+ this->devcon_ = devcon;
+ this->hwnd_ = hwnd;
+
+ processNode(pScene->mRootNode, pScene);
+
+ return true;
+}
+
+void ModelLoader::Draw(ID3D11DeviceContext * devcon) {
+ for (size_t i = 0; i < meshes_.size(); ++i ) {
+ meshes_[i].Draw(devcon);
+ }
+}
+
+Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) {
+ // Data to fill
+ std::vector<VERTEX> vertices;
+ std::vector<UINT> indices;
+ std::vector<Texture> textures;
+
+ // Walk through each of the mesh's vertices
+ for (UINT i = 0; i < mesh->mNumVertices; i++) {
+ VERTEX vertex;
+
+ vertex.X = mesh->mVertices[i].x;
+ vertex.Y = mesh->mVertices[i].y;
+ vertex.Z = mesh->mVertices[i].z;
+
+ if (mesh->mTextureCoords[0]) {
+ vertex.texcoord.x = (float)mesh->mTextureCoords[0][i].x;
+ vertex.texcoord.y = (float)mesh->mTextureCoords[0][i].y;
+ }
+
+ vertices.push_back(vertex);
+ }
+
+ for (UINT i = 0; i < mesh->mNumFaces; i++) {
+ aiFace face = mesh->mFaces[i];
+
+ for (UINT j = 0; j < face.mNumIndices; j++)
+ indices.push_back(face.mIndices[j]);
+ }
+
+ if (mesh->mMaterialIndex >= 0) {
+ aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
+
+ std::vector<Texture> diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse", scene);
+ textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
+ }
+
+ return Mesh(dev_, vertices, indices, textures);
+}
+
+std::vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, std::string typeName, const aiScene * scene) {
+ std::vector<Texture> textures;
+ for (UINT i = 0; i < mat->GetTextureCount(type); i++) {
+ aiString str;
+ mat->GetTexture(type, i, &str);
+ // Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture
+ bool skip = false;
+ for (UINT j = 0; j < textures_loaded_.size(); j++) {
+ if (std::strcmp(textures_loaded_[j].path.c_str(), str.C_Str()) == 0) {
+ textures.push_back(textures_loaded_[j]);
+ skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization)
+ break;
+ }
+ }
+ if (!skip) { // If texture hasn't been loaded already, load it
+ HRESULT hr;
+ Texture texture;
+
+ const aiTexture* embeddedTexture = scene->GetEmbeddedTexture(str.C_Str());
+ if (embeddedTexture != nullptr) {
+ texture.texture = loadEmbeddedTexture(embeddedTexture);
+ } else {
+ std::string filename = std::string(str.C_Str());
+ filename = directory_ + '/' + filename;
+ std::wstring filenamews = std::wstring(filename.begin(), filename.end());
+ hr = CreateWICTextureFromFile(dev_, devcon_, filenamews.c_str(), nullptr, &texture.texture);
+ if (FAILED(hr))
+ MessageBox(hwnd_, "Texture couldn't be loaded", "Error!", MB_ICONERROR | MB_OK);
+ }
+ texture.type = typeName;
+ texture.path = str.C_Str();
+ textures.push_back(texture);
+ this->textures_loaded_.push_back(texture); // Store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures.
+ }
+ }
+ return textures;
+}
+
+void ModelLoader::Close() {
+ for (auto& t : textures_loaded_)
+ t.Release();
+
+ for (size_t i = 0; i < meshes_.size(); i++) {
+ meshes_[i].Close();
+ }
+}
+
+void ModelLoader::processNode(aiNode * node, const aiScene * scene) {
+ for (UINT i = 0; i < node->mNumMeshes; i++) {
+ aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
+ meshes_.push_back(this->processMesh(mesh, scene));
+ }
+
+ for (UINT i = 0; i < node->mNumChildren; i++) {
+ this->processNode(node->mChildren[i], scene);
+ }
+}
+
+ID3D11ShaderResourceView * ModelLoader::loadEmbeddedTexture(const aiTexture* embeddedTexture) {
+ HRESULT hr;
+ ID3D11ShaderResourceView *texture = nullptr;
+
+ if (embeddedTexture->mHeight != 0) {
+ // Load an uncompressed ARGB8888 embedded texture
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = embeddedTexture->mWidth;
+ desc.Height = embeddedTexture->mHeight;
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+
+ D3D11_SUBRESOURCE_DATA subresourceData;
+ subresourceData.pSysMem = embeddedTexture->pcData;
+ subresourceData.SysMemPitch = embeddedTexture->mWidth * 4;
+ subresourceData.SysMemSlicePitch = embeddedTexture->mWidth * embeddedTexture->mHeight * 4;
+
+ ID3D11Texture2D *texture2D = nullptr;
+ hr = dev_->CreateTexture2D(&desc, &subresourceData, &texture2D);
+ if (FAILED(hr))
+ MessageBox(hwnd_, "CreateTexture2D failed!", "Error!", MB_ICONERROR | MB_OK);
+
+ hr = dev_->CreateShaderResourceView(texture2D, nullptr, &texture);
+ if (FAILED(hr))
+ MessageBox(hwnd_, "CreateShaderResourceView failed!", "Error!", MB_ICONERROR | MB_OK);
+
+ return texture;
+ }
+
+ // mHeight is 0, so try to load a compressed texture of mWidth bytes
+ const size_t size = embeddedTexture->mWidth;
+
+ hr = CreateWICTextureFromMemory(dev_, devcon_, reinterpret_cast<const unsigned char*>(embeddedTexture->pcData), size, nullptr, &texture);
+ if (FAILED(hr))
+ MessageBox(hwnd_, "Texture couldn't be created from memory!", "Error!", MB_ICONERROR | MB_OK);
+
+ return texture;
+}