qq_40812445 2024-04-18 20:48 采纳率: 100%
浏览 2
已结题

threeJS 如何能在旋转的过程中,保持原来的裁剪呢?

在使用threejs 的裁剪,手动旋转时正常,写代码旋转时,裁剪异常了。主要代码如下:

const camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 1000);
const renderer = new THREE.WebGLRenderer({antialias: true}); 
renderer.localClippingEnabled = true;

const scene = new THREE.Scene(); 
scene.autoUpdate = true;

const arcballControl = new ArcballControls(camera, renderer.domElement,scene);
arcballControl.setGizmosVisible(false);

const holderLight = new THREE.DirectionalLight( 0xffffff, 5 );
scene.add( holderLight );

const meshGroup = new THREE.Group();
const mesh = new THREE.Mesh(geometry,material);
const mesh2 = new THREE.Mesh(geometry2,material2);
meshGroup.add(mesh);
meshGroup.add(mesh2);
scene.add(meshGroup);

const animate = function () {
  holderLight.position.copy(camera.position);
  renderer.render(scene, camera);
  requestAnimationFrame(animate);
};
animate();

有一个按纽控制裁剪,执行:

const changeView = () =>{
  mesh.material.clippingPlanes = [new THREE.Plane(new THREE.Vector3(1, 0, 0), 1)];
  mesh.material.clipIntersection = true;
  mesh2.material.clippingPlanes = [new THREE.Plane(new THREE.Vector3(-1, 0, 0), 1)];
  mesh2.material.clipIntersection = true;
}

此时没有什么问题,鼠标手动旋转正常。

再写一个按纽,让其自动旋转1圈:

const rotatePosition = () =>{
    var pi = Math.PI*2
    const i = pi/360
    timer = setInterval(function(){
        if(pi > 0){
            meshGroup.rotation.y -= pi>i?i:pi;
            pi -= i;

        } else {
          clearInterval(timer);
        }
    }, 20);
}

旋转正常,但是裁剪的显示明显的异常,就是mesh 物体在转,在裁剪的位置一直固定在那,没有跟随着转
感觉裁剪的内容一直在变化。
如何才能让自动旋转正常呢?

  • 写回答

4条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-18 20:48
    关注

    引自免费微信小程序:皆我百晓生

    为了解决这个问题,你需要确保裁剪平面(clipping plane)随着场景中的对象一起旋转。当前,裁剪平面是相对于世界坐标系定位的,而不是跟随meshGroup对象。为了使裁剪平面随meshGroup旋转,我们需要在每次渲染前更新裁剪平面的朝向。可以通过计算新的裁剪平面法线来实现这一点。

    首先,创建一个函数来根据meshGroup的旋转更新裁剪平面的法线:

    function updateClippingPlaneRotation(meshGroup) {
      // 获取 meshGroup 的旋转矩阵
      const rotationMatrix = new THREE.Matrix4().makeRotationFromQuaternion(meshGroup.quaternion);
    
      // 计算两个裁剪平面的新法线
      const normal1 = new THREE.Vector3(1, 0, 0).applyMatrix4(rotationMatrix);
      const normal2 = new THREE.Vector3(-1, 0, 0).applyMatrix4(rotationMatrix);
    
      // 更新两个物体的裁剪平面
      mesh.material.clippingPlanes = [new THREE.Plane(normal1, 1)];
      mesh2.material.clippingPlanes = [new THREE.Plane(normal2, 1)];
    
      // 确保裁剪平面的方向正确(正面还是背面)
      if (normal1.z < 0) {
        mesh.material.clippingPlanes[0].set(-normal1.x, -normal1.y, -normal1.z, -mesh.material.clippingPlanes[0].constant);
      }
    
      if (normal2.z < 0) {
        mesh2.material.clippingPlanes[0].set(-normal2.x, -normal2.y, -normal2.z, -mesh2.material.clippingPlanes[0].constant);
      }
    }
    

    接下来,在动画循环中调用这个函数:

    const animate = function () {
      holderLight.position.copy(camera.position);
      updateClippingPlaneRotation(meshGroup); // 在这里添加这行代码
      renderer.render(scene, camera);
      requestAnimationFrame(animate);
    };
    

    现在,当自动旋转meshGroup时,裁剪平面会随着它一起旋转,从而避免了显示异常。整个代码如下:

    // ... (之前的代码不变)
    
    function updateClippingPlaneRotation(meshGroup) {
      const rotationMatrix = new THREE.Matrix4().makeRotationFromQuaternion(meshGroup.quaternion);
      const normal1 = new THREE.Vector3(1, 0, 0).applyMatrix4(rotationMatrix);
      const normal2 = new THREE.Vector3(-1, 0, 0).applyMatrix4(rotationMatrix);
    
      mesh.material.clippingPlanes = [new THREE.Plane(normal1, 1)];
      mesh2.material.clippingPlanes = [new THREE.Plane(normal2, 1)];
    
      if (normal1.z < 0) {
        mesh.material.clippingPlanes[0].set(-normal1.x, -normal1.y, -normal1.z, -mesh.material.clippingPlanes[0].constant);
      }
    
      if (normal2.z < 0) {
        mesh2.material.clippingPlanes[0].set(-normal2.x, -normal2.y, -normal2.z, -mesh2.material.clippingPlanes[0].constant);
      }
    }
    
    const animate = function () {
      holderLight.position.copy(camera.position);
      updateClippingPlaneRotation(meshGroup);
      renderer.render(scene, camera);
      requestAnimationFrame(animate);
    };
    
    // ... (之后的代码不变)
    

    这样,当你点击按钮触发自动旋转时,裁剪应该会随着meshGroup的旋转而正确地改变。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 4月30日
  • 已采纳回答 4月22日
  • 修改了问题 4月18日
  • 修改了问题 4月18日
  • 展开全部

悬赏问题

  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 关于大棚监测的pcb板设计
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器