Browse Source

Finally a hex sphere, albeit pointy

I still need to flatten the hexagons and pentagons to make it a true dual
polyhedron of the icosahedron.

Also needs performance improvements. Like caching the vertices, switching from
fan subdivision to a different method that represents hexagons and pentagons
with less triangles.
Tyler Hallada 5 years ago
parent
commit
113de04cbe
2 changed files with 86 additions and 14 deletions
  1. 1 1
      package.json
  2. 85 13
      src/index.js

+ 1 - 1
package.json

@@ -5,7 +5,7 @@
5 5
   "main": "index.js",
6 6
   "scripts": {
7 7
     "test": "echo \"Error: no test specified\" && exit 1",
8
-    "start": "webpack-dev-server --mode development --watch-poll --progress --hot",
8
+    "start": "webpack-dev-server --mode development --watch --progress --hot",
9 9
     "build": "webpack"
10 10
   },
11 11
   "author": "",

+ 85 - 13
src/index.js

@@ -5,24 +5,96 @@ var OrbitControls = require("three-orbit-controls")(THREE);
5 5
 const scene = new THREE.Scene();
6 6
 var camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000);
7 7
 
8
-var geometry = new THREE.IcosahedronBufferGeometry(5, 7);
9
-
10
-var position = geometry.getAttribute("position");
11
-var colors = [];
12
-var color = new THREE.Color(Math.random(), Math.random(), Math.random());
13
-for (var i = 0; i < position.count / 3; i += 1) {
14
-  color.setRGB(i / (position.count / 3), i / (position.count / 3), i / (position.count / 3));
15
-  colors.push(color.r, color.g, color.b);
16
-  colors.push(color.r, color.g, color.b);
17
-  colors.push(color.r, color.g, color.b);
8
+var geometry = new THREE.IcosahedronGeometry(10, 2);
9
+
10
+var vertToFaces = {};
11
+var newVertices = geometry.vertices;
12
+var newFaces = [];
13
+
14
+for (var i = 0; i < geometry.faces.length; i += 1) {
15
+  var face = geometry.faces[i];
16
+
17
+  if (vertToFaces[face.a]) {
18
+    vertToFaces[face.a].push(i);
19
+  } else {
20
+    vertToFaces[face.a] = [i];
21
+  }
22
+
23
+  if (vertToFaces[face.b]) {
24
+    vertToFaces[face.b].push(i);
25
+  } else {
26
+    vertToFaces[face.b] = [i];
27
+  }
28
+
29
+  if (vertToFaces[face.c]) {
30
+    vertToFaces[face.c].push(i);
31
+  } else {
32
+    vertToFaces[face.c] = [i];
33
+  }
34
+}
35
+
36
+var originalVertCount = geometry.vertices.length;
37
+
38
+var faceCentroids = {};
39
+for (var i = 0; i < geometry.faces.length; i += 1) {
40
+  var face = geometry.faces[i];
41
+  var vertexA = geometry.vertices[face.a];
42
+  var vertexB = geometry.vertices[face.b];
43
+  var vertexC = geometry.vertices[face.c];
44
+  var centroid = new THREE.Vector3(
45
+    (vertexA.x + vertexB.x + vertexC.x) / 3,
46
+    (vertexA.y + vertexB.y + vertexC.y) / 3,
47
+    (vertexA.z + vertexB.z + vertexC.z) / 3,
48
+  );
49
+
50
+  var centroidIndex = newVertices.push(centroid) - 1;
51
+  faceCentroids[i] = centroidIndex;
52
+}
53
+
54
+for (var i = 0; i < originalVertCount; i += 1) {
55
+  var faces = vertToFaces[i];
56
+  var color = new THREE.Color(Math.random(), Math.random(), Math.random());
57
+  for (var j = 0; j < faces.length; j += 1) {
58
+    var faceIndex = faces[j];
59
+    var face = geometry.faces[faceIndex];
60
+    var nonCenterVerts = [face.a, face.b, face.c].filter(vert => vert !== i);
61
+    var sortedFace = new THREE.Face3(i, nonCenterVerts[0], nonCenterVerts[1]);
62
+
63
+    var vertexA = geometry.vertices[sortedFace.a];
64
+    var vertexB = geometry.vertices[sortedFace.b];
65
+    var vertexC = geometry.vertices[sortedFace.c];
66
+    var halfAB = vertexA.clone().lerp(vertexB, 0.5);
67
+    var halfAC = vertexA.clone().lerp(vertexC, 0.5);
68
+    var halfBC = vertexB.clone().lerp(vertexC, 0.5);
69
+
70
+    // TODO: cache these and retrieve in future iteration (use .toFixed(3) in hash)
71
+    var centroidIndex = faceCentroids[faceIndex];
72
+    var halfABIndex = newVertices.push(halfAB) - 1;
73
+    var halfACIndex = newVertices.push(halfAC) - 1;
74
+    var halfBCIndex = newVertices.push(halfBC) - 1;
75
+
76
+    var face1 = new THREE.Face3(sortedFace.a, centroidIndex, halfABIndex);
77
+    face1.color = color;
78
+    var face2 = new THREE.Face3(sortedFace.a, centroidIndex, halfACIndex);
79
+    face2.color = color;
80
+
81
+    newFaces.push(face1, face2);
82
+  }
18 83
 }
19 84
 
20 85
 function disposeArray() {
21 86
   this.array = null;
22 87
 }
23
-geometry.addAttribute("color", new THREE.Float32BufferAttribute(colors, 3).onUpload(disposeArray));
24
-var material = new THREE.MeshBasicMaterial({ vertexColors: THREE.FaceColors });
25
-var sphere = new THREE.Mesh(geometry, material);
88
+
89
+var newGeometry = new THREE.Geometry();
90
+newGeometry.vertices = newVertices;
91
+newGeometry.faces = newFaces;
92
+newGeometry.computeFaceNormals();
93
+newGeometry.computeVertexNormals();
94
+newGeometry.normalize();
95
+
96
+var material = new THREE.MeshBasicMaterial({ vertexColors: THREE.FaceColors, side: THREE.DoubleSide });
97
+var sphere = new THREE.Mesh(newGeometry, material);
26 98
 scene.add(sphere);
27 99
 
28 100
 var controls = new OrbitControls(camera);