当前位置:   article > 正文

Three.js-光线投射(raycaster)

raycaster

目录

1.光线投射Raycaster

1.1 构造器

1.2 属性

1.3 方法

 2. 示例:点击变换颜色


1.光线投射Raycaster

这个类用于进行raycasting(光线投射)。 光线投射用于进行鼠标拾取(在三维空间中计算出鼠标移过了什么物体)。

1.1 构造器

 Raycaster( origin : Vector3, direction : Vector3, near : Float, far : Float )

origin —— 光线投射的原点向量。
direction —— 向射线提供方向的方向向量,应当被标准化。
near —— 返回的所有结果比near远。near不能为负值,其默认值为0。
far —— 返回的所有结果都比far近。far不能小于near,其默认值为Infinity(正无穷。)

1.2 属性

.far : Float

raycaster的远距离因数(投射远点)。这个值表明哪些对象可以基于该距离而被raycaster所丢弃。 这个值不应当为负,并且应当比near属性大。

.near : Float

raycaster的近距离因数(投射近点)。这个值表明哪些对象可以基于该距离而被raycaster所丢弃。 这个值不应当为负,并且应当比far属性小。

.camera : Camera

对依赖于视图的对象(例如Sprites等广告牌对象)进行光线投射时使用的相机。该字段可以手动设置,也可以在调用“setFromCamera”时设置。默认为空。

.layers : Layers

Raycaster 在执行相交测试时使用它来选择性地忽略 3D 对象。以下代码示例确保Raycaster 实例 仅支持第1层上的 3D 对象。

  1. raycaster.layers.set( 1 );
  2. object.layers.enable( 1 );

.params : Object

具有以下属性的对象:

  1. {
  2. Mesh: {},
  3. Line: { threshold: 1 },
  4. LOD: {},
  5. Points: { threshold: 1 },
  6. Sprite: {}
  7. }

其中threshold是光线投射器在与对象相交时的精度,以世界单位为单位。

.ray : Ray

用于进行光线投射的Ray(射线)。

1.3 方法

.set ( origin : Vector3, direction : Vector3 ) : undefined

origin —— 光线投射的原点向量。
direction —— 为光线提供方向的标准化方向向量。

使用一个新的原点和方向来更新射线。

.setFromCamera ( coords : Vector2, camera : Camera ) : undefined

coords —— 在标准化设备坐标中鼠标的二维坐标 —— X分量与Y分量应当在-1到1之间。
camera —— 射线所来源的摄像机。

使用一个新的原点和方向来更新射线。

.intersectObject ( object : Object3D, recursive : Boolean, optionalTarget : Array ) : Array

object —— 检查与射线相交的物体。
recursive —— 若为true,则同时也会检查所有的后代。否则将只会检查对象本身。默认值为true。
optionalTarget — (可选)设置结果的目标数组。如果不设置这个值,则一个新的Array会被实例化;如果设置了这个值,则在每次调用之前必须清空这个数组(例如:array.length = 0;)。

检测所有在射线与物体之间,包括或不包括后代的相交部分。返回结果时,相交部分将按距离进行排序,最近的位于第一个。
该方法返回一个包含有交叉部分的数组:

[ { distance, point, face, faceIndex, object }, ... ]

distance —— 射线投射原点和相交部分之间的距离。
point —— 相交部分的点(世界坐标)
face —— 相交的面
faceIndex —— 相交的面的索引
object —— 相交的物体
uv —— 相交部分的点的UV坐标。
uv2 —— Second set of U,V coordinates at point of intersection
instanceId – The index number of the instance where the ray intersects the InstancedMesh

当计算这条射线是否和物体相交的时候,Raycaster将传入的对象委托给raycast方法。 这将可以让mesh对于光线投射的响应不同于lines和pointclouds。

请注意:对于网格来说,面必须朝向射线的原点,以便其能够被检测到。 用于交互的射线穿过面的背侧时,将不会被检测到。如果需要对物体中面的两侧进行光线投射, 你需要将material中的side属性设置为THREE.DoubleSide

.intersectObjects ( objects : Array, recursive : Boolean, optionalTarget : Array ) : Array

objects —— 检测和射线相交的一组物体。
recursive —— 若为true,则同时也会检测所有物体的后代。否则将只会检测对象本身的相交部分。默认值为true。
optionalTarget —— (可选)设置结果的目标数组。如果不设置这个值,则一个新的Array会被实例化;如果设置了这个值,则在每次调用之前必须清空这个数组(例如:array.length = 0;)。

检测所有在射线与这些物体之间,包括或不包括后代的相交部分。返回结果时,相交部分将按距离进行排序,最近的位于第一个),相交部分和.intersectObject所返回的格式是相同的。

 2. 示例:点击变换颜色

  1. import * as THREE from "three";
  2. // 导入轨道控制器
  3. import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
  4. // 目标:raycaster
  5. // 1、创建场景
  6. const scene = new THREE.Scene();
  7. // 2、创建相机
  8. const camera = new THREE.PerspectiveCamera(
  9. 75,
  10. window.innerWidth / window.innerHeight,
  11. 0.1,
  12. 300
  13. );
  14. const textureLoader = new THREE.TextureLoader();
  15. const particlesTexture = textureLoader.load("./textures/particles/1.png");
  16. // 设置相机位置
  17. camera.position.set(0, 0, 20);
  18. scene.add(camera);
  19. const cubeGeometry = new THREE.BoxBufferGeometry(1, 1, 1);
  20. const material = new THREE.MeshBasicMaterial({
  21. wireframe: true,
  22. });
  23. const redMaterial = new THREE.MeshBasicMaterial({
  24. color: "#ff0000",
  25. });
  26. // 1000立方体
  27. let cubeArr = [];
  28. for (let i = -5; i < 5; i++) {
  29. for (let j = -5; j < 5; j++) {
  30. for (let z = -5; z < 5; z++) {
  31. const cube = new THREE.Mesh(cubeGeometry, material);
  32. cube.position.set(i, j, z);
  33. scene.add(cube);
  34. cubeArr.push(cube);
  35. }
  36. }
  37. }
  38. // 创建投射光线对象
  39. const raycaster = new THREE.Raycaster();
  40. // 鼠标的位置对象
  41. const mouse = new THREE.Vector2();
  42. // 监听鼠标的点击位置
  43. window.addEventListener("click", (event) => {
  44. // console.log(event);
  45. mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  46. mouse.y = -((event.clientY / window.innerHeight) * 2 - 1);
  47. raycaster.setFromCamera(mouse, camera);
  48. let result = raycaster.intersectObjects(cubeArr);
  49. // console.log(result);
  50. // result[0].object.material = redMaterial;
  51. result.forEach((item) => {
  52. item.object.material = redMaterial;
  53. });
  54. });
  55. // 初始化渲染器
  56. const renderer = new THREE.WebGLRenderer();
  57. // 设置渲染的尺寸大小
  58. renderer.setSize(window.innerWidth, window.innerHeight);
  59. // 开启场景中的阴影贴图
  60. renderer.shadowMap.enabled = true;
  61. renderer.physicallyCorrectLights = true;
  62. // console.log(renderer);
  63. // 将webgl渲染的canvas内容添加到body
  64. document.body.appendChild(renderer.domElement);
  65. // // 使用渲染器,通过相机将场景渲染进来
  66. // renderer.render(scene, camera);
  67. // 创建轨道控制器
  68. const controls = new OrbitControls(camera, renderer.domElement);
  69. // 设置控制器阻尼,让控制器更有真实效果,必须在动画循环里调用.update()。
  70. controls.enableDamping = true;
  71. // 添加坐标轴辅助器
  72. const axesHelper = new THREE.AxesHelper(5);
  73. scene.add(axesHelper);
  74. // 设置时钟
  75. const clock = new THREE.Clock();
  76. function render() {
  77. let time = clock.getElapsedTime();
  78. controls.update();
  79. renderer.render(scene, camera);
  80. // 渲染下一帧的时候就会调用render函数
  81. requestAnimationFrame(render);
  82. }
  83. render();
  84. // 监听画面变化,更新渲染画面
  85. window.addEventListener("resize", () => {
  86. // console.log("画面变化了");
  87. // 更新摄像头
  88. camera.aspect = window.innerWidth / window.innerHeight;
  89. // 更新摄像机的投影矩阵
  90. camera.updateProjectionMatrix();
  91. // 更新渲染器
  92. renderer.setSize(window.innerWidth, window.innerHeight);
  93. // 设置渲染器的像素比
  94. renderer.setPixelRatio(window.devicePixelRatio);
  95. });

实现效果:

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/926351
推荐阅读
相关标签
  

闽ICP备14008679号