如何围绕组内的一个点旋转 Three.js 组?

Posted

技术标签:

【中文标题】如何围绕组内的一个点旋转 Three.js 组?【英文标题】:How can I rotate a Three.js group around a point inside the group? 【发布时间】:2021-09-24 03:23:41 【问题描述】:

tl;dr:目标是改变围绕圆圈的箭头方向。

我们有一种方法可以将形状 (https://imgur.com/a/F6M43kF)(由三个网格组成)添加到场景中。 默认绘制指向右侧,但我们希望给它一个旋转(90°,Pi/2 指向上,180°,Pi 指向右侧等)。中心点(两个圆)应始终在同一位置,只有三角形应围绕中心点旋转。

我们尝试使用欧拉旋转并将轴设置到中心点。 大多数时候,旋转节点会改变位置,但组对象中的 x-y 坐标不会改变。

那么有人可以解决我们如何围绕中心旋转节点吗? 下面我添加了我们用来将节点添加到场景中的代码。

let scene;
let renderer;
let camera;

setup();

//params: xcoord, ycoord, rotation (in degrees)
drawNode(1, 1, 0);

renderer.render(scene, camera);

function setup() 
  scene = new THREE.Scene();

  renderer = new THREE.WebGLRenderer(
    alpha: true, //Tranpart
    antialias: true //For smoother edges
  );

  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  //we use ortographic camera so perspective doesn't manipulate how we see the objects
  //example: https://i.stack.imgur.com/q1SNB.png
  camera = new THREE.OrthographicCamera(
    window.innerWidth / -100, //Camera frustum left plane.
    window.innerWidth / 100, // Camera frustum right plane.
    window.innerHeight / 100, //Camera frustum top plane.   
    window.innerHeight / -100, //Camera frustum bottom plane
    -1, //near — Camera frustum near plane.
    100 //far — Camera frustum far plane.
    //frustum:https://en.wikipedia.org/wiki/Viewing_frustum
  );

  //Creates background grid 
  const gridHelper = new THREE.GridHelper(50, 50);
  gridHelper.rotateX(-Math.PI / 2); //Rotate is necessary because we changed the axis so Z is aimed to the screen
  scene.add(gridHelper);


function drawNode(xcoord, ycoord, rotation) 

  //Small white circle
  const innerCircleGeometry = new THREE.CircleGeometry(1 / 32, 32);
  const innerCircle = new THREE.Mesh(innerCircleGeometry, new THREE.MeshBasicMaterial(
    color: 0xFFFFFF
  ));

  innerCircle.position.set(xcoord, ycoord, 0);

  //Bigger grey circle
  const outerCircleGeometry = new THREE.CircleGeometry(1 / 16, 32);
  const outerCircle = new THREE.Mesh(outerCircleGeometry, new THREE.MeshBasicMaterial(
    color: 0xC4C4C4
  ));

  outerCircle.position.set(xcoord, ycoord, 0);

  //Points of the triangle
  const points = [];
  points.push(new THREE.Vector3(xcoord, ycoord - 1 / 4, 0));
  points.push(new THREE.Vector3(xcoord, ycoord + 1 / 4, 0));
  points.push(new THREE.Vector3(xcoord + 1 / 4, ycoord, 0));
  points.push(new THREE.Vector3(xcoord, ycoord - 1 / 4, 0));

  const geometrytriangle = new THREE.BufferGeometry().setFromPoints(points); //connects the points
  const triangle = new THREE.Mesh(geometrytriangle, new THREE.MeshBasicMaterial(
    side: THREE.DoubleSide,
    color: 0x5C5C5C
  ));

  //Set order so triangle is always on the bottom
  triangle.renderOrder = 0;
  outerCircle.renderOrder = 1;
  innerCircle.renderOrder = 2;

  const nodeGroup = new THREE.Group();
  nodeGroup.add(triangle);
  nodeGroup.add(outerCircle);
  nodeGroup.add(innerCircle);

  //TODO: rotate the node
  //Rotate that goes wrong: nodeGroup.rotateZ(THREE.MathUtils.degToRad(rotation));

  scene.add(nodeGroup);

  //Unique identifer of nodegroup, each child has own uuid.
  return nodeGroup.uuid;
body  min-height: 100vh; 
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
  <script src="https://github.com/mrdoob/three.js/blob/master/examples/jsm/controls/OrbitControls.js"></script>
  <title>Document</title>
</head>

<body>

</body>

</html>

【问题讨论】:

改变组的轴心点 @Rodener Dajes 你能详细说明一下吗?当然,他们已经尝试过了,但没有成功。 ***.com/questions/37779104/… 这能回答你的问题吗? How can I rotate around the center of a group in Three.js 【参考方案1】:

这里的诀窍是所有的旋转大约是 0,0,0。为了旋转箭头,您需要将要旋转的点放在原点的中心,旋转它,然后平移它。

function drawNode(xcoord, ycoord, rotation) 

  //Small white circle
  const innerCircleGeometry = new THREE.CircleGeometry(1 / 32, 32);
  const innerCircle = new THREE.Mesh(innerCircleGeometry, new THREE.MeshBasicMaterial(
    color: 0xFFFFFF
  ));

  innerCircle.position.set(0, 0, 0);

  //Bigger grey circle
  const outerCircleGeometry = new THREE.CircleGeometry(1 / 16, 32);
  const outerCircle = new THREE.Mesh(outerCircleGeometry, new THREE.MeshBasicMaterial(
    color: 0xC4C4C4
  ));

  outerCircle.position.set(0, 0, 0);

  //Points of the triangle
  const points = [];
  points.push(new THREE.Vector3(0, 0 - 1 / 4, 0));
  points.push(new THREE.Vector3(0, 0 + 1 / 4, 0));
  points.push(new THREE.Vector3(0 + 1 / 4, 0, 0));
  points.push(new THREE.Vector3(0, 0 - 1 / 4, 0));

  const geometrytriangle = new THREE.BufferGeometry().setFromPoints(points); //connects the points
  const triangle = new THREE.Mesh(geometrytriangle, new THREE.MeshBasicMaterial(
    side: THREE.DoubleSide,
    color: 0x5C5C5C
  ));

  //Set order so triangle is always on the bottom
  triangle.renderOrder = 0;
  outerCircle.renderOrder = 1;
  innerCircle.renderOrder = 2;

  const nodeGroup = new THREE.Group();
  nodeGroup.add(triangle);
  nodeGroup.add(outerCircle);
  nodeGroup.add(innerCircle);

  nodeGroup.rotateZ(rotation*3.14/180);
  nodeGroup.position.set(xcoord, ycoord, 0)

  scene.add(nodeGroup);

  //Unique identifer of nodegroup, each child has own uuid.
  return nodeGroup.uuid;

您可以查看我的工作示例here

【讨论】:

以上是关于如何围绕组内的一个点旋转 Three.js 组?的主要内容,如果未能解决你的问题,请参考以下文章

使用鼠标围绕中心旋转 Three.js 相机

如何在three.js中围绕对象的中心旋转?

如何围绕轴旋转 Three.js Vector3?

three.js围绕边缘旋转三角形

Three.js - 围绕某个轴旋转球体

three.js 围绕 Y 轴的相机旋转似乎关闭