ThreeJS中的曲线应用


参考:https://threejs.org/open in new window

曲线运动

  // 从一系列的点创建一条平滑的三维样条曲线。
  curve = new THREE.CatmullRomCurve3(
    [
      new THREE.Vector3(-10, 0, 10),
      new THREE.Vector3(-5, 5, 5),
      new THREE.Vector3(0, 0, 5),
      new THREE.Vector3(5, -5, 5),
      new THREE.Vector3(10, 0, 10),
    ],
    true
  );
  // 使用getPoint(t)返回一组divisions+1的点
  const points = curve.getPoints(500);
  // 通过点队列设置该 BufferGeometry 的 attribute。
  const geometry = new THREE.BufferGeometry().setFromPoints(points);

  const material = new THREE.LineBasicMaterial({ color: 0xff0000 });
  const curveObject = new THREE.Line(geometry, material);
  scene.add(curveObject);


  function animate(){
      renderer.render(scene, camera);
      const elapsed = clock.getElapsedTime();
      const time = elapsed/10%1;
      const point = curve.getPoint(time);
      moon.position.copy(point);
      camera.position.copy(point);
      camera.lookAt(earth.position)
      requestAnimationFrame(animate)
  }

const curveHandles = []; // 曲线控制点数组
  // 初始化曲线控制点,设置成立方样条曲线
  const initialPoints = [
    { x: 1, y: 0, z: -1 },
    { x: 1, y: 0, z: 1 },
    { x: -1, y: 0, z: 1 },
    { x: -1, y: 0, z: -1 },
  ];
  const boxGeometry = new THREE.BoxGeometry(0.1, 0.1, 0.1);
  const boxMaterial = new THREE.MeshBasicMaterial();
  for (const handlePos of initialPoints) {
    const handle = new THREE.Mesh(boxGeometry, boxMaterial);
    handle.position.copy(handlePos);
    curveHandles.push(handle);
    scene.add(handle);
  }

   // 创建立方样条曲线
 const curve = new THREE.CatmullRomCurve3(
   curveHandles.map((handle) => handle.position)
 );
 curve.curveType = "centripetal"; // 曲线类型(切向加速调整)
 curve.closed = true; // 是否封闭
 // 创建曲线并根据关键点更新线条
 const points = curve.getPoints(50);
 const line = new THREE.LineLoop(
   new THREE.BufferGeometry().setFromPoints(points),
   new THREE.LineBasicMaterial({ color: 0x00ff00 })
 );
 scene.add(line);
 // 加载字体并创建 3D 文本
 const loader = new FontLoader();
 loader.load("fonts/helvetiker_regular.typeface.json", function (font) {
   const geometry = new TextGeometry("Hello three.js!", {
     font: font,
     size: 0.2,
     height: 0.05,
     curveSegments: 12,
     bevelEnabled: true,
     bevelThickness: 0.02,
     bevelSize: 0.01,
     bevelOffset: 0,
     bevelSegments: 5,
   });
   geometry.rotateX(Math.PI);
   const material = new THREE.MeshStandardMaterial({
     color: 0x99ffff,
   });
   const objectToCurve = new THREE.Mesh(geometry, material);
   /*
   
   
   */
   flow = new Flow(objectToCurve);
   flow.updateCurve(0, curve);
   scene.add(flow.object3D);
 });
 // 创建射线对象
 rayCaster = new THREE.Raycaster();
 // 创建变换控制器对象
 control = new TransformControls(camera, renderer.domElement);
 control.addEventListener("dragging-changed", function (event) {
   if (!event.value) {
     const points = curve.getPoints(50);
     line.geometry.setFromPoints(points);
     flow.updateCurve(0, curve);
   }
 });

  // 逐帧动画函数
function animate() {
  requestAnimationFrame(animate);

  // 判断是否点击场景
  if (action === ACTION_SELECT) {
    rayCaster.setFromCamera(mouse, camera);
    action = ACTION_NONE;
    const intersects = rayCaster.intersectObjects(curveHandles, false);
    if (intersects.length) {
      const target = intersects[0].object;
      control.attach(target);
      scene.add(control);
    }
  }

  // 曲线模拟器运动
  if (flow) {
    flow.moveAlongCurve(0.001);
  }

  // 渲染场景
  render();
}
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.13.0