diff --git a/src/mol-geo/primitive/box.ts b/src/mol-geo/primitive/box.ts
index 9ba23149f07dfba0daea75f5656101119a272145..ee7e5b906485c4546c6a9bfb29e07c11b627e35c 100644
--- a/src/mol-geo/primitive/box.ts
+++ b/src/mol-geo/primitive/box.ts
@@ -7,6 +7,7 @@
 // adapted from three.js, MIT License Copyright 2010-2018 three.js authors
 
 import { Vec3 } from 'mol-math/linear-algebra'
+import { Primitive } from './primitive';
 
 export const DefaultBoxProps = {
     width: 1,
@@ -17,7 +18,7 @@ export type BoxProps = Partial<typeof DefaultBoxProps>
 
 const tmpVector = Vec3.zero();
 
-export function Box(props?: BoxProps) {
+export function Box(props?: BoxProps): Primitive {
     const { width, height, depth } = { ...DefaultBoxProps, ...props }
 
     // buffers
diff --git a/src/mol-geo/primitive/cylinder.ts b/src/mol-geo/primitive/cylinder.ts
index a17cc3ff8d68539e0f19c4365b82ab6d967f7acf..58f8b893e80e64bbca425e43d42f293c7ef2ded3 100644
--- a/src/mol-geo/primitive/cylinder.ts
+++ b/src/mol-geo/primitive/cylinder.ts
@@ -7,6 +7,7 @@
 // adapted from three.js, MIT License Copyright 2010-2018 three.js authors
 
 import { Vec3 } from 'mol-math/linear-algebra'
+import { Primitive } from './primitive';
 
 export const DefaultCylinderProps = {
     radiusTop: 1,
@@ -21,7 +22,7 @@ export const DefaultCylinderProps = {
 }
 export type CylinderProps = Partial<typeof DefaultCylinderProps>
 
-export function Cylinder(props?: CylinderProps) {
+export function Cylinder(props?: CylinderProps): Primitive {
     const { radiusTop, radiusBottom, height, radialSegments, heightSegments, topCap, bottomCap, thetaStart, thetaLength } = { ...DefaultCylinderProps, ...props };
 
     // buffers
diff --git a/src/mol-geo/primitive/icosahedron.ts b/src/mol-geo/primitive/icosahedron.ts
index d9383aa0fe1dc119ec344dc351b1d80e098c6ea6..096945994adb3b20a1bc5680814117cbecc7a694 100644
--- a/src/mol-geo/primitive/icosahedron.ts
+++ b/src/mol-geo/primitive/icosahedron.ts
@@ -4,35 +4,23 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-// adapted from three.js, MIT License Copyright 2010-2018 three.js authors
-
-import { Polyhedron } from './polyhedron'
+import { createPrimitive, Primitive } from './primitive';
 
 const t = ( 1 + Math.sqrt( 5 ) ) / 2;
 
-const vertices = [
-    - 1, t, 0, 	1, t, 0, 	- 1, - t, 0, 	1, - t, 0,
-     0, - 1, t, 	0, 1, t,	0, - 1, - t, 	0, 1, - t,
-     t, 0, - 1, 	t, 0, 1, 	- t, 0, - 1, 	- t, 0, 1
+const icosahedronVertices: ReadonlyArray<number> = [
+    -1, t, 0,   1, t, 0,  -1, -t, 0,   1, -t, 0,
+     0, -1, t,  0, 1, t,   0, -1, -t,  0, 1, -t,
+     t, 0, -1,  t, 0, 1,  -t, 0, -1,  -t, 0, 1
 ];
 
-const indices = [
-     0, 11, 5, 	0, 5, 1, 	0, 1, 7, 	0, 7, 10, 	0, 10, 11,
-     1, 5, 9, 	5, 11, 4,	11, 10, 2,	10, 7, 6,	7, 1, 8,
-     3, 9, 4, 	3, 4, 2,	3, 2, 6,	3, 6, 8,	3, 8, 9,
-     4, 9, 5, 	2, 4, 11,	6, 2, 10,	8, 6, 7,	9, 8, 1
+const icosahedronIndices: ReadonlyArray<number> = [
+    0, 11, 5,  0, 5, 1,    0, 1, 7,    0, 7, 10,  0, 10, 11,
+    1, 5, 9,   5, 11, 4,  11, 10, 2,  10, 7, 6,   7, 1, 8,
+    3, 9, 4,   3, 4, 2,    3, 2, 6,    3, 6, 8,   3, 8, 9,
+    4, 9, 5,   2, 4, 11,   6, 2, 10,   8, 6, 7,   9, 8, 1
 ];
 
-export function icosahedronVertexCount(detail: number) {
-    return 10 * Math.pow(Math.pow(2, detail), 2) + 2
-}
-
-export const DefaultIcosahedronProps = {
-    radius: 1,
-    detail: 0
-}
-export type IcosahedronProps = Partial<typeof DefaultIcosahedronProps>
+const icosahedron = createPrimitive(icosahedronVertices, icosahedronIndices)
 
-export function Icosahedron(props?: IcosahedronProps) {
-    return Polyhedron(vertices, indices, { ...DefaultIcosahedronProps, ...props })
-}
\ No newline at end of file
+export function Icosahedron(): Primitive { return icosahedron }
\ No newline at end of file
diff --git a/src/mol-geo/primitive/octahedron.ts b/src/mol-geo/primitive/octahedron.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3375145fa02c4984f6121038392c6b6cd90b696b
--- /dev/null
+++ b/src/mol-geo/primitive/octahedron.ts
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { createPrimitive, Primitive } from './primitive';
+
+export const octahedronVertices: ReadonlyArray<number> = [
+    0.5, 0, 0,   -0.5, 0, 0,    0, 0.5, 0,
+    0, -0.5, 0,     0, 0, 0.5,  0, 0, -0.5
+];
+
+export const octahedronIndices: ReadonlyArray<number> = [
+    0, 2, 4,  0, 4, 3,  0, 3, 5,
+    0, 5, 2,  1, 2, 5,  1, 5, 3,
+    1, 3, 4,  1, 4, 2
+];
+
+const octahedron = createPrimitive(octahedronVertices, octahedronIndices)
+
+export function Octahedron(): Primitive { return octahedron }
\ No newline at end of file
diff --git a/src/mol-geo/primitive/plane.ts b/src/mol-geo/primitive/plane.ts
index c6e02744074056da32d3627050132a0e9d1c9267..aeeeb371d933a4f18a333709790d626cd505a19b 100644
--- a/src/mol-geo/primitive/plane.ts
+++ b/src/mol-geo/primitive/plane.ts
@@ -1,3 +1,5 @@
+import { Primitive } from './primitive';
+
 /**
  * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
@@ -10,7 +12,7 @@ export const DefaultPlaneProps = {
 }
 export type PlaneProps = Partial<typeof DefaultPlaneProps>
 
-export function Plane(props?: PlaneProps) {
+export function Plane(props?: PlaneProps): Primitive {
     const { width, height } = { ...DefaultPlaneProps, ...props }
 
     return {
diff --git a/src/mol-geo/primitive/polyhedron.ts b/src/mol-geo/primitive/polyhedron.ts
index d5818b6a77ff30a2f9ae72d2e416cec4dc112655..120d127be6e49b4b3151113e8fa3018ef2349520 100644
--- a/src/mol-geo/primitive/polyhedron.ts
+++ b/src/mol-geo/primitive/polyhedron.ts
@@ -8,6 +8,7 @@
 
 import { Vec3 } from 'mol-math/linear-algebra'
 import { computeIndexedVertexNormals, appplyRadius } from '../util'
+import { Primitive } from './primitive';
 
 export const DefaultPolyhedronProps = {
     radius: 1,
@@ -15,7 +16,7 @@ export const DefaultPolyhedronProps = {
 }
 export type PolyhedronProps = Partial<typeof DefaultPolyhedronProps>
 
-export function Polyhedron(_vertices: Helpers.NumberArray, _indices: Helpers.NumberArray, props?: PolyhedronProps) {
+export function Polyhedron(_vertices: ArrayLike<number>, _indices: ArrayLike<number>, props?: PolyhedronProps): Primitive {
     const { radius, detail } = { ...DefaultPolyhedronProps, ...props }
     const builder = createBuilder()
     const { vertices, indices } = builder
@@ -85,20 +86,6 @@ export function Polyhedron(_vertices: Helpers.NumberArray, _indices: Helpers.Num
             }
         }
 
-        // // construct all of the faces
-        // for (let i = 0; i < cols; ++i) {
-        //     for (let j = 0; j < 2 * (cols - i) - 1; ++j) {
-        //         const k = Math.floor(j / 2)
-        //         if (j % 2 === 0) {
-        //             vertices.push(...v[i][k + 1], ...v[i + 1][k], ...v[i][k])
-        //         } else {
-        //             vertices.push(...v[i][k + 1], ...v[i + 1][k + 1], ...v[i + 1][k])
-        //         }
-        //         const l = vertices.length / 3
-        //         indices.push(l - 3, l - 2, l - 1)
-        //     }
-        // }
-
         // construct all of the faces
         for (let i = 0; i < cols; ++i) {
             for (let j = 0; j < 2 * (cols - i) - 1; ++j) {
diff --git a/src/mol-geo/primitive/primitive.ts b/src/mol-geo/primitive/primitive.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c49d17f09485552ade99c076a3450f8c30243887
--- /dev/null
+++ b/src/mol-geo/primitive/primitive.ts
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { Vec3 } from 'mol-math/linear-algebra';
+
+export interface Primitive {
+    vertices: ArrayLike<number>
+    normals: ArrayLike<number>
+    indices: ArrayLike<number>
+}
+
+const tri = [ Vec3.zero(), Vec3.zero(), Vec3.zero() ]
+const n = Vec3.zero()
+
+/** Create primitive with face normals from vertices and indices */
+export function createPrimitive(_vertices: ArrayLike<number>, _indices: ArrayLike<number>): Primitive {
+    const count = _indices.length
+    const vertices = new Float32Array(count * 3)
+    const normals = new Float32Array(count * 3)
+    const indices = new Uint32Array(count)
+
+    for (let i = 0; i < count; i += 3) {
+        for (let j = 0; j < 3; ++j) {
+            Vec3.fromArray(tri[j], _vertices, _indices[i + j] * 3)
+            Vec3.toArray(tri[j], vertices, i * 3 + j * 3)
+        }
+
+        Vec3.triangleNormal(n, tri[0], tri[1], tri[2])
+
+        for (let j = 0; j < 3; ++j) {
+            Vec3.toArray(n, normals, i * 3 + j * 3)
+            indices[i + j] = i + j
+        }
+    }
+
+    return { vertices, normals, indices }
+}
\ No newline at end of file
diff --git a/src/mol-geo/primitive/sheet.ts b/src/mol-geo/primitive/sheet.ts
index 194a0871a9ff056135c59a2f4256cbbeef35f556..7176f04ba40fa08380075fec443c8137f0a915b4 100644
--- a/src/mol-geo/primitive/sheet.ts
+++ b/src/mol-geo/primitive/sheet.ts
@@ -30,7 +30,7 @@ const p6 = Vec3.zero()
 const p7 = Vec3.zero()
 const p8 = Vec3.zero()
 
-export function addSheet(controlPoints: Helpers.NumberArray, normalVectors: Helpers.NumberArray, binormalVectors: Helpers.NumberArray, linearSegments: number, width: number, height: number, arrowHeight: number, startCap: boolean, endCap: boolean, state: MeshBuilderState) {
+export function addSheet(controlPoints: ArrayLike<number>, normalVectors: ArrayLike<number>, binormalVectors: ArrayLike<number>, linearSegments: number, width: number, height: number, arrowHeight: number, startCap: boolean, endCap: boolean, state: MeshBuilderState) {
     const { vertices, normals, indices } = state
 
     let vertexCount = vertices.elementCount
diff --git a/src/mol-geo/primitive/sphere.ts b/src/mol-geo/primitive/sphere.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bcf1460dca677832fa68f057e4ef87b2ca6d87b8
--- /dev/null
+++ b/src/mol-geo/primitive/sphere.ts
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { Polyhedron } from './polyhedron'
+import { Icosahedron } from  './icosahedron'
+import { Primitive } from './primitive';
+
+const { vertices, indices } = Icosahedron()
+
+/** Calculate vertex count for subdived icosahedron */
+export function sphereVertexCount(detail: number) {
+    return 10 * Math.pow(Math.pow(2, detail), 2) + 2
+}
+
+export const DefaultSphereProps = {
+    radius: 1,
+    detail: 0
+}
+export type SphereProps = Partial<typeof DefaultSphereProps>
+
+/** Create sphere by subdividing an icosahedron */
+export function Sphere(props?: SphereProps): Primitive {
+    return Polyhedron(vertices, indices, { ...DefaultSphereProps, ...props })
+}
\ No newline at end of file
diff --git a/src/mol-geo/primitive/star.ts b/src/mol-geo/primitive/star.ts
index f55871a87f9780711c1ccd7ba19aba21672d1c6c..fbbf5043906fbe131db051731b4f817213f996d2 100644
--- a/src/mol-geo/primitive/star.ts
+++ b/src/mol-geo/primitive/star.ts
@@ -5,6 +5,7 @@
  */
 
 import { Vec3 } from 'mol-math/linear-algebra'
+import { Primitive } from './primitive';
 
 export const DefaultStarProps = {
     pointCount: 5,
@@ -21,7 +22,7 @@ const p1 = Vec3.zero()
 const p2 = Vec3.zero()
 const p3 = Vec3.zero()
 
-export function Star(props?: StarProps) {
+export function Star(props?: StarProps): Primitive {
     const { outerRadius, innerRadius, thickness, pointCount } = { ...DefaultStarProps, ...props }
 
     const triangleCount = pointCount * 2 * 2
diff --git a/src/mol-geo/primitive/tube.ts b/src/mol-geo/primitive/tube.ts
index ade73172b2ed986f3d836ff4d13ffe7a2b8aa2f7..7bc62c2c0f494a261ebd5ca28a50eb82fb97f668 100644
--- a/src/mol-geo/primitive/tube.ts
+++ b/src/mol-geo/primitive/tube.ts
@@ -18,7 +18,7 @@ const b = Vec3.zero()
 const u = Vec3.zero()
 const v = Vec3.zero()
 
-export function addTube(controlPoints: Helpers.NumberArray, normalVectors: Helpers.NumberArray, binormalVectors: Helpers.NumberArray, linearSegments: number, radialSegments: number, width: number, height: number, waveFactor: number, startCap: boolean, endCap: boolean, state: MeshBuilderState) {
+export function addTube(controlPoints: ArrayLike<number>, normalVectors: ArrayLike<number>, binormalVectors: ArrayLike<number>, linearSegments: number, radialSegments: number, width: number, height: number, waveFactor: number, startCap: boolean, endCap: boolean, state: MeshBuilderState) {
     const { vertices, normals, indices } = state
 
     let vertexCount = vertices.elementCount
diff --git a/src/mol-geo/primitive/wedge.ts b/src/mol-geo/primitive/wedge.ts
index f15642e1e428e824d8efed00e51c7599112e5224..1b00533691b83741e101278050762b9c8db19dd9 100644
--- a/src/mol-geo/primitive/wedge.ts
+++ b/src/mol-geo/primitive/wedge.ts
@@ -5,6 +5,7 @@
  */
 
 import { Vec3 } from 'mol-math/linear-algebra'
+import { Primitive } from './primitive';
 
 export const DefaultWedgeProps = {
     width: 1,
@@ -31,7 +32,7 @@ const nacdf = Vec3.zero()
 
 const s = Vec3.zero()
 
-export function Wedge(props?: WedgeProps) {
+export function Wedge(props?: WedgeProps): Primitive {
     const { width, height, depth } = { ...DefaultWedgeProps, ...props }
 
     const vertices = new Float32Array(54)
diff --git a/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts b/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts
index ad9c384dabeefb3071fa5fbb4ada91bb9d7621cf..1459b499dd52ea8fca99c58518b83451383cd891 100644
--- a/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts
+++ b/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts
@@ -28,6 +28,8 @@ async function createCarbohydrateSymbolMesh(ctx: RuntimeContext, structure: Stru
     const builder = MeshBuilder.create(256, 128, mesh)
 
     const t = Mat4.identity()
+    const sMat = Mat4.identity()
+    const sVec = Vec3.zero()
     const p = Vec3.zero()
     const pd = Vec3.zero()
     const p1 = Vec3.zero()
@@ -54,11 +56,12 @@ async function createCarbohydrateSymbolMesh(ctx: RuntimeContext, structure: Stru
         const shapeType = getSaccharideShape(c.component.type)
         switch (shapeType) {
             case SaccharideShapes.FilledSphere:
-                builder.addIcosahedron(cGeo.center, radius, 2)
+                builder.addSphere(cGeo.center, radius, 2)
                 break;
             case SaccharideShapes.FilledCube:
                 centerAlign(cGeo.center, cGeo.normal, cGeo.direction)
                 builder.addBox(t, { width: side, height: side, depth: side })
+                builder.addOctahedron(t)
                 break;
             case SaccharideShapes.CrossedCube:
                 // TODO split
@@ -85,7 +88,18 @@ async function createCarbohydrateSymbolMesh(ctx: RuntimeContext, structure: Stru
                 builder.addStar(t, { outerRadius: side, innerRadius: side / 2, thickness: side / 2, pointCount: 5 })
                 break
             case SaccharideShapes.FilledDiamond:
+                centerAlign(cGeo.center, cGeo.normal, cGeo.direction)
+                Mat4.fromScaling(sMat, Vec3.set(sVec, side * 1.4, side * 1.4, side * 1.4))
+                Mat4.mul(t, t, sMat)
+                builder.addOctahedron(t)
+                break
             case SaccharideShapes.DividedDiamond:
+                // TODO split
+                centerAlign(cGeo.center, cGeo.normal, cGeo.direction)
+                Mat4.fromScaling(sMat, Vec3.set(sVec, side * 1.4, side * 1.4, side * 1.4))
+                Mat4.mul(t, t, sMat)
+                builder.addOctahedron(t)
+                break
             case SaccharideShapes.FlatDiamond:
             case SaccharideShapes.Pentagon:
                 centerAlign(cGeo.center, cGeo.normal, cGeo.direction)
diff --git a/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts b/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts
index 6e095c7f13d4bbc89d7fa94468625fd2ccc74830..d1f289ec99b41a30b4356e43b2dfbf80da4f2a22 100644
--- a/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts
+++ b/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts
@@ -46,7 +46,7 @@ async function createPolymerGapCylinderMesh(ctx: RuntimeContext, unit: Unit, mes
         if (centerA.element === centerB.element) {
             builder.setId(centerA.element)
             pos(elements[centerA.element], pA)
-            builder.addIcosahedron(pA, 0.6, 0)
+            builder.addSphere(pA, 0.6, 0)
         } else {
             pos(elements[centerA.element], pA)
             pos(elements[centerB.element], pB)
diff --git a/src/mol-geo/representation/structure/visual/util/element.ts b/src/mol-geo/representation/structure/visual/util/element.ts
index 50a44321e32420b54cf80f80a4ab28f2cbc140e7..885b96aec12a1b09e8a815e48bbb401b001374ef 100644
--- a/src/mol-geo/representation/structure/visual/util/element.ts
+++ b/src/mol-geo/representation/structure/visual/util/element.ts
@@ -8,7 +8,7 @@ import { Vec3 } from 'mol-math/linear-algebra';
 import { Unit, StructureElement } from 'mol-model/structure';
 import { SizeTheme } from '../../../../theme';
 import { RuntimeContext } from 'mol-task';
-import { icosahedronVertexCount } from '../../../../primitive/icosahedron';
+import { sphereVertexCount } from '../../../../primitive/sphere';
 import { Mesh } from '../../../../shape/mesh';
 import { MeshBuilder } from '../../../../shape/mesh-builder';
 import { ValueCell, defaults } from 'mol-util';
@@ -33,7 +33,7 @@ export function getElementRadius(unit: Unit, props: SizeTheme): StructureElement
 export async function createElementSphereMesh(ctx: RuntimeContext, unit: Unit, radius: StructureElement.Property<number>, detail: number, mesh?: Mesh) {
     const { elements } = unit;
     const elementCount = elements.length;
-    const vertexCount = elementCount * icosahedronVertexCount(detail)
+    const vertexCount = elementCount * sphereVertexCount(detail)
     const meshBuilder = MeshBuilder.create(vertexCount, vertexCount / 2, mesh)
 
     const v = Vec3.zero()
@@ -46,7 +46,7 @@ export async function createElementSphereMesh(ctx: RuntimeContext, unit: Unit, r
         pos(elements[i], v)
 
         meshBuilder.setId(i)
-        meshBuilder.addIcosahedron(v, radius(l), detail)
+        meshBuilder.addSphere(v, radius(l), detail)
 
         if (i % 10000 === 0 && ctx.shouldUpdate) {
             await ctx.update({ message: 'Sphere mesh', current: i, max: elementCount });
diff --git a/src/mol-geo/shape/mesh-builder.ts b/src/mol-geo/shape/mesh-builder.ts
index f566e1b08e37aa3afc290ef5a027edbf5e1adbe9..9427faa6981313720e1e77208d1c375090507b30 100644
--- a/src/mol-geo/shape/mesh-builder.ts
+++ b/src/mol-geo/shape/mesh-builder.ts
@@ -12,18 +12,14 @@ import { Box, BoxProps } from '../primitive/box';
 import { Plane, PlaneProps } from '../primitive/plane';
 import { Wedge, WedgeProps } from '../primitive/wedge';
 import { Cylinder, CylinderProps } from '../primitive/cylinder';
-import { Icosahedron, IcosahedronProps } from '../primitive/icosahedron';
+import { Sphere, SphereProps } from '../primitive/sphere';
 import { Mesh } from './mesh';
 import { getNormalMatrix } from '../util';
 import { addSheet } from '../primitive/sheet';
 import { addTube } from '../primitive/tube';
 import { StarProps, Star } from '../primitive/star';
-
-interface Primitive {
-    vertices: Float32Array
-    normals: Float32Array
-    indices: Uint32Array
-}
+import { Octahedron } from '../primitive/octahedron';
+import { Primitive } from '../primitive/primitive';
 
 export interface MeshBuilderState {
     vertices: ChunkedArray<number, 3>
@@ -32,23 +28,24 @@ export interface MeshBuilderState {
 }
 
 export interface MeshBuilder {
-    add(t: Mat4, _vertices: Float32Array, _normals: Float32Array, _indices?: Uint32Array): void
+    add(t: Mat4, _vertices: ArrayLike<number>, _normals: ArrayLike<number>, _indices?: ArrayLike<number>): void
     addBox(t: Mat4, props?: BoxProps): void
     addPlane(t: Mat4, props?: PlaneProps): void
     addWedge(t: Mat4, props?: WedgeProps): void
     addStar(t: Mat4, props?: StarProps): void
+    addOctahedron(t: Mat4): void
     addCylinder(start: Vec3, end: Vec3, lengthScale: number, props: CylinderProps): void
     addDoubleCylinder(start: Vec3, end: Vec3, lengthScale: number, shift: Vec3, props: CylinderProps): void
     addFixedCountDashedCylinder(start: Vec3, end: Vec3, lengthScale: number, segmentCount: number, props: CylinderProps): void
-    addIcosahedron(center: Vec3, radius: number, detail: number): void
-    addTube(centers: Helpers.NumberArray, normals: Helpers.NumberArray, binormals: Helpers.NumberArray, linearSegments: number, radialSegments: number, width: number, height: number, waveFactor: number, startCap: boolean, endCap: boolean): void
-    addSheet(centers: Helpers.NumberArray, normals: Helpers.NumberArray, binormals: Helpers.NumberArray, linearSegments: number, width: number, height: number, arrowHeight: number, startCap: boolean, endCap: boolean): void
+    addSphere(center: Vec3, radius: number, detail: number): void
+    addTube(centers: ArrayLike<number>, normals: ArrayLike<number>, binormals: ArrayLike<number>, linearSegments: number, radialSegments: number, width: number, height: number, waveFactor: number, startCap: boolean, endCap: boolean): void
+    addSheet(centers: ArrayLike<number>, normals: ArrayLike<number>, binormals: ArrayLike<number>, linearSegments: number, width: number, height: number, arrowHeight: number, startCap: boolean, endCap: boolean): void
     setId(id: number): void
     getMesh(): Mesh
 }
 
 const cylinderMap = new Map<string, Primitive>()
-const icosahedronMap = new Map<string, Primitive>()
+const sphereMap = new Map<string, Primitive>()
 
 const up = Vec3.create(0, 1, 0)
 const tmpV = Vec3.zero()
@@ -83,20 +80,20 @@ function getCylinder(props: CylinderProps) {
     return cylinder
 }
 
-const tmpIcosahedronMat = Mat4.identity()
+const tmpSphereMat = Mat4.identity()
 
-function setIcosahedronMat(m: Mat4, center: Vec3) {
+function setSphereMat(m: Mat4, center: Vec3) {
     return Mat4.setTranslation(m, center)
 }
 
-function getIcosahedron(props: IcosahedronProps) {
+function getSphere(props: SphereProps) {
     const key = JSON.stringify(props)
-    let icosahedron = icosahedronMap.get(key)
-    if (icosahedron === undefined) {
-        icosahedron = Icosahedron(props)
-        icosahedronMap.set(key, icosahedron)
+    let sphere = sphereMap.get(key)
+    if (sphere === undefined) {
+        sphere = Sphere(props)
+        sphereMap.set(key, sphere)
     }
-    return icosahedron
+    return sphere
 }
 
 // TODO cache primitives based on props
@@ -113,7 +110,7 @@ export namespace MeshBuilder {
 
         let currentId = -1
 
-        function add(t: Mat4, _vertices: Float32Array, _normals: Float32Array, _indices: Uint32Array) {
+        function add(t: Mat4, _vertices: ArrayLike<number>, _normals: ArrayLike<number>, _indices: ArrayLike<number>) {
             const { elementCount } = vertices
             const n = getNormalMatrix(tmpMat3, t)
             for (let i = 0, il = _vertices.length; i < il; i += 3) {
@@ -151,6 +148,10 @@ export namespace MeshBuilder {
                 const { vertices, normals, indices } = Star(props)
                 add(t, vertices, normals, indices)
             },
+            addOctahedron: (t: Mat4) => {
+                const { vertices, normals, indices } = Octahedron()
+                add(t, vertices, normals, indices)
+            },
             addCylinder: (start: Vec3, end: Vec3, lengthScale: number, props: CylinderProps) => {
                 const d = Vec3.distance(start, end) * lengthScale
                 props.height = d
@@ -197,16 +198,16 @@ export namespace MeshBuilder {
                     add(tmpCylinderMat, vertices, normals, indices)
                 }
             },
-            addIcosahedron: (center: Vec3, radius: number, detail: number) => {
-                const { vertices, normals, indices } = getIcosahedron({ radius, detail })
-                setIcosahedronMat(tmpIcosahedronMat, center)
-                add(tmpIcosahedronMat, vertices, normals, indices)
+            addSphere: (center: Vec3, radius: number, detail: number) => {
+                const { vertices, normals, indices } = getSphere({ radius, detail })
+                setSphereMat(tmpSphereMat, center)
+                add(tmpSphereMat, vertices, normals, indices)
             },
-            addTube: (centers: Helpers.NumberArray, normals: Helpers.NumberArray, binormals: Helpers.NumberArray, linearSegments: number, radialSegments: number, width: number, height: number, waveFactor: number, startCap: boolean, endCap: boolean) => {
+            addTube: (centers: ArrayLike<number>, normals: ArrayLike<number>, binormals: ArrayLike<number>, linearSegments: number, radialSegments: number, width: number, height: number, waveFactor: number, startCap: boolean, endCap: boolean) => {
                 const addedVertexCount = addTube(centers, normals, binormals, linearSegments, radialSegments, width, height, waveFactor, startCap, endCap, state)
                 for (let i = 0, il = addedVertexCount; i < il; ++i) ChunkedArray.add(ids, currentId);
             },
-            addSheet: (controls: Helpers.NumberArray, normals: Helpers.NumberArray, binormals: Helpers.NumberArray, linearSegments: number, width: number, height: number, arrowHeight: number, startCap: boolean, endCap: boolean) => {
+            addSheet: (controls: ArrayLike<number>, normals: ArrayLike<number>, binormals: ArrayLike<number>, linearSegments: number, width: number, height: number, arrowHeight: number, startCap: boolean, endCap: boolean) => {
                 const addedVertexCount = addSheet(controls, normals, binormals, linearSegments, width, height, arrowHeight, startCap, endCap, state)
                 for (let i = 0, il = addedVertexCount; i < il; ++i) ChunkedArray.add(ids, currentId);
             },
diff --git a/src/mol-math/linear-algebra/3d/vec3.ts b/src/mol-math/linear-algebra/3d/vec3.ts
index 7d45fb810d52d8965f7275f82454034aa12b9083..2527ca8724068857a12562845ee7895800901c72 100644
--- a/src/mol-math/linear-algebra/3d/vec3.ts
+++ b/src/mol-math/linear-algebra/3d/vec3.ts
@@ -46,7 +46,7 @@ namespace Vec3 {
         return { x: v[0], y: v[1], z: v[2] };
     }
 
-    export function fromArray(v: Vec3, array: Helpers.NumberArray, offset: number) {
+    export function fromArray(v: Vec3, array: ArrayLike<number>, offset: number) {
         v[0] = array[offset + 0]
         v[1] = array[offset + 1]
         v[2] = array[offset + 2]