Просмотр исходного кода

Converted all primitives to use indexed vertices, rewrote normal and tangent genration to be much faster (will not generate smooth normals/tangents for unconnected non-indexed faces anymore)

Ivan Safrin 12 лет назад
Родитель
Сommit
6478b258ef

+ 2 - 0
Core/Contents/Include/PolyMesh.h

@@ -371,6 +371,8 @@ namespace Polycode {
         
 		protected:
         
+            Vector3 calculateFaceTangent(Vertex *v1, Vertex *v2, Vertex *v3);
+        
             bool useFaceNormals;
         
             VertexBuffer *vertexBuffer;

+ 286 - 189
Core/Contents/Source/PolyMesh.cpp

@@ -72,6 +72,9 @@ void Mesh::clearMesh() {
         delete vertices[i];
     }
     vertices.clear();
+    indices.clear();
+    faceNormals.clear();
+    
     if(vertexBuffer)
         delete vertexBuffer;
     vertexBuffer = NULL;
@@ -507,77 +510,47 @@ Vector3 Mesh::calculateBBox() {
     return retVec*2;
 }
 
-void Mesh::createSphere(Number _radius, int _segmentsH, int _segmentsW) {
-
-    setMeshType(Mesh::TRI_MESH);
+void Mesh::createSphere(Number radius, int segmentsH, int segmentsW) {
 
-    Vector3 **grid = (Vector3 **) malloc(sizeof(Vector3*) * (_segmentsH+1));
-    for (int i=0 ; i < _segmentsH+1; i++) {
-        grid[i] = (Vector3*) malloc(sizeof(Vector3) * _segmentsW+1);		
-    }
+    segmentsH++;
+    segmentsW++;
     
-    for (int i = 0; i < _segmentsW; i++) {
-        grid[0][i] = Vector3(0,-_radius,0);
-    }
-        
-    for (int j = 1; j < _segmentsH; j++) {
-        Number horangle = ((float)j) / ((float)_segmentsH) * PI;
-        Number z = -_radius * cos(horangle);
-        Number ringradius = _radius * sin(horangle);
-        for (int i = 0; i < _segmentsW; i++) {
-            Number verangle = 2.0 * ((float)i) / ((float)_segmentsW) * PI;
-            Number x = ringradius * sin(verangle);
-            Number y = ringradius * cos(verangle);
-            grid[j][i] = Vector3(y, z, x);
-        }
-    }
-
-    for (int i = 0; i < _segmentsW; i++) {
-            grid[_segmentsH][i] = Vector3(0,_radius, 0);
-    }
-
-    for (int j = 1; j <= _segmentsH; j++) {
-        for (int i = 0; i < _segmentsW; i++) {
-            Vector3 a = grid[j][i];
-            Vector3 b = grid[j][(i-1+_segmentsW) % _segmentsW];
-            Vector3 c = grid[j-1][(i-1+_segmentsW) % _segmentsW];
-            Vector3 d = grid[j-1][i];
-
-            int i2 = i;
-            if (i == 0) i2 = _segmentsW;
-
-            Number vab = ((float)j) / ((float)_segmentsH);
-            Number vcd = (((float)j)-1.0) / ((float)_segmentsH);
-            Number uad = ((float)i2) / ((float)_segmentsW);
-            Number ubc = (((float)i2)-1.0) / ((float)_segmentsW);
-            Vector2 uva = Vector2(uad,vab);
-            Vector2 uvb = Vector2(ubc,vab);
-            Vector2 uvc = Vector2(ubc,vcd);
-            Vector2 uvd = Vector2(uad,vcd);
+    setMeshType(Mesh::TRI_MESH);
+    indexedMesh = true;
 
-            if (j < _segmentsH) {
-                addVertex(c.x, c.y, c.z, uvc.x ,uvc.y);
-                addVertex(b.x, b.y, b.z, uvb.x ,uvb.y);							
-                addVertex(a.x, a.y, a.z, uva.x ,uva.y);
-            }
-            if (j > 1) {
-                addVertex(d.x, d.y, d.z, uvd.x ,uvd.y);
-                addVertex(c.x, c.y, c.z, uvc.x ,uvc.y);
-                addVertex(a.x, a.y, a.z, uva.x ,uva.y);
-            }
+    Number tdelta = 360.f/(segmentsW-1);
+    Number pdelta = 180.f/(segmentsH-1);
+    
+    Number phi = -90;
+    Number theta = 0;
+    
+    for(unsigned int i = 0; i< segmentsH; i++) {
+        for(unsigned int j = 0; j < segmentsW; j++) {
+            Vector3 v;
+            v.x = radius * cos(phi*M_PI/180.f) * cos(theta*M_PI/180.f);
+            v.y = radius * sin(phi*M_PI/180.f);
+            v.z = radius * cos(phi*M_PI/180.f) * sin(theta*M_PI/180.f);
+            Vertex *vert = addVertex(v.x, v.y, v.z);
+            v.Normalize();
+            vert->normal = v;
+            vert->texCoord = Vector2(-theta/(360.f) , (phi+90.f)/180.f);
+            theta += tdelta;
         }
+        phi += pdelta;
+        theta = 0;
     }
     
-    for (int i=0 ; i < _segmentsH+1; i++) {
-        free(grid[i]);
+    for(unsigned int i = 0; i < segmentsH-1; i++) {
+        for(unsigned int j = 0; j< segmentsW-1; j++) {
+            addIndexedFace(((i+1)*segmentsW) + j, ((i+1)*segmentsW) + j+1, (i*segmentsW) + j+1);
+            addIndexedFace((i*segmentsW) + j+1, (i*segmentsW)+j, ((i+1)*segmentsW) + j);
+        }
     }
-    free(grid);
 
-    calculateNormals();
     calculateTangents();
-    arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
-    arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
-    arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
+    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;		
 }
@@ -590,61 +563,46 @@ unsigned int Mesh::getVertexCount() {
     }
 }
 
-void Mesh::createTorus(Number radius, Number tubeRadius, int rSegments, int tSegments) {
+void Mesh::createTorus(Number radius, Number tubeRadius, int segmentsH, int segmentsW) {
 
+    segmentsH++;
+    segmentsW++;
+    
     setMeshType(Mesh::TRI_MESH);
-        
-    Vector3 **grid = (Vector3 **) malloc(sizeof(Vector3*) * rSegments);
-    for (int i=0 ; i < rSegments; i++) {
-        grid[i] = (Vector3*) malloc(sizeof(Vector3) * tSegments);		
-    }
+    indexedMesh = true;
     
-    for (int i=0 ; i < rSegments; i++) {
-        for (int j = 0; j < tSegments; ++j) {
-            Number u = ((Number)i) / rSegments * 2.0 * PI;
-            Number v = ((Number)j) / tSegments * 2.0 * PI;	
-
-            grid[i][j] = Vector3((radius + tubeRadius*cos(v))*cos(u), tubeRadius*sin(v), (radius + tubeRadius*cos(v))*sin(u));							
-                                                
-        }
-    }	
+    Number tdelta = 360.f/(segmentsW-1);
+    Number pdelta = 360.f/(segmentsH-1);
     
-    for (int i=0 ; i < rSegments; i++) {
-        for (int j = 0; j < tSegments; ++j) {
-
-            int ip = (i+1) % rSegments;
-            int jp = (j+1) % tSegments;
-                
-            Vector3 a = grid[i ][j];
-            Vector3 b = grid[ip][j];
-            Vector3 c = grid[i ][jp];
-            Vector3 d = grid[ip][jp];
-
-            Vector2 uva = Vector2(((Number)i)     / ((Number)rSegments), ((Number)j)     / ((Number)tSegments));
-            Vector2 uvb = Vector2((((Number)i)+1.0) / ((Number)rSegments), ((Number)j)     / ((Number)tSegments));
-            Vector2 uvc = Vector2(((Number)i)    / ((Number)rSegments), (((Number)j)+1.0) / ((Number)tSegments));
-            Vector2 uvd = Vector2((((Number)i)+1.0) / ((Number)rSegments), (((Number)j)+1.0) / ((Number)tSegments));
-
-
-            addVertex(c.x, c.y, c.z, uvc.x ,uvc.y);
-            addVertex(b.x, b.y, b.z, uvb.x ,uvb.y);							
-            addVertex(a.x, a.y, a.z, uva.x ,uva.y);
-
-            addVertex(b.x, b.y, b.z, uvb.x ,uvb.y);
-            addVertex(c.x, c.y, c.z, uvc.x ,uvc.y);					
-            addVertex(d.x, d.y, d.z, uvd.x ,uvd.y);
+    Number phi = -90;
+    Number theta = 0;
+    
+    for(unsigned int i = 0; i< segmentsH; i++) {
+        for(unsigned int j = 0; j < segmentsW; j++) {
+            Vector3 v;
+            
+            v.x = (radius + tubeRadius*cos(phi*TORADIANS))*cos(theta*TORADIANS);
+            v.y = tubeRadius*sin(phi*TORADIANS);
+            v.z = (radius + tubeRadius*cos(phi*TORADIANS))*sin(theta*TORADIANS);
+            
+            Vertex *vert = addVertex(v.x, v.y, v.z);
+            vert->texCoord = Vector2(-theta/(360.f) , (phi/(360.f)) + 0.5);
+            theta += tdelta;
         }
+        phi += pdelta;
+        theta = 0;
     }
     
-    for (int i=0 ; i < rSegments; i++) {
-        free(grid[i]);
-    }		
-    free(grid);
+    for(unsigned int i = 0; i < segmentsH-1; i++) {
+        for(unsigned int j = 0; j< segmentsW-1; j++) {
+            addIndexedFace(((i+1)*segmentsW) + j, ((i+1)*segmentsW) + j+1, (i*segmentsW) + j+1);
+            addIndexedFace((i*segmentsW) + j+1, (i*segmentsW)+j, ((i+1)*segmentsW) + j);
+        }
+    }
     
-
     calculateNormals();
     calculateTangents();
-    arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
+    arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;
     arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
     arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
     arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
@@ -654,35 +612,33 @@ void Mesh::createTorus(Number radius, Number tubeRadius, int rSegments, int tSeg
 void Mesh::createCylinder(Number height, Number radius, int numSegments, bool capped) {
 
     setMeshType(Mesh::TRI_MESH);
+    indexedMesh = true;
+    
     Number lastx = 0;
     Number lastz = 0;
-    Number lastv = 0;		
-    for (int i=0 ; i < numSegments+1; i++) {
-        Number v = ((Number)i)/((Number)numSegments);
-        Number pos = ((PI*2.0)/((Number)numSegments)) * i;
-        Number x = sin(pos) * radius;
-        Number z = cos(pos) * radius;
+    Number lastv = 0;
+    
+    numSegments++;
+    
+    if(capped) {
+        addVertex(0,0,0,0.5,0.5)->setNormal(0.0, -1.0, 0.0);
+        addVertex(0,height,0,0.5,0.5)->setNormal(0.0, 1.0, 0.0);
+    }
+    
+    for (int i=0 ; i < numSegments; i++) {
+        Number v = ((Number)i)/((Number)numSegments-1);
+        Number pos = ((PI*2.0)/((Number)numSegments-1)) * i;
+        Number x = sin(pos);
+        Number z = cos(pos);
         
-        if(i > 0) {
-            addVertex(lastx,0,lastz,lastv,0);				
-            addVertex(x,0,z, v, 0);
-            addVertex(x,height,z, v, 1);
-
-            addVertex(x,height,z, v, 1);							
-            addVertex(lastx,height,lastz, lastv, 1);
-            addVertex(lastx,0,lastz,lastv,0);
-            
-            if(capped) {
-                addVertex(lastx,height,lastz, 0.5+(lastz/radius*0.5), 0.5+(lastx/radius*0.5));			
-                addVertex(x,height,z, 0.5+(z/radius*0.5), 0.5+(x/radius*0.5));
-                addVertex(0,height,0,0.5,0.5);
-
-                addVertex(lastx,0,lastz, 0.5+(lastz/radius*0.5), 0.5+(lastx/radius*0.5));						
-                addVertex(0,0,0,0.5,0.5);
-                addVertex(x,0,z, 0.5+(z/radius*0.5), 0.5+(x/radius*0.5));
-            }
-                            
+        addVertex(x*radius,0,z*radius, v, 0)->setNormal(x, 0, z);
+        addVertex(x*radius,height,z*radius, v, 1)->setNormal(x,0,z);
+        
+        if(capped) {
+            addVertex(x*radius,0,z*radius, 0.5+(z*0.5), 0.5+(x*0.5))->setNormal(0.0, -1.0, 0.0);
+            addVertex(x*radius,height,z*radius, 0.5+(z*0.5), 0.5+(x*0.5))->setNormal(0.0, 1.0, 0.0);
         }
+
         lastx = x;
         lastz = z;			
         lastv = v;
@@ -692,8 +648,27 @@ void Mesh::createCylinder(Number height, Number radius, int numSegments, bool ca
         vertices[i]->y = vertices[i]->y - (height/2.0f);
     }
     
+    int vertexOffset = 2;
+    int vertexInterval = 1;
+    if(capped) {
+        vertexInterval = 3;
+        vertexOffset = 6;
+    }
+
+    
+    for (int i=1 ; i <= numSegments-1; i++) {
+        addIndexedFace(vertexOffset, vertexOffset-vertexInterval, vertexOffset-vertexInterval-1 );
+        addIndexedFace(vertexOffset, vertexOffset+1, vertexOffset-vertexInterval );
+        vertexOffset += 2;
+        
+        if(capped) {
+            addIndexedFace(vertexOffset, vertexOffset-vertexInterval-1, 0);
+            addIndexedFace(1, vertexOffset-vertexInterval, vertexOffset+1);
+            vertexOffset += 2;
+        }
+    }
+    
     
-    calculateNormals();
     calculateTangents();
     arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
     arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
@@ -703,101 +678,147 @@ void Mesh::createCylinder(Number height, Number radius, int numSegments, bool ca
 }
 
 void Mesh::createCone(Number height, Number radius, int numSegments) {
-
+    
     setMeshType(Mesh::TRI_MESH);
+    indexedMesh = true;
     
     Number lastx = 0;
-    Number lasty = 0;
-    Number lastv = 0;
+    Number lastz = 0;
     
-    for (int i=0 ; i < numSegments+1; i++) {
-        Number v = ((Number)i)/((Number)numSegments);
-        Number pos = ((PI*2.0)/((Number)numSegments)) * i;
-        Number x = sin(pos) * radius * 0.5;
-        Number y = cos(pos) * radius * 0.5;
-        
-        if(i > 0) {
-            
-            addVertex(lastx,0, lasty, 0.5+(lasty/radius*0.5), 0.5+(lastx/radius*0.5))->setNormal(0.0, -1.0, 0.0);
-            addVertex(x,0,y, 0.5+(y/radius*0.5), 0.5+(x/radius*0.5))->setNormal(0.0, -1.0, 0.0);                
-            addVertex(0,height,0,0.5,0.5)->setNormal(0.0, -1.0, 0.0);
-            
-            addVertex(0,0,0,0.5,0.5)->setNormal(0.0, -1.0, 0.0);
-            addVertex(x,0,y, 0.5+(y/radius*0.5), 0.5+(x/radius*0.5))->setNormal(0.0, -1.0, 0.0);
-            addVertex(lastx,0, lasty, 0.5+(lasty/radius*0.5), 0.5+(lastx/radius*0.5))->setNormal(0.0, -1.0, 0.0);
+    numSegments *= 2;
+    
+    if(!(numSegments % 2)) {
+        numSegments++;
+    }
+    
+    addVertex(0,0,0,0.5,0.5)->setNormal(0.0, -1.0, 0.0);
+    
+    for (int i=0 ; i < numSegments; i++) {
+        Number pos = ((PI*2.0)/((Number)numSegments-1)) * i;
+        Number x = sin(pos);
+        Number z = cos(pos);
+
+        if(!(i % 2)) {
+            addVertex(x*radius,0,z*radius, 0.5+(z*0.5), 0.5+(x*0.5))->setNormal(x, 0.0, z);
+            addVertex(x*radius,0,z*radius, 0.5+(z*0.5), 0.5+(x*0.5))->setNormal(0.0, -1.0, 0.0);
+        } else {
+            addVertex(0,height,0, 0.5, 0.5)->setNormal(0.0, 1.0, 0.0);
         }
+        
         lastx = x;
-        lastv = v;
-        lasty = y;
+        lastz = z;
+
     }
     
     for(int i=0; i < vertices.size(); i++) {
         vertices[i]->y = vertices[i]->y - (height/2.0f);
     }
     
-    calculateNormals();
+    int vertexOffset = 4;
+    
+    for (int i=1 ; i <= (numSegments-1)/2; i++) {
+        addIndexedFace(vertexOffset, vertexOffset-1, vertexOffset-3);
+        addIndexedFace(vertexOffset+1, vertexOffset-2, 0);
+        vertexOffset += 3;
+    }
+    
+    
     calculateTangents();
-    arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
-    arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
+    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;			
+    arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;
 
 }
 
 void Mesh::addIndex(unsigned int index) {
-    indices.push_back(index);
+    if(!vertices.size()) {
+        return;
+    }
+    indices.push_back(index % vertices.size());
 }
 
 void Mesh::addIndexedFace(unsigned int i1, unsigned int i2, unsigned int i3) {
-    indices.push_back(i1);
-    indices.push_back(i2);
-    indices.push_back(i3);
+    if(!vertices.size()) {
+        return;
+    }
+    indices.push_back(i1 % vertices.size());
+    indices.push_back(i2 % vertices.size());
+    indices.push_back(i3 % vertices.size());
 }
 
 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);
+    if(!vertices.size()) {
+        return;
+    }
+    indices.push_back(i1 % vertices.size());
+    indices.push_back(i2 % vertices.size());
+    indices.push_back(i3 % vertices.size());
+    indices.push_back(i4 % vertices.size());
 }
 
 void Mesh::createBox(Number w, Number d, Number h) {
     setMeshType(Mesh::TRI_MESH);
-    indexedMesh = true;
+    indexedMesh = false;
     
     addVertex(w,0,h, 1, 1);
     addVertex(0,0,h, 1, 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,d,h, 1, 1);
-    addVertex(0,d,h, 1, 0);
+    addVertex(w,d,0, 1, 0);
     addVertex(0,d,0,0,0);
-    addVertex(w,d,0,0,1);
-
+    
+    addVertex(w,d,h, 1, 1);
+    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);
+    
     for(int i=0; i < vertices.size(); i++) {
         vertices[i]->x = vertices[i]->x - (w/2.0f);
         vertices[i]->y = vertices[i]->y - (d/2.0f);
         vertices[i]->z = vertices[i]->z - (h/2.0f);
     }
     
-    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);
-    
+    calculateNormals();
     calculateTangents();
+    
     arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
     arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
     arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
@@ -824,7 +845,62 @@ Vertex *Mesh::getVertex(unsigned int index) const {
     }
 }
 
+Vector3 Mesh::calculateFaceTangent(Vertex *v1, Vertex *v2, Vertex *v3) {
+    Vector3 tangent;
+    Vector3 side0 = *v1 - *v2;
+    Vector3 side1 = *v3 - *v1;
+    Vector3 normal = side1.crossProduct(side0);
+    normal.Normalize();
+    Number deltaV0 = v1->texCoord.y - v2->texCoord.y;
+    Number deltaV1 = v3->texCoord.y - v1->texCoord.y;
+    tangent = side0 * deltaV1 - side1 * deltaV0;
+    tangent.Normalize();
+    
+    Number deltaU0 = v1->texCoord.x - v2->texCoord.x;
+    Number deltaU1 = v3->texCoord.x - v1->texCoord.x;
+    Vector3 binormal = side0 * deltaU1 - side1 * deltaU0;
+    binormal.Normalize();
+    Vector3 tangentCross = tangent.crossProduct(binormal);
+    
+    if (tangentCross.dot(normal) < 0.0f) {
+        tangent = tangent * -1;
+    }
+    return tangent;
+}
+
 void Mesh::calculateTangents() {
+    
+    int polySize = 3;
+    if(meshType == Mesh::QUAD_MESH) {
+        polySize = 4;
+    }
+    
+    faceNormals.clear();
+    for(int i=0; i < vertices.size(); i++) {
+        vertices[i]->tangent = Vector3();
+    }
+    
+    if(indexedMesh) {
+        for(int i=0; i+polySize-1 < indices.size(); i += polySize) {
+            Vector3 tangent = calculateFaceTangent(vertices[indices[i]], vertices[indices[i+1]], vertices[indices[i+2]]);
+            
+            for(int j=0; j < polySize; j++) {
+                vertices[indices[i+j]]->tangent -= tangent;
+            }
+        }
+    } else {
+        for(int i=0; i+polySize-1 < vertices.size(); i += polySize) {
+            Vector3 tangent = calculateFaceTangent(vertices[i], vertices[i+1], vertices[i+2]);
+            
+            for(int j=0; j < polySize; j++) {
+                vertices[i+j]->tangent = tangent * 1.0;
+            }
+        }
+    }
+    
+    for(int i=0; i < vertices.size(); i++) {
+        vertices[i]->tangent.Normalize();
+    }
 
     arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;		
 }
@@ -861,10 +937,24 @@ void Mesh::calculateNormals(bool generateFaceNormals) {
             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;
+            
+            for(int j=0; j < polySize; j++) {
+                vertices[indices[i+j]]->normal -= no;
+            }
+            
+            if(generateFaceNormals) {
+                faceNormals.push_back(no * -1.0);
+            }
+        }
+    } else {
+        for(int i=0; i+polySize-1 < 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);
+            
+            for(int j=0; j < polySize; j++) {
+                vertices[i+j]->normal = no * -1.0;
+            }
             
             if(generateFaceNormals) {
                 faceNormals.push_back(no * -1.0);
@@ -872,6 +962,13 @@ void Mesh::calculateNormals(bool generateFaceNormals) {
         }
     }
     
+    for(int i=0; i < vertices.size(); i++) {
+        vertices[i]->normal.Normalize();
+    }
+    for(int i=0; i < faceNormals.size(); i++) {
+        faceNormals[i].Normalize();
+    }
+    
     arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;		
 }
 

+ 4 - 1
Core/Contents/Source/PolyParticleEmitter.cpp

@@ -48,6 +48,8 @@ void SceneParticleEmitter::resetParticle(unsigned int index) {
     particles[index].velocity = q.applyTo(directionVector);
     particles[index].position = Vector3(-emitterSize.x + (emitterSize.x * RANDOM_NUMBER * 2.0), -emitterSize.y + (emitterSize.y * RANDOM_NUMBER * 2.0), -emitterSize.z + (emitterSize.z * RANDOM_NUMBER * 2.0));
     
+    particles[index].rotation = Vector3(RANDOM_NUMBER * 360.0 *particleRotationSpeed.x, RANDOM_NUMBER * 360.0 *particleRotationSpeed.y, RANDOM_NUMBER * 360.0 *particleRotationSpeed.z);
+    
     if(particlesInWorldSpace) {
         particles[index].position = systemTrasnformMatrix * particles[index].position;
         particles[index].velocity = systemTrasnformMatrix.rotateVector( particles[index].velocity);
@@ -89,7 +91,8 @@ void SceneParticleEmitter::setParticleSize(Number particleSize) {
 void SceneParticleEmitter::setParticleRotationSpeed(const Vector3 &rotationSpeed) {
     particleRotationSpeed = rotationSpeed;
     for(int i=0; i < particles.size(); i++) {
-        particles[i].rotation = Vector3();
+        resetParticle(i);
+        particles[i].lifetime = RANDOM_NUMBER * lifetime;
     }
 }
 

+ 2 - 2
IDE/Contents/Source/EntityEditorPropertyView.cpp

@@ -106,9 +106,9 @@ void EntityEditorPropertyView::updateShaderOptions() {
         if(sceneMesh->getMaterial() && sceneMesh->getLocalShaderOptions()) {
             
             // can't edit the textures manually on a scene label or sprite
-            if(!sceneLabel && !sceneSprite) {
+//            if(!sceneLabel && !sceneSprite) {
             shaderTexturesSheet->setShader(sceneMesh->getMaterial()->getShader(0), sceneMesh->getMaterial(), sceneMesh->getLocalShaderOptions());
-            }
+  //          }
             
             shaderOptionsSheet->setShader(sceneMesh->getMaterial()->getShader(0), sceneMesh->getMaterial(), sceneMesh->getLocalShaderOptions());
         }