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

Icospheres are useful primitives to have around. If you need a sphere with even distribution of triangles

Bill Robinson 11 лет назад
Родитель
Сommit
ce9ad51859
2 измененных файлов с 101 добавлено и 0 удалено
  1. 7 0
      Core/Contents/Include/PolyMesh.h
  2. 94 0
      Core/Contents/Source/PolyMesh.cpp

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

@@ -220,6 +220,13 @@ namespace Polycode {
 			*/ 						
 			void createSphere(Number radius, int numRings, int numSegments);
 
+			/**
+			* Creates an icosphere of specified radius
+			* @param radius Radius of sphere.
+			* @param subdivisions 0 means you get an icosahedron, don't recommend ever going above about 4 or 5 as they get really big
+			*/
+			void createIcosphere(Number radius, int subdivisions);
+
 			/**
 			* Creates a cylinder mesh.
 			* @param height Height of the cylinder.

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

@@ -600,6 +600,100 @@ void Mesh::createSphere(Number radius, int segmentsH, int segmentsW) {
     arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;		
 }
 
+void Mesh::createIcosphere(Number radius, int subdivisions) {
+
+	const float a = 0.5257311121191336;
+	const float b = 0.85065080835204;
+
+	indexedMesh = true;
+
+	Vector3 icosahedron_points[12]={
+		Vector3(-a,  b, 0),
+		Vector3( a,  b, 0),
+		Vector3(-a, -b, 0),
+		Vector3( a, -b, 0),
+		Vector3(0, -a,  b),
+		Vector3(0,  a,  b),
+		Vector3(0, -a, -b),
+		Vector3(0,  a, -b),
+		Vector3( b, 0, -a),
+		Vector3( b, 0,  a),
+		Vector3(-b, 0, -a),
+		Vector3(-b, 0,  a)
+	};
+
+	for(int i =0;i<12;i++) {
+		Vector3 n = icosahedron_points[i];
+		Vector3 v = n * radius;
+		addVertex(new Vertex(v.x, v.y, v.z, n.x, n.y, n.z));
+	}
+
+	addIndexedFace(0, 11, 5);
+	addIndexedFace(0, 5, 1);
+	addIndexedFace(0, 1, 7);
+	addIndexedFace(0, 7, 10);
+	addIndexedFace(0, 10, 11);
+	addIndexedFace(1, 5, 9);
+	addIndexedFace(5, 11, 4);
+	addIndexedFace(11, 10, 2);
+	addIndexedFace(10, 7, 6);
+	addIndexedFace(7, 1, 8);
+	addIndexedFace(3, 9, 4);
+	addIndexedFace(3, 4, 2);
+	addIndexedFace(3, 2, 6);
+	addIndexedFace(3, 6, 8);
+	addIndexedFace(3, 8, 9);
+	addIndexedFace(4, 9, 5);
+	addIndexedFace(2, 4, 11);
+	addIndexedFace(6, 2, 10);
+	addIndexedFace(8, 6, 7);
+	addIndexedFace(9, 8, 1);
+
+	for (int s = 0; s < subdivisions; s++) {
+		//Take a copy of the number of face indices at the BEGINNING, so we don't go on forever
+		for (int i = 0, n = indices.size(); i < n; i += 3) {
+
+			int vi0 = indices[i];
+			int vi1 = indices[i+1];
+			int vi2 = indices[i+2];
+
+			Vertex* v0 = vertices[vi0];
+			Vertex* v1 = vertices[vi1];
+			Vertex* v2 = vertices[vi2];
+
+			//Midpoints
+			Vector3 vm01 = ((*v0) + (*v1)) * 0.5f;
+			Vector3 vm12 = ((*v1) + (*v2)) * 0.5f;
+			Vector3 vm20 = ((*v2) + (*v0)) * 0.5f;
+
+			//Normalize so they're pushed outwards to the sphere
+			vm01 = vm01 * (radius / vm01.length());
+			vm12 = vm12 * (radius / vm12.length());
+			vm20 = vm20 * (radius / vm20.length());
+
+			int vmi01 = vertices.size(); addVertex(vm01.x, vm01.y, vm01.z);
+			int vmi12 = vertices.size(); addVertex(vm12.x, vm12.y, vm12.z);
+			int vmi20 = vertices.size(); addVertex(vm20.x, vm20.y, vm20.z);
+
+			addIndexedFace(vi0, vmi01, vmi20);
+			addIndexedFace(vi1, vmi12, vmi01);
+			addIndexedFace(vi2, vmi20, vmi12);
+
+			//Recycle the original face to be the new central face
+			indices[i] = vmi01;
+			indices[i+1] = vmi12;
+			indices[i+2] = vmi20;
+		}
+	}
+
+	calculateTangents();
+	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;
+}
+
 unsigned int Mesh::getActualVertexCount() const {
     return vertices.size();    
 }