javascript - 如何围绕组内的某个点旋转 Three.js 组?

标签 javascript three.js html5-canvas

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

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

我们尝试使用欧拉旋转并将轴设置为中心点。 大多数情况下,旋转节点会改变位置,但组对象中的 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: /image/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>

最佳答案

这里的技巧是所有旋转都大约为 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

关于javascript - 如何围绕组内的某个点旋转 Three.js 组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68390081/

相关文章:

javascript - 需要将光标位置设置到 contentEditable div 的末尾,选择和范围对象问题

javascript - 在 Web Audio API 中转换采样率

javascript - 使 typescript 函数可用于窗口命名空间

Three.js 法线贴图渲染方式不同 windows/mac

javascript - 检查上传的图片是否被压缩

javascript - HTML5 Canvas - drawImage 并不总是绘制图像

javascript - 将图像一层层堆叠

javascript - 在 three.js 中挤出一条线

javascript - 根据管端法线将旋转应用于圆柱体

javascript - 请解释这段代码的逻辑是什么以及kinetic js部分