Reputation: 33
tl;dr:The goal is to change the direction of the arrow around the circle.
We have a method that adds a shape (https://i.sstatic.net/l3lZB.jpg)(that consists of three Meshes) to the scene. Default it's drawn pointing to the right, but we want to give it a rotation (90°, Pi/2 pointing up, 180°, Pi pointing right and so on). The center point (the two circles) should always be at the same palce, only the triangle should rotate around the center point.
We tried working with Euler rotation and setting the axis tot the center point. Most of the time, rotating the node changes the position, but the x-y coordinates aren't changed in the group object.
So someone a solution on how we can rotate the node around the center? Below I've added the code which we use to add the node to the scene.
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.sstatic.net/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>
Upvotes: 3
Views: 1619
Reputation: 113
The trick here is that all rotations are about 0,0,0. In order to rotate the arrow, you need to center the spot you want to rotate about on the origin, rotate it, and then translate it.
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;
}
You can see my working example here
Upvotes: 2