@openhps/core
Version:
Open Hybrid Positioning System - Core component
302 lines (251 loc) • 10.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.CameraHelper = void 0;
var _Camera = require("../cameras/Camera.js");
var _Vector = require("../math/Vector3.js");
var _LineSegments = require("../objects/LineSegments.js");
var _Color = require("../math/Color.js");
var _LineBasicMaterial = require("../materials/LineBasicMaterial.js");
var _BufferGeometry = require("../core/BufferGeometry.js");
var _BufferAttribute = require("../core/BufferAttribute.js");
var _constants = require("../constants.js");
const _vector = /*@__PURE__*/new _Vector.Vector3();
const _camera = /*@__PURE__*/new _Camera.Camera();
/**
* This helps with visualizing what a camera contains in its frustum. It
* visualizes the frustum of a camera using a line segments.
*
* Based on frustum visualization in [lightgl.js shadowmap example]{@link https://github.com/evanw/lightgl.js/blob/master/tests/shadowmap.html}.
*
* `CameraHelper` must be a child of the scene.
*
* ```js
* const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
* const helper = new THREE.CameraHelper( camera );
* scene.add( helper );
* ```
*
* @augments LineSegments
*/
class CameraHelper extends _LineSegments.LineSegments {
/**
* Constructs a new arrow helper.
*
* @param {Camera} camera - The camera to visualize.
*/
constructor(camera) {
const geometry = new _BufferGeometry.BufferGeometry();
const material = new _LineBasicMaterial.LineBasicMaterial({
color: 0xffffff,
vertexColors: true,
toneMapped: false
});
const vertices = [];
const colors = [];
const pointMap = {};
// near
addLine('n1', 'n2');
addLine('n2', 'n4');
addLine('n4', 'n3');
addLine('n3', 'n1');
// far
addLine('f1', 'f2');
addLine('f2', 'f4');
addLine('f4', 'f3');
addLine('f3', 'f1');
// sides
addLine('n1', 'f1');
addLine('n2', 'f2');
addLine('n3', 'f3');
addLine('n4', 'f4');
// cone
addLine('p', 'n1');
addLine('p', 'n2');
addLine('p', 'n3');
addLine('p', 'n4');
// up
addLine('u1', 'u2');
addLine('u2', 'u3');
addLine('u3', 'u1');
// target
addLine('c', 't');
addLine('p', 'c');
// cross
addLine('cn1', 'cn2');
addLine('cn3', 'cn4');
addLine('cf1', 'cf2');
addLine('cf3', 'cf4');
function addLine(a, b) {
addPoint(a);
addPoint(b);
}
function addPoint(id) {
vertices.push(0, 0, 0);
colors.push(0, 0, 0);
if (pointMap[id] === undefined) {
pointMap[id] = [];
}
pointMap[id].push(vertices.length / 3 - 1);
}
geometry.setAttribute('position', new _BufferAttribute.Float32BufferAttribute(vertices, 3));
geometry.setAttribute('color', new _BufferAttribute.Float32BufferAttribute(colors, 3));
super(geometry, material);
this.type = 'CameraHelper';
/**
* The camera being visualized.
*
* @type {Camera}
*/
this.camera = camera;
if (this.camera.updateProjectionMatrix) this.camera.updateProjectionMatrix();
this.matrix = camera.matrixWorld;
this.matrixAutoUpdate = false;
/**
* This contains the points used to visualize the camera.
*
* @type {Object<string,Array<number>>}
*/
this.pointMap = pointMap;
this.update();
// colors
const colorFrustum = new _Color.Color(0xffaa00);
const colorCone = new _Color.Color(0xff0000);
const colorUp = new _Color.Color(0x00aaff);
const colorTarget = new _Color.Color(0xffffff);
const colorCross = new _Color.Color(0x333333);
this.setColors(colorFrustum, colorCone, colorUp, colorTarget, colorCross);
}
/**
* Defines the colors of the helper.
*
* @param {Color} frustum - The frustum line color.
* @param {Color} cone - The cone line color.
* @param {Color} up - The up line color.
* @param {Color} target - The target line color.
* @param {Color} cross - The cross line color.
*/
setColors(frustum, cone, up, target, cross) {
const geometry = this.geometry;
const colorAttribute = geometry.getAttribute('color');
// near
colorAttribute.setXYZ(0, frustum.r, frustum.g, frustum.b);
colorAttribute.setXYZ(1, frustum.r, frustum.g, frustum.b); // n1, n2
colorAttribute.setXYZ(2, frustum.r, frustum.g, frustum.b);
colorAttribute.setXYZ(3, frustum.r, frustum.g, frustum.b); // n2, n4
colorAttribute.setXYZ(4, frustum.r, frustum.g, frustum.b);
colorAttribute.setXYZ(5, frustum.r, frustum.g, frustum.b); // n4, n3
colorAttribute.setXYZ(6, frustum.r, frustum.g, frustum.b);
colorAttribute.setXYZ(7, frustum.r, frustum.g, frustum.b); // n3, n1
// far
colorAttribute.setXYZ(8, frustum.r, frustum.g, frustum.b);
colorAttribute.setXYZ(9, frustum.r, frustum.g, frustum.b); // f1, f2
colorAttribute.setXYZ(10, frustum.r, frustum.g, frustum.b);
colorAttribute.setXYZ(11, frustum.r, frustum.g, frustum.b); // f2, f4
colorAttribute.setXYZ(12, frustum.r, frustum.g, frustum.b);
colorAttribute.setXYZ(13, frustum.r, frustum.g, frustum.b); // f4, f3
colorAttribute.setXYZ(14, frustum.r, frustum.g, frustum.b);
colorAttribute.setXYZ(15, frustum.r, frustum.g, frustum.b); // f3, f1
// sides
colorAttribute.setXYZ(16, frustum.r, frustum.g, frustum.b);
colorAttribute.setXYZ(17, frustum.r, frustum.g, frustum.b); // n1, f1
colorAttribute.setXYZ(18, frustum.r, frustum.g, frustum.b);
colorAttribute.setXYZ(19, frustum.r, frustum.g, frustum.b); // n2, f2
colorAttribute.setXYZ(20, frustum.r, frustum.g, frustum.b);
colorAttribute.setXYZ(21, frustum.r, frustum.g, frustum.b); // n3, f3
colorAttribute.setXYZ(22, frustum.r, frustum.g, frustum.b);
colorAttribute.setXYZ(23, frustum.r, frustum.g, frustum.b); // n4, f4
// cone
colorAttribute.setXYZ(24, cone.r, cone.g, cone.b);
colorAttribute.setXYZ(25, cone.r, cone.g, cone.b); // p, n1
colorAttribute.setXYZ(26, cone.r, cone.g, cone.b);
colorAttribute.setXYZ(27, cone.r, cone.g, cone.b); // p, n2
colorAttribute.setXYZ(28, cone.r, cone.g, cone.b);
colorAttribute.setXYZ(29, cone.r, cone.g, cone.b); // p, n3
colorAttribute.setXYZ(30, cone.r, cone.g, cone.b);
colorAttribute.setXYZ(31, cone.r, cone.g, cone.b); // p, n4
// up
colorAttribute.setXYZ(32, up.r, up.g, up.b);
colorAttribute.setXYZ(33, up.r, up.g, up.b); // u1, u2
colorAttribute.setXYZ(34, up.r, up.g, up.b);
colorAttribute.setXYZ(35, up.r, up.g, up.b); // u2, u3
colorAttribute.setXYZ(36, up.r, up.g, up.b);
colorAttribute.setXYZ(37, up.r, up.g, up.b); // u3, u1
// target
colorAttribute.setXYZ(38, target.r, target.g, target.b);
colorAttribute.setXYZ(39, target.r, target.g, target.b); // c, t
colorAttribute.setXYZ(40, cross.r, cross.g, cross.b);
colorAttribute.setXYZ(41, cross.r, cross.g, cross.b); // p, c
// cross
colorAttribute.setXYZ(42, cross.r, cross.g, cross.b);
colorAttribute.setXYZ(43, cross.r, cross.g, cross.b); // cn1, cn2
colorAttribute.setXYZ(44, cross.r, cross.g, cross.b);
colorAttribute.setXYZ(45, cross.r, cross.g, cross.b); // cn3, cn4
colorAttribute.setXYZ(46, cross.r, cross.g, cross.b);
colorAttribute.setXYZ(47, cross.r, cross.g, cross.b); // cf1, cf2
colorAttribute.setXYZ(48, cross.r, cross.g, cross.b);
colorAttribute.setXYZ(49, cross.r, cross.g, cross.b); // cf3, cf4
colorAttribute.needsUpdate = true;
}
/**
* Updates the helper based on the projection matrix of the camera.
*/
update() {
const geometry = this.geometry;
const pointMap = this.pointMap;
const w = 1,
h = 1;
// we need just camera projection matrix inverse
// world matrix must be identity
_camera.projectionMatrixInverse.copy(this.camera.projectionMatrixInverse);
// Adjust z values based on coordinate system
const nearZ = this.camera.coordinateSystem === _constants.WebGLCoordinateSystem ? -1 : 0;
// center / target
setPoint('c', pointMap, geometry, _camera, 0, 0, nearZ);
setPoint('t', pointMap, geometry, _camera, 0, 0, 1);
// near
setPoint('n1', pointMap, geometry, _camera, -w, -h, nearZ);
setPoint('n2', pointMap, geometry, _camera, w, -h, nearZ);
setPoint('n3', pointMap, geometry, _camera, -w, h, nearZ);
setPoint('n4', pointMap, geometry, _camera, w, h, nearZ);
// far
setPoint('f1', pointMap, geometry, _camera, -w, -h, 1);
setPoint('f2', pointMap, geometry, _camera, w, -h, 1);
setPoint('f3', pointMap, geometry, _camera, -w, h, 1);
setPoint('f4', pointMap, geometry, _camera, w, h, 1);
// up
setPoint('u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, nearZ);
setPoint('u2', pointMap, geometry, _camera, -w * 0.7, h * 1.1, nearZ);
setPoint('u3', pointMap, geometry, _camera, 0, h * 2, nearZ);
// cross
setPoint('cf1', pointMap, geometry, _camera, -w, 0, 1);
setPoint('cf2', pointMap, geometry, _camera, w, 0, 1);
setPoint('cf3', pointMap, geometry, _camera, 0, -h, 1);
setPoint('cf4', pointMap, geometry, _camera, 0, h, 1);
setPoint('cn1', pointMap, geometry, _camera, -w, 0, nearZ);
setPoint('cn2', pointMap, geometry, _camera, w, 0, nearZ);
setPoint('cn3', pointMap, geometry, _camera, 0, -h, nearZ);
setPoint('cn4', pointMap, geometry, _camera, 0, h, nearZ);
geometry.getAttribute('position').needsUpdate = true;
}
/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
dispose() {
this.geometry.dispose();
this.material.dispose();
}
}
exports.CameraHelper = CameraHelper;
function setPoint(point, pointMap, geometry, camera, x, y, z) {
_vector.set(x, y, z).unproject(camera);
const points = pointMap[point];
if (points !== undefined) {
const position = geometry.getAttribute('position');
for (let i = 0, l = points.length; i < l; i++) {
position.setXYZ(points[i], _vector.x, _vector.y, _vector.z);
}
}
}