Procházet zdrojové kódy

Added mesh particle support to particle system (no IDE options for it yet), optimized VBO creation slightly

Ivan Safrin před 11 roky
rodič
revize
bfc2510042

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

@@ -380,6 +380,9 @@ namespace Polycode {
         
             void addFaceNormal(Vector3 faceNormal);
         
+            unsigned int getIndexCount();
+            unsigned int getIndexAt(unsigned int index);
+        
 		protected:
         
             Vector3 calculateFaceTangent(Vertex *v1, Vertex *v2, Vertex *v3);

+ 7 - 1
Core/Contents/Include/PolyParticleEmitter.h

@@ -39,6 +39,7 @@ namespace Polycode {
             Number brightnessDeviation;
             Number scale;
             Color color;
+            int varianceIndex;
     };
     
     class SceneParticleEmitter : public SceneMesh {
@@ -104,7 +105,7 @@ namespace Polycode {
         
             static const int PARTICLE_TYPE_POINT = 0;
             static const int PARTICLE_TYPE_QUAD = 1;
-
+            static const int PARTICLE_TYPE_MESH = 2;
         
             bool useScaleCurve;
         
@@ -135,12 +136,17 @@ namespace Polycode {
         
             Color colorDeviation;
         
+            void addSourceMesh(Mesh *mesh);
+            int getNumSourceMeshes();
+            Mesh *getSourcesMeshAtIndex(int index);
+            void removeSourceMeshAtIndex(int index);
         
             virtual Entity *Clone(bool deepClone, bool ignoreEditorOnly) const;
             virtual void applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly) const;
         
         protected:
         
+            std::vector<Mesh*> sourceMeshes;
             void resetParticle(unsigned int index);
         
             bool systemEnabled;

+ 44 - 54
Core/Contents/Source/PolyGLVertexBuffer.cpp

@@ -52,104 +52,94 @@ OpenGLVertexBuffer::OpenGLVertexBuffer(Mesh *mesh) : VertexBuffer() {
 	
 	meshType = mesh->getMeshType();
 	
-	long bufferSize = 0;
-	long newBufferSize = 0;		
-	GLfloat *buffer = (GLfloat*)malloc(1);	
-	
+	long bufferOffset = 0;
+    int bufferSize = mesh->getVertexCount() * sizeof(GLfloat) * 3;
+	GLfloat *buffer = (GLfloat*)malloc(bufferSize);
+    
 	vertexCount = 0;
 	for(int i=0; i < mesh->getVertexCount(); i++) {
         vertexCount++;
-        newBufferSize = bufferSize + 3;
-        buffer = (GLfloat*)realloc(buffer, newBufferSize * sizeof(GLfloat));			
-        buffer[bufferSize+0] = mesh->getVertex(i)->x;
-        buffer[bufferSize+1] = mesh->getVertex(i)->y;
-        buffer[bufferSize+2] = mesh->getVertex(i)->z;
-        bufferSize = newBufferSize;
+        buffer[bufferOffset+0] = mesh->getVertex(i)->x;
+        buffer[bufferOffset+1] = mesh->getVertex(i)->y;
+        buffer[bufferOffset+2] = mesh->getVertex(i)->z;
+        bufferOffset += 3;
 	}
-	glBufferDataARB(GL_ARRAY_BUFFER_ARB, bufferSize*sizeof(GLfloat), buffer, GL_STATIC_DRAW_ARB);	
+	glBufferDataARB(GL_ARRAY_BUFFER_ARB, bufferSize, buffer, GL_STATIC_DRAW_ARB);
 	free(buffer);
 
 	glGenBuffersARB(1, &texCoordBufferID);
 	glBindBufferARB(GL_ARRAY_BUFFER_ARB, texCoordBufferID);
 	
-	bufferSize = 0;	
-	newBufferSize = 0;		
-	buffer = (GLfloat*)malloc(1);	
+    bufferOffset = 0;
+	bufferSize = mesh->getVertexCount() * sizeof(GLfloat) * 2;
+	buffer = (GLfloat*)malloc(bufferSize);
 	
 	for(int i=0; i < mesh->getVertexCount(); i++) {
-        newBufferSize = bufferSize + 2;
-        buffer = (GLfloat*)realloc(buffer, newBufferSize * sizeof(GLfloat));		
-        buffer[bufferSize+0] = mesh->getVertex(i)->getTexCoord().x;
-        buffer[bufferSize+1] = mesh->getVertex(i)->getTexCoord().y;
-        bufferSize = newBufferSize;
+        buffer[bufferOffset+0] = mesh->getVertex(i)->getTexCoord().x;
+        buffer[bufferOffset+1] = mesh->getVertex(i)->getTexCoord().y;
+        bufferOffset += 2;
 	}
 	
-	glBufferDataARB(GL_ARRAY_BUFFER_ARB, bufferSize*sizeof(GLfloat), buffer, GL_STATIC_DRAW_ARB);	
+	glBufferDataARB(GL_ARRAY_BUFFER_ARB, bufferSize, buffer, GL_STATIC_DRAW_ARB);
 	free(buffer);
 	
 	glGenBuffersARB(1, &normalBufferID);
 	glBindBufferARB(GL_ARRAY_BUFFER_ARB, normalBufferID);
 	
-	bufferSize = 0;
-	newBufferSize = 0;		
-	buffer = (GLfloat*)malloc(1);	
+	bufferSize = mesh->getVertexCount() * sizeof(GLfloat) * 3;
+    bufferOffset = 0;
+	buffer = (GLfloat*)malloc(bufferSize);
 	
 	for(int i=0; i < mesh->getVertexCount(); i++) {
-        newBufferSize = bufferSize + 3;
-        buffer = (GLfloat*)realloc(buffer, newBufferSize * sizeof(GLfloat));
         if(mesh->getUseFaceNormals()) {
             Vector3 n = mesh->getFaceNormalForVertex(i);
-            buffer[bufferSize+0] = n.x;
-            buffer[bufferSize+1] = n.y;
-            buffer[bufferSize+2] = n.z;
+            buffer[bufferOffset+0] = n.x;
+            buffer[bufferOffset+1] = n.y;
+            buffer[bufferOffset+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;
+            buffer[bufferOffset+0] = mesh->getVertex(i)->normal.x;
+            buffer[bufferOffset+1] = mesh->getVertex(i)->normal.y;
+            buffer[bufferOffset+2] = mesh->getVertex(i)->normal.z;
         }
-        bufferSize = newBufferSize;
+        bufferOffset += 3;
 	}
 	
-	glBufferDataARB(GL_ARRAY_BUFFER_ARB, bufferSize*sizeof(GLfloat), buffer, GL_STATIC_DRAW_ARB);	
+	glBufferDataARB(GL_ARRAY_BUFFER_ARB, bufferSize, buffer, GL_STATIC_DRAW_ARB);
 	free(buffer);	
 
 	glGenBuffersARB(1, &tangentBufferID);
 	glBindBufferARB(GL_ARRAY_BUFFER_ARB, tangentBufferID);
 	
-	bufferSize = 0;
-	newBufferSize = 0;		
-	buffer = (GLfloat*)malloc(1);	
+	bufferSize = mesh->getVertexCount() * sizeof(GLfloat) * 3;
+    bufferOffset = 0;
+	buffer = (GLfloat*)malloc(bufferSize);
 	
 	for(int i=0; i < mesh->getVertexCount(); i++) {
-        newBufferSize = bufferSize + 3;
-        buffer = (GLfloat*)realloc(buffer, newBufferSize * sizeof(GLfloat));		
-        buffer[bufferSize+0] = mesh->getVertex(i)->tangent.x;
-        buffer[bufferSize+1] = mesh->getVertex(i)->tangent.y;
-        buffer[bufferSize+2] = mesh->getVertex(i)->tangent.z;
-        bufferSize = newBufferSize;
+        buffer[bufferOffset+0] = mesh->getVertex(i)->tangent.x;
+        buffer[bufferOffset+1] = mesh->getVertex(i)->tangent.y;
+        buffer[bufferOffset+2] = mesh->getVertex(i)->tangent.z;
+        bufferOffset += 3;
 	}
 	
-	glBufferDataARB(GL_ARRAY_BUFFER_ARB, bufferSize*sizeof(GLfloat), buffer, GL_STATIC_DRAW_ARB);	
+	glBufferDataARB(GL_ARRAY_BUFFER_ARB, bufferSize, buffer, GL_STATIC_DRAW_ARB);
 	free(buffer);	
 	
 	glGenBuffersARB(1, &colorBufferID);
 	glBindBufferARB(GL_ARRAY_BUFFER_ARB, colorBufferID);
 	
-	bufferSize = 0;
-	newBufferSize = 0;		
-	buffer = (GLfloat*)malloc(1);	
+	bufferSize = mesh->getVertexCount() * sizeof(GLfloat) * 4;
+	bufferOffset = 0;
+	buffer = (GLfloat*)malloc(bufferSize);
 	
 	for(int i=0; i < mesh->getVertexCount(); i++) {
-        newBufferSize = bufferSize + 4;
-        buffer = (GLfloat*)realloc(buffer, newBufferSize * sizeof(GLfloat));
-        buffer[bufferSize+0] = mesh->getVertex(i)->vertexColor.r;
-        buffer[bufferSize+1] = mesh->getVertex(i)->vertexColor.g;
-        buffer[bufferSize+2] = mesh->getVertex(i)->vertexColor.b;
-        buffer[bufferSize+3] = mesh->getVertex(i)->vertexColor.a;
-        bufferSize = newBufferSize;
+        buffer[bufferOffset+0] = mesh->getVertex(i)->vertexColor.r;
+        buffer[bufferOffset+1] = mesh->getVertex(i)->vertexColor.g;
+        buffer[bufferOffset+2] = mesh->getVertex(i)->vertexColor.b;
+        buffer[bufferOffset+3] = mesh->getVertex(i)->vertexColor.a;
+        bufferOffset += 4;
 	}
 	
-	glBufferDataARB(GL_ARRAY_BUFFER_ARB, bufferSize*sizeof(GLfloat), buffer, GL_STATIC_DRAW_ARB);	
+	glBufferDataARB(GL_ARRAY_BUFFER_ARB, bufferSize, buffer, GL_STATIC_DRAW_ARB);
 	free(buffer);	
 	
 }

+ 15 - 1
Core/Contents/Source/PolyMesh.cpp

@@ -105,7 +105,10 @@ bool Mesh::getUseFaceNormals() {
 }
 
 
-void Mesh::setVertexBuffer(VertexBuffer *buffer) {
+void Mesh::setVertexBuffer(VertexBuffer *buffer) {    
+    if(vertexBuffer) {
+        delete vertexBuffer;
+    }
     vertexBuffer = buffer;
     meshHasVertexBuffer = true;
 }
@@ -607,6 +610,17 @@ unsigned int Mesh::getVertexCount() {
     }
 }
 
+unsigned int Mesh::getIndexCount() {
+    return indices.size();
+}
+
+unsigned int Mesh::getIndexAt(unsigned int index) {
+    if(index < indices.size()) {
+        return indices[index];
+    }
+    return 0;
+}
+
 void Mesh::createTorus(Number radius, Number tubeRadius, int segmentsW, int segmentsH) {
 
     segmentsH++;

+ 82 - 22
Core/Contents/Source/PolyParticleEmitter.cpp

@@ -50,6 +50,27 @@ Entity *SceneParticleEmitter::Clone(bool deepClone, bool ignoreEditorOnly) const
     return newEmitter;
 }
 
+void SceneParticleEmitter::addSourceMesh(Mesh *mesh) {
+    sourceMeshes.push_back(mesh);
+}
+
+int SceneParticleEmitter::getNumSourceMeshes() {
+    return sourceMeshes.size();
+}
+
+Mesh *SceneParticleEmitter::getSourcesMeshAtIndex(int index) {
+    if(index > 0 && index < sourceMeshes.size()) {
+        return sourceMeshes[index];
+    }
+    return false;
+}
+
+void SceneParticleEmitter::removeSourceMeshAtIndex(int index) {
+    if(index > 0 && index < sourceMeshes.size()) {
+        sourceMeshes.erase(sourceMeshes.begin() + index);
+    }
+}
+
 void SceneParticleEmitter::applyClone(Entity *clone, bool deepClone, bool ignoreEditorOnly) const {
     
     SceneMesh::applyClone(clone, deepClone, ignoreEditorOnly);
@@ -87,6 +108,13 @@ void SceneParticleEmitter::applyClone(Entity *clone, bool deepClone, bool ignore
 
 void SceneParticleEmitter::resetParticle(unsigned int index) {
     particles[index].lifetime = 0.0;
+    
+    if(sourceMeshes.size() > 0) {
+        particles[index].varianceIndex = rand() % sourceMeshes.size();
+    } else {
+        particles[index].varianceIndex = 0;
+    }
+    
     q.fromAxes(-directionDeviation.x + (directionDeviation.x * RANDOM_NUMBER * 2.0), -directionDeviation.y + (directionDeviation.y * RANDOM_NUMBER * 2.0), -directionDeviation.z + (directionDeviation.z * RANDOM_NUMBER * 2.0));
     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));
@@ -186,9 +214,9 @@ void SceneParticleEmitter::rebuildParticles() {
             }
         }
         break;
+        case PARTICLE_TYPE_MESH:
         case PARTICLE_TYPE_QUAD:
         {
-            mesh->setMeshType(Mesh::QUAD_MESH);
             Matrix4 cameraMatrix = renderer->getCameraMatrix();
             Quaternion q;
             
@@ -207,25 +235,55 @@ void SceneParticleEmitter::rebuildParticles() {
                     particlePosition = inverseMatrix * particlePosition;
                 }
                 
-                Vector3 vertexPosition = Vector3(-finalParticleSize, -finalParticleSize, 0.0);
-                vertexPosition = q.applyTo(vertexPosition);
-                vertexPosition = cameraMatrix.rotateVector(vertexPosition);
-                mesh->addVertex(particlePosition.x+vertexPosition.x, particlePosition.y+vertexPosition.y, particlePosition.z+vertexPosition.z, 0.0, 0.0)->vertexColor = vertexColor;
-                
-                vertexPosition = Vector3(finalParticleSize, -finalParticleSize, 0.0);
-                vertexPosition = q.applyTo(vertexPosition);
-                vertexPosition = cameraMatrix.rotateVector(vertexPosition);
-                mesh->addVertex(particlePosition.x+vertexPosition.x, particlePosition.y+vertexPosition.y, particlePosition.z+vertexPosition.z, 1.0, 0.0)->vertexColor = vertexColor;
-
-                vertexPosition = Vector3(finalParticleSize, finalParticleSize, 0.0);
-                vertexPosition = q.applyTo(vertexPosition);
-                vertexPosition = cameraMatrix.rotateVector(vertexPosition);
-                mesh->addVertex(particlePosition.x+vertexPosition.x, particlePosition.y+vertexPosition.y, particlePosition.z+vertexPosition.z, 1.0, 1.0)->vertexColor = vertexColor;
-
-                vertexPosition = Vector3(-finalParticleSize, finalParticleSize, 0.0);
-                vertexPosition = q.applyTo(vertexPosition);
-                vertexPosition = cameraMatrix.rotateVector(vertexPosition);
-                mesh->addVertex(particlePosition.x+vertexPosition.x, particlePosition.y+vertexPosition.y, particlePosition.z+vertexPosition.z, 0.0, 1.0)->vertexColor = vertexColor;
+                if(particleType == PARTICLE_TYPE_MESH) {
+                    mesh->setMeshType(Mesh::TRI_MESH);
+                    
+                    int indexOffset = 0;
+                    
+                    int meshIndex = particles[i].varianceIndex;
+                    if(meshIndex < sourceMeshes.size()) {
+                        
+                        indexOffset = mesh->getActualVertexCount();
+                        
+                        for(int v=0; v <  sourceMeshes[meshIndex]->getActualVertexCount(); v++) {
+                            Vertex *sv = sourceMeshes[meshIndex]->getActualVertex(v);
+                            Vector3 vpos = Vector3(sv->x, sv->y, sv->z) * finalParticleSize;
+                            vpos = q.applyTo(vpos);
+                            
+                            vpos += particlePosition;
+                            Vertex *newV = mesh->addVertex(vpos.x, vpos.y, vpos.z, sv->texCoord.x, sv->texCoord.y);
+                            newV->vertexColor = vertexColor;
+                            newV->normal = q.applyTo(sv->normal);
+                        }
+                        
+                        for(int v=0; v < sourceMeshes[meshIndex]->getIndexCount(); v++) {
+                            mesh->addIndex(indexOffset + sourceMeshes[meshIndex]->getIndexAt(v));
+                        }
+                    }
+                    
+                } else {
+                    mesh->setMeshType(Mesh::QUAD_MESH);
+                    
+                    Vector3 vertexPosition = Vector3(-finalParticleSize, -finalParticleSize, 0.0);
+                    vertexPosition = q.applyTo(vertexPosition);
+                    vertexPosition = cameraMatrix.rotateVector(vertexPosition);
+                    mesh->addVertex(particlePosition.x+vertexPosition.x, particlePosition.y+vertexPosition.y, particlePosition.z+vertexPosition.z, 0.0, 0.0)->vertexColor = vertexColor;
+                    
+                    vertexPosition = Vector3(finalParticleSize, -finalParticleSize, 0.0);
+                    vertexPosition = q.applyTo(vertexPosition);
+                    vertexPosition = cameraMatrix.rotateVector(vertexPosition);
+                    mesh->addVertex(particlePosition.x+vertexPosition.x, particlePosition.y+vertexPosition.y, particlePosition.z+vertexPosition.z, 1.0, 0.0)->vertexColor = vertexColor;
+
+                    vertexPosition = Vector3(finalParticleSize, finalParticleSize, 0.0);
+                    vertexPosition = q.applyTo(vertexPosition);
+                    vertexPosition = cameraMatrix.rotateVector(vertexPosition);
+                    mesh->addVertex(particlePosition.x+vertexPosition.x, particlePosition.y+vertexPosition.y, particlePosition.z+vertexPosition.z, 1.0, 1.0)->vertexColor = vertexColor;
+
+                    vertexPosition = Vector3(-finalParticleSize, finalParticleSize, 0.0);
+                    vertexPosition = q.applyTo(vertexPosition);
+                    vertexPosition = cameraMatrix.rotateVector(vertexPosition);
+                    mesh->addVertex(particlePosition.x+vertexPosition.x, particlePosition.y+vertexPosition.y, particlePosition.z+vertexPosition.z, 0.0, 1.0)->vertexColor = vertexColor;
+                }
 
             }
         }
@@ -234,8 +292,10 @@ void SceneParticleEmitter::rebuildParticles() {
     }
   
     mesh->dirtyArrays();
-//    mesh->dirtyArray(RenderDataArray::VERTEX_DATA_ARRAY);
- //   mesh->dirtyArray(RenderDataArray::COLOR_DATA_ARRAY);
+    
+    if(useVertexBuffer) {
+		CoreServices::getInstance()->getRenderer()->createVertexBufferForMesh(mesh);
+    }
 }
 
 unsigned int SceneParticleEmitter::getParticleCount() const {

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

@@ -356,7 +356,10 @@ void SceneMesh::Render() {
 	}
     
 	if(useVertexBuffer) {
-		renderer->drawVertexBuffer(mesh->getVertexBuffer(), mesh->useVertexColors);
+        VertexBuffer *vb = mesh->getVertexBuffer();
+        if(vb){
+            renderer->drawVertexBuffer(vb, mesh->useVertexColors);
+        }
 	} else {
 		renderMeshLocally();
 	}