Three.js InsatncedMesh rotation on each instance does not change - three.js

I am using instancedmesh to show tons of objects on scene.
How can I translate the rotation of each instance likes correct rectangle shape.Current condition is all of the instances are bending to the left side, I want to get red rectangle like below image.
Please check the image link: https://i.stack.imgur.com/jpAhb.png
I tried to set the Eucler and Quaternion on following code but not reflected.
var dummy = new THREE.Object3D();
let finalMatrix = new THREE.Matrix4();
child.geometry.computeBoundingBox();
let matrix = new THREE.Vector3();
let offset = child.geometry.boundingBox.getCenter(matrix);
finalMatrix.makeTranslation(-offset.x, -offset.y, -offset.z);
child.geometry.applyMatrix4(finalMatrix);
dummy.position.copy(offset);
dummy.updateMatrix();
INSTANCEMESH.setMatrixAt(i, dummy.matrix);
INSTANCEMESH.setColorAt(i, child.material.color);
Quaternion
{
"_x": 0,
"_y": 0,
"_z": 0,
"_w": 1
}
Eucler
{
"_x": 0,
"_y": 0,
"_z": 0,
"_order": "XYZ"
}
Do you know how to solve this problem?
Thanks.

Related

Three js: How to get normal of rotated plane

I am trying to get normal of rotated plane. My solution is to copy the updated plane then get normals.
It is working when I rotate by only 1 angle, but not works in rotating by 2 or 3 angles. jsFiddle
Green one is copied plane, purple one rotated plane.
enter image description here
How to solve this? Please help me
My copy function:
function copyPlane() {
let copyPlaneGeom = new THREE.PlaneGeometry(3, 3, 3);
copyPlaneGeom.rotateX(plane.rotation.x);
copyPlaneGeom.rotateY(plane.rotation.y);
copyPlaneGeom.rotateZ(plane.rotation.z);
let copyPlane = new THREE.Mesh(copyPlaneGeom, new THREE.MeshBasicMaterial({color: 0x00ff00}));
scene.add(copyPlane)
let normals = copyPlane.geometry.faces[0].normal
I think with that approach, you'll always get a vector of 0, 0, 1 because a plane's face normal is always (0, 0, 1) * objectRotation.
Instead, try starting with a Vector3 of 0, 0, 1, and then apply the object's rotation to it:
var originalNormal = new Vector3(0, 0, 1);
// Get the mesh rotation
var objRotation = plane.rotation;
// Apply mesh rotation to vector
originalNormal.applyEuler(objRotation);
now you have a Vector3 with the updated wold normal, instead of the local normal! Read about .applyEuler() here.

Three js: How to normalize a mesh generated by vertices

I'm somewhat new to Three js, and my linear algebra days were back in the 90s so I don't recall much about quarternions. My issue is I have 8 vertices for a cube that I can use to create a custom geometry mesh from, but it doesn't set the position / rotation / scale info for its world matrix. Therefor it can not be used cleanly by other three js modules like controls. I can look up the math and calculate what position / scale / rotation (rotation gets a bit hairy with some fun acos stuff) should be and create a standard boxgeometry from that. But it seems like there should be some way to do it via three js objects if I can generate the proper matrix to apply to it. The quarternion setFromUnitVectors looked interesting, but I'd still have to do some work to generate the vectors. Any ideas would be appreciated thanks
Edit: :) So let me try and simplify. I have 8 vertices, I want to create a box geometry. But box geometry doesn't take vertices. It takes width, height, depth (relatively easy to calculate) and then you set the position/scale/rotation. So here's my code thus far:
5____4
1/___0/|
| 6__|_7
2/___3/
const box = new Box3();
box.setFromPoints(points);
const width = points[1].distanceTo(points[0]);
const height = points[3].distanceTo(points[0]);
const depth = points[4].distanceTo(points[0]);
const geometry = new BoxGeometry(width, height, depth);
mesh = new Mesh(geometry, material);
const center = box.getCenter(new Vector3());
const normalizedCorner = points[0].clone().sub(center);
const quarterian = new Quaternion();
quarterian.setFromUnitVectors(geometry.vertices[0], normalizedCorner);
mesh.setRotationFromQuaternion(quarterian);
mesh.position.copy(center);
The problem being my rotation element is wrong (besides my vectors not being unit vectors). I'm apparently not getting the correct quarternion to rotate my mesh correctly.
Edit: From WestLangley's suggestion, I'm creating a rotation matrix. However, while it rotates in the correct plane, the angle is off. Here's what I have added:
const matrix = new Matrix4();
const widthVector = new Vector3().subVectors(points[6], points[7]).normalize();
const heightVector = new Vector3().subVectors(points[6], points[5]).normalize();
const depthVector = new Vector3().subVectors(points[6], points[2]).normalize();
matrix.set(
widthVector.x, heightVector.x, depthVector.x, 0,
widthVector.y, heightVector.y, depthVector.y, 0,
widthVector.z, heightVector.z, depthVector.z, 0,
0, 0, 0, 1,
);
mesh.quaternion.setFromRotationMatrix(matrix);
Per WestLangley's comments I wasn't creating my matrix correctly. The correct matrix looks like:
const matrix = new Matrix4();
const widthVector = new Vector3().subVectors(points[7], points[6]).normalize();
const heightVector = new Vector3().subVectors(points[5], points[6]).normalize();
const depthVector = new Vector3().subVectors(points[2], points[6]).normalize();
matrix.set(
widthVector.x, heightVector.x, depthVector.x, 0,
widthVector.y, heightVector.y, depthVector.y, 0,
widthVector.z, heightVector.z, depthVector.z, 0,
0, 0, 0, 1,
);
mesh.quaternion.setFromRotationMatrix(matrix);

Orbiting a cube in WebGL with glMatrix

https://jsfiddle.net/sepoto/Ln7qvv7w/2/
I have a base set up to display a cube with different colored faces. What I am trying to do is set up a camera and apply a combined X axis and Y axis rotation so that the cube spins around both axis concurrently. There seems to be some problems with the matrices I set up as I can see the blue face doesn't look quite right. There are some examples of how this is done using older versions of glMatrix however the code in the examples no longer works because of some changes in vec4 of the glMatrix library. Does anyone know how this can be done using the latest version of glMatrix as I have attached a CDN to the fiddle?
Thank you!
function drawScene() {
gl.viewport(0,0,gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.ortho( mOrtho, -5, 5, 5, -5, 2, -200);
mat4.identity(mMove);
var rotMatrix = mat4.create();
mat4.identity(rotMatrix);
rotMatrix = mat4.fromYRotation(rotMatrix, yRot,rotMatrix);
rotMatrix = mat4.fromXRotation(rotMatrix, xRot,rotMatrix);
mat4.multiply(mMove, rotMatrix, mMove);
setMatrixUniforms();
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, triangleVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, triangleColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, triangleColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, triangleVertexPositionBuffer.numItems);
yRot += 0.01;
xRot += 0.01;
}
As the name says, fromYRotation() initializes a matrix to a given rotation. Hence, you need two temporary matrices for the partial rotations, which you can then combine:
var rotMatrix = mat4.create();
var rotMatrixX = mat4.create();
var rotMatrixY = mat4.create();
mat4.fromYRotation(rotMatrixY, yRot);
mat4.fromXRotation(rotMatrixX, xRot);
mat4.multiply(rotMatrix, rotMatrixY, rotMatrixX);
And the reason why your blue face was behaving strangely, was the missing depth test. Enable it in your initialization method:
gl.enable(gl.DEPTH_TEST);
You dont need to use three matrices:
// you should do allocations outside of the renderloop
var rotMat = mat4.create();
// no need to set the matrix to identity as
// fromYRotation resets rotMats contents anyway
mat4.fromYRotation(rotMat, yRot);
mat4.rotateX(rotMat,xRot);

How to rotate an object to make it face a certain direction?

If I know what direction an object is facing for example (0, 0, 1). What is the easiest way to rotate the object to face a direction vector of (1, 1, 1)?
Edit:
I've tried this, but something is wrong with this logic:
var newDir = new THREE.Vector3(1,1,1);
var objectDir= new THREE.Vector3(0, 0, 1);
objectDir.applyQuaternion(object.quaternion); // rotate this vector to object's facing direction
var pos = new THREE.Vector3();
pos.addVectors(newDir, object.position);
var axis = objectDir.cross(newDir).normalize();
var angle = objectDir.angleTo(pos);
object.rotateOnAxis(axis, angle);
Solved it with lookAt:
var newDir = new THREE.Vector3(1, 1, 1);
var pos = new THREE.Vector3();
pos.addVectors(newDir, object.position);
object.lookAt(pos);

Create ArrowHelper with correct rotation

How do I create an ArrowHelper in Three.js (r58) with correct rotation?
var point1 = new THREE.Vector3(0, 0, 0);
var point2 = new THREE.Vector3(10, 10, 10);
var direction = new THREE.Vector3().subVectors(point1, point2);
var arrow = new THREE.ArrowHelper(direction.normalize(), point1);
console.log(arrow.rotation);
I always end up with with Object {x: 0, y: 0, z: 0} for the arrow rotation. What am I doing wrong?
ArrowHelper uses quaternions to specify it's orientation.
If you do this:
var rotation = new THREE.Euler().setFromQuaternion( arrow.quaternion );
you will see an equivalent orientation expressed in Euler angles, although in r.59, arrow.rotation is now automatically updated, so you will no longer see zeros.
EDIT: answer updated to three.js r.59

Resources