diff --git a/src/mol-geo/geometry/lines/lines-builder.ts b/src/mol-geo/geometry/lines/lines-builder.ts index db6ae4b45f0e5162cf755fff1f3aad23522c3830..ac9d7a94f8a27b13f6bb30f77c111fb4c7752279 100644 --- a/src/mol-geo/geometry/lines/lines-builder.ts +++ b/src/mol-geo/geometry/lines/lines-builder.ts @@ -7,12 +7,18 @@ import { ValueCell } from 'mol-util/value-cell' import { ChunkedArray } from 'mol-data/util'; import { Lines } from './lines'; +import { Mat4, Vec3 } from 'mol-math/linear-algebra'; +import { Cage } from 'mol-geo/primitive/cage'; export interface LinesBuilder { add(startX: number, startY: number, startZ: number, endX: number, endY: number, endZ: number, group: number): void + addCage(t: Mat4, cage: Cage, group: number): void getLines(): Lines } +const tmpA = Vec3.zero() +const tmpB = Vec3.zero() + export namespace LinesBuilder { export function create(initialCount = 2048, chunkSize = 1024, lines?: Lines): LinesBuilder { const mappings = ChunkedArray.create(Float32Array, 2, chunkSize, lines ? lines.mappingBuffer.ref.value : initialCount); @@ -21,20 +27,32 @@ export namespace LinesBuilder { const starts = ChunkedArray.create(Float32Array, 3, chunkSize, lines ? lines.startBuffer.ref.value : initialCount); const ends = ChunkedArray.create(Float32Array, 3, chunkSize, lines ? lines.endBuffer.ref.value : initialCount); + const add = (startX: number, startY: number, startZ: number, endX: number, endY: number, endZ: number, group: number) => { + const offset = mappings.elementCount + for (let i = 0; i < 4; ++i) { + ChunkedArray.add3(starts, startX, startY, startZ); + ChunkedArray.add3(ends, endX, endY, endZ); + ChunkedArray.add(groups, group); + } + ChunkedArray.add2(mappings, -1, 1); + ChunkedArray.add2(mappings, -1, -1); + ChunkedArray.add2(mappings, 1, 1); + ChunkedArray.add2(mappings, 1, -1); + ChunkedArray.add3(indices, offset, offset + 1, offset + 2); + ChunkedArray.add3(indices, offset + 1, offset + 3, offset + 2); + } + return { - add: (startX: number, startY: number, startZ: number, endX: number, endY: number, endZ: number, group: number) => { - const offset = mappings.elementCount - for (let i = 0; i < 4; ++i) { - ChunkedArray.add3(starts, startX, startY, startZ); - ChunkedArray.add3(ends, endX, endY, endZ); - ChunkedArray.add(groups, group); + add, + addCage: (t: Mat4, cage: Cage, group: number) => { + const { vertices, edges } = cage + for (let i = 0, il = edges.length; i < il; i += 2) { + Vec3.fromArray(tmpA, vertices, edges[i] * 3) + Vec3.fromArray(tmpB, vertices, edges[i + 1] * 3) + Vec3.transformMat4(tmpA, tmpA, t) + Vec3.transformMat4(tmpB, tmpB, t) + add(tmpA[0], tmpA[1], tmpA[2], tmpB[0], tmpB[1], tmpB[2], group) } - ChunkedArray.add2(mappings, -1, 1); - ChunkedArray.add2(mappings, -1, -1); - ChunkedArray.add2(mappings, 1, 1); - ChunkedArray.add2(mappings, 1, -1); - ChunkedArray.add3(indices, offset, offset + 1, offset + 2); - ChunkedArray.add3(indices, offset + 1, offset + 3, offset + 2); }, getLines: () => { const mb = ChunkedArray.compact(mappings, true) as Float32Array diff --git a/src/mol-geo/primitive/cage.ts b/src/mol-geo/primitive/cage.ts index 45519a3f00626c1390b4d35063420197e3fa3e07..6c235c61f28ff2fecfd317bad4568f99c3233800 100644 --- a/src/mol-geo/primitive/cage.ts +++ b/src/mol-geo/primitive/cage.ts @@ -5,6 +5,10 @@ */ export interface Cage { - vertices: ArrayLike<number> - edges: ArrayLike<number> + readonly vertices: ArrayLike<number> + readonly edges: ArrayLike<number> +} + +export function createCage(vertices: ArrayLike<number>, edges: ArrayLike<number>): Cage { + return { vertices, edges } } \ No newline at end of file diff --git a/src/mol-geo/primitive/dodecahedron.ts b/src/mol-geo/primitive/dodecahedron.ts index 1602100a440ebe64934eb22ea083bf8eef16ab81..8d63af07bca418028c724b311704a407c62670f7 100644 --- a/src/mol-geo/primitive/dodecahedron.ts +++ b/src/mol-geo/primitive/dodecahedron.ts @@ -5,12 +5,13 @@ */ import { createPrimitive, Primitive } from './primitive'; +import { Cage, createCage } from './cage'; const t = (1 + Math.sqrt(5)) / 2; -const a = 0.5; -const b = 0.5 * 1 / t; -const c = 0.5 * (2 - t); +const a = 1; +const b = 1 / t; +const c = 2 - t; const dodecahedronVertices: ReadonlyArray<number> = [ c, 0, a, -c, 0, a, -b, b, b, 0, a, c, b, b, b, @@ -19,29 +20,34 @@ const dodecahedronVertices: ReadonlyArray<number> = [ -b, b, -b, a, c, 0, -a, c, 0, -a, -c, 0, a, -c, 0 ]; -const dodecahedronIndices: ReadonlyArray<number> = [ - 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 +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 12, 11, 10, 10, 9, 8, 12, 10, 8, // 12, 11, 10, 9, 8 15, 14, 13, 13, 8, 9, 15, 13, 9, // 15, 14, 13, 8, 9 14, 3, 4, 4, 16, 13, 14, 4, 13, // 14, 3, 4, 16, 13 - 3, 14, 15, 15, 17, 2, 3, 15, 2, // 3, 14, 15, 17, 2 + 3, 14, 15, 15, 17, 2, 3, 15, 2, // 3, 14, 15, 17, 2 11, 6, 7, 7, 18, 10, 11, 7, 10, // 11, 6, 7, 18, 10 - 6, 11, 12, 12, 19, 5, 6, 12, 5, // 6, 11, 12, 19, 5 - 4, 0, 5, 5, 19, 16, 4, 5, 16, // 4, 0, 5, 19, 16 + 6, 11, 12, 12, 19, 5, 6, 12, 5, // 6, 11, 12, 19, 5 + 4, 0, 5, 5, 19, 16, 4, 5, 16, // 4, 0, 5, 19, 16 12, 8, 13, 13, 16, 19, 12, 13, 19, // 12, 8, 13, 16, 19 15, 9, 10, 10, 18, 17, 15, 10, 17, // 15, 9, 10, 18, 17 - 7, 1, 2, 2, 17, 18, 7, 2, 18, // 7, 1, 2, 17, 18 + 7, 1, 2, 2, 17, 18, 7, 2, 18, // 7, 1, 2, 17, 18 ]; -// const dodecahedronEdgeIndices: ReadonlyArray<number> = [ -// 0, 1, 0, 4, 0, 5, 1, 2, 1, 7, 2, 3, 2, 17, 3, 4, 3, 14, 4, 16, -// 5, 6, 5, 19, 6, 7, 6, 11, 7, 18, 8, 9, 8, 12, 8, 13, 9, 10, 9, 15, -// 0, 11, 0, 18, 1, 12, 2, 19, 3, 14, 3, 16, 4, 15, 5, 17, 6, 19, 7, 18, -// ] +const dodecahedronEdgeIndices: ReadonlyArray<number> = [ + 0, 1, 0, 4, 0, 5, 1, 2, 1, 7, 2, 3, 2, 17, 3, 4, 3, 14, 4, 16, + 5, 6, 5, 19, 6, 7, 6, 11, 7, 18, 8, 9, 8, 12, 8, 13, 9, 10, 9, 15, + 10, 11, 10, 18, 11, 12, 12, 19, 13, 14, 13, 16, 14, 15, 15, 17, 16, 19, 17, 18, +] let dodecahedron: Primitive export function Dodecahedron(): Primitive { if (!dodecahedron) dodecahedron = createPrimitive(dodecahedronVertices, dodecahedronIndices) return dodecahedron +} + +const dodecahedronCage = createCage(dodecahedronVertices, dodecahedronEdgeIndices) +export function DodecahedronCage(): Cage { + return dodecahedronCage } \ No newline at end of file diff --git a/src/tests/browser/render-lines.ts b/src/tests/browser/render-lines.ts new file mode 100644 index 0000000000000000000000000000000000000000..9eeecd9a090d762b12fb75c563488aad41d40da6 --- /dev/null +++ b/src/tests/browser/render-lines.ts @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import './index.html' +import { Canvas3D } from 'mol-canvas3d/canvas3d'; +import { Mat4 } from 'mol-math/linear-algebra'; +import { Representation } from 'mol-repr/representation'; +import { Color } from 'mol-util/color'; +import { createRenderObject } from 'mol-gl/render-object'; +import { Lines } from 'mol-geo/geometry/lines/lines'; +import { LinesBuilder } from 'mol-geo/geometry/lines/lines-builder'; +import { DodecahedronCage } from 'mol-geo/primitive/dodecahedron'; + +const parent = document.getElementById('app')! +parent.style.width = '100%' +parent.style.height = '100%' + +const canvas = document.createElement('canvas') +canvas.style.width = '100%' +canvas.style.height = '100%' +parent.appendChild(canvas) + +const canvas3d = Canvas3D.create(canvas, parent) +canvas3d.animate() + +function linesRepr() { + const linesBuilder = LinesBuilder.create() + const t = Mat4.identity() + const dodecahedronCage = DodecahedronCage() + linesBuilder.addCage(t, dodecahedronCage, 0) + const lines = linesBuilder.getLines() + + const values = Lines.Utils.createValuesSimple(lines, {}, Color(0xFF0000), 3) + const state = Lines.Utils.createRenderableState({}) + const renderObject = createRenderObject('lines', values, state) + const repr = Representation.fromRenderObject('cage-lines', renderObject) + return repr +} + +canvas3d.add(linesRepr()) +canvas3d.resetCamera() \ No newline at end of file diff --git a/src/tests/browser/render-shape.ts b/src/tests/browser/render-shape.ts index 39f9406adc8dd48cfd0569ea04cbebb877d2a5f9..943a50476785bf19aedb3bd7b959cc210ce54c75 100644 --- a/src/tests/browser/render-shape.ts +++ b/src/tests/browser/render-shape.ts @@ -15,7 +15,6 @@ import { ColorNames } from 'mol-util/color/tables'; import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { labelFirst } from 'mol-theme/label'; import { RuntimeContext, Progress } from 'mol-task'; -import { Dodecahedron } from 'mol-geo/primitive/dodecahedron'; const parent = document.getElementById('app')! parent.style.width = '100%' @@ -57,7 +56,7 @@ async function getSphereMesh(ctx: RuntimeContext, centers: number[], mesh?: Mesh const builderState = MeshBuilder.createState(centers.length * 128, centers.length * 128 / 2, mesh) const t = Mat4.identity() const v = Vec3.zero() - const sphere = Dodecahedron() // Sphere(2) + const sphere = Sphere(2) builderState.currentGroup = 0 for (let i = 0, il = centers.length / 3; i < il; ++i) { // for production, calls to update should be guarded by `if (ctx.shouldUpdate)` diff --git a/webpack.config.js b/webpack.config.js index 0298bc8f7b726c2d45c12a3d1263e698b47d26d6..bda3612a92f256206750a7c20e5422ed44d57fc9 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -102,6 +102,7 @@ module.exports = [ createApp('model-server-query'), createBrowserTest('font-atlas'), + createBrowserTest('render-lines'), createBrowserTest('render-mesh'), createBrowserTest('render-shape'), createBrowserTest('render-spheres'),