diff --git a/src/mol-geo/util/marching-cubes/algorithm.ts b/src/mol-geo/util/marching-cubes/algorithm.ts index e9d9e4ad46ee87691bc4c9d34b01dfe8a476b071..d2f524f2c308399cce8f598cd8622c51b007dba8 100644 --- a/src/mol-geo/util/marching-cubes/algorithm.ts +++ b/src/mol-geo/util/marching-cubes/algorithm.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal <david.sehnal@gmail.com> * @author Alexander Rose <alexander.rose@weirdbyte.de> @@ -12,7 +12,6 @@ import { Index, EdgeIdInfo, CubeEdges, EdgeTable, TriTable } from './tables' import { defaults } from 'mol-util' import { MarchinCubesBuilder, MarchinCubesMeshBuilder, MarchinCubesLinesBuilder } from './builder'; import { Lines } from '../../geometry/lines/lines'; -// import { Lines } from '../../geometry/lines/lines'; /** * The parameters required by the algorithm. @@ -156,17 +155,38 @@ class MarchingCubesState { const ret = this.verticesOnEdges[edgeId]; if (ret > 0) return ret - 1; + const sf = this.scalarField + const sfg = this.scalarFieldGet + const edge = CubeEdges[edgeNum]; const a = edge.a, b = edge.b; const li = a.i + this.i, lj = a.j + this.j, lk = a.k + this.k; const hi = b.i + this.i, hj = b.j + this.j, hk = b.k + this.k; - const v0 = this.scalarFieldGet(this.scalarField, li, lj, lk); - const v1 = this.scalarFieldGet(this.scalarField, hi, hj, hk); + const v0 = sfg(sf, li, lj, lk); + const v1 = sfg(sf, hi, hj, hk); const t = (this.isoLevel - v0) / (v0 - v1); - const id = this.builder.addVertex(li + t * (li - hi), lj + t * (lj - hj), lk + t * (lk - hk)); + const id = this.builder.addVertex( + li + t * (li - hi), + lj + t * (lj - hj), + lk + t * (lk - hk) + ); this.verticesOnEdges[edgeId] = id + 1; + const n0x = sfg(sf, Math.max(0, li - 1), lj, lk) - sfg(sf, Math.min(this.nX - 1, li + 1), lj, lk) + const n0y = sfg(sf, li, Math.max(0, lj - 1), lk) - sfg(sf, li, Math.min(this.nY - 1, lj + 1), lk) + const n0z = sfg(sf, li, lj, Math.max(0, lk - 1)) - sfg(sf, li, lj, Math.min(this.nZ, lk + 1)) + + const n1x = sfg(sf, Math.max(0, hi - 1), hj, hk) - sfg(sf, Math.min(this.nX - 1, hi + 1), hj, hk) + const n1y = sfg(sf, hi, Math.max(0, hj - 1), hk) - sfg(sf, hi, Math.min(this.nY - 1, hj + 1), hk) + const n1z = sfg(sf, hi, hj, Math.max(0, hk - 1)) - sfg(sf, hi, hj, Math.min(this.nZ - 1, hk + 1)) + + this.builder.addNormal( + n0x + t * (n0x - n1x), + n0y + t * (n0y - n1y), + n0z + t * (n0z - n1z) + ) + if (this.idField) { const u = this.idFieldGet!(this.idField, li, lj, lk); const v = this.idFieldGet!(this.idField, hi, hj, hk) diff --git a/src/mol-geo/util/marching-cubes/builder.ts b/src/mol-geo/util/marching-cubes/builder.ts index be7abebb915efd13d1d86f11e3ce866633b09263..8d78d9f32614947573d734bc390fee08b05e9b9d 100644 --- a/src/mol-geo/util/marching-cubes/builder.ts +++ b/src/mol-geo/util/marching-cubes/builder.ts @@ -7,7 +7,7 @@ */ import { ChunkedArray } from '../../../mol-data/util'; -import { ValueCell } from 'mol-util'; +import { ValueCell, noop } from 'mol-util'; import { Mesh } from '../../geometry/mesh/mesh'; import { AllowedContours } from './tables'; import { LinesBuilder } from '../../geometry/lines/lines-builder'; @@ -15,6 +15,7 @@ import { Lines } from '../../geometry/lines/lines'; export interface MarchinCubesBuilder<T> { addVertex(x: number, y: number, z: number): number + addNormal(x: number, y: number, z: number): void addGroup(group: number): void addTriangle(vertList: number[], a: number, b: number, c: number, edgeFilter: number): void get(): T @@ -24,6 +25,7 @@ export function MarchinCubesMeshBuilder(vertexChunkSize: number, mesh?: Mesh): M const triangleChunkSize = Math.min(1 << 16, vertexChunkSize * 4) const vertices = ChunkedArray.create(Float32Array, 3, vertexChunkSize, mesh && mesh.vertexBuffer.ref.value); + const normals = ChunkedArray.create(Float32Array, 3, vertexChunkSize, mesh && mesh.normalBuffer.ref.value); const groups = ChunkedArray.create(Float32Array, 1, vertexChunkSize, mesh && mesh.groupBuffer.ref.value); const indices = ChunkedArray.create(Uint32Array, 3, triangleChunkSize, mesh && mesh.indexBuffer.ref.value); @@ -35,6 +37,9 @@ export function MarchinCubesMeshBuilder(vertexChunkSize: number, mesh?: Mesh): M ++vertexCount return ChunkedArray.add3(vertices, x, y, z ); }, + addNormal: (x: number, y: number, z: number) => { + ChunkedArray.add3(normals, x, y, z ); + }, addGroup: (group: number) => { ChunkedArray.add(groups, group); }, @@ -44,6 +49,7 @@ export function MarchinCubesMeshBuilder(vertexChunkSize: number, mesh?: Mesh): M }, get: () => { const vb = ChunkedArray.compact(vertices, true) as Float32Array; + const nb = ChunkedArray.compact(normals, true) as Float32Array; const ib = ChunkedArray.compact(indices, true) as Uint32Array; const gb = ChunkedArray.compact(groups, true) as Float32Array; @@ -54,8 +60,8 @@ export function MarchinCubesMeshBuilder(vertexChunkSize: number, mesh?: Mesh): M vertexBuffer: mesh ? ValueCell.update(mesh.vertexBuffer, vb) : ValueCell.create(vb), groupBuffer: mesh ? ValueCell.update(mesh.groupBuffer, gb) : ValueCell.create(gb), indexBuffer: mesh ? ValueCell.update(mesh.indexBuffer, ib) : ValueCell.create(ib), - normalBuffer: mesh ? mesh.normalBuffer : ValueCell.create(new Float32Array(0)), - normalsComputed: false + normalBuffer: mesh ? ValueCell.update(mesh.normalBuffer, nb) : ValueCell.create(nb), + normalsComputed: true } } } @@ -72,6 +78,7 @@ export function MarchinCubesLinesBuilder(vertexChunkSize: number, lines?: Lines) addVertex: (x: number, y: number, z: number) => { return ChunkedArray.add3(vertices, x, y, z); }, + addNormal: () => noop, addGroup: (group: number) => { ChunkedArray.add(groups, group); }, diff --git a/src/mol-repr/structure/visual/gaussian-surface-mesh.ts b/src/mol-repr/structure/visual/gaussian-surface-mesh.ts index a538309b830c33b9806f3b58d3a80ee94906330d..d4253e03d599ae818313a955edfc85e5bc3ecb82 100644 --- a/src/mol-repr/structure/visual/gaussian-surface-mesh.ts +++ b/src/mol-repr/structure/visual/gaussian-surface-mesh.ts @@ -47,7 +47,6 @@ async function createGaussianSurfaceMesh(ctx: VisualContext, unit: Unit, structu const surface = await computeMarchingCubesMesh(params, mesh).runAsChild(ctx.runtime) Mesh.transformImmediate(surface, transform) - Mesh.computeNormalsImmediate(surface) Mesh.uniformTriangleGroup(surface) return surface diff --git a/src/mol-repr/structure/visual/molecular-surface-mesh.ts b/src/mol-repr/structure/visual/molecular-surface-mesh.ts index 24c0e973052c5575d6598f285e0b8e90fd172983..aea6b6de911d54e3b67996e1cb028cf1c9881db8 100644 --- a/src/mol-repr/structure/visual/molecular-surface-mesh.ts +++ b/src/mol-repr/structure/visual/molecular-surface-mesh.ts @@ -37,7 +37,6 @@ async function createMolecularSurfaceMesh(ctx: VisualContext, unit: Unit, struct const surface = await computeMarchingCubesMesh(params, mesh).runAsChild(ctx.runtime) Mesh.transformImmediate(surface, transform) - Mesh.computeNormalsImmediate(surface) Mesh.uniformTriangleGroup(surface) return surface diff --git a/src/mol-repr/volume/isosurface.ts b/src/mol-repr/volume/isosurface.ts index 364e3c42e4afdeac974c990881cff75732d03c3d..224afe6779457f11d03b73c9a9e4806d41d0e752 100644 --- a/src/mol-repr/volume/isosurface.ts +++ b/src/mol-repr/volume/isosurface.ts @@ -78,7 +78,6 @@ export async function createVolumeIsosurfaceMesh(ctx: VisualContext, volume: Vol const transform = VolumeData.getGridToCartesianTransform(volume); ctx.runtime.update({ message: 'Transforming mesh...' }); Mesh.transformImmediate(surface, transform); - Mesh.computeNormalsImmediate(surface) return surface; }