diff --git a/src/mol-canvas3d/helper/bounding-sphere-helper.ts b/src/mol-canvas3d/helper/bounding-sphere-helper.ts index 78dcca7ba9e5ff5c4f5ab28ca30b21431adc4a6e..1101e7881740dd54b9545f0abc88d72dfe3e4f90 100644 --- a/src/mol-canvas3d/helper/bounding-sphere-helper.ts +++ b/src/mol-canvas3d/helper/bounding-sphere-helper.ts @@ -15,6 +15,9 @@ import { Sphere3D } from 'mol-math/geometry'; import { Color } from 'mol-util/color'; import { ColorNames } from 'mol-util/color/tables'; import { TransformData } from 'mol-geo/geometry/transform-data'; +import { sphereVertexCount } from 'mol-geo/primitive/sphere'; +import { ValueCell } from 'mol-util'; +import { Geometry } from 'mol-geo/geometry/geometry'; export const DebugHelperParams = { sceneBoundingSpheres: PD.Boolean(false, { description: 'Show scene bounding spheres.' }), @@ -24,10 +27,11 @@ export const DebugHelperParams = { export type DebugHelperParams = typeof DebugHelperParams export type DebugHelperProps = PD.Values<DebugHelperParams> -type BoundingSphereData = { boundingSphere: Sphere3D, renderObject: RenderObject } +type BoundingSphereData = { boundingSphere: Sphere3D, renderObject: RenderObject, mesh: Mesh } export class BoundingSphereHelper { readonly scene: Scene + private readonly parent: Scene private _props: DebugHelperProps private objectsData = new Map<RenderObject, BoundingSphereData>() @@ -44,9 +48,6 @@ export class BoundingSphereHelper { const newSceneData = updateBoundingSphereData(this.scene, this.parent.boundingSphere, this.sceneData, ColorNames.grey) if (newSceneData) this.sceneData = newSceneData - const oldRO = new Set<RenderObject>() - this.objectsData.forEach((_, ro) => oldRO.add(ro)) - this.instancesData.forEach((_, ro) => oldRO.add(ro)) this.parent.forEach((r, ro) => { const objectData = this.objectsData.get(ro) const newObjectData = updateBoundingSphereData(this.scene, r.boundingSphere, objectData, ColorNames.tomato) @@ -63,17 +64,16 @@ export class BoundingSphereHelper { }) if (newInstanceData) this.instancesData.set(ro, newInstanceData) } - - oldRO.delete(ro) }) - oldRO.forEach(ro => { - const objectData = this.objectsData.get(ro) - if (objectData) { + + this.objectsData.forEach((objectData, ro) => { + if (!this.parent.has(ro)) { this.scene.remove(objectData.renderObject) this.objectsData.delete(ro) } - const instanceData = this.instancesData.get(ro) - if (instanceData) { + }) + this.instancesData.forEach((instanceData, ro) => { + if (!this.parent.has(ro)) { this.scene.remove(instanceData.renderObject) this.instancesData.delete(ro) } @@ -83,7 +83,7 @@ export class BoundingSphereHelper { } syncVisibility() { - if(this.sceneData) { + if (this.sceneData) { this.sceneData.renderObject.state.visible = this._props.sceneBoundingSpheres } @@ -114,18 +114,27 @@ export class BoundingSphereHelper { } function updateBoundingSphereData(scene: Scene, boundingSphere: Sphere3D, data: BoundingSphereData | undefined, color: Color, transform?: TransformData) { - if (!data || !Sphere3D.exactEquals(data.boundingSphere, boundingSphere)) { - if (data) scene.remove(data.renderObject) - const renderObject = createBoundingSphereRenderObject(boundingSphere, color, transform) - scene.add(renderObject) - return { boundingSphere: Sphere3D.clone(boundingSphere), renderObject } + if (!data || !Sphere3D.equals(data.boundingSphere, boundingSphere)) { + const mesh = createBoundingSphereMesh(boundingSphere, data && data.mesh) + const renderObject = data ? data.renderObject : createBoundingSphereRenderObject(mesh, color, transform) + if (data) { + ValueCell.update(renderObject.values.drawCount, Geometry.getDrawCount(mesh)) + } else { + scene.add(renderObject) + } + return { boundingSphere: Sphere3D.clone(boundingSphere), renderObject, mesh } } } -function createBoundingSphereRenderObject(boundingSphere: Sphere3D, color: Color, transform?: TransformData) { - const builderState = MeshBuilder.createState(1024, 512) - if (boundingSphere.radius) addSphere(builderState, boundingSphere.center, boundingSphere.radius, 2) - const mesh = MeshBuilder.getMesh(builderState) +function createBoundingSphereMesh(boundingSphere: Sphere3D, mesh?: Mesh) { + const detail = 2 + const vertexCount = sphereVertexCount(detail) + const builderState = MeshBuilder.createState(vertexCount, vertexCount / 2, mesh) + if (boundingSphere.radius) addSphere(builderState, boundingSphere.center, boundingSphere.radius, detail) + return MeshBuilder.getMesh(builderState) +} + +function createBoundingSphereRenderObject(mesh: Mesh, color: Color, transform?: TransformData) { const values = Mesh.createValuesSimple(mesh, { alpha: 0.1, doubleSided: false }, color, transform) return createMeshRenderObject(values, { visible: true, pickable: false, opaque: false }) } \ No newline at end of file diff --git a/src/mol-geo/geometry/transform-data.ts b/src/mol-geo/geometry/transform-data.ts index 9c4b093c359ab71a6e1eb72e6155145ea27b0500..993c279c564fc208b1c798e16c48c5bb0f7b2ff1 100644 --- a/src/mol-geo/geometry/transform-data.ts +++ b/src/mol-geo/geometry/transform-data.ts @@ -19,6 +19,7 @@ export type TransformData = { export function createTransform(transformArray: Float32Array, instanceCount: number, transformData?: TransformData): TransformData { if (transformData) { ValueCell.update(transformData.aTransform, transformArray) + ValueCell.update(transformData.transform, new Float32Array(transformArray)) ValueCell.update(transformData.uInstanceCount, instanceCount) ValueCell.update(transformData.instanceCount, instanceCount) const aInstance = transformData.aInstance.ref.value.length >= instanceCount ? transformData.aInstance.ref.value : new Float32Array(instanceCount) @@ -38,7 +39,7 @@ export function createTransform(transformArray: Float32Array, instanceCount: num const identityTransform = new Float32Array(16) Mat4.toArray(Mat4.identity(), identityTransform, 0) export function createIdentityTransform(transformData?: TransformData): TransformData { - return createTransform(identityTransform, 1, transformData) + return createTransform(new Float32Array(identityTransform), 1, transformData) } const tmpTransformMat4 = Mat4.identity() diff --git a/src/mol-gl/scene.ts b/src/mol-gl/scene.ts index 3c58bd0bbbb11f0fc6c95292efb0ec93fddc5a34..5e7b9a8ff291ccbbb3fb0b1398b95fe99f9d3e67 100644 --- a/src/mol-gl/scene.ts +++ b/src/mol-gl/scene.ts @@ -27,7 +27,7 @@ function calculateBoundingSphere(renderables: Renderable<RenderableValues & Base const r = renderables[i] if (!r.boundingSphere.radius) continue; boundaryHelper.extendStep(r.boundingSphere.center, r.boundingSphere.radius); - }; + } Vec3.copy(boundingSphere.center, boundaryHelper.center); boundingSphere.radius = boundaryHelper.radius; @@ -43,6 +43,7 @@ interface Scene extends Object3D { update: (keepBoundingSphere?: boolean) => void add: (o: RenderObject) => void remove: (o: RenderObject) => void + has: (o: RenderObject) => boolean clear: () => void forEach: (callbackFn: (value: Renderable<any>, key: RenderObject) => void) => void } @@ -89,6 +90,9 @@ namespace Scene { boundingSphereDirty = true } }, + has: (o: RenderObject) => { + return renderableMap.has(o) + }, clear: () => { for (let i = 0, il = renderables.length; i < il; ++i) { renderables[i].dispose()