mirror of
https://github.com/visgl/luma.gl.git
synced 2025-12-08 17:36:19 +00:00
Add getBounds() to ScenegraphNode (#1733)
This commit is contained in:
parent
9e235e1ca8
commit
7eb9f2eaad
@ -46,6 +46,10 @@ var node = new Model(gl, props);
|
||||
|
||||
Note that setting orientation props does not actually update the object's matrix. `update()` must be called.
|
||||
|
||||
### getBounds() : [min: number[], max: number[]] | null
|
||||
|
||||
Calculate the bounding box of the node.
|
||||
|
||||
### update() - DEPRECATED
|
||||
|
||||
Update the model matrix. Useful to update changes to the `position`, `rotation` or `scale` properties.
|
||||
|
||||
@ -125,7 +125,7 @@ export class GLTFInstantiator {
|
||||
? gltfPrimitive.indices.count
|
||||
: this.getVertexCount(gltfPrimitive.attributes);
|
||||
|
||||
return createGLTFModel(
|
||||
const model = createGLTFModel(
|
||||
this.device,
|
||||
{
|
||||
id: gltfPrimitive.name || `${gltfMesh.name || gltfMesh.id}-primitive-${i}`,
|
||||
@ -136,6 +136,9 @@ export class GLTFInstantiator {
|
||||
...this.options
|
||||
}
|
||||
);
|
||||
model.bounds = [gltfPrimitive.attributes.POSITION.min, gltfPrimitive.attributes.POSITION.max];
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
getVertexCount(attributes: any) {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import {Matrix4} from '@math.gl/core';
|
||||
import {Matrix4, Vector3} from '@math.gl/core';
|
||||
import {log} from '@luma.gl/api';
|
||||
import {ScenegraphNode, ScenegraphNodeProps} from './scenegraph-node';
|
||||
|
||||
@ -23,6 +23,40 @@ export class GroupNode extends ScenegraphNode {
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
override getBounds(): [number[], number[]] | null {
|
||||
const result: [number[], number[]] = [[Infinity, Infinity, Infinity], [-Infinity, -Infinity, -Infinity]];
|
||||
|
||||
this.traverse((node, {worldMatrix}) => {
|
||||
const bounds = node.getBounds();
|
||||
if (!bounds) {
|
||||
return;
|
||||
}
|
||||
const [min, max] = bounds;
|
||||
const center = new Vector3(min).add(max).divide([2, 2, 2]);
|
||||
worldMatrix.transformAsPoint(center, center);
|
||||
const halfSize = new Vector3(max).subtract(min).divide([2, 2, 2]);
|
||||
worldMatrix.transformAsVector(halfSize, halfSize);
|
||||
|
||||
for (let v = 0; v < 8; v++) {
|
||||
// Test all 8 corners of the box
|
||||
const position = new Vector3(
|
||||
v & 0b001 ? -1 : 1,
|
||||
v & 0b010 ? -1 : 1,
|
||||
v & 0b100 ? -1 : 1
|
||||
).multiply(halfSize).add(center);
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
result[0][i] = Math.min(result![0][i], position[i]);
|
||||
result[1][i] = Math.max(result![1][i], position[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!Number.isFinite(result[0][0])) {
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
override destroy(): void {
|
||||
this.children.forEach((child) => child.destroy());
|
||||
this.removeAll();
|
||||
@ -55,7 +89,7 @@ export class GroupNode extends ScenegraphNode {
|
||||
return this;
|
||||
}
|
||||
|
||||
traverse(visitor, {worldMatrix = new Matrix4()} = {}) {
|
||||
traverse(visitor: (node: ScenegraphNode, context: {worldMatrix: Matrix4}) => void, {worldMatrix = new Matrix4()} = {}) {
|
||||
const modelMatrix = new Matrix4(worldMatrix).multiplyRight(this.matrix);
|
||||
|
||||
for (const child of this.children) {
|
||||
|
||||
@ -8,6 +8,7 @@ export type ModelNodeProps = ScenegraphNodeProps & ModelProps & {
|
||||
|
||||
export class ModelNode extends ScenegraphNode {
|
||||
readonly model: Model;
|
||||
bounds: [number[], number[]] | null = null;
|
||||
|
||||
AfterRender = null;
|
||||
managedResources: any[];
|
||||
@ -38,6 +39,10 @@ export class ModelNode extends ScenegraphNode {
|
||||
return this;
|
||||
}
|
||||
|
||||
override getBounds(): [number[], number[]] | null {
|
||||
return this.bounds;
|
||||
}
|
||||
|
||||
override destroy(): void {
|
||||
if (this.model) {
|
||||
this.model.delete();
|
||||
|
||||
@ -31,6 +31,10 @@ export class ScenegraphNode {
|
||||
this._setScenegraphNodeProps(props);
|
||||
}
|
||||
|
||||
getBounds(): [number[], number[]] | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
destroy(): void {}
|
||||
|
||||
/** @deprecated use .destroy() */
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
// luma.gl, MIT license
|
||||
|
||||
import test from 'tape-promise/tape';
|
||||
import {GroupNode, ScenegraphNode} from '@luma.gl/experimental';
|
||||
import {GroupNode, ScenegraphNode, ModelNode} from '@luma.gl/experimental';
|
||||
import {Matrix4} from '@math.gl/core';
|
||||
import {fixture} from 'test/setup';
|
||||
import {DUMMY_VS, DUMMY_FS} from './model-node.spec';
|
||||
|
||||
const {gl} = fixture;
|
||||
|
||||
test('GroupNode#construction', (t) => {
|
||||
const grandChild = new ScenegraphNode();
|
||||
@ -102,3 +106,34 @@ test('GroupNode#traverse', (t) => {
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('GroupNode#getBounds', (t) => {
|
||||
const matrix = new Matrix4().translate([0, 0, 1]).scale(2);
|
||||
|
||||
const childSNode = new ModelNode(gl, {id: 'childSNode', vs: DUMMY_VS, fs: DUMMY_FS});
|
||||
const grandChildSNode = new ModelNode(gl, {id: 'grandChildSNode', vs: DUMMY_VS, fs: DUMMY_FS});
|
||||
const child1 = new GroupNode({id: 'child-1', matrix, children: [grandChildSNode]});
|
||||
const groupNode = new GroupNode({id: 'parent', matrix, children: [child1, childSNode]});
|
||||
|
||||
t.deepEqual(groupNode.getBounds(), null, 'child bounds are not defined');
|
||||
|
||||
childSNode.bounds = [
|
||||
[0, 0, 0],
|
||||
[1, 1, 1]
|
||||
];
|
||||
grandChildSNode.bounds = [
|
||||
[-1, -1, -1],
|
||||
[0, 0, 0]
|
||||
];
|
||||
|
||||
t.deepEqual(
|
||||
groupNode.getBounds(),
|
||||
[
|
||||
[-4, -4, -1],
|
||||
[2, 2, 3]
|
||||
],
|
||||
'bounds calculated'
|
||||
);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
@ -6,11 +6,11 @@ import {makeSpy} from '@probe.gl/test-utils';
|
||||
import {Model} from '@luma.gl/webgl-legacy';
|
||||
import {ModelNode} from '@luma.gl/experimental';
|
||||
|
||||
const DUMMY_VS = `
|
||||
export const DUMMY_VS = `
|
||||
void main() { gl_Position = vec4(1.0); }
|
||||
`;
|
||||
|
||||
const DUMMY_FS = `
|
||||
export const DUMMY_FS = `
|
||||
precision highp float;
|
||||
void main() { gl_FragColor = vec4(1.0); }
|
||||
`;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user