util.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import * as THREE from 'three';
  2. import { TransformControls } from 'three/examples/jsm/controls/TransformControls'; // 引入模块
  3. import * as dat from "dat.gui";
  4. let modal, cubeList:THREE.Mesh[] = [], curve, line
  5. //创建gui对象
  6. const gui = new dat.GUI();
  7. gui.domElement.style.top = '300'
  8. gui.domElement.style.clientTop = 300
  9. gui.domElement.style.zIndex = 9999
  10. // 画点
  11. const addCube = (initialPoints, scene) => {
  12. return initialPoints.map(pos => {
  13. const geometry = new THREE.BoxBufferGeometry(1, 1, 1);
  14. const material = new THREE.MeshBasicMaterial({
  15. color: 0xffffff,
  16. side: THREE.DoubleSide
  17. });
  18. const cube = new THREE.Mesh(geometry, material);
  19. cube.position.copy(pos);
  20. scene.add(cube);
  21. cubeList.push(cube)
  22. // gui.add(cube.position, 'x', -1000, 1000)
  23. // gui.add(cube.position, 'y', -1000, 1000)
  24. // gui.add(cube.position, 'z', -1000, 1000)
  25. });
  26. }
  27. // 画线
  28. export const drawLine = (initialPoints, obj) => {
  29. modal = obj
  30. addCube(initialPoints, modal.scene)
  31. curve = new THREE.CatmullRomCurve3(
  32. cubeList.map((cube) => cube.position) // 直接绑定方块的position以便后续用方块调整曲线
  33. );
  34. curve.curveType = 'chordal'; // 曲线类型
  35. curve.closed = false; // 曲线是否闭合
  36. const points = curve.getPoints(50); // 50等分获取曲线点数组
  37. line = new THREE.LineLoop(
  38. new THREE.BufferGeometry().setFromPoints(points),
  39. new THREE.LineBasicMaterial({ color: 0xffffff,
  40. linewidth: 10 })
  41. ); // 绘制实体线条,仅用于示意曲线,后面的向量线条同理,相关代码就省略了
  42. modal.scene.add(line);
  43. addChangeEvent()
  44. }
  45. // 获取点击位置
  46. const addChangeEvent = () => {
  47. debugger
  48. const control = new TransformControls(modal.camera, modal.renderer.domElement);
  49. // 获取点击位置
  50. const mouse = new THREE.Vector2();
  51. window.addEventListener(
  52. 'click',
  53. (event) => {
  54. debugger
  55. mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  56. mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  57. // mouse.x = ((event.clientX - dom.offsetLeft) / dom.clientWidth) * 2 - 1; // dom.offsetLeft -- dom元素距离浏览器左侧的距离 dom.clientWidth -- dom元素宽度
  58. // mouse.y = -((event.clientY - dom.offsetTop) / dom.clientHeight) * 2 + 1; // dom.offsetTop -- dom元素距离浏览器顶部的距离 dom.clientHeight -- dom元素高度
  59. //根据照相机,把这个向量转换到视点坐标系
  60. const vector = new THREE.Vector3(mouse.x, mouse.y, 0.5).unproject(modal.camera);
  61. // 方块点击检测
  62. // const rayCaster = new THREE.Raycaster();
  63. //在视点坐标系中形成射线,射线的起点向量是照相机, 射线的方向向量是照相机到点击的点,这个向量应该归一标准化。
  64. const rayCaster = new THREE.Raycaster(modal.camera.position, vector.sub(modal.camera.position).normalize());
  65. // rayCaster.setFromCamera(mouse, modal.camera);
  66. const intersects = rayCaster.intersectObjects(cubeList);
  67. if (intersects.length) {
  68. const target = intersects[0].object;
  69. control.attach(target); // 绑定controls和方块
  70. modal.scene.add(control);
  71. }
  72. },
  73. false
  74. );
  75. // 修改曲线后同步修改实体线条
  76. control.addEventListener('dragging-changed', (event) => {
  77. if (!event.value) {
  78. console.log(event.value);
  79. const points = curve.getPoints(50);
  80. line.geometry.setFromPoints(points);
  81. }
  82. });
  83. }