Explorar o código

Mesh vertex manipulation utilities

Bill Robinson %!s(int64=11) %!d(string=hai) anos
pai
achega
703a286013
Modificáronse 2 ficheiros con 92 adicións e 2 borrados
  1. 25 2
      Core/Contents/Include/PolyMesh.h
  2. 67 0
      Core/Contents/Source/PolyMesh.cpp

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

@@ -305,7 +305,16 @@ namespace Polycode {
 
             void setUseFaceNormals(bool val);
             bool getUseFaceNormals();
-        
+
+			inline unsigned int getIndexGroupSize() {
+				switch (meshType) {
+				case QUAD_MESH: return 4;
+				case TRI_MESH: return 3;
+				case LINE_MESH: return 2;
+				default: return 1;
+				}
+			}
+
 			/**
 			* Calculates the mesh bounding box.
 			*/
@@ -374,7 +383,21 @@ namespace Polycode {
             void addIndexedFace(unsigned int i1, unsigned int i2);
             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);
+			void addIndex(unsigned int index);
+
+			/** Removes a range of vertices starting at beginRemoveVertex. vertexRemovalCount should be a multiple of the num
+			 * if you want to keep your mesh data clean. If this is an indexedMesh, will also remove any faces that reference
+			 * @param beginRemoveVertex First element of the vertex array to remove
+			 * @param vertexRemovalCount Number of elements to remove from the vertex array */
+			void removeVertexRange(unsigned int beginRemoveVertex, int vertexRemovalCount = 3);
+
+			/** Removes a face from the mesh. Face is defined as a quad for QUAD_MESH, a triangle for TRI_MESH, a line for LI
+			 *  In indexedMesh mode this may result in orphaned vertices.
+			 * @param faceIndex The 0-indexed face of the mesh (and NOT the index into the indices array!) */
+			void removeFace(unsigned int faceIndex);
+
+			/** For indexedMesh only, removes any unused vertices from the mesh. */
+			int removeUnusedVertices();
         
             Vector3 getFaceNormalForVertex(unsigned int index);
         

+ 67 - 0
Core/Contents/Source/PolyMesh.cpp

@@ -834,6 +834,73 @@ void Mesh::addIndexedFace(unsigned int i1, unsigned int i2, unsigned int i3, uns
     indices.push_back(i4 % vertices.size());
 }
 
+void Mesh::removeFace(unsigned int faceIndex) {
+	unsigned int groupSize = getIndexGroupSize();
+	unsigned int startOffset = faceIndex * groupSize;
+	if (indexedMesh) {
+		std::vector<unsigned int>::iterator start = indices.begin() + startOffset;
+		indices.erase(start, start+groupSize);
+	}
+	else {
+		removeVertexRange(startOffset, startOffset + groupSize);
+	}
+}
+
+void Mesh::removeVertexRange(unsigned int beginRemoveVertex, int vertexRemovalCount) {
+	if (!vertices.size()) return;
+	unsigned int endRemoveVertex = beginRemoveVertex + vertexRemovalCount;
+	vertices.erase(vertices.begin() + beginRemoveVertex, vertices.begin() + endRemoveVertex);
+	if (indexedMesh) {
+		unsigned int groupSize = getIndexGroupSize();
+		for (unsigned int i = 0; i < indices.size(); ) {
+			unsigned int faceVertexIndex = indices[i];
+			//Encountered a face that references an index being removed
+			if (faceVertexIndex >= beginRemoveVertex && faceVertexIndex < endRemoveVertex) {
+				//Rewind to beginning of group, going to remove entire face
+				unsigned int faceIndex = i/groupSize;
+				i = faceIndex * groupSize;
+				indices.erase(indices.begin() + i, indices.begin() + i + groupSize);
+				if (useFaceNormals) {
+					faceNormals.erase(faceNormals.begin() + i);
+				}
+			}
+			else {
+				if (faceVertexIndex > beginRemoveVertex) {
+					indices[i] = faceVertexIndex - vertexRemovalCount;
+				}
+				i++;
+			}
+		}
+	}
+}
+
+int Mesh::removeUnusedVertices() {
+	int removals = 0;
+	if (indexedMesh) {
+		std::vector<unsigned int> vertexMap(vertices.size());
+		//Mark all used vertices first
+		for (unsigned int i = 0; i < indices.size(); i++) {
+			vertexMap[indices[i]] = 1;
+		}
+		//Create relocation map, move vertices
+		unsigned int dst = 0;
+		for (unsigned int src = 0; src < vertexMap.size(); src++) {
+			if (vertexMap[src]) {
+				vertices[dst] = vertices[src];
+				vertexMap[src] = dst;
+				dst++;
+			}
+		}
+		removals = dst - vertices.size();
+		vertices.resize(dst);
+		//Apply map to indices
+		for (unsigned int i = 0; i < indices.size(); i++) {
+			indices[i] = vertexMap[indices[i]];
+		}
+	}
+	return removals;
+}
+
 void Mesh::createBox(Number w, Number d, Number h) {
     setMeshType(Mesh::TRI_MESH);
     indexedMesh = false;