UNPKG

@openhps/core

Version:

Open Hybrid Positioning System - Core component

208 lines (192 loc) 10.6 kB
import { Camera } from "../cameras/Camera.js"; import { Ray } from "../math/Ray.js"; import { Vector2 } from "../math/Vector2.js"; import { Vector3 } from "../math/Vector3.js"; import { XRTargetRaySpace } from "../renderers/webxr/WebXRController.js"; import { Layers } from "./Layers.js"; import { Object3D } from "./Object3D.js"; export interface Face { a: number; b: number; c: number; normal: Vector3; materialIndex: number; } export interface Intersection<TIntersected extends Object3D = Object3D> { /** Distance between the origin of the ray and the intersection */ distance: number; distanceToRay?: number | undefined; /** Point of intersection, in world coordinates */ point: Vector3; index?: number | undefined; /** Intersected face */ face?: Face | null | undefined; /** Index of the intersected face */ faceIndex?: number | undefined; /** The intersected object */ object: TIntersected; uv?: Vector2 | undefined; uv1?: Vector2 | undefined; normal?: Vector3; /** The index number of the instance where the ray intersects the {@link THREE.InstancedMesh | InstancedMesh } */ instanceId?: number | undefined; pointOnLine?: Vector3; batchId?: number; } export interface RaycasterParameters { Mesh: any; Line: { threshold: number }; Line2?: { threshold: number }; LOD: any; Points: { threshold: number }; Sprite: any; } /** * This class is designed to assist with {@link https://en.wikipedia.org/wiki/Ray_casting | raycasting} * @remarks * Raycasting is used for mouse picking (working out what objects in the 3d space the mouse is over) amongst other things. * @example * ```typescript * const raycaster = new THREE.Raycaster(); * const pointer = new THREE.Vector2(); * * function onPointerMove(event) { * // calculate pointer position in normalized device coordinates (-1 to +1) for both components * pointer.x = (event.clientX / window.innerWidth) * 2 - 1; * pointer.y = -(event.clientY / window.innerHeight) * 2 + 1; * } * * function render() { * // update the picking ray with the camera and pointer position * raycaster.setFromCamera(pointer, camera); * // calculate objects intersecting the picking ray * const intersects = raycaster.intersectObjects(scene.children); * for (let i = 0; i & lt; intersects.length; i++) { * intersects[i].object.material.color.set(0xff0000); * } * renderer.render(scene, camera); * } * window.addEventListener('pointermove', onPointerMove); * window.requestAnimationFrame(render); * ``` * @see Example: {@link https://threejs.org/examples/#webgl_interactive_cubes | Raycasting to a Mesh} * @see Example: {@link https://threejs.org/examples/#webgl_interactive_cubes_ortho | Raycasting to a Mesh in using an OrthographicCamera} * @see Example: {@link https://threejs.org/examples/#webgl_interactive_buffergeometry | Raycasting to a Mesh with BufferGeometry} * @see Example: {@link https://threejs.org/examples/#webgl_instancing_raycast | Raycasting to a InstancedMesh} * @see Example: {@link https://threejs.org/examples/#webgl_interactive_lines | Raycasting to a Line} * @see Example: {@link https://threejs.org/examples/#webgl_interactive_raycasting_points | Raycasting to Points} * @see Example: {@link https://threejs.org/examples/#webgl_geometry_terrain_raycast | Terrain raycasting} * @see Example: {@link https://threejs.org/examples/#webgl_interactive_voxelpainter | Raycasting to paint voxels} * @see Example: {@link https://threejs.org/examples/#webgl_raycaster_texture | Raycast to a Texture} * @see {@link https://threejs.org/docs/index.html#api/en/core/Raycaster | Official Documentation} * @see {@link https://github.com/mrdoob/three.js/blob/master/src/core/Raycaster.js | Source} */ export class Raycaster { /** * This creates a new {@link Raycaster} object. * @param origin The origin vector where the ray casts from. Default `new Vector3()` * @param direction The direction vector that gives direction to the ray. Should be normalized. Default `new Vector3(0, 0, -1)` * @param near All results returned are further away than near. Near can't be negative. Expects a `Float`. Default `0` * @param far All results returned are closer than far. Far can't be lower than near. Expects a `Float`. Default `Infinity` */ constructor(origin?: Vector3, direction?: Vector3, near?: number, far?: number); /** * The {@link THREE.RaycasterRay | Ray} used for the raycasting. */ ray: Ray; /** * The near factor of the raycaster. This value indicates which objects can be discarded based on the distance. * This value shouldn't be negative and should be smaller than the far property. * @remarks Expects a `Float` * @defaultValue `0` */ near: number; /** * The far factor of the raycaster. This value indicates which objects can be discarded based on the distance. * This value shouldn't be negative and should be larger than the near property. * @remarks Expects a `Float` * @defaultValue `Infinity` */ far: number; /** * The camera to use when raycasting against view-dependent objects such as billboarded objects like {@link THREE.Sprites | Sprites}. * This field can be set manually or is set when calling {@link setFromCamera}. * @defaultValue `null` */ camera: Camera; /** * Used by {@link Raycaster} to selectively ignore 3D objects when performing intersection tests. * The following code example ensures that only 3D objects on layer `1` will be honored by the instance of Raycaster. * ``` * raycaster.layers.set( 1 ); * object.layers.enable( 1 ); * ``` * @defaultValue `new THREE.Layers()` - See {@link THREE.Layers | Layers}. */ layers: Layers; /** * An data object where threshold is the precision of the {@link Raycaster} when intersecting objects, in world units. * @defaultValue `{ Mesh: {}, Line: { threshold: 1 }, LOD: {}, Points: { threshold: 1 }, Sprite: {} }` */ params: RaycasterParameters; /** * Updates the ray with a new origin and direction * @remarks * Please note that this method only copies the values from the arguments. * @param origin The origin vector where the ray casts from. * @param direction The normalized direction vector that gives direction to the ray. */ set(origin: Vector3, direction: Vector3): void; /** * Updates the ray with a new origin and direction. * @param coords 2D coordinates of the mouse, in normalized device coordinates (NDC)---X and Y components should be between -1 and 1. * @param camera camera from which the ray should originate */ setFromCamera(coords: Vector2, camera: Camera): void; /** * Updates the ray with a new origin and direction. * @param controller The controller to copy the position and direction from. */ setFromXRController(controller: XRTargetRaySpace): this; /** * Checks all intersection between the ray and the object with or without the descendants * @remarks Intersections are returned sorted by distance, closest first * @remarks {@link Raycaster} delegates to the {@link Object3D.raycast | raycast} method of the passed object, when evaluating whether the ray intersects the object or not * This allows {@link THREE.Mesh | meshes} to respond differently to ray casting than {@link THREE.Line | lines} and {@link THREE.Points | pointclouds}. * **Note** that for meshes, faces must be pointed towards the origin of the {@link Raycaster.ray | ray} in order to be detected; * intersections of the ray passing through the back of a face will not be detected * To raycast against both faces of an object, you'll want to set the {@link Mesh.material | material}'s {@link Material.side | side} property to `THREE.DoubleSide`. * @see {@link intersectObjects | .intersectObjects()}. * @param object The object to check for intersection with the ray. * @param recursive If true, it also checks all descendants. Otherwise it only checks intersection with the object. Default `true` * @param optionalTarget Target to set the result. Otherwise a new {@link Array | Array} is instantiated. * If set, you must clear this array prior to each call (i.e., array.length = 0;). Default `[]` * @returns An array of intersections is returned. */ intersectObject<TIntersected extends Object3D>( object: Object3D, recursive?: boolean, optionalTarget?: Array<Intersection<TIntersected>>, ): Array<Intersection<TIntersected>>; /** * Checks all intersection between the ray and the objects with or without the descendants * @remarks Intersections are returned sorted by distance, closest first * @remarks Intersections are of the same form as those returned by {@link intersectObject | .intersectObject()}. * @remarks {@link Raycaster} delegates to the {@link Object3D.raycast | raycast} method of the passed object, when evaluating whether the ray intersects the object or not * This allows {@link THREE.Mesh | meshes} to respond differently to ray casting than {@link THREE.Line | lines} and {@link THREE.Points | pointclouds}. * **Note** that for meshes, faces must be pointed towards the origin of the {@link Raycaster.ray | ray} in order to be detected; * intersections of the ray passing through the back of a face will not be detected * To raycast against both faces of an object, you'll want to set the {@link Mesh.material | material}'s {@link Material.side | side} property to `THREE.DoubleSide`. * @see {@link intersectObject | .intersectObject()}. * @param objects The objects to check for intersection with the ray. * @param recursive If true, it also checks all descendants of the objects. Otherwise it only checks intersection with the objects. Default `true` * @param optionalTarget Target to set the result. Otherwise a new {@link Array | Array} is instantiated. * If set, you must clear this array prior to each call (i.e., array.length = 0;). Default `[]` * @returns An array of intersections is returned. */ intersectObjects<TIntersected extends Object3D>( objects: Object3D[], recursive?: boolean, optionalTarget?: Array<Intersection<TIntersected>>, ): Array<Intersection<TIntersected>>; }