2
0
Эх сурвалжийг харах

Added indexed mesh support to Polycode, added indexed mesh support to .mesh format, polyimport will now always generate an indexed mesh file, rewrote .mesh format to support flags for different vertex attributes, updated polyimport with options to only include chosen vertex attributes, changed 3d asset import UI to reflect new polyimport changes, added support for secondary UV coordinates

Ivan Safrin 12 жил өмнө
parent
commit
56d250823c

+ 20 - 6
Core/Contents/Include/PolyMesh.h

@@ -152,10 +152,10 @@ namespace Polycode {
 			* Saves mesh to a file.
 			* Saves mesh to a file.
 			* @param fileName Path to file to save to.
 			* @param fileName Path to file to save to.
 			*/			
 			*/			
-			void saveToFile(const String& fileName);
+			void saveToFile(const String& fileName, bool writeNormals = true, bool writeTangents = true, bool writeColors = true, bool writeBoneWeights = true, bool writeUVs = true, bool writeSecondaryUVs = false);
 
 
 			void loadFromFile(OSFILE *inFile);
 			void loadFromFile(OSFILE *inFile);
-			void saveToFile(OSFILE *outFile);
+			void saveToFile(OSFILE *outFile, bool writeNormals = true, bool writeTangents = true, bool writeColors = true, bool writeBoneWeights = true, bool writeUVs = true, bool writeSecondaryUVs = false);
 			
 			
 			
 			
 			/**
 			/**
@@ -274,7 +274,7 @@ namespace Polycode {
 			* @param smooth If true, will use smooth normals.
 			* @param smooth If true, will use smooth normals.
 			* @param smoothAngle If smooth, this parameter sets the angle tolerance for the approximation function.
 			* @param smoothAngle If smooth, this parameter sets the angle tolerance for the approximation function.
 			*/
 			*/
-			void calculateNormals(bool smooth=true, Number smoothAngle=90.0);	
+			void calculateNormals(bool generateFaceNormals = false);
 
 
 			/**
 			/**
 			* Recalculates the tangent space vector for all vertices.
 			* Recalculates the tangent space vector for all vertices.
@@ -295,6 +295,9 @@ namespace Polycode {
 			void dirtyArray(unsigned int arrayIndex);
 			void dirtyArray(unsigned int arrayIndex);
 			void dirtyArrays();
 			void dirtyArrays();
 
 
+            void setUseFaceNormals(bool val);
+            bool getUseFaceNormals();
+        
 			/**
 			/**
 			* Calculates the mesh bounding box.
 			* Calculates the mesh bounding box.
 			*/
 			*/
@@ -358,13 +361,24 @@ namespace Polycode {
 			* If set to true, the renderer will use the vertex colors instead of entity color transform to render this mesh.
 			* If set to true, the renderer will use the vertex colors instead of entity color transform to render this mesh.
 			*/
 			*/
 			bool useVertexColors;
 			bool useVertexColors;
-			
-		
+            bool indexedMesh;
+        
+            void addIndexedFace(unsigned int i1, unsigned int i2, unsigned int i3);
+            void addIndexedFace(unsigned int i1, unsigned int i2, unsigned int i3, unsigned int i4);
+            void addIndex(unsigned int index);
+        
+            Vector3 getFaceNormalForVertex(unsigned int index);
+        
 		protected:
 		protected:
-					
+        
+            bool useFaceNormals;
+        
             VertexBuffer *vertexBuffer;
             VertexBuffer *vertexBuffer;
             bool meshHasVertexBuffer;
             bool meshHasVertexBuffer;
             int meshType;
             int meshType;
+        
+            std::vector<Vector3> faceNormals;
+            std::vector<unsigned int> indices;
             std::vector <Vertex*> vertices;
             std::vector <Vertex*> vertices;
 	};
 	};
 }
 }

+ 6 - 2
Core/Contents/Include/PolyVertex.h

@@ -147,7 +147,10 @@ namespace Polycode {
 			* @param v New vertical texture coordinate.			
 			* @param v New vertical texture coordinate.			
 			*/
 			*/
 			void setTexCoord(Number u, Number v);
 			void setTexCoord(Number u, Number v);
-			
+
+			Vector2 getSecondaryTexCoord();
+            void setSecondaryTexCoord(Number u, Number v);
+        
 			/**
 			/**
 			* Sets the normal
 			* Sets the normal
 			* @param x Normal x.
 			* @param x Normal x.
@@ -185,7 +188,8 @@ namespace Polycode {
 			* Texture coordinates
 			* Texture coordinates
 			*/
 			*/
 			Vector2 texCoord;
 			Vector2 texCoord;
-			
+			Vector2 secondaryTexCoord;
+        
 			bool useVertexColor;
 			bool useVertexColor;
 				
 				
 		protected:
 		protected:

+ 10 - 3
Core/Contents/Source/PolyGLRenderer.cpp

@@ -909,9 +909,16 @@ RenderDataArray *OpenGLRenderer::createRenderDataArrayForMesh(Mesh *mesh, int ar
 			for(int i=0; i < mesh->getVertexCount(); i++) {
 			for(int i=0; i < mesh->getVertexCount(); i++) {
                 newBufferSize = bufferSize + 3;
                 newBufferSize = bufferSize + 3;
                 buffer = (GLfloat*)realloc(buffer, newBufferSize * sizeof(GLfloat));
                 buffer = (GLfloat*)realloc(buffer, newBufferSize * sizeof(GLfloat));
-                buffer[bufferSize+0] = mesh->getVertex(i)->normal.x;
-                buffer[bufferSize+1] = mesh->getVertex(i)->normal.y;
-                buffer[bufferSize+2] = mesh->getVertex(i)->normal.z;
+                if(mesh->getUseFaceNormals()) {
+                    Vector3 n = mesh->getFaceNormalForVertex(i);
+                    buffer[bufferSize+0] = n.x;
+                    buffer[bufferSize+1] = n.y;
+                    buffer[bufferSize+2] = n.z;
+                } else {
+                    buffer[bufferSize+0] = mesh->getVertex(i)->normal.x;
+                    buffer[bufferSize+1] = mesh->getVertex(i)->normal.y;
+                    buffer[bufferSize+2] = mesh->getVertex(i)->normal.z;
+                }
                 bufferSize = newBufferSize;
                 bufferSize = newBufferSize;
 			}			
 			}			
 		}
 		}

+ 10 - 3
Core/Contents/Source/PolyGLVertexBuffer.cpp

@@ -97,9 +97,16 @@ OpenGLVertexBuffer::OpenGLVertexBuffer(Mesh *mesh) : VertexBuffer() {
 	for(int i=0; i < mesh->getVertexCount(); i++) {
 	for(int i=0; i < mesh->getVertexCount(); i++) {
         newBufferSize = bufferSize + 3;
         newBufferSize = bufferSize + 3;
         buffer = (GLfloat*)realloc(buffer, newBufferSize * sizeof(GLfloat));
         buffer = (GLfloat*)realloc(buffer, newBufferSize * sizeof(GLfloat));
-        buffer[bufferSize+0] = mesh->getVertex(i)->normal.x;
-        buffer[bufferSize+1] = mesh->getVertex(i)->normal.y;
-        buffer[bufferSize+2] = mesh->getVertex(i)->normal.z;
+        if(mesh->getUseFaceNormals()) {
+            Vector3 n = mesh->getFaceNormalForVertex(i);
+            buffer[bufferSize+0] = n.x;
+            buffer[bufferSize+1] = n.y;
+            buffer[bufferSize+2] = n.z;
+        } else {
+            buffer[bufferSize+0] = mesh->getVertex(i)->normal.x;
+            buffer[bufferSize+1] = mesh->getVertex(i)->normal.y;
+            buffer[bufferSize+2] = mesh->getVertex(i)->normal.z;
+        }
         bufferSize = newBufferSize;
         bufferSize = newBufferSize;
 	}
 	}
 	
 	

+ 235 - 111
Core/Contents/Source/PolyMesh.cpp

@@ -37,12 +37,13 @@ Mesh::Mesh(const String& fileName) {
         renderDataArrays[i] = NULL;
         renderDataArrays[i] = NULL;
     }
     }
 
 
-    
+    indexedMesh = false;
     meshType = TRI_MESH;
     meshType = TRI_MESH;
     meshHasVertexBuffer = false;
     meshHasVertexBuffer = false;
     loadMesh(fileName);
     loadMesh(fileName);
     vertexBuffer = NULL;			
     vertexBuffer = NULL;			
     useVertexColors = false;
     useVertexColors = false;
+    useFaceNormals = false;
 }
 }
 
 
 Mesh::Mesh(int meshType) {
 Mesh::Mesh(int meshType) {
@@ -53,7 +54,9 @@ Mesh::Mesh(int meshType) {
     this->meshType = meshType;
     this->meshType = meshType;
     meshHasVertexBuffer = false;		
     meshHasVertexBuffer = false;		
     vertexBuffer = NULL;
     vertexBuffer = NULL;
-    useVertexColors = false;				
+    useVertexColors = false;
+    indexedMesh = false;
+    useFaceNormals = false;
 }
 }
 
 
 Mesh *Mesh::MeshFromFileName(String& fileName) {
 Mesh *Mesh::MeshFromFileName(String& fileName) {
@@ -80,6 +83,8 @@ void Mesh::clearMesh() {
             renderDataArrays[i] = NULL;
             renderDataArrays[i] = NULL;
         }
         }
     }
     }
+    indexedMesh = false;
+    useFaceNormals = false;
     meshHasVertexBuffer = false;
     meshHasVertexBuffer = false;
 }
 }
 
 
@@ -87,6 +92,16 @@ VertexBuffer *Mesh::getVertexBuffer() {
     return vertexBuffer;
     return vertexBuffer;
 }
 }
 
 
+void Mesh::setUseFaceNormals(bool val) {
+    useFaceNormals = val;
+    arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;
+}
+
+bool Mesh::getUseFaceNormals() {
+    return useFaceNormals;
+}
+
+
 void Mesh::setVertexBuffer(VertexBuffer *buffer) {
 void Mesh::setVertexBuffer(VertexBuffer *buffer) {
     vertexBuffer = buffer;
     vertexBuffer = buffer;
     meshHasVertexBuffer = true;
     meshHasVertexBuffer = true;
@@ -104,10 +119,36 @@ Number Mesh::getRadius() {
     return hRad;
     return hRad;
 }
 }
 
 
-void Mesh::saveToFile(OSFILE *outFile) {				
+void Mesh::saveToFile(OSFILE *outFile, bool writeNormals, bool writeTangents, bool writeColors, bool writeBoneWeights, bool writeUVs, bool writeSecondaryUVs) {
+    
+    unsigned char meshFlags = 0;
+    
+    if(indexedMesh) {
+        meshFlags |= 1 << 0;
+    }
+    if(writeNormals) {
+        meshFlags |= 1 << 1;
+    }
+    if(writeTangents) {
+        meshFlags |= 1 << 2;
+    }
+    if(writeColors) {
+        meshFlags |= 1 << 3;
+    }
+    if(writeUVs) {
+        meshFlags |= 1 << 4;
+    }
+    if(writeSecondaryUVs) {
+        meshFlags |= 1 << 5;
+    }
+    if(writeBoneWeights) {
+        meshFlags |= 1 << 6;
+    }
+    
+    OSBasics::write(&meshFlags, sizeof(unsigned char), 1, outFile);
+    
     unsigned int numVertices = vertices.size();
     unsigned int numVertices = vertices.size();
-
-    OSBasics::write(&meshType, sizeof(unsigned int), 1, outFile);		
+    OSBasics::write(&meshType, sizeof(unsigned int), 1, outFile);
     OSBasics::write(&numVertices, sizeof(unsigned int), 1, outFile);
     OSBasics::write(&numVertices, sizeof(unsigned int), 1, outFile);
 
 
     Vector3_struct pos;
     Vector3_struct pos;
@@ -115,7 +156,8 @@ void Mesh::saveToFile(OSFILE *outFile) {
     Vector3_struct tan;
     Vector3_struct tan;
     Vector4_struct col;
     Vector4_struct col;
     Vector2_struct tex;
     Vector2_struct tex;
-
+    Vector2_struct tex2;
+    
     for(int i=0; i < vertices.size(); i++) {
     for(int i=0; i < vertices.size(); i++) {
         pos.x =  vertices[i]->x;
         pos.x =  vertices[i]->x;
         pos.y =  vertices[i]->y;
         pos.y =  vertices[i]->y;
@@ -136,30 +178,66 @@ void Mesh::saveToFile(OSFILE *outFile) {
         
         
         tex.x = vertices[i]->getTexCoord().x;
         tex.x = vertices[i]->getTexCoord().x;
         tex.y = vertices[i]->getTexCoord().y;
         tex.y = vertices[i]->getTexCoord().y;
-        
+
+        tex2.x = vertices[i]->getSecondaryTexCoord().x;
+        tex2.y = vertices[i]->getSecondaryTexCoord().y;
+
         OSBasics::write(&pos, sizeof(Vector3_struct), 1, outFile);
         OSBasics::write(&pos, sizeof(Vector3_struct), 1, outFile);
-        OSBasics::write(&nor, sizeof(Vector3_struct), 1, outFile);
-        OSBasics::write(&tan, sizeof(Vector3_struct), 1, outFile);				
-        OSBasics::write(&col, sizeof(Vector4_struct), 1, outFile);				
-        OSBasics::write(&tex, sizeof(Vector2_struct), 1, outFile);
-
-        unsigned int numBoneWeights = vertices[i]->getNumBoneAssignments();
-        OSBasics::write(&numBoneWeights, sizeof(unsigned int), 1, outFile);					
-        for(int b=0; b < numBoneWeights; b++) {
-            BoneAssignment *a = vertices[i]->getBoneAssignment(b);
-            unsigned int boneID = a->boneID;
-            float weight = a->weight;
-            OSBasics::write(&boneID, sizeof(unsigned int), 1, outFile);
-            OSBasics::write(&weight, sizeof(float), 1, outFile);												
+        
+        if(writeNormals) {
+            OSBasics::write(&nor, sizeof(Vector3_struct), 1, outFile);
+        }
+        if(writeTangents) {
+            OSBasics::write(&tan, sizeof(Vector3_struct), 1, outFile);
+        }
+        if(writeColors) {
+            OSBasics::write(&col, sizeof(Vector4_struct), 1, outFile);
+        }
+        if(writeUVs) {
+            OSBasics::write(&tex, sizeof(Vector2_struct), 1, outFile);
+        }
+        if(writeSecondaryUVs) {
+            OSBasics::write(&tex2, sizeof(Vector2_struct), 1, outFile);
+        }
+        
+        if(writeBoneWeights) {
+            unsigned int numBoneWeights = vertices[i]->getNumBoneAssignments();
+            OSBasics::write(&numBoneWeights, sizeof(unsigned int), 1, outFile);					
+            for(int b=0; b < numBoneWeights; b++) {
+                BoneAssignment *a = vertices[i]->getBoneAssignment(b);
+                unsigned int boneID = a->boneID;
+                float weight = a->weight;
+                OSBasics::write(&boneID, sizeof(unsigned int), 1, outFile);
+                OSBasics::write(&weight, sizeof(float), 1, outFile);												
+            }
+        }
+    }
+    
+    if(indexedMesh) {
+        unsigned int numIndices = indices.size();
+        OSBasics::write(&numIndices, sizeof(unsigned int), 1, outFile);
+        for(int i=0; i < numIndices; i++) {
+            OSBasics::write(&indices[i], sizeof(unsigned int), 1, outFile);
         }
         }
     }
     }
 }
 }
 
 
 
 
 void Mesh::loadFromFile(OSFILE *inFile) {
 void Mesh::loadFromFile(OSFILE *inFile) {
-
+    
+    unsigned char meshFlags;
+    OSBasics::read(&meshFlags, sizeof(unsigned char), 1, inFile);
+    
+    indexedMesh = meshFlags & (1 << 0);
+    bool hasNormals = meshFlags & (1 << 1);
+    bool hasTangents = meshFlags & (1 << 2);
+    bool hasColors = meshFlags & (1 << 3);
+    bool hasUV = meshFlags & (1 << 4);
+    bool hasSecondaryUVs = meshFlags & (1 << 5);
+    bool hasBoneWeights = meshFlags & (1 << 6);
+    
     unsigned int meshType;		
     unsigned int meshType;		
-    OSBasics::read(&meshType, sizeof(unsigned int), 1, inFile);				
+    OSBasics::read(&meshType, sizeof(unsigned int), 1, inFile);
     setMeshType(meshType);
     setMeshType(meshType);
     
     
     unsigned int numVertices;
     unsigned int numVertices;
@@ -173,47 +251,70 @@ void Mesh::loadFromFile(OSFILE *inFile) {
     
     
     for(int i=0; i < numVertices; i++) {
     for(int i=0; i < numVertices; i++) {
         OSBasics::read(&pos, sizeof(Vector3_struct), 1, inFile);
         OSBasics::read(&pos, sizeof(Vector3_struct), 1, inFile);
-        OSBasics::read(&nor, sizeof(Vector3_struct), 1, inFile);
-        OSBasics::read(&tan, sizeof(Vector3_struct), 1, inFile);				
-        OSBasics::read(&col, sizeof(Vector4_struct), 1, inFile);						
-        OSBasics::read(&tex, sizeof(Vector2_struct), 1, inFile);						
-        
         Vertex *vertex = new Vertex(pos.x, pos.y, pos.z);
         Vertex *vertex = new Vertex(pos.x, pos.y, pos.z);
-        vertex->setNormal(nor.x,nor.y, nor.z);
-        vertex->tangent = Vector3(tan.x, tan.y, tan.z);
-        vertex->restNormal.set(nor.x,nor.y, nor.z);
-        vertex->vertexColor.setColor(col.x,col.y, col.z, col.w);
-        vertex->setTexCoord(tex.x, tex.y);
         
         
-        unsigned int numBoneWeights;
-        OSBasics::read(&numBoneWeights, sizeof(unsigned int), 1, inFile);								
-        for(int b=0; b < numBoneWeights; b++) {
-            float weight;
-            unsigned int boneID;
-            OSBasics::read(&boneID, sizeof(unsigned int), 1, inFile);													
-            OSBasics::read(&weight, sizeof(float), 1, inFile);																		
-            vertex->addBoneAssignment(boneID, weight);
+        if(hasNormals) {
+            OSBasics::read(&nor, sizeof(Vector3_struct), 1, inFile);
+            vertex->setNormal(nor.x,nor.y, nor.z);
+            vertex->restNormal.set(nor.x,nor.y, nor.z);
+        }
+        if(hasTangents) {
+            OSBasics::read(&tan, sizeof(Vector3_struct), 1, inFile);
+            vertex->tangent = Vector3(tan.x, tan.y, tan.z);
         }
         }
         
         
-        Number totalWeight = 0;				
-        for(int m=0; m < vertex->getNumBoneAssignments(); m++) {
-            BoneAssignment *ba = vertex->getBoneAssignment(m);					
-            totalWeight += ba->weight;
-        }				
-
-        for(int m=0; m < vertex->getNumBoneAssignments(); m++) {
-            BoneAssignment *ba = vertex->getBoneAssignment(m);					
-            ba->weight = ba->weight/totalWeight;
-        }				
+        if(hasColors) {
+            OSBasics::read(&col, sizeof(Vector4_struct), 1, inFile);
+            vertex->vertexColor.setColor(col.x,col.y, col.z, col.w);
+        }
         
         
+        if(hasUV) {
+            OSBasics::read(&tex, sizeof(Vector2_struct), 1, inFile);
+            vertex->setTexCoord(tex.x, tex.y);
+        }
+        
+        if(hasSecondaryUVs) {
+            OSBasics::read(&tex, sizeof(Vector2_struct), 1, inFile);
+            vertex->setSecondaryTexCoord(tex.x, tex.y);
+        }
+        
+        if(hasBoneWeights) {
+            unsigned int numBoneWeights;
+            OSBasics::read(&numBoneWeights, sizeof(unsigned int), 1, inFile);								
+            for(int b=0; b < numBoneWeights; b++) {
+                float weight;
+                unsigned int boneID;
+                OSBasics::read(&boneID, sizeof(unsigned int), 1, inFile);													
+                OSBasics::read(&weight, sizeof(float), 1, inFile);																		
+                vertex->addBoneAssignment(boneID, weight);
+            }
+            
+            Number totalWeight = 0;				
+            for(int m=0; m < vertex->getNumBoneAssignments(); m++) {
+                BoneAssignment *ba = vertex->getBoneAssignment(m);					
+                totalWeight += ba->weight;
+            }				
+
+            for(int m=0; m < vertex->getNumBoneAssignments(); m++) {
+                BoneAssignment *ba = vertex->getBoneAssignment(m);					
+                ba->weight = ba->weight/totalWeight;
+            }				
+        }
         addVertex(vertex);
         addVertex(vertex);
     }
     }
+    
+    if(indexedMesh) {
+        unsigned int numIndices;
+        OSBasics::read(&numIndices, sizeof(unsigned int), 1, inFile);
+        indices.clear();
+        unsigned int val;
+        for(int i=0; i < numIndices; i++) {
+            OSBasics::read(&val, sizeof(unsigned int), 1, inFile);
+            indices.push_back(val);
+        }
+    }
 
 
-    arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
-    arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
-    arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;
-    arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;	
-    arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;								
+    dirtyArrays();
 }
 }
 
 
 Vertex *Mesh::addVertex(Number x, Number y, Number z) {
 Vertex *Mesh::addVertex(Number x, Number y, Number z) {
@@ -232,12 +333,12 @@ Vertex *Mesh::addVertex(Number x, Number y, Number z, Number u, Number v) {
     return vertex;
     return vertex;
 }
 }
 
 
-void Mesh::saveToFile(const String& fileName) {
+void Mesh::saveToFile(const String& fileName, bool writeNormals, bool writeTangents, bool writeColors, bool writeBoneWeights, bool writeUVs, bool writeSecondaryUVs) {
     OSFILE *outFile = OSBasics::open(fileName, "wb");
     OSFILE *outFile = OSBasics::open(fileName, "wb");
     if(!outFile) {
     if(!outFile) {
         Logger::log("Error opening mesh file for saving: %s", fileName.c_str());
         Logger::log("Error opening mesh file for saving: %s", fileName.c_str());
     }
     }
-    saveToFile(outFile);
+    saveToFile(outFile, writeNormals, writeTangents, writeColors, writeBoneWeights, writeUVs, writeSecondaryUVs);
     OSBasics::close(outFile);	
     OSBasics::close(outFile);	
 
 
 }
 }
@@ -423,7 +524,6 @@ void Mesh::createSphere(Number _radius, int _segmentsH, int _segmentsW) {
         Number horangle = ((float)j) / ((float)_segmentsH) * PI;
         Number horangle = ((float)j) / ((float)_segmentsH) * PI;
         Number z = -_radius * cos(horangle);
         Number z = -_radius * cos(horangle);
         Number ringradius = _radius * sin(horangle);
         Number ringradius = _radius * sin(horangle);
-
         for (int i = 0; i < _segmentsW; i++) {
         for (int i = 0; i < _segmentsW; i++) {
             Number verangle = 2.0 * ((float)i) / ((float)_segmentsW) * PI;
             Number verangle = 2.0 * ((float)i) / ((float)_segmentsW) * PI;
             Number x = ringradius * sin(verangle);
             Number x = ringradius * sin(verangle);
@@ -483,7 +583,11 @@ void Mesh::createSphere(Number _radius, int _segmentsH, int _segmentsW) {
 }
 }
 
 
 unsigned int Mesh::getVertexCount() {
 unsigned int Mesh::getVertexCount() {
-    return vertices.size();
+    if(indexedMesh) {
+        return indices.size();
+    } else {
+        return vertices.size();
+    }
 }
 }
 
 
 void Mesh::createTorus(Number radius, Number tubeRadius, int rSegments, int tSegments) {
 void Mesh::createTorus(Number radius, Number tubeRadius, int rSegments, int tSegments) {
@@ -641,64 +745,58 @@ void Mesh::createCone(Number height, Number radius, int numSegments) {
 
 
 }
 }
 
 
+void Mesh::addIndex(unsigned int index) {
+    indices.push_back(index);
+}
+
+void Mesh::addIndexedFace(unsigned int i1, unsigned int i2, unsigned int i3) {
+    indices.push_back(i1);
+    indices.push_back(i2);
+    indices.push_back(i3);
+}
+
+void Mesh::addIndexedFace(unsigned int i1, unsigned int i2, unsigned int i3, unsigned int i4) {
+    indices.push_back(i1);
+    indices.push_back(i2);
+    indices.push_back(i3);
+    indices.push_back(i4);
+}
+
 void Mesh::createBox(Number w, Number d, Number h) {
 void Mesh::createBox(Number w, Number d, Number h) {
     setMeshType(Mesh::TRI_MESH);
     setMeshType(Mesh::TRI_MESH);
+    indexedMesh = true;
     
     
     addVertex(w,0,h, 1, 1);
     addVertex(w,0,h, 1, 1);
     addVertex(0,0,h, 1, 0);
     addVertex(0,0,h, 1, 0);
     addVertex(0,0,0,0,0);
     addVertex(0,0,0,0,0);
-    
-    addVertex(w,0,h, 1, 1);
-    addVertex(0,0,0,0,0);
     addVertex(w,0,0,0,1);
     addVertex(w,0,0,0,1);
-
-    addVertex(w,d,h, 1, 1);
-    addVertex(w,d,0, 1, 0);
-    addVertex(0,d,0,0,0);
-
     addVertex(w,d,h, 1, 1);
     addVertex(w,d,h, 1, 1);
+    addVertex(0,d,h, 1, 0);
     addVertex(0,d,0,0,0);
     addVertex(0,d,0,0,0);
-    addVertex(0,d,h,0,1);
-
-    addVertex(0,d,0,0,1);
-    addVertex(w,d,0, 1, 1);
-    addVertex(w,0,0, 1, 0);
-
-    addVertex(0,d,0,0,1);
-    addVertex(w,0,0, 1, 0);
-    addVertex(0,0,0,0,0);
-
-    addVertex(0,0,h,0,0);
-    addVertex(w,0,h, 1, 0);
-    addVertex(w,d,h, 1, 1);
-
-    addVertex(0,0,h,0,0);
-    addVertex(w,d,h, 1, 1);
-    addVertex(0,d,h,0,1);
-
-    addVertex(0,0,h,0,1);
-    addVertex(0,d,h, 1, 1);
-    addVertex(0,d,0, 1, 0);
-
-    addVertex(0,0,h,0,1);
-    addVertex(0,d,0, 1, 0);
-    addVertex(0,0,0,0,0);
-
-    addVertex(w,0,h,0,1);
-    addVertex(w,0,0, 1, 1);
-    addVertex(w,d,0, 1, 0);
-
-    addVertex(w,0,h,0,1);
-    addVertex(w,d,0, 1, 0);
-    addVertex(w,d,h,0,0);
+    addVertex(w,d,0,0,1);
 
 
     for(int i=0; i < vertices.size(); i++) {
     for(int i=0; i < vertices.size(); i++) {
         vertices[i]->x = vertices[i]->x - (w/2.0f);
         vertices[i]->x = vertices[i]->x - (w/2.0f);
         vertices[i]->y = vertices[i]->y - (d/2.0f);
         vertices[i]->y = vertices[i]->y - (d/2.0f);
         vertices[i]->z = vertices[i]->z - (h/2.0f);
         vertices[i]->z = vertices[i]->z - (h/2.0f);
     }
     }
-
-    calculateNormals(false);
+    
+    addIndexedFace(0, 1, 2);
+    addIndexedFace(0, 2, 3);
+    addIndexedFace(4, 7, 6);
+    addIndexedFace(4, 6, 5);
+    addIndexedFace(6, 7, 3);
+    addIndexedFace(6, 3, 2);
+    addIndexedFace(1, 0, 4);
+    addIndexedFace(1, 4, 5);
+    addIndexedFace(1, 5, 6);
+    addIndexedFace(1, 6, 2);
+    addIndexedFace(0, 3, 7);
+    addIndexedFace(0, 7, 4);
+
+    calculateNormals(true);
+    setUseFaceNormals(true);
+    
     calculateTangents();
     calculateTangents();
     arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
     arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
     arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
     arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
@@ -719,7 +817,11 @@ void Mesh::dirtyArrays() {
 }
 }
 
 
 Vertex *Mesh::getVertex(unsigned int index) const {
 Vertex *Mesh::getVertex(unsigned int index) const {
-    return vertices[index];
+    if(indexedMesh) {
+        return vertices[indices[index]];
+    } else {
+        return vertices[index];
+    }
 }
 }
 
 
 void Mesh::calculateTangents() {
 void Mesh::calculateTangents() {
@@ -727,25 +829,47 @@ void Mesh::calculateTangents() {
     arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;		
     arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;		
 }
 }
 
 
-void Mesh::calculateNormals(bool smooth, Number smoothAngle) {
+Vector3 Mesh::getFaceNormalForVertex(unsigned int index) {
+    unsigned int faceNormalIndex;
+    if(meshType == Mesh::QUAD_MESH) {
+        faceNormalIndex = floor(index/4);
+    } else {
+        faceNormalIndex = floor(index/3);
+    }
+    
+    if(faceNormalIndex < faceNormals.size()) {
+        return faceNormals[faceNormalIndex];
+    } else {
+        return Vector3();
+    }
+}
+
+void Mesh::calculateNormals(bool generateFaceNormals) {
     
     
     int polySize = 3;
     int polySize = 3;
     if(meshType == Mesh::QUAD_MESH) {
     if(meshType == Mesh::QUAD_MESH) {
         polySize = 4;
         polySize = 4;
     }
     }
     
     
+    faceNormals.clear();
     for(int i=0; i < vertices.size(); i++) {
     for(int i=0; i < vertices.size(); i++) {
         vertices[i]->normal = Vector3();
         vertices[i]->normal = Vector3();
     }
     }
 
 
-    for(int i=0; i+2 < vertices.size(); i += polySize) {
-        const Vector3 e1 = *(vertices[i]) - *(vertices[i+1]);
-        const Vector3 e2 = *(vertices[i+2]) - *(vertices[i+1]);
-        const Vector3 no = e1.crossProduct(e2);
+    if(indexedMesh) {
+        for(int i=0; i+polySize-1 < indices.size(); i += polySize) {
+            const Vector3 e1 = *(vertices[indices[i]]) - *(vertices[indices[i+1]]);
+            const Vector3 e2 = *(vertices[indices[i+2]]) - *(vertices[indices[i+1]]);
+            const Vector3 no = e1.crossProduct(e2);
+                
+            vertices[indices[i]]->normal -= no;
+            vertices[indices[i+1]]->normal -= no;
+            vertices[indices[i+2]]->normal -= no;
             
             
-        vertices[i]->normal -= no;
-        vertices[i+1]->normal -= no;
-        vertices[i+2]->normal -= no;
+            if(generateFaceNormals) {
+                faceNormals.push_back(no * -1.0);
+            }
+        }
     }
     }
     
     
     arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;		
     arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;		

+ 9 - 0
Core/Contents/Source/PolyVertex.cpp

@@ -108,4 +108,13 @@ Vector2 Vertex::getTexCoord() {
 void Vertex::setTexCoord(Number u, Number v) {
 void Vertex::setTexCoord(Number u, Number v) {
 	texCoord.x = u;
 	texCoord.x = u;
 	texCoord.y = v;
 	texCoord.y = v;
+}
+
+Vector2 Vertex::getSecondaryTexCoord() {
+	return secondaryTexCoord;
+}
+
+void Vertex::setSecondaryTexCoord(Number u, Number v) {
+	secondaryTexCoord.x = u;
+	secondaryTexCoord.y = v;
 }
 }

+ 1 - 1
IDE/Contents/Include/PolycodeToolLauncher.h

@@ -53,7 +53,7 @@ class PolycodeToolLauncher {
 		static void openExternalEditor(String app, String file, String inFolder);
 		static void openExternalEditor(String app, String file, String inFolder);
 		static String generateTempPath(PolycodeProject *project);
 		static String generateTempPath(PolycodeProject *project);
 		static void buildProject(PolycodeProject *project, String destinationPath, bool compileScripts);
 		static void buildProject(PolycodeProject *project, String destinationPath, bool compileScripts);
-		static String importAssets(String sourceFile, String inFolder, bool addMeshes, String prefix, bool swapZY, bool generateTangents, bool listOnly);
+		static String importAssets(String sourceFile, String inFolder, bool addMeshes, String prefix, bool swapZY, bool generateTangents, bool listOnly,bool writeNormals, bool writeTangents, bool writeColors, bool writeBoneWeights, bool writeUVs, bool writeSecondaryUVs);
 
 
 		static void runPolyapp(String polyappPath);
 		static void runPolyapp(String polyappPath);
 };
 };

+ 8 - 1
IDE/Contents/Include/ToolWindows.h

@@ -112,7 +112,14 @@ class AssetImporterWindow : public UIWindow {
 		UICheckBox *addMeshesCheckbox;
 		UICheckBox *addMeshesCheckbox;
 		UICheckBox *generateTangensCheckbox;
 		UICheckBox *generateTangensCheckbox;
 		UICheckBox *swapZYAxisCheckbox;
 		UICheckBox *swapZYAxisCheckbox;
-				
+
+        UICheckBox *exportNormals;
+        UICheckBox *exportTangents;
+        UICheckBox *exportColors;
+        UICheckBox *exportBoneWeights;
+        UICheckBox *exportUVs;
+        UICheckBox *exportSecondaryUVs;
+    
 		Entity *filesAnchor;
 		Entity *filesAnchor;
 		UIScrollContainer *filesScroller;
 		UIScrollContainer *filesScroller;
 
 

+ 1 - 1
IDE/Contents/Source/PolycodeMeshEditor.cpp

@@ -131,7 +131,7 @@ bool PolycodeMeshEditor::openFile(OSFileEntry filePath) {
 	previewBase->addChild(previewMesh);
 	previewBase->addChild(previewMesh);
 	previewMesh->setMaterialByName("Default");
 	previewMesh->setMaterialByName("Default");
 	PolycodeEditor::openFile(filePath);
 	PolycodeEditor::openFile(filePath);
-	
+
 	previewMesh->alphaTest = true;
 	previewMesh->alphaTest = true;
 	CoreServices::getInstance()->getRenderer()->alphaTestValue = 0.9;
 	CoreServices::getInstance()->getRenderer()->alphaTestValue = 0.9;
 	
 	

+ 21 - 1
IDE/Contents/Source/PolycodeToolLauncher.cpp

@@ -113,7 +113,7 @@ void PolycodeToolLauncher::buildProject(PolycodeProject *project, String destina
 
 
 }
 }
 
 
-String PolycodeToolLauncher::importAssets(String sourceFile, String inFolder, bool addMeshes, String prefix, bool swapZY, bool generateTangents, bool listOnly) {
+String PolycodeToolLauncher::importAssets(String sourceFile, String inFolder, bool addMeshes, String prefix, bool swapZY, bool generateTangents, bool listOnly, bool writeNormals, bool writeTangents, bool writeColors, bool writeBoneWeights, bool writeUVs, bool writeSecondaryUVs) {
 
 
 	String ret;
 	String ret;
 	String polycodeBasePath = CoreServices::getInstance()->getCore()->getDefaultWorkingDirectory();
 	String polycodeBasePath = CoreServices::getInstance()->getCore()->getDefaultWorkingDirectory();
@@ -131,9 +131,29 @@ String PolycodeToolLauncher::importAssets(String sourceFile, String inFolder, bo
 	if(generateTangents) {
 	if(generateTangents) {
 		args = "-t "+args;
 		args = "-t "+args;
 	}
 	}
+    if(writeNormals) {
+		args = "-n "+args;
+    }
+    if(writeTangents) {
+		args = "-g "+args;
+    }
+    if(writeColors) {
+		args = "-c "+args;
+    }
+    if(writeBoneWeights) {
+		args = "-w "+args;
+    }
+    if(writeUVs) {
+		args = "-u "+args;
+    }
+    if(writeSecondaryUVs) {
+		args = "-v "+args;
+    }
+    
 	if(prefix != "") {
 	if(prefix != "") {
 		args = "-p "+prefix+" "+args;
 		args = "-p "+prefix+" "+args;
 	}
 	}
+    
 
 
 	
 	
 #ifdef _WINDOWS
 #ifdef _WINDOWS

+ 36 - 11
IDE/Contents/Source/ToolWindows.cpp

@@ -197,7 +197,7 @@ YesNoCancelPopup::~YesNoCancelPopup() {
 	
 	
 }
 }
 
 
-AssetImporterWindow::AssetImporterWindow() : UIWindow("3D Asset Importer", 500, 300) {
+AssetImporterWindow::AssetImporterWindow() : UIWindow("3D Asset Importer", 650, 250) {
 	filesToImportLabel = new UILabel("Files that will be imported:", 12);
 	filesToImportLabel = new UILabel("Files that will be imported:", 12);
 	addChild(filesToImportLabel);
 	addChild(filesToImportLabel);
 	filesToImportLabel->setPosition(padding, 35);
 	filesToImportLabel->setPosition(padding, 35);
@@ -211,37 +211,62 @@ AssetImporterWindow::AssetImporterWindow() : UIWindow("3D Asset Importer", 500,
 	cancelButton = new UIButton(L"Cancel", 100);
 	cancelButton = new UIButton(L"Cancel", 100);
 	cancelButton->addEventListener(this, UIEvent::CLICK_EVENT);
 	cancelButton->addEventListener(this, UIEvent::CLICK_EVENT);
 	addChild(cancelButton);
 	addChild(cancelButton);
-	cancelButton->setPosition(padding+500-100-100-10-10, 285);		
+	cancelButton->setPosition(padding+650-100-100-10-10, 235);
 	
 	
 	okButton = new UIButton(L"OK", 100);
 	okButton = new UIButton(L"OK", 100);
 	okButton->addEventListener(this, UIEvent::CLICK_EVENT);
 	okButton->addEventListener(this, UIEvent::CLICK_EVENT);
 	addChild(okButton);
 	addChild(okButton);
-	okButton->setPosition(padding+500-100-10, 285);
+	okButton->setPosition(padding+650-100-10, 235);
 	
 	
 	closeOnEscape = true;
 	closeOnEscape = true;
 
 
 	prefixInput = new UITextInput(false, 200, 16);
 	prefixInput = new UITextInput(false, 200, 16);
-	prefixInput->setPosition(290, 60);
+	prefixInput->setPosition(290, 30);
 	addChild(prefixInput); 
 	addChild(prefixInput); 
 	prefixInput->addEventListener(this, UIEvent::CHANGE_EVENT);
 	prefixInput->addEventListener(this, UIEvent::CHANGE_EVENT);
 		
 		
 	usePrefixCheckbox = new UICheckBox("Custom filename prefix", false);
 	usePrefixCheckbox = new UICheckBox("Custom filename prefix", false);
-	usePrefixCheckbox->setPosition(290, 90);
+	usePrefixCheckbox->setPosition(290, 60);
 	addChild(usePrefixCheckbox);
 	addChild(usePrefixCheckbox);
 	usePrefixCheckbox->addEventListener(this, UIEvent::CHANGE_EVENT);
 	usePrefixCheckbox->addEventListener(this, UIEvent::CHANGE_EVENT);
 	
 	
 	addMeshesCheckbox = new UICheckBox("Add all meshes to a single mesh", false);
 	addMeshesCheckbox = new UICheckBox("Add all meshes to a single mesh", false);
-	addMeshesCheckbox->setPosition(290, 120);
+	addMeshesCheckbox->setPosition(290, 90);
 	addChild(addMeshesCheckbox); 
 	addChild(addMeshesCheckbox); 
 	addMeshesCheckbox->addEventListener(this, UIEvent::CHANGE_EVENT);
 	addMeshesCheckbox->addEventListener(this, UIEvent::CHANGE_EVENT);
 	
 	
 	generateTangensCheckbox = new UICheckBox("Generate tangents", true);
 	generateTangensCheckbox = new UICheckBox("Generate tangents", true);
-	generateTangensCheckbox->setPosition(290, 150);
+	generateTangensCheckbox->setPosition(290, 120);
 	addChild(generateTangensCheckbox); 
 	addChild(generateTangensCheckbox); 
 	
 	
 	swapZYAxisCheckbox = new UICheckBox("Swap Z/Y axis (e.g. for Blender)", false);
 	swapZYAxisCheckbox = new UICheckBox("Swap Z/Y axis (e.g. for Blender)", false);
-	swapZYAxisCheckbox->setPosition(290, 180);
-	addChild(swapZYAxisCheckbox); 
+	swapZYAxisCheckbox->setPosition(290, 150);
+	addChild(swapZYAxisCheckbox);
+    
+    exportNormals = new UICheckBox("Vertex normals", true);
+	exportNormals->setPosition(520, 30);
+	addChild(exportNormals);
+    
+    exportTangents = new UICheckBox("Vertex tangents", true);
+	exportTangents->setPosition(520, 60);
+	addChild(exportTangents);
+    
+    exportColors = new UICheckBox("Vertex colors", false);
+	exportColors->setPosition(520, 90);
+	addChild(exportColors);
+    
+    exportBoneWeights = new UICheckBox("Bone weights", false);
+	exportBoneWeights->setPosition(520, 120);
+	addChild(exportBoneWeights);
+    
+    exportUVs = new UICheckBox("UV coordinates", true);
+	exportUVs->setPosition(520, 150);
+	addChild(exportUVs);
+    
+    exportSecondaryUVs = new UICheckBox("Secondary UVs", true);
+	exportSecondaryUVs->setPosition(520, 180);
+	addChild(exportSecondaryUVs);
+    
 }
 }
 
 
 void AssetImporterWindow::handleEvent(Event *event) {
 void AssetImporterWindow::handleEvent(Event *event) {
@@ -254,7 +279,7 @@ void AssetImporterWindow::handleEvent(Event *event) {
 		if(usePrefixCheckbox->isChecked() && prefixInput->getText() != "") {
 		if(usePrefixCheckbox->isChecked() && prefixInput->getText() != "") {
 			prefixString = prefixInput->getText().replace(" ", "_");
 			prefixString = prefixInput->getText().replace(" ", "_");
 		}
 		}
-		PolycodeToolLauncher::importAssets(file, folder, addMeshesCheckbox->isChecked(), prefixString, swapZYAxisCheckbox->isChecked(), generateTangensCheckbox->isChecked(), false);	
+		PolycodeToolLauncher::importAssets(file, folder, addMeshesCheckbox->isChecked(), prefixString, swapZYAxisCheckbox->isChecked(), generateTangensCheckbox->isChecked(), false, exportNormals->isChecked(), exportTangents->isChecked(), exportColors->isChecked(), exportBoneWeights->isChecked(), exportUVs->isChecked(), exportSecondaryUVs->isChecked());
 	
 	
 		dispatchEvent(new UIEvent(), UIEvent::OK_EVENT);
 		dispatchEvent(new UIEvent(), UIEvent::OK_EVENT);
 		dispatchEvent(new UIEvent(), UIEvent::CLOSE_EVENT);	
 		dispatchEvent(new UIEvent(), UIEvent::CLOSE_EVENT);	
@@ -301,7 +326,7 @@ void AssetImporterWindow::refreshPreview() {
 	if(usePrefixCheckbox->isChecked() && prefixInput->getText() != "") {
 	if(usePrefixCheckbox->isChecked() && prefixInput->getText() != "") {
 		prefixString = prefixInput->getText().replace(" ", "_");
 		prefixString = prefixInput->getText().replace(" ", "_");
 	}
 	}
-	String fileList = PolycodeToolLauncher::importAssets(file, folder, addMeshesCheckbox->isChecked(), prefixString, swapZYAxisCheckbox->isChecked(), generateTangensCheckbox->isChecked(), true);
+	String fileList = PolycodeToolLauncher::importAssets(file, folder, addMeshesCheckbox->isChecked(), prefixString, swapZYAxisCheckbox->isChecked(), generateTangensCheckbox->isChecked(), true, false, false, false, false, false, false);
 	setFilesToImport(fileList);		
 	setFilesToImport(fileList);		
 }
 }
 
 

+ 117 - 72
Tools/Contents/polyimport/Source/polyimport.cpp

@@ -12,6 +12,13 @@ bool hasWeights = false;
 vector<aiBone*> bones;
 vector<aiBone*> bones;
 unsigned int numBones = 0;
 unsigned int numBones = 0;
 
 
+bool writeNormals = false;
+bool writeTangents = false;
+bool writeColors = false;
+bool writeBoneWeights = false;
+bool writeUVs = false;
+bool writeSecondaryUVs = false;
+
 unsigned int addBone(aiBone *bone) {
 unsigned int addBone(aiBone *bone) {
 	for(int i=0; i < bones.size(); i++) {
 	for(int i=0; i < bones.size(); i++) {
 		if(bones[i]->mName == bone->mName)
 		if(bones[i]->mName == bone->mName)
@@ -30,6 +37,7 @@ void addToMesh(String prefix, Polycode::Mesh *tmesh, const struct aiScene *sc, c
 	
 	
 		if(!addSubmeshes) {
 		if(!addSubmeshes) {
 			tmesh = new Polycode::Mesh(Mesh::TRI_MESH);
 			tmesh = new Polycode::Mesh(Mesh::TRI_MESH);
+            tmesh->indexedMesh = true;
 		}
 		}
 	
 	
 		const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]];
 		const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]];
@@ -41,61 +49,73 @@ void addToMesh(String prefix, Polycode::Mesh *tmesh, const struct aiScene *sc, c
 			printf("Importing mesh:%s (%d vertices) (%d faces) \n", mesh->mName.data, mesh->mNumVertices, mesh->mNumFaces);
 			printf("Importing mesh:%s (%d vertices) (%d faces) \n", mesh->mName.data, mesh->mNumVertices, mesh->mNumFaces);
 		}
 		}
 		//apply_material(sc->mMaterials[mesh->mMaterialIndex]);
 		//apply_material(sc->mMaterials[mesh->mMaterialIndex]);
-
-		for (t = 0; t < mesh->mNumFaces; ++t) {
-			const struct aiFace* face = &mesh->mFaces[t];
-	
-			for(i = 0; i < face->mNumIndices; i++) {
-				Vertex *vertex = new Vertex();
-
-				int index = face->mIndices[i];
-				if(mesh->mColors[0] != NULL) {
-					vertex->vertexColor.setColorRGBA(mesh->mColors[0][index].r, mesh->mColors[0][index].g, mesh->mColors[0][index].b, mesh->mColors[0][index].a);
-				}
-
-				if(mesh->mTangents != NULL)  {
-					if(swapZY)
-						vertex->tangent = Vector3(mesh->mTangents[index].x, mesh->mTangents[index].z, -mesh->mTangents[index].y);
-					else
-						vertex->tangent = Vector3(mesh->mTangents[index].x, mesh->mTangents[index].y, mesh->mTangents[index].z);
-				}
-
-				if(mesh->mNormals != NULL)  {
-					if(swapZY)
-						vertex->setNormal(mesh->mNormals[index].x, mesh->mNormals[index].z, -mesh->mNormals[index].y);
-					else
-						vertex->setNormal(mesh->mNormals[index].x, mesh->mNormals[index].y, mesh->mNormals[index].z);
-				}
-
-				if(mesh->HasTextureCoords(0))
-				{
-					vertex->setTexCoord(mesh->mTextureCoords[0][index].x, mesh->mTextureCoords[0][index].y);
-				}
-
-				for( unsigned int a = 0; a < mesh->mNumBones; a++) {
-					aiBone* bone = mesh->mBones[a];
-					unsigned int boneIndex = addBone(bone);
-
-					for( unsigned int b = 0; b < bone->mNumWeights; b++) {
-						if(bone->mWeights[b].mVertexId == index) {
-							vertex->addBoneAssignment(boneIndex, bone->mWeights[b].mWeight);
-							hasWeights = true;
-						}
-					}
-				}
-	
-				if(swapZY)
+        
+		for (t = 0; t < mesh->mNumVertices; ++t) {
+            Vertex *vertex = new Vertex();
+            int index = t;
+            if(mesh->mColors[0] != NULL) {
+                vertex->vertexColor.setColorRGBA(mesh->mColors[0][index].r, mesh->mColors[0][index].g, mesh->mColors[0][index].b, mesh->mColors[0][index].a);
+            }
+
+            if(mesh->mTangents != NULL)  {
+                if(swapZY)
+                    vertex->tangent = Vector3(mesh->mTangents[index].x, mesh->mTangents[index].z, -mesh->mTangents[index].y);
+                else
+                    vertex->tangent = Vector3(mesh->mTangents[index].x, mesh->mTangents[index].y, mesh->mTangents[index].z);
+            }
+
+            if(mesh->mNormals != NULL)  {
+                if(swapZY)
+                    vertex->setNormal(mesh->mNormals[index].x, mesh->mNormals[index].z, -mesh->mNormals[index].y);
+                else
+                    vertex->setNormal(mesh->mNormals[index].x, mesh->mNormals[index].y, mesh->mNormals[index].z);
+            }
+
+            if(mesh->HasTextureCoords(0))
+            {
+                vertex->setTexCoord(mesh->mTextureCoords[0][index].x, mesh->mTextureCoords[0][index].y);
+            }
+
+            if(mesh->HasTextureCoords(1))
+            {
+                vertex->setSecondaryTexCoord(mesh->mTextureCoords[1][index].x, mesh->mTextureCoords[1][index].y);
+            }
+
+            
+            for( unsigned int a = 0; a < mesh->mNumBones; a++) {
+                aiBone* bone = mesh->mBones[a];
+                unsigned int boneIndex = addBone(bone);
+
+                for( unsigned int b = 0; b < bone->mNumWeights; b++) {
+                    if(bone->mWeights[b].mVertexId == index) {
+                        vertex->addBoneAssignment(boneIndex, bone->mWeights[b].mWeight);
+                        hasWeights = true;
+                    }
+                }
+            }
+
+            if(swapZY) {
 					vertex->set(mesh->mVertices[index].x, mesh->mVertices[index].z, -mesh->mVertices[index].y);
 					vertex->set(mesh->mVertices[index].x, mesh->mVertices[index].z, -mesh->mVertices[index].y);
-				else
-					vertex->set(mesh->mVertices[index].x, mesh->mVertices[index].y, mesh->mVertices[index].z);
-				tmesh->addVertex(vertex);
-			}
+            } else {
+                vertex->set(mesh->mVertices[index].x, mesh->mVertices[index].y, mesh->mVertices[index].z);
+            }
+            tmesh->addVertex(vertex);
 		}
 		}
+        
+
+         for (t = 0; t < mesh->mNumFaces; ++t) {
+             const struct aiFace* face = &mesh->mFaces[t];
+
+             for(i = 0; i < face->mNumIndices; i++) {
+                 int index = face->mIndices[i];
+                 tmesh->addIndex(index);
+             }
+         }
 		
 		
 		if(!addSubmeshes && !listOnly) {
 		if(!addSubmeshes && !listOnly) {
 			String fileNameMesh = prefix+String(nd->mName.data)+".mesh";			
 			String fileNameMesh = prefix+String(nd->mName.data)+".mesh";			
 			OSFILE *outFile = OSBasics::open(fileNameMesh.c_str(), "wb");	
 			OSFILE *outFile = OSBasics::open(fileNameMesh.c_str(), "wb");	
-			tmesh->saveToFile(outFile);
+			tmesh->saveToFile(outFile, writeNormals, writeTangents, writeColors, writeBoneWeights, writeUVs, writeSecondaryUVs);
 			OSBasics::close(outFile);
 			OSBasics::close(outFile);
 			delete tmesh;
 			delete tmesh;
 		}
 		}
@@ -139,6 +159,7 @@ void addToISkeleton(ISkeleton *skel, IBone *parent, const struct aiScene *sc, co
 int exportToFile(String prefix, bool swapZY, bool addSubmeshes, bool listOnly) {
 int exportToFile(String prefix, bool swapZY, bool addSubmeshes, bool listOnly) {
 		
 		
 	Polycode::Mesh *mesh = new Polycode::Mesh(Mesh::TRI_MESH);
 	Polycode::Mesh *mesh = new Polycode::Mesh(Mesh::TRI_MESH);
+    mesh->indexedMesh = true;
 	addToMesh(prefix, mesh, scene, scene->mRootNode, swapZY, addSubmeshes, listOnly);
 	addToMesh(prefix, mesh, scene, scene->mRootNode, swapZY, addSubmeshes, listOnly);
 	
 	
 	if(addSubmeshes) {		
 	if(addSubmeshes) {		
@@ -153,7 +174,7 @@ int exportToFile(String prefix, bool swapZY, bool addSubmeshes, bool listOnly) {
 			printf("%s\n", fileNameMesh.c_str());
 			printf("%s\n", fileNameMesh.c_str());
 		} else {
 		} else {
 			OSFILE *outFile = OSBasics::open(fileNameMesh.c_str(), "wb");	
 			OSFILE *outFile = OSBasics::open(fileNameMesh.c_str(), "wb");	
-			mesh->saveToFile(outFile);
+			mesh->saveToFile(outFile, writeNormals, writeTangents, writeColors, writeBoneWeights, writeUVs, writeSecondaryUVs);
 			OSBasics::close(outFile);
 			OSBasics::close(outFile);
 		}
 		}
 	}
 	}
@@ -234,12 +255,30 @@ int main(int argc, char **argv) {
 	bool addSubmeshes = false;
 	bool addSubmeshes = false;
 	bool listOnly = false;
 	bool listOnly = false;
 	bool showAssimpDebug = false;
 	bool showAssimpDebug = false;
-	
+	   
 	String prefix;
 	String prefix;
 	
 	
 	int opt;
 	int opt;
-	while ((opt = getopt(argc, argv, "adlhp:st")) != -1) {
+	while ((opt = getopt(argc, argv, "ngcwuvadlhp:st")) != -1) {
 		switch ((char)opt) {
 		switch ((char)opt) {
+            case 'n':
+                writeNormals = true;
+            break;
+            case 'g':
+                writeTangents = true;
+            break;
+            case 'c':
+                writeColors = true;
+            break;
+            case 'w':
+                writeBoneWeights = true;
+            break;
+            case 'u':
+                writeUVs = true;
+            break;
+            case 'v':
+                writeSecondaryUVs = true;
+            break;
 			case 's':
 			case 's':
 				swapZYAxis = true;
 				swapZYAxis = true;
 			break;
 			break;
@@ -280,15 +319,24 @@ int main(int argc, char **argv) {
 		return 0;		
 		return 0;		
 	}
 	}
 	
 	
-	if(showHelp) {
-		printf("usage: polyimport [-adhlst] [-p output_prefix] source_file\n\n");
-		printf("a: Add all meshes to a single mesh.\n");
+	if(showHelp || argc < 2) {
+		printf("usage: polyimport [-adhlstngcwuv] [-p output_prefix] source_file\n\n");
+		printf("Misc options:\n");
 		printf("d: Show Assimp debug info.\n");
 		printf("d: Show Assimp debug info.\n");
-		printf("h: Show this help.\n");		
-		printf("l: List output files, but do not convert.\n");				
-		printf("p: Specify a file prefix for exported files.\n");			
+		printf("h: Show this help.\n");
+		printf("l: List output files, but do not convert.\n");
+		printf("p: Specify a file prefix for exported files.\n\n");
+		printf("Mesh import options:\n");
+		printf("a: Add all meshes to a single mesh.\n");
 		printf("s: Swap Z/Y axis (e.g. import from Blender)\n");
 		printf("s: Swap Z/Y axis (e.g. import from Blender)\n");
-		printf("t: Generate tangents.\n");
+		printf("t: Generate tangents.\n\n");
+		printf("Mesh export options:\n");
+		printf("n: Export normals\n");
+		printf("g: Export tangents\n");
+		printf("c: Export colors\n");
+		printf("w: Export bone weights\n");
+		printf("u: Export UV coordinates\n");
+		printf("v: Export secondary UV coordinates\n");
 		printf("\n");
 		printf("\n");
 		return 0;
 		return 0;
 	}
 	}
@@ -300,25 +348,22 @@ int main(int argc, char **argv) {
 		stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL);
 		stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL);
 		aiAttachLogStream(&stream);
 		aiAttachLogStream(&stream);
 	}
 	}
-	
-	if(argc < 2) {
-		printf("Please specify input filename\n");
-		return 0;
-	}	
-	
+		
 	int inputArg = argc-1;
 	int inputArg = argc-1;
 
 
 	if(!listOnly) {
 	if(!listOnly) {
 		printf("Loading %s...\n", argv[inputArg]);
 		printf("Loading %s...\n", argv[inputArg]);
 	}
 	}
 	
 	
-	scene = aiImportFile(argv[inputArg],aiProcessPreset_TargetRealtime_Quality);
-	
-	if(generateTangents && !listOnly) {
-		aiApplyPostProcessing(scene, aiProcess_CalcTangentSpace);
-	}
-	
-	if(scene) {
+	scene = aiImportFile(argv[inputArg], aiProcess_JoinIdenticalVertices|
+                         aiProcess_Triangulate);
+    
+    if(scene) {
+        
+        if(generateTangents && !listOnly) {
+            aiApplyPostProcessing(scene, aiProcess_CalcTangentSpace);
+        }
+        
 		exportToFile(prefix, swapZYAxis, addSubmeshes, listOnly);
 		exportToFile(prefix, swapZYAxis, addSubmeshes, listOnly);
 	} else {
 	} else {
 		printf("Error opening scene...\n");
 		printf("Error opening scene...\n");