1 /** 2 * Retrograde Engine 3 * 4 * Authors: 5 * Mike Bierlee, m.bierlee@lostmoment.com 6 * Copyright: 2014-2021 Mike Bierlee 7 * License: 8 * This software is licensed under the terms of the MIT license. 9 * The full terms of the license can be found in the LICENSE.txt file. 10 */ 11 12 module retrograde.pipeline.assimp; 13 14 version(Have_derelict_assimp3) { 15 16 import retrograde.file; 17 import retrograde.geometry; 18 import retrograde.math; 19 20 import std.string; 21 import std.exception; 22 23 import derelict.assimp3.assimp; 24 25 class AssimpImportException : Exception { 26 mixin basicExceptionCtors; 27 } 28 29 class AssimpSceneImporter { 30 31 public const(aiScene*) importScene(File file) { 32 auto scene = aiImportFile(file.fileName.toStringz(), aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType | aiProcess_GenUVCoords | aiProcess_TransformUVCoords); 33 34 if (!scene) { 35 auto errorMessage = cast(string) aiGetErrorString().fromStringz(); 36 throw new AssimpImportException(errorMessage); 37 } 38 39 return scene; 40 } 41 42 public void releaseImport(const(aiScene*) scene) { 43 aiReleaseImport(scene); 44 } 45 46 } 47 48 version(Have_derelict_gl3) { 49 50 import retrograde.graphics.threedee.opengl.model; 51 52 class ModelCreationException : Exception { 53 mixin basicExceptionCtors; 54 } 55 56 class AssimpOpenglModelFactory { 57 58 public OpenGlModel createFromScene(const(aiScene*) scene) { 59 Mesh[] meshes; 60 61 foreach(meshIndex; 0 .. scene.mNumMeshes) { 62 auto assimpMesh = scene.mMeshes[meshIndex]; 63 64 aiColor4D* assimpColorSet; 65 if (assimpMesh.mColors[0]) { 66 assimpColorSet = cast(aiColor4D*) assimpMesh.mColors[0]; 67 } 68 69 aiVector3D* assimpTextureCoordinates; 70 if (assimpMesh.mTextureCoords[0]) { 71 assimpTextureCoordinates = cast(aiVector3D*) assimpMesh.mTextureCoords[0]; 72 } 73 74 75 Vertex[] vertices; 76 foreach(vertexIndex; 0 .. assimpMesh.mNumVertices) { 77 auto assimpVertex = assimpMesh.mVertices[vertexIndex]; 78 79 float red = 1; 80 float green = 1; 81 float blue = 1; 82 float alpha = 1; 83 if (assimpColorSet) { 84 auto color = assimpColorSet[vertexIndex]; 85 red = color.r; 86 green = color.g; 87 blue = color.b; 88 alpha = color.a; 89 } 90 91 float u = 0; 92 float v = 0; 93 if (assimpTextureCoordinates) { 94 u = assimpTextureCoordinates[vertexIndex].x; 95 v = assimpTextureCoordinates[vertexIndex].y; 96 } 97 98 vertices ~= Vertex(assimpVertex.x, assimpVertex.y, assimpVertex.z, 1, red, green, blue, alpha, u, v); 99 } 100 101 Face[] faces; 102 foreach(faceIndex; 0 .. assimpMesh.mNumFaces) { 103 auto assimpFace = assimpMesh.mFaces[faceIndex]; 104 if (assimpFace.mNumIndices != 3) { 105 throw new ModelCreationException(format("Face in mesh contains an unexpect amount of indices (expected 3, got %s), is the mesh triangulated?", assimpFace.mNumIndices)); 106 } 107 108 faces ~= Face(assimpFace.mIndices[0], assimpFace.mIndices[1], assimpFace.mIndices[2]); 109 } 110 111 meshes ~= Mesh(cast(immutable Vertex[]) vertices, cast(immutable Face[]) faces); 112 } 113 114 return new OpenGlModel(cast(immutable Mesh[]) meshes); 115 } 116 117 } 118 119 } 120 }