@awayjs/view
Version:
View for AwayJS
123 lines (95 loc) • 3.63 kB
text/typescript
import { Box, Matrix3D, PlaneClassification, Plane3D, Vector3D } from '@awayjs/core';
import { BoundingVolumeBase } from './BoundingVolumeBase';
import { BoundingVolumePool } from './BoundingVolumePool';
import { ContainerNode } from '../partition/ContainerNode';
/**
* BoundingBox represents a bounding box volume that has its planes aligned to the local coordinate axes of the bounded object.
* This is useful for most sprites.
*/
export class BoundingBox extends BoundingVolumeBase {
private _box: Box;
private _centerX: number = 0;
private _centerY: number = 0;
private _centerZ: number = 0;
private _halfExtentsX: number = 0;
private _halfExtentsY: number = 0;
private _halfExtentsZ: number = 0;
/**
* @inheritDoc
*/
public nullify(): void {
this._centerX = this._centerY = this._centerZ = 0;
this._halfExtentsX = this._halfExtentsY = this._halfExtentsZ = 0;
}
/**
* @inheritDoc
*/
public isInFrustum(planes: Array<Plane3D>, numPlanes: number): boolean {
if (this._invalid)
this._update();
if (this._box == null)
return;
for (let i: number = 0; i < numPlanes; ++i) {
const plane: Plane3D = planes[i];
const a: number = plane.a;
const b: number = plane.b;
const c: number = plane.c;
const flippedExtentX: number = a < 0 ? -this._halfExtentsX : this._halfExtentsX;
const flippedExtentY: number = b < 0 ? -this._halfExtentsY : this._halfExtentsY;
const flippedExtentZ: number = c < 0 ? -this._halfExtentsZ : this._halfExtentsZ;
const projDist: number = a * (this._centerX + flippedExtentX) + b * (this._centerY + flippedExtentY) + c * (this._centerZ + flippedExtentZ) - plane.d;
if (projDist < 0)
return false;
}
return true;
}
public rayIntersection(position: Vector3D, direction: Vector3D, targetNormal: Vector3D): number {
if (this._invalid)
this._update();
if (this._box == null)
return -1;
return this._box.rayIntersection(position, direction, targetNormal);
}
public getBox(): Box {
if (this._invalid)
this._update();
return this._box;
}
public classifyToPlane(plane: Plane3D): number {
let a: number = plane.a;
let b: number = plane.b;
let c: number = plane.c;
const centerDistance: number = a * this._centerX + b * this._centerY + c * this._centerZ - plane.d;
if (a < 0)
a = -a;
if (b < 0)
b = -b;
if (c < 0)
c = -c;
const boundOffset: number = a * this._halfExtentsX + b * this._halfExtentsY + c * this._halfExtentsZ;
return centerDistance > boundOffset ? PlaneClassification.FRONT : centerDistance < -boundOffset ? PlaneClassification.BACK : PlaneClassification.INTERSECT;
}
public _update(): void {
super._update();
const targetCoordinateSpace: ContainerNode = <ContainerNode> this._asset;
const picker = (<BoundingVolumePool> this._pool).picker;
// a null invTargetMatrix means local coords to the node
const invTargetMatrix: Matrix3D = (targetCoordinateSpace != picker.node)
? targetCoordinateSpace.getInverseMatrix3D()
: null;
this._box = picker._getBoxBoundsInternal(invTargetMatrix, this._strokeFlag, this._fastFlag, this._box);
if (this._box == null)
return;
this._halfExtentsX = this._box.width / 2;
this._halfExtentsY = this._box.height / 2;
this._halfExtentsZ = this._box.depth / 2;
this._centerX = this._box.x + this._halfExtentsX;
this._centerY = this._box.y + this._halfExtentsY;
this._centerZ = this._box.z + this._halfExtentsZ;
}
// public _createBoundsPrimitive():Sprite
// {
// this._prefab = new PrimitiveCubePrefab(null, ElementsType.LINE);
// return <Sprite> this._prefab.getNewObject();
// }
}