Skip to content
Snippets Groups Projects
Commit 0815ca69 authored by Alexander Rose's avatar Alexander Rose
Browse files

added invariant bounding sphere, instance bounding sphere to helper

parent 8ef5a2a5
No related branches found
No related tags found
No related merge requests found
......@@ -12,23 +12,24 @@ import { ParamDefinition as PD } from 'mol-util/param-definition';
import Scene from 'mol-gl/scene';
import { WebGLContext } from 'mol-gl/webgl/context';
import { Sphere3D } from 'mol-math/geometry';
import { Vec3, Mat4 } from 'mol-math/linear-algebra';
export const DebugHelperParams = {
sceneBoundingSpheres: PD.Boolean(false, { description: 'Show scene bounding spheres.' }),
objectBoundingSpheres: PD.Boolean(false, { description: 'Show bounding spheres of render objects.' }),
instanceBoundingSpheres: PD.Boolean(false, { description: 'Show bounding spheres of instances.' }),
}
export type DebugHelperParams = typeof DebugHelperParams
export type DebugHelperProps = PD.Values<DebugHelperParams>
type BoundingSphereData = { boundingSphere: Sphere3D, renderObject: RenderObject }
// TODO per-object-transform bounding spheres
export class BoundingSphereHelper {
readonly scene: Scene
private readonly parent: Scene
private _props: DebugHelperProps
private objectsData = new Map<RenderObject, BoundingSphereData>()
private instancesData = new Map<RenderObject, BoundingSphereData>()
private sceneData: BoundingSphereData | undefined
constructor(ctx: WebGLContext, parent: Scene, props: Partial<DebugHelperProps>) {
......@@ -43,9 +44,16 @@ export class BoundingSphereHelper {
const oldRO = new Set<RenderObject>()
this.parent.forEach((r, ro) => {
let objectData = this.objectsData.get(ro)
const objectData = this.objectsData.get(ro)
const newObjectData = updateBoundingSphereData(this.scene, r.boundingSphere, objectData)
if (newObjectData) this.objectsData.set(ro, newObjectData)
if (ro.type === 'mesh' || ro.type === 'lines' || ro.type === 'points') {
const instanceData = this.instancesData.get(ro)
const newInstanceData = updateBoundingSphereData(this.scene, ro.values.invariantBoundingSphere.ref.value, instanceData, ro.values.aTransform.ref.value, ro.values.instanceCount.ref.value)
if (newInstanceData) this.instancesData.set(ro, newInstanceData)
}
oldRO.delete(ro)
})
oldRO.forEach(ro => {
......@@ -65,7 +73,9 @@ export class BoundingSphereHelper {
this.parent.forEach((_, ro) => {
const objectData = this.objectsData.get(ro)
if (objectData) objectData.renderObject.state.visible = ro.state.visible && this._props.objectBoundingSpheres
else console.error('expected to have debug render object')
const instanceData = this.instancesData.get(ro)
if (instanceData) instanceData.renderObject.state.visible = ro.state.visible && this._props.instanceBoundingSpheres
})
}
......@@ -76,7 +86,7 @@ export class BoundingSphereHelper {
}
get isEnabled() {
return this._props.sceneBoundingSpheres || this._props.objectBoundingSpheres
return this._props.sceneBoundingSpheres || this._props.objectBoundingSpheres || this._props.instanceBoundingSpheres
}
get props() { return this._props as Readonly<DebugHelperProps> }
......@@ -86,21 +96,28 @@ export class BoundingSphereHelper {
}
}
function updateBoundingSphereData(scene: Scene, boundingSphere: Sphere3D, data?: BoundingSphereData) {
function updateBoundingSphereData(scene: Scene, boundingSphere: Sphere3D, data: BoundingSphereData | undefined, transform?: Float32Array, transformCount?: number) {
if (!data || !Sphere3D.exactEquals(data.boundingSphere, boundingSphere)) {
if (data) scene.remove(data.renderObject)
const renderObject = createBoundingSphereRenderObject(boundingSphere)
const renderObject = createBoundingSphereRenderObject(boundingSphere, transform, transformCount)
scene.add(renderObject)
return { boundingSphere, renderObject }
}
}
function createBoundingSphereRenderObject(boundingSphere: Sphere3D) {
const tmpCenter = Vec3.zero()
const tmpM = Mat4.identity()
function createBoundingSphereRenderObject(boundingSphere: Sphere3D, transform?: Float32Array, transformCount?: number) {
const builderState = MeshBuilder.createState(1024, 512)
if (boundingSphere.radius) {
addSphere(builderState, boundingSphere.center, boundingSphere.radius, 2)
} else if (isNaN(boundingSphere.radius)) {
console.warn('boundingSphere.radius is NaN')
if (transform && transformCount) {
// TODO create instanced mesh?
for (let i = 0, _i = transformCount; i < _i; ++i) {
Mat4.fromArray(tmpM, transform, i * 16)
Vec3.transformMat4(tmpCenter, boundingSphere.center, tmpM)
if (boundingSphere.radius) addSphere(builderState, tmpCenter, boundingSphere.radius, 1)
}
} else {
if (boundingSphere.radius) addSphere(builderState, boundingSphere.center, boundingSphere.radius, 2)
}
const mesh = MeshBuilder.getMesh(builderState)
const values = Mesh.createValuesSimple(mesh, { alpha: 0.1, doubleSided: false })
......
......@@ -91,7 +91,7 @@ export namespace DirectVolume {
const counts = { drawCount: VolumeBox.indices.length, groupCount, instanceCount }
const boundingSphere = getBoundingSphere(gridDimension.ref.value, gridTransform.ref.value, transform.aTransform.ref.value, transform.instanceCount.ref.value)
const { boundingSphere, invariantBoundingSphere } = getBoundingSphere(gridDimension.ref.value, gridTransform.ref.value, transform.aTransform.ref.value, transform.instanceCount.ref.value)
const controlPoints = getControlPointsFromVec2Array(props.controlPoints)
const transferTex = createTransferFunctionTexture(controlPoints, props.list)
......@@ -107,6 +107,7 @@ export namespace DirectVolume {
aPosition: ValueCell.create(VolumeBox.vertices as Float32Array),
elements: ValueCell.create(VolumeBox.indices as Uint32Array),
boundingSphere: ValueCell.create(boundingSphere),
invariantBoundingSphere: ValueCell.create(invariantBoundingSphere),
uIsoValue: ValueCell.create(props.isoValue),
uBboxMin: bboxMin,
......@@ -135,10 +136,13 @@ export namespace DirectVolume {
}
export function updateBoundingSphere(values: DirectVolumeValues, directVolume: DirectVolume) {
const boundingSphere = getBoundingSphere(values.uGridDim.ref.value, values.uTransform.ref.value, values.aTransform.ref.value, values.instanceCount.ref.value)
const { boundingSphere, invariantBoundingSphere } = getBoundingSphere(values.uGridDim.ref.value, values.uTransform.ref.value, values.aTransform.ref.value, values.instanceCount.ref.value)
if (!Sphere3D.equals(boundingSphere, values.boundingSphere.ref.value)) {
ValueCell.update(values.boundingSphere, boundingSphere)
}
if (!Sphere3D.equals(invariantBoundingSphere, values.invariantBoundingSphere.ref.value)) {
ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere)
}
}
export function createRenderableState(props: PD.Values<Params>): RenderableState {
......
......@@ -106,17 +106,9 @@ export namespace Lines {
const counts = { drawCount: lines.lineCount * 2 * 3, groupCount, instanceCount }
const boundingSphere = Sphere3D.addSphere(
calculateBoundingSphere(
lines.startBuffer.ref.value, lines.lineCount,
transform.aTransform.ref.value, transform.instanceCount.ref.value
),
calculateBoundingSphere(
lines.startBuffer.ref.value, lines.lineCount,
transform.aTransform.ref.value, transform.instanceCount.ref.value
)
)
const { boundingSphere, invariantBoundingSphere } = getBoundingSphere(lines.startBuffer.ref.value, lines.endBuffer.ref.value, lines.lineCount,
transform.aTransform.ref.value, transform.instanceCount.ref.value)
return {
aMapping: lines.mappingBuffer,
aGroup: lines.groupBuffer,
......@@ -124,6 +116,7 @@ export namespace Lines {
aEnd: lines.endBuffer,
elements: lines.indexBuffer,
boundingSphere: ValueCell.create(boundingSphere),
invariantBoundingSphere: ValueCell.create(invariantBoundingSphere),
...color,
...size,
...marker,
......@@ -142,18 +135,22 @@ export namespace Lines {
}
export function updateBoundingSphere(values: LinesValues, lines: Lines) {
const boundingSphere = Sphere3D.addSphere(
calculateBoundingSphere(
values.aStart.ref.value, lines.lineCount,
values.aTransform.ref.value, values.instanceCount.ref.value
),
calculateBoundingSphere(
values.aEnd.ref.value, lines.lineCount,
values.aTransform.ref.value, values.instanceCount.ref.value
),
)
const { boundingSphere, invariantBoundingSphere } = getBoundingSphere(values.aStart.ref.value, values.aEnd.ref.value, lines.lineCount,
values.aTransform.ref.value, values.instanceCount.ref.value)
if (!Sphere3D.equals(boundingSphere, values.boundingSphere.ref.value)) {
ValueCell.update(values.boundingSphere, boundingSphere)
}
if (!Sphere3D.equals(invariantBoundingSphere, values.invariantBoundingSphere.ref.value)) {
ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere)
}
}
}
function getBoundingSphere(lineStart: Float32Array, lineEnd: Float32Array, lineCount: number, transform: Float32Array, transformCount: number) {
const start = calculateBoundingSphere(lineStart, lineCount, transform, transformCount)
const end = calculateBoundingSphere(lineEnd, lineCount, transform, transformCount)
return {
boundingSphere: Sphere3D.addSphere(start.boundingSphere, end.boundingSphere),
invariantBoundingSphere: Sphere3D.addSphere(start.invariantBoundingSphere, end.invariantBoundingSphere)
}
}
\ No newline at end of file
......@@ -356,7 +356,7 @@ export namespace Mesh {
const counts = { drawCount: mesh.triangleCount * 3, groupCount, instanceCount }
const boundingSphere = calculateBoundingSphere(
const { boundingSphere, invariantBoundingSphere } = calculateBoundingSphere(
mesh.vertexBuffer.ref.value, mesh.vertexCount,
transform.aTransform.ref.value, transform.instanceCount.ref.value
)
......@@ -367,6 +367,7 @@ export namespace Mesh {
aGroup: mesh.groupBuffer,
elements: mesh.indexBuffer,
boundingSphere: ValueCell.create(boundingSphere),
invariantBoundingSphere: ValueCell.create(invariantBoundingSphere),
...color,
...marker,
...transform,
......@@ -386,7 +387,7 @@ export namespace Mesh {
const counts = { drawCount: mesh.triangleCount * 3, groupCount: 1, instanceCount: 1 }
const boundingSphere = calculateBoundingSphere(
const { boundingSphere, invariantBoundingSphere } = calculateBoundingSphere(
mesh.vertexBuffer.ref.value, mesh.vertexCount,
transform.aTransform.ref.value, transform.instanceCount.ref.value
)
......@@ -397,6 +398,7 @@ export namespace Mesh {
aGroup: mesh.groupBuffer,
elements: mesh.indexBuffer,
boundingSphere: ValueCell.create(boundingSphere),
invariantBoundingSphere: ValueCell.create(invariantBoundingSphere),
...color,
...marker,
...transform,
......@@ -416,13 +418,16 @@ export namespace Mesh {
}
export function updateBoundingSphere(values: MeshValues, mesh: Mesh) {
const boundingSphere = calculateBoundingSphere(
const { boundingSphere, invariantBoundingSphere } = calculateBoundingSphere(
values.aPosition.ref.value, mesh.vertexCount,
values.aTransform.ref.value, values.instanceCount.ref.value
)
if (!Sphere3D.equals(boundingSphere, values.boundingSphere.ref.value)) {
ValueCell.update(values.boundingSphere, boundingSphere)
}
if (!Sphere3D.equals(invariantBoundingSphere, values.invariantBoundingSphere.ref.value)) {
ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere)
}
}
}
......
......@@ -71,7 +71,7 @@ export namespace Points {
const counts = { drawCount: points.pointCount, groupCount, instanceCount }
const boundingSphere = calculateBoundingSphere(
const { boundingSphere, invariantBoundingSphere } = calculateBoundingSphere(
points.centerBuffer.ref.value, points.pointCount,
transform.aTransform.ref.value, transform.instanceCount.ref.value
)
......@@ -80,6 +80,7 @@ export namespace Points {
aPosition: points.centerBuffer,
aGroup: points.groupBuffer,
boundingSphere: ValueCell.create(boundingSphere),
invariantBoundingSphere: ValueCell.create(invariantBoundingSphere),
...color,
...size,
...marker,
......@@ -100,13 +101,16 @@ export namespace Points {
}
export function updateBoundingSphere(values: PointsValues, points: Points) {
const boundingSphere = calculateBoundingSphere(
const { boundingSphere, invariantBoundingSphere } = calculateBoundingSphere(
values.aPosition.ref.value, points.pointCount,
values.aTransform.ref.value, values.instanceCount.ref.value
)
if (!Sphere3D.equals(boundingSphere, values.boundingSphere.ref.value)) {
ValueCell.update(values.boundingSphere, boundingSphere)
}
if (!Sphere3D.equals(invariantBoundingSphere, values.invariantBoundingSphere.ref.value)) {
ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere)
}
}
export function createRenderableState(props: PD.Values<Params>): RenderableState {
......
......@@ -29,12 +29,12 @@ describe('renderable', () => {
2, 0, 0, 0
])
const bs = calculateBoundingSphere(
const { boundingSphere } = calculateBoundingSphere(
position, position.length / 3,
transform, transform.length / 16
)
expect(bs.radius).toBe(1.5)
expect(bs.center).toEqual([1.5, 0.0, 0.0])
expect(boundingSphere.radius).toBe(1.5)
expect(boundingSphere.center).toEqual([1.5, 0.0, 0.0])
})
})
......@@ -58,6 +58,7 @@ function createPoints() {
Mat4.toArray(m4, aTransform.ref.value, 0)
const boundingSphere = ValueCell.create(Sphere3D.create(Vec3.zero(), 2))
const invariantBoundingSphere = ValueCell.create(Sphere3D.create(Vec3.zero(), 2))
const values: PointsValues = {
aPosition,
......@@ -77,6 +78,7 @@ function createPoints() {
drawCount: ValueCell.create(3),
instanceCount: ValueCell.create(1),
boundingSphere,
invariantBoundingSphere,
dPointSizeAttenuation: ValueCell.create(true),
dPointFilledCircle: ValueCell.create(false),
......
......@@ -29,6 +29,7 @@ export const DirectVolumeSchema = {
drawCount: ValueSpec('number'),
instanceCount: ValueSpec('number'),
boundingSphere: ValueSpec('sphere'),
invariantBoundingSphere: ValueSpec('sphere'),
aPosition: AttributeSpec('float32', 3, 0),
elements: ElementsSpec('uint32'),
......
......@@ -199,6 +199,7 @@ export const BaseSchema = {
drawCount: ValueSpec('number'),
instanceCount: ValueSpec('number'),
boundingSphere: ValueSpec('sphere'),
invariantBoundingSphere: ValueSpec('sphere'),
dUseFog: DefineSpec('boolean'),
}
......
......@@ -55,7 +55,7 @@ export function calculateBoundingSphereFromValues(values: PositionValues) {
return calculateBoundingSphere(position, positionCount, transform, transformCount)
}
export function calculateBoundingSphere(position: Float32Array, positionCount: number, transform: Float32Array, transformCount: number): Sphere3D {
export function calculateBoundingSphere(position: Float32Array, positionCount: number, transform: Float32Array, transformCount: number): { boundingSphere: Sphere3D, invariantBoundingSphere: Sphere3D } {
const m = Mat4.zero()
......@@ -105,5 +105,5 @@ export function calculateBoundingSphere(position: Float32Array, positionCount: n
radius = Math.max(radius, Vec3.distance(center, ct) + r)
}
return { center, radius };
return { boundingSphere: { center, radius }, invariantBoundingSphere: { center: c, radius: r } };
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment