瀏覽代碼

added spiked ball

Alexander Rose 6 年之前
父節點
當前提交
625fdec8ce
共有 3 個文件被更改,包括 82 次插入5 次删除
  1. 17 1
      src/mol-geo/primitive/dodecahedron.ts
  2. 62 0
      src/mol-geo/primitive/spiked-ball.ts
  3. 3 4
      src/tests/browser/render-mesh.ts

+ 17 - 1
src/mol-geo/primitive/dodecahedron.ts

@@ -13,13 +13,29 @@ const a = 1;
 const b = 1 / t;
 const c = 2 - t;
 
-const dodecahedronVertices: ReadonlyArray<number> = [
+export const dodecahedronVertices: ReadonlyArray<number> = [
      c, 0, a,    -c, 0, a,    -b, b, b,    0, a, c,     b, b, b,
      b, -b, b,    0, -a, c,   -b, -b, b,   c, 0, -a,   -c, 0, -a,
     -b, -b, -b,   0, -a, -c,   b, -b, -b,  b,  b, -b,   0, a, -c,
     -b, b, -b,    a, c, 0,    -a, c, 0,   -a, -c, 0,    a, -c, 0
 ];
 
+/** indices of pentagonal faces, groups of five  */
+export const dodecahedronFaces: ReadonlyArray<number> = [
+     4, 3, 2, 1, 0,
+     7, 6, 5, 0, 1,
+    12, 11, 10, 9, 8,
+    15, 14, 13, 8, 9,
+    14, 3, 4, 16, 13,
+     3, 14, 15, 17, 2,
+    11, 6, 7, 18, 10,
+     6, 11, 12, 19, 5,
+     4, 0, 5, 19, 16,
+    12, 8, 13, 16, 19,
+    15, 9, 10, 18, 17,
+     7, 1, 2, 17, 18
+];
+
 const dodecahedronIndices: ReadonlyArray<number> = [  // pentagonal faces
      4, 3, 2,     2, 1, 0,     4, 2, 0,    // 4, 3, 2, 1, 0
      7, 6, 5,     5, 0, 1,     7, 5, 1,    // 7, 6, 5, 0, 1

+ 62 - 0
src/mol-geo/primitive/spiked-ball.ts

@@ -0,0 +1,62 @@
+/**
+ * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { createPrimitive, Primitive } from './primitive';
+import { dodecahedronVertices, dodecahedronFaces } from './dodecahedron';
+import { Vec3 } from 'mol-math/linear-algebra';
+
+function calcCenter(out: Vec3, ...vec3s: Vec3[]) {
+    Vec3.set(out, 0, 0, 0)
+    for (let i = 0, il = vec3s.length; i < il; ++i) {
+        Vec3.add(out, out, vec3s[i])
+    }
+    Vec3.scale(out, out, 1 / vec3s.length)
+    return out
+}
+
+const center = Vec3.zero()
+const dir = Vec3.zero()
+const tip = Vec3.zero()
+
+const vecA = Vec3.zero()
+const vecB = Vec3.zero()
+const vecC = Vec3.zero()
+const vecD = Vec3.zero()
+const vecE = Vec3.zero()
+
+/**
+ * Create a spiked ball derived from a dodecahedron
+ * @param radiusRatio ratio between inner radius (dodecahedron) and outher radius (spikes)
+ */
+export function SpikedBall(radiusRatio = 1): Primitive {
+    const vertices = dodecahedronVertices.slice(0)
+    const indices: number[] = []
+
+    let offset = vertices.length / 3
+
+    for (let i = 0, il = dodecahedronFaces.length; i < il; i += 5) {
+        Vec3.fromArray(vecA, dodecahedronVertices, dodecahedronFaces[i] * 3)
+        Vec3.fromArray(vecB, dodecahedronVertices, dodecahedronFaces[i + 1] * 3)
+        Vec3.fromArray(vecC, dodecahedronVertices, dodecahedronFaces[i + 2] * 3)
+        Vec3.fromArray(vecD, dodecahedronVertices, dodecahedronFaces[i + 3] * 3)
+        Vec3.fromArray(vecE, dodecahedronVertices, dodecahedronFaces[i + 4] * 3)
+
+        calcCenter(center, vecA, vecB, vecC, vecD, vecE)
+        Vec3.triangleNormal(dir, vecA, vecB, vecC)
+        Vec3.scaleAndAdd(tip, center, dir, radiusRatio)
+
+        Vec3.toArray(tip, vertices, offset * 3)
+        indices.push(offset, dodecahedronFaces[i], dodecahedronFaces[i + 1])
+        indices.push(offset, dodecahedronFaces[i + 1], dodecahedronFaces[i + 2])
+        indices.push(offset, dodecahedronFaces[i + 2], dodecahedronFaces[i + 3])
+        indices.push(offset, dodecahedronFaces[i + 3], dodecahedronFaces[i + 4])
+        indices.push(offset, dodecahedronFaces[i + 4], dodecahedronFaces[i])
+
+        offset += 1
+    }
+
+    return createPrimitive(vertices, indices)
+}

+ 3 - 4
src/tests/browser/render-mesh.ts

@@ -7,12 +7,12 @@
 import './index.html'
 import { Canvas3D } from 'mol-canvas3d/canvas3d';
 import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder';
-import { Sphere } from 'mol-geo/primitive/sphere';
 import { Mat4 } from 'mol-math/linear-algebra';
 import { Mesh } from 'mol-geo/geometry/mesh/mesh';
 import { Representation } from 'mol-repr/representation';
 import { Color } from 'mol-util/color';
 import { createRenderObject } from 'mol-gl/render-object';
+import { SpikedBall } from 'mol-geo/primitive/spiked-ball';
 
 const parent = document.getElementById('app')!
 parent.style.width = '100%'
@@ -29,14 +29,13 @@ canvas3d.animate()
 function meshRepr() {
     const builderState = MeshBuilder.createState()
     const t = Mat4.identity()
-    const sphere = Sphere(2)
-    MeshBuilder.addPrimitive(builderState, t, sphere)
+    MeshBuilder.addPrimitive(builderState, t, SpikedBall(3))
     const mesh = MeshBuilder.getMesh(builderState)
 
     const values = Mesh.Utils.createValuesSimple(mesh, {}, Color(0xFF0000), 1)
     const state = Mesh.Utils.createRenderableState({})
     const renderObject = createRenderObject('mesh', values, state)
-    const repr = Representation.fromRenderObject('sphere-mesh', renderObject)
+    const repr = Representation.fromRenderObject('mesh', renderObject)
     return repr
 }