1 /** 2 * Defines the Mesh class, which controls all meshes loaded into the world. 3 */ 4 module components.mesh; 5 6 import core.properties; 7 import components.component; 8 import graphics.graphics, graphics.shaders; 9 import utility.output; 10 11 import derelict.assimp3.assimp; 12 import derelict.opengl3.gl3; 13 14 import std.stdio, std.stream, std.format, std.math; 15 16 class Mesh : Component 17 { 18 public: 19 mixin Property!( "uint", "glVertexArray", "protected" ); 20 mixin Property!( "uint", "numVertices", "protected" ); 21 mixin Property!( "uint", "numIndices", "protected" ); 22 mixin BackedProperty!( "uint", "_glIndexBuffer", "glIndexBuffer" ); 23 mixin BackedProperty!( "uint", "_glVertexBuffer", "glVertexBuffer" ); 24 enum FloatsPerVertex = 11; 25 enum VertexSize = float.sizeof * FloatsPerVertex; 26 27 this( string filePath ) 28 { 29 super( null ); 30 31 // Initial assimp start 32 DerelictASSIMP3.load(); 33 34 // Load the scene via assimp 35 const aiScene* scene = aiImportFile(( filePath ~ "\0" ).ptr, 36 aiProcess_CalcTangentSpace | aiProcess_Triangulate | 37 aiProcess_JoinIdenticalVertices | aiProcess_SortByPType );//| 38 //aiProcess_FlipWindingOrder ); 39 float[] outputData; 40 uint[] indices; 41 if(!scene) 42 { 43 // Did not load 44 log( OutputType.Error, "Mesh not loaded: ", filePath ); 45 } 46 else 47 { 48 // Get the mesh 49 auto mesh = scene.mMeshes[0]; 50 51 // For each vertex on each face 52 int meshFaces = mesh.mNumFaces; 53 for( int i = 0; i < meshFaces; i++ ) 54 { 55 auto face = mesh.mFaces[i]; 56 for( int j = 0; j < 3; j++ ) 57 { 58 // Get the vertex data 59 aiVector3D pos = mesh.mVertices[ face.mIndices[ j ] ]; 60 aiVector3D uv = mesh.mTextureCoords[ 0 ][ face.mIndices[ j ] ]; 61 aiVector3D normal = mesh.mNormals[ face.mIndices[ j ] ]; 62 aiVector3D tangent = mesh.mTangents[ face.mIndices[ j ] ]; 63 aiVector3D bitangent = mesh.mBitangents[ face.mIndices[ j ] ]; 64 65 // Append the data 66 outputData ~= pos.x; 67 outputData ~= pos.y; 68 outputData ~= pos.z; 69 outputData ~= uv.x; 70 outputData ~= uv.y; 71 outputData ~= normal.x; 72 outputData ~= normal.y; 73 outputData ~= normal.z; 74 outputData ~= tangent.x; 75 outputData ~= tangent.y; 76 outputData ~= tangent.z; 77 //outputData ~= bitangent.x; 78 //outputData ~= bitangent.y; 79 //outputData ~= bitangent.z; 80 } 81 } 82 83 numVertices = cast(uint)( outputData.length / FloatsPerVertex ); // 11 is num floats per vertex 84 numIndices = numVertices; 85 86 indices = new uint[ numIndices ]; 87 foreach( ii; 0..numIndices ) 88 indices[ ii ] = ii; 89 } 90 // Release assimp instance now that we have all the model data 91 aiReleaseImport( scene ); 92 93 94 // make and bind the VAO 95 glGenVertexArrays( 1, &_glVertexArray ); 96 glBindVertexArray( glVertexArray ); 97 98 // make and bind the VBO 99 glGenBuffers( 1, &_glVertexBuffer ); 100 glBindBuffer( GL_ARRAY_BUFFER, glVertexBuffer ); 101 102 // Buffer the data 103 glBufferData( GL_ARRAY_BUFFER, outputData.length * GLfloat.sizeof, outputData.ptr, GL_STATIC_DRAW ); 104 105 uint POSITION_ATTRIBUTE = 0; 106 uint UV_ATTRIBUTE = 1; 107 uint NORMAL_ATTRIBUTE = 2; 108 uint TANGENT_ATTRIBUTE = 3; 109 uint BINORMAL_ATTRIBUTE = 4; 110 111 // Connect the position to the inputPosition attribute of the vertex shader 112 glEnableVertexAttribArray( POSITION_ATTRIBUTE ); 113 glVertexAttribPointer( POSITION_ATTRIBUTE, 3, GL_FLOAT, GL_FALSE, VertexSize, cast(const(void)*)0 ); 114 // Connect uv to the textureCoordinate attribute of the vertex shader 115 glEnableVertexAttribArray( UV_ATTRIBUTE ); 116 glVertexAttribPointer( UV_ATTRIBUTE, 2, GL_FLOAT, GL_FALSE, VertexSize, cast(char*)0 + ( GLfloat.sizeof * 3 ) ); 117 // Connect normals to the shaderPosition attribute of the vertex shader 118 glEnableVertexAttribArray( NORMAL_ATTRIBUTE ); 119 glVertexAttribPointer( NORMAL_ATTRIBUTE, 3, GL_FLOAT, GL_FALSE, VertexSize, cast(char*)0 + ( GLfloat.sizeof * 5 ) ); 120 // Connect the tangent to the vertex shader 121 glEnableVertexAttribArray( TANGENT_ATTRIBUTE ); 122 glVertexAttribPointer( TANGENT_ATTRIBUTE, 3, GL_FLOAT, GL_FALSE, VertexSize, cast(char*)0 + ( GLfloat.sizeof * 8 ) ); 123 // Connect the binormal to the vertex shader 124 //glEnableVertexAttribArray( BINORMAL_ATTRIBUTE ); 125 //glVertexAttribPointer( BINORMAL_ATTRIBUTE, 3, GL_FLOAT, GL_FALSE, VertexSize, cast(char*)0 + ( GLfloat.sizeof * 11 ) ); 126 127 // Generate index buffer 128 glGenBuffers( 1, &_glIndexBuffer ); 129 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, glIndexBuffer ); 130 131 // Buffer index data 132 glBufferData( GL_ELEMENT_ARRAY_BUFFER, uint.sizeof * numVertices, indices.ptr, GL_STATIC_DRAW ); 133 134 // unbind the VBO and VAO 135 glBindBuffer( GL_ARRAY_BUFFER, 0 ); 136 glBindVertexArray( 0 ); 137 } 138 139 override void update() 140 { 141 142 } 143 144 override void shutdown() 145 { 146 glDeleteBuffers( 1, &_glVertexBuffer ); 147 glDeleteBuffers( 1, &_glVertexArray ); 148 } 149 150 private: 151 union 152 { 153 uint _glIndexBuffer; 154 } 155 156 union 157 { 158 uint _glVertexBuffer; 159 } 160 }