diff --git a/src/mol-canvas3d/canvas3d.ts b/src/mol-canvas3d/canvas3d.ts index 00d773e513f8a656f99bfb15bf62f34c834a4e6c..0e84165ba188af11a9efe1c32cabde9d350790c3 100644 --- a/src/mol-canvas3d/canvas3d.ts +++ b/src/mol-canvas3d/canvas3d.ts @@ -27,6 +27,7 @@ import { Loci, EmptyLoci, isEmptyLoci } from 'mol-model/loci'; import { Color } from 'mol-util/color'; import { Camera } from './camera'; import { ParamDefinition as PD } from 'mol-util/param-definition'; +import { BoundingSphereHelper } from './helper/bounding-sphere-helper'; export const Canvas3DParams = { // TODO: FPS cap? @@ -35,6 +36,9 @@ export const Canvas3DParams = { cameraMode: PD.Select('perspective', [['perspective', 'Perspective'], ['orthographic', 'Orthographic']]), backgroundColor: PD.Color(Color(0x000000)), pickingAlphaThreshold: PD.Numeric(0.5, { min: 0.0, max: 1.0, step: 0.01 }, { description: 'The minimum opacity value needed for an object to be pickable.' }), + debug: PD.Group({ + showBoundingSpheres: PD.Boolean(true, { description: 'Show bounding spheres of render objects.' }), + }) } export type Canvas3DParams = typeof Canvas3DParams @@ -122,6 +126,8 @@ namespace Canvas3D { let drawPending = false let lastRenderTime = -1 + const boundingSphereHelper = new BoundingSphereHelper(scene, p.debug.showBoundingSpheres) + function getLoci(pickingId: PickingId) { let loci: Loci = EmptyLoci let repr: Representation.Any = Representation.Empty @@ -292,6 +298,7 @@ namespace Canvas3D { } reprRenderObjects.set(repr, newRO) reprCount.next(reprRenderObjects.size) + boundingSphereHelper.update() scene.update() requestDraw(true) } @@ -324,6 +331,7 @@ namespace Canvas3D { renderObjects.forEach(o => scene.remove(o)) reprRenderObjects.delete(repr) reprCount.next(reprRenderObjects.size) + boundingSphereHelper.update() scene.update() } }, @@ -369,6 +377,9 @@ namespace Canvas3D { if (props.pickingAlphaThreshold !== undefined && props.pickingAlphaThreshold !== renderer.props.pickingAlphaThreshold) { renderer.setPickingAlphaThreshold(props.pickingAlphaThreshold) } + if (props.debug && props.debug.showBoundingSpheres) { + boundingSphereHelper.visible = props.debug.showBoundingSpheres + } requestDraw(true) }, @@ -378,6 +389,9 @@ namespace Canvas3D { cameraMode: camera.state.mode, backgroundColor: renderer.props.clearColor, pickingAlphaThreshold: renderer.props.pickingAlphaThreshold, + debug: { + showBoundingSpheres: boundingSphereHelper.visible + } } }, get input() { diff --git a/src/mol-canvas3d/helper/bounding-sphere-helper.ts b/src/mol-canvas3d/helper/bounding-sphere-helper.ts new file mode 100644 index 0000000000000000000000000000000000000000..2b7d436163bfc667393fefee0d54f69b0f2288f3 --- /dev/null +++ b/src/mol-canvas3d/helper/bounding-sphere-helper.ts @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import { createMeshRenderObject, MeshRenderObject } from 'mol-gl/render-object' +import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder'; +import { addSphere } from 'mol-geo/geometry/mesh/builder/sphere'; +import { Mesh } from 'mol-geo/geometry/mesh/mesh'; +import { Geometry } from 'mol-geo/geometry/geometry'; +import { ValueCell } from 'mol-util'; +import Scene from 'mol-gl/scene'; + +export class BoundingSphereHelper { + private mesh: Mesh + private renderObject: MeshRenderObject + + constructor(private scene: Scene, visible: boolean) { + const builder = MeshBuilder.create(1024, 512) + this.mesh = builder.getMesh() + const values = Mesh.createValuesSimple(this.mesh, { alpha: 0.1 }) + this.renderObject = createMeshRenderObject(values, { visible, pickable: false }) + scene.add(this.renderObject) + } + + update() { + const builder = MeshBuilder.create(1024, 512, this.mesh) + if (this.scene.boundingSphere.radius) { + addSphere(builder, this.scene.boundingSphere.center, this.scene.boundingSphere.radius, 3) + } + this.scene.forEach(r => { + if (r.boundingSphere.radius) { + addSphere(builder, r.boundingSphere.center, r.boundingSphere.radius, 3) + } + }) + this.mesh = builder.getMesh() + ValueCell.update(this.renderObject.values.drawCount, Geometry.getDrawCount(this.mesh)) + } + + get visible() { return this.renderObject.state.visible } + set visible(value: boolean) { this.renderObject.state.visible = value } +} \ No newline at end of file diff --git a/src/mol-geo/geometry/geometry.ts b/src/mol-geo/geometry/geometry.ts index 95e8611c3eb4f5525912744873bdebfcb133bdfc..7612971c9e9bfefc131ccdbb96b469e5443be470 100644 --- a/src/mol-geo/geometry/geometry.ts +++ b/src/mol-geo/geometry/geometry.ts @@ -108,7 +108,7 @@ export function createRenderableState(props: PD.Values<Geometry.Params>): Render } export function updateRenderableState(state: RenderableState, props: PD.Values<Geometry.Params>) { - + } // diff --git a/src/mol-geo/geometry/mesh/mesh.ts b/src/mol-geo/geometry/mesh/mesh.ts index 02349efaea155858f8acb30fb9dd9bf725ef5a61..d3c44ab60da06e52cdb463a40b5ff7b38850a3bb 100644 --- a/src/mol-geo/geometry/mesh/mesh.ts +++ b/src/mol-geo/geometry/mesh/mesh.ts @@ -11,14 +11,16 @@ import { Sphere3D } from 'mol-math/geometry' import { transformPositionArray/* , transformDirectionArray, getNormalMatrix */ } from '../../util'; import { Geometry } from '../geometry'; import { createMarkers } from '../marker-data'; -import { TransformData } from '../transform-data'; +import { TransformData, createIdentityTransform } from '../transform-data'; import { LocationIterator } from '../../util/location-iterator'; -import { createColors } from '../color-data'; +import { createColors, createValueColor } from '../color-data'; import { ChunkedArray } from 'mol-data/util'; import { ParamDefinition as PD } from 'mol-util/param-definition'; import { calculateBoundingSphere } from 'mol-gl/renderable/util'; import { Theme } from 'mol-theme/theme'; import { MeshValues } from 'mol-gl/renderable/mesh'; +import { ColorTheme } from 'mol-theme/color'; +import { NullLocation } from 'mol-model/location'; export interface Mesh { readonly kind: 'mesh', @@ -376,6 +378,36 @@ export namespace Mesh { } } + export function createValuesSimple(mesh: Mesh, props: Partial<PD.Values<Params>>): MeshValues { + const p = { ...PD.getDefaultValues(Params), ...props } + const transform = createIdentityTransform() + const color = createValueColor(ColorTheme.Empty.color(NullLocation, false)) + const marker = createMarkers(1) + + const counts = { drawCount: mesh.triangleCount * 3, groupCount: 1, instanceCount: 1 } + + const boundingSphere = calculateBoundingSphere( + mesh.vertexBuffer.ref.value, mesh.vertexCount, + transform.aTransform.ref.value, transform.instanceCount.ref.value + ) + + return { + aPosition: mesh.vertexBuffer, + aNormal: mesh.normalBuffer, + aGroup: mesh.groupBuffer, + elements: mesh.indexBuffer, + boundingSphere: ValueCell.create(boundingSphere), + ...color, + ...marker, + ...transform, + + ...Geometry.createValues(p, counts), + dDoubleSided: ValueCell.create(p.doubleSided), + dFlatShaded: ValueCell.create(p.flatShaded), + dFlipSided: ValueCell.create(p.flipSided), + } + } + export function updateValues(values: MeshValues, props: PD.Values<Params>) { const boundingSphere = calculateBoundingSphere( values.aPosition.ref.value, Math.floor(values.aPosition.ref.value.length / 3), diff --git a/src/mol-theme/theme.ts b/src/mol-theme/theme.ts index f52ad6fd7635663b5d0124b77a3cd8d9384bc520..4bd6aa1b08f640168484c60c0d04ee6c57dfb4ba 100644 --- a/src/mol-theme/theme.ts +++ b/src/mol-theme/theme.ts @@ -30,10 +30,7 @@ export interface Theme { type Props = { [k: string]: any } export function createTheme(ctx: ThemeRegistryContext, data: ThemeDataContext, props: Props, theme?: Theme) { - theme = theme || { - color: ColorTheme.Empty, - size: SizeTheme.Empty - } + theme = theme || createEmptyTheme() const colorProps = props.colorTheme as PD.NamedParams const sizeProps = props.sizeTheme as PD.NamedParams @@ -42,4 +39,8 @@ export function createTheme(ctx: ThemeRegistryContext, data: ThemeDataContext, p theme.size = ctx.sizeThemeRegistry.create(sizeProps.name, data, sizeProps.params) return theme +} + +export function createEmptyTheme() { + return { color: ColorTheme.Empty, size: SizeTheme.Empty } } \ No newline at end of file