如何按照 THREE.js 香草 webgl 解决方案中所述围绕枢轴点旋转对象?

How to rotate object around a pivot point as described in THREE.js solution in vanilla webgl?

我想使用 webgl 围绕轴心点进行变换。灵感来自 Three.js 和 this comment

Create a object that will act as pivot:

mesh.position.y = 10;

var pivot = new THREE.Object3D(); pivot.add( mesh );

scene.add( pivot );

我正在尝试将枢轴设置到某个点并旋转对象。这是我执行这些操作的代码:

  let transforms = {};

  this.makeTransform = (name, transform) => {

    transforms[name] = modelMatrix(transform);

  };

  const modelMatrix = transform => {
    let matrix = transforms[transform.transform] || mat4.identity();

    return mat4.transform(matrix, transform);
  };


  const mvpMatrix = modelMatrix => {
    const { pos: camPos, target, up } = camera;
    const { fov, aspect, near, far } = camera;

    let camMatrix = mat4.lookAt(camPos, target, up);
    let viewMatrix = mat4.inverse(camMatrix);

    let projectionMatrix = mat4.perspective(fov, aspect, near, far);

    let viewProjectionMatrix = mat4.multiply(projectionMatrix, viewMatrix);

    return mat4.multiply(viewProjectionMatrix, modelMatrix);
  };



  this.drawMesh = (name, transform) => {    
    const uMatrix = mvpMatrix(modelMatrix(transform));
    // set uMatrix as uniform and draw
  }

用法(渲染代码):

r.makeTransform('root', {
  translate: [100, 0, 0]
});

r.drawMesh('sample', {
  transform: 'root',
  translate: [0.0, 0.0, 2.0],
  rotate: [0.0,
           Math.PI,
           0.0]
});

所以我没有场景图,但我制作了变换矩阵并将它们应用于对象。这里 sample 网格应用了 root 变换。这会在 x 轴上平移对象,并且仍然围绕其原点旋转对象。

但我无法使用上述方法围绕轴心点旋转对象。

基于 gman 回答 这行得通:

r.makeTransform('root', {
  translate: [0, 0, 0],
  rotate: [0.0, u.PI, 0.0]
});

r.drawMesh('sample', {
  transform: 'root',
  translate: [100.0, 0.0, 0.0]
});

默认情况下THREE.js如何绕物体中心旋转?

因为几何体中的顶点被定义为对象中心位于 0,0 原点。

喜欢here

 var x = ix * segmentWidth - widthHalf;

here

  for (let i = 0; i < vertices.length; i+=3) {
    vertices[i] -= widthHalf;
    vertices[i+1] -= heightHalf;
    vertices[i+2] -= depthHalf;
  }

场景图只是表示矩阵层次结构的一种方式。这是一个简单的人物场景图

root
 └─base
    └─waist
       ├─chest
       │  ├─neck
       │  │  └─head
       │  ├─left arm
       │  │  └─left forearm
       │  │     └─left hand
       │  └─right arm
       │     └─right forearm
       │        └─right hand
       ├─left thigh
       │  └─left leg
       │     └─left foot
       └─right thigh
          └─right left
             └─right foot

所以根据刻板的 webgl 矩阵数学绘制右臂

projectionMatrix * viewMatrix * rootMatrix * baseMatrix
   * waistMatrix * chestMatrix * rightArmMatrix * rightForeArmMatrix
   * rightHandMatrix 

因此,您可以将任何 three.js 场景图转换为纯矩阵数学。如果是

scene.add(pivot);
pivot.add(mesh);

那么你的场景图是这样的

scene
 └─pivot
    └─mesh

所以你需要以

结尾
projectionMatrix * viewMatrix * sceneMatrix * pivotMatrix * meshMatrix

或者换个角度看

modelMatrix = sceneMatrix * pivotMatrix * meshMatrix

projectMatrix * viewMatrix * modelMatrix

场景图本身只是一种简化以通用和灵活的方式组织矩阵的方式,而不是对所有数学进行硬编码。

注意:sceneMatrix 通常是标识,因此您可以将其省略,但从技术上讲,three.js 中的场景是场景图中的另一个节点,因此它本身代表一个矩阵。