@ar-js-org/ar.js-threejs
Version:
AR.js (THREEx, ARjs) modular package - Typescript version
145 lines (123 loc) • 5.16 kB
text/typescript
//import * as THREE from "three";
import { Camera, Mesh, MeshBasicMaterial, Object3D, PerspectiveCamera, PlaneGeometry, Quaternion, Raycaster, Scene, Vector2, Vector3 } from "three";
// TODO this is useless - prefere arjs-HitTesting.js
/**
* - maybe support .onClickFcts in each object3d
* - seems an easy light layer for clickable object
* - up to
*/
export class HitTestingPlane {
private _sourceElement: any;
private _pickingScene: any;
private _pickingPlane: any;
private _pickingCamera: any;
constructor (sourceElement: HTMLElement) {
this._sourceElement = sourceElement;
// create _pickingScene
this._pickingScene = new Scene();
// create _pickingPlane
var geometry = new PlaneGeometry(20, 20, 19, 19).rotateX(-Math.PI / 2);
// var geometry = new THREE.PlaneGeometry(20,20).rotateX(-Math.PI/2)
var material = new MeshBasicMaterial({
// opacity: 0.5,
// transparent: true,
wireframe: true,
});
// material.visible = false
this._pickingPlane = new Mesh(geometry, material);
this._pickingScene.add(this._pickingPlane);
// Create pickingCamera
var fullWidth = parseInt(sourceElement.style.width);
var fullHeight = parseInt(sourceElement.style.height);
// TODO hardcoded fov - couch
this._pickingCamera = new PerspectiveCamera(
42,
fullWidth / fullHeight,
0.1,
30
);
}
//////////////////////////////////////////////////////////////////////////////
// update function
//////////////////////////////////////////////////////////////////////////////
update (
camera: Camera,
pickingRoot: Object3D,
changeMatrixMode: string
) {
this.onResize();
if (changeMatrixMode === "modelViewMatrix") {
// set pickingPlane position
var pickingPlane = this._pickingPlane;
pickingRoot.parent.updateMatrixWorld();
pickingPlane.matrix.copy(pickingRoot.parent.matrixWorld);
// set position/quaternion/scale from pickingPlane.matrix
pickingPlane.matrix.decompose(
pickingPlane.position,
pickingPlane.quaternion,
pickingPlane.scale
);
} else if (changeMatrixMode === "cameraTransformMatrix") {
// set pickingPlane position
var pickingCamera = this._pickingCamera;
camera.updateMatrixWorld();
pickingCamera.matrix.copy(camera.matrixWorld);
// set position/quaternion/scale from pickingCamera.matrix
pickingCamera.matrix.decompose(
pickingCamera.position,
pickingCamera.quaternion,
pickingCamera.scale
);
} else console.assert(false);
// var position = this._pickingPlane.position
// console.log('pickingPlane position', position.x.toFixed(2), position.y.toFixed(2), position.z.toFixed(2))
// var position = this._pickingCamera.position
// console.log('his._pickingCamera position', position.x.toFixed(2), position.y.toFixed(2), position.z.toFixed(2))
};
//////////////////////////////////////////////////////////////////////////////
// resize camera
//////////////////////////////////////////////////////////////////////////////
onResize () {
var sourceElement = this._sourceElement;
var pickingCamera = this._pickingCamera;
// FIXME why using css here ??? not even computed style
// should get the size of the elment directly independantly
var fullWidth = parseInt(sourceElement.style.width);
var fullHeight = parseInt(sourceElement.style.height);
pickingCamera.aspect = fullWidth / fullHeight;
pickingCamera.updateProjectionMatrix();
};
//////////////////////////////////////////////////////////////////////////////
// Perform test
//////////////////////////////////////////////////////////////////////////////
test (mouseX: number, mouseY: number) {
// convert mouseX, mouseY to [-1, +1]
mouseX = (mouseX - 0.5) * 2;
mouseY = -(mouseY - 0.5) * 2;
this._pickingScene.updateMatrixWorld(true);
// compute intersections between mouseVector3 and pickingPlane
var raycaster = new Raycaster();
//var mouseVector3 = new THREE.Vector3(mouseX, mouseY, 1);
var mouseVector2 = new Vector2(mouseX, mouseY);
raycaster.setFromCamera(mouseVector2, this._pickingCamera);
var intersects = raycaster.intersectObjects([this._pickingPlane]);
if (intersects.length === 0) return null;
// set new demoRoot position
var position = this._pickingPlane.worldToLocal(intersects[0].point.clone());
// TODO here do a look at the camera ?
var quaternion = new Quaternion();
var scale = new Vector3(1, 1, 1); //.multiplyScalar(1)
return {
position: position,
quaternion: quaternion,
scale: scale,
};
};
//////////////////////////////////////////////////////////////////////////////
// render the pickingPlane for debug
//////////////////////////////////////////////////////////////////////////////
renderDebug (renderer: any) {
// render sceneOrtho
renderer.render(this._pickingScene, this._pickingCamera);
};
};