/** * Raycaster for R3.D3 * @param graphics R3.Runtime.Graphics * @param apiRaycaster * @constructor */ R3.D3.Raycaster = function( graphics, apiRaycaster ) { this.graphics = graphics; this.graphics.isNotThreeThrow(); if (R3.Utils.UndefinedOrNull(apiRaycaster)) { apiRaycaster = {}; } R3.D3.API.Raycaster.call( this, apiRaycaster.id, apiRaycaster.name, apiRaycaster.parent, apiRaycaster.position, apiRaycaster.direction ); this.position = new R3.Vector3( this.graphics, this.position, this ); this.direction = new R3.Vector3( this.graphics, this.direction, this ); R3.Component.call(this); }; R3.D3.Raycaster.prototype = Object.create(R3.Component.prototype); R3.D3.Raycaster.prototype.constructor = R3.D3.Raycaster; /** * Creates or updates a raycaster instance */ R3.D3.Raycaster.prototype.createInstance = function() { this.instance = new THREE.Raycaster(); this.instance.set( this.position.instance, this.direction.instance ); R3.Component.prototype.createInstance.call(this); }; R3.D3.Raycaster.prototype.updateInstance = function(property) { if (property === 'position') { this.position.instance.x = this.position.x; this.position.instance.y = this.position.y; this.position.instance.z = this.position.z; this.instance.setPosition(this.position.instance); return; } if (property === 'direction') { this.direction.instance.x = this.direction.x; this.direction.instance.y = this.direction.y; this.direction.instance.z = this.direction.z; this.instance.setDirection(this.direction.instance); return; } R3.Component.prototype.updateInstance.call(this, property); }; R3.D3.Raycaster.prototype.toApiObject = function() { return new R3.D3.API.Raycaster( this.id, this.name, R3.Utils.IdOrNull(this.parent), this.position.toApiObject(), this.direction.toApiObject() ) }; /** * Sets the direction and position of this raycaster * @param position R3.Vector3 * @param direction R3.Vector3 */ R3.D3.Raycaster.prototype.set = function( position, direction ) { this.position.x = position.x; this.position.y = position.y; this.position.z = position.z; this.direction.x = direction.x; this.direction.y = direction.y; this.direction.z = direction.z; this.position.updateInstance(); this.direction.updateInstance(); }; /** * Sets the direction of this raycaster * @param direction R3.Vector3 */ R3.D3.Raycaster.prototype.setDirection = function( direction ) { this.direction.x = direction.x; this.direction.y = direction.y; this.direction.z = direction.z; this.direction.updateInstance(); }; /** * Sets the position of this raycaster * @param position R3.Vector3 */ R3.D3.Raycaster.prototype.setPosition = function( position ) { this.position.x = position.x; this.position.y = position.y; this.position.z = position.z; this.position.updateInstance(); }; /** * Sets the ray position and direction from the mouse coordinates (in proper x and y (-1 to 1)) * @param mouse * @param camera */ R3.D3.Raycaster.prototype.setFromCamera = function( mouse, camera ) { this.instance.setFromCamera( mouse, camera.instance ); this.position.x = this.instance.ray.origin.x; this.position.y = this.instance.ray.origin.y; this.position.z = this.instance.ray.origin.z; this.direction.x = this.instance.ray.direction.x; this.direction.y = this.instance.ray.direction.y; this.direction.z = this.instance.ray.direction.z; }; /** * Gets all interesected R3.D3.Mesh objects * @param meshes [R3.D3.Mesh] */ R3.D3.Raycaster.prototype.getIntersectedObjects = function(meshes) { return meshes.reduce( function(result, mesh) { var intersects = this.instance.intersectObject(mesh.instance); if (intersects.length > 0) { result.push( { mesh: mesh, distance : intersects[0].distance, face: mesh.geometry.faces[intersects[0].faceIndex], faceIndex: intersects[0].faceIndex, uv : { x : intersects[0].uv.x, y : intersects[0].uv.y } } ); } return result; }.bind(this), [] ); }; /** * Returns the face normal (if any) of an intersection between current ray position, direction and a provided mesh * @param mesh R3.D3.Mesh * @returns {null | R3.Vector3} */ R3.D3.Raycaster.prototype.getFaceNormal = function(mesh) { var normal = null; var intersect = this.instance.intersectObject( mesh.instance ); if (intersect && intersect.length > 0) { normal = new R3.Vector3( this.graphics, new R3.API.Vector3( intersect[0].face.normal.x, intersect[0].face.normal.y, intersect[0].face.normal.z ), this ); } return normal; }; /** * Returns the face normal (if any) of an intersection between current ray position, direction and a provided mesh * @param mesh R3.D3.Mesh * @returns {null | R3.Vector3} */ R3.D3.Raycaster.prototype.getIntersectPoint = function(mesh) { var point = null; var intersect = this.instance.intersectObject( mesh.instance ); if (intersect && intersect.length > 0) { point = new R3.Vector3( this.graphics, new R3.API.Vector3( intersect[0].point.x, intersect[0].point.y, intersect[0].point.z ), this ); } return point; };