How to Rotate a 3D Object on Axis Three.Js

How to rotate a 3D object on axis three.js?

Here are the two functions I use. They are based on matrix rotations. and can rotate around arbitrary axes. To rotate using the world's axes you would want to use the second function rotateAroundWorldAxis().

// Rotate an object around an arbitrary axis in object space
var rotObjectMatrix;
function rotateAroundObjectAxis(object, axis, radians) {
rotObjectMatrix = new THREE.Matrix4();
rotObjectMatrix.makeRotationAxis(axis.normalize(), radians);

// old code for Three.JS pre r54:
// object.matrix.multiplySelf(rotObjectMatrix); // post-multiply
// new code for Three.JS r55+:
object.matrix.multiply(rotObjectMatrix);

// old code for Three.js pre r49:
// object.rotation.getRotationFromMatrix(object.matrix, object.scale);
// old code for Three.js r50-r58:
// object.rotation.setEulerFromRotationMatrix(object.matrix);
// new code for Three.js r59+:
object.rotation.setFromRotationMatrix(object.matrix);
}

var rotWorldMatrix;
// Rotate an object around an arbitrary axis in world space
function rotateAroundWorldAxis(object, axis, radians) {
rotWorldMatrix = new THREE.Matrix4();
rotWorldMatrix.makeRotationAxis(axis.normalize(), radians);

// old code for Three.JS pre r54:
// rotWorldMatrix.multiply(object.matrix);
// new code for Three.JS r55+:
rotWorldMatrix.multiply(object.matrix); // pre-multiply

object.matrix = rotWorldMatrix;

// old code for Three.js pre r49:
// object.rotation.getRotationFromMatrix(object.matrix, object.scale);
// old code for Three.js pre r59:
// object.rotation.setEulerFromRotationMatrix(object.matrix);
// code for r59+:
object.rotation.setFromRotationMatrix(object.matrix);
}

So you should call these functions within your anim function (requestAnimFrame callback), resulting in a rotation of 90 degrees on the x-axis:

var xAxis = new THREE.Vector3(1,0,0);
rotateAroundWorldAxis(mesh, xAxis, Math.PI / 180);

Rotating an 3D object around it's y-axis in three.js

Simply add galaxy.rotateY(0.005 * Math.PI); to render(), right before renderer.render(scene, camera) call, like this:

// pulled from the CodePen
function render(a) {

// ... omitted for brevity

prevHovered = hovered.slice(0);
attributeSizes.needsUpdate = true;
attributePositions.needsUpdate = true;

galaxy.rotateY(0.005 * Math.PI);

renderer.render(scene, camera);
}

I used a multiplier of 0.005 to give the globe a nice, lazy spin.

The 'galaxy' object is a THREE.Group, a wrapper of sorts for collections of THREE.Object3D objects. The Object3D has all sorts of nifty functions to help rotate, translate, and transform 3D objects. The rotateY() will spin the model around its local y-axis.

Axis change the rotation axis three js

What's happening here is that the origin of your mesh is not at its center, as your duck pictures (well done!) clearly illustrate.

A solution is to translate the mesh's vertices in the Y-direction, so that the origin goes to the middle (also see this answer):

geometry.translate( distX, distY, distZ );

There is also an automatic way of resetting the origin of your mesh by using a bounding box to define its center (that is, you don't have to calculate how far along the Y-axis you should translate the vertices):

// Create a bounding box:
var box = new THREE.Box3().setFromObject( mesh );
// Reset mesh position:
box.center(mesh.position);
mesh.position.multiplyScalar(-1);

Then add the mesh to a pivot object:

var pivot = new THREE.Group();
scene.add(pivot);
pivot.add(mesh);

(See also this answer). You should now be able to rotate your duck around the x-axis as desired.

Loop Rotation on any axis for a 3D obj Three js

The rotation of your object is only changed once : when the model is loaded.

If you want to continuously rotate it, you need to update its rotation every frame. Therefore, you should move the object.rotation.x += 0.01 line inside the animate() function.

var scene6, camera6, renderer6, light, shipMtl, shipObj;
var obj; // global reference to your model, once loaded

function init() {
scene6 = new THREE.Scene();
camera6 = new THREE.PerspectiveCamera(35, 1, 1, 1000);
camera6.position.z = 400;

//LIGHTS
light = new THREE.PointLight(0xffffff, 2, 0);
light.position.set(200, 100, 300);
scene6.add(light);

//3D MODEL
shipMtl = new THREE.MTLLoader();
shipMtl.load('../models/spaceCraft1.mtl', function(materials) {
materials.preload();
shipObj = new THREE.OBJLoader();
shipObj.setMaterials(materials);
shipObj.load('../models/spaceCraft1.obj', function(object) {
object.scale.set(10, 10, 10);
// no need to change the rotation here
obj = object; // put your object as global
scene6.add(object);
});
});

renderer6 = new THREE.WebGLRenderer({ canvas: document.getElementById('model'), antialias: true });
renderer6.setClearColor(0x000000);
renderer6.setPixelRatio(window.devicePixelRatio);

animate6();
}

function animate6() {
requestAnimationFrame(animate6);

obj.rotation.x += 0.01;

renderer6.render(scene6, camera6);
}

window.onload = init;

How do I rotate a mesh group about the axis of a random 3d object/mesh/3d line within the Three.js workspace?

So, yeah, this was a work in progress. And I've now gone far beyond that. For me this was a learning exercise in using Three.js for engineering related analysis. I'd like to share some tips I've learned.

  1. I found this posting with answer from "Stranger in the Q" The code is of a rotating Solar System with Sun, Earth (with revolving moon and rocks) and Mars (with two other planets.) I went through this example very carefully, understanding, really understanding all that was going on. The program made clear how rotations are propagated through to children (Moon rotates around the Earth, while the Earth rotates around the Sun, etc...) The content was managed by a simple object external to the ThreeJS scene. The program uses some recursive functions to manage actions by children elements in the animation functioning. There are some updates required, e.g. the constructor for THREE.Object3d no longer takes names. The corrective action was to simple add a name value after object creation. When you name everything accurately, its much easier to understand the entire child hierarchy. Again this example was instrumental in helping me to understand some of this stuff.

  2. The other thing I found was a posting with an answer from BadAskTechie The response was simple, and directly to the point.

    //rotates a mesh's geometry about a specified axis and pivot
    //the axis is a normalized Vector3
    const rotateAbout = (mesh, axis, axisPosition, angle) => {
    mesh.geometry.applyMatrix(new THREE.Matrix4().makeTranslation(mesh.position.x-axisPosition.x, mesh.position.y-axisPosition.y, mesh.position.z-axisPosition.z)); //translate geometry to axis location
    mesh.geometry.applyMatrix(new THREE.Matrix4().makeRotationAxis(axis, angle)); //rotate geometry about axis
    mesh.geometry.applyMatrix(new THREE.Matrix4().makeTranslation(axisPosition.x-mesh.position.x, axisPosition.y-mesh.position.y, axisPosition.z-mesh.position.z)); //translate geometry back to original location
    }
  3. One tip for complicated nested 3d meshes. Do all the geometry work, including component part orientation / translation / rotation, in the THREE.abcGeometry object stage. Don't create the meshs and then try to orient objects in the scene space. When you do the translations and rotations in geometry, everything lines up perfectly when it comes time for animation. Until I tried that nothing was making sense. The axis directions all seemed mixed up.

  4. There was one technique I found useful. I wanted to know where my elements were located in 3d space during rotation/animation functions. I could not figure out how to do that on 3d mesh objects. There are too many vertices to be useful. Instead I created a simple line object, and maneuver that along with the rest of the assembly during rotations. After an interim move, I could query the line by checking its two vertices, create a new 3d vector.normalize() and utilize that in future calculations. This seemed to work pretty well.

  5. The question I've asked above is really superseded by lots of progress on the whole skateboard truck model problem. Some of the code in the sandbox above is terrible. Please don't even waste time looking at it. Instead, I think what I'll do is open source the completed project, and list the github repo link and demo here, so others can get a glimpse on to my progress on same.

Perhaps that would be of use to others learning ThreeJS.

Rotate ThreeJS Object3D on a tilted Y axis

There are a few ways to achieve this; one solution would be to add additional hierarchy to your scene by introducing a group node. Here the group is added as a child to the scene, and your mesh is added as a child to that group:

this.mesh = new Mesh(this.geometry, this.material);

/* New group */
this.group = new THREE.Group();
/* Tilt group */
this.group.rotateOnAxis(this.axis, Math.degToRad(25));
/* Add mesh to group */
this.group.add( this.mesh );
/* Add group to scene */
this.scene.add( group );

With this added hierarchy, the "axis tilt" is applied to the group instead of to the mesh. In threejs, doing this causes any children (ie mesh) of the group to inherit that tilt as well.

This method provides an intuitive way of combing the tilt with locally applied rotation (ie as you are doing via rotation.y += 0.005) to achieve the desired axis based rotation.

Here's a working codesandbox. Hope that helps!

Alternative method

Alternatively, you could use the rotateY() method to apply a rotation transform around the mesh object's local frame:

this.mesh.rotateY(0.005);

// this.mesh.rotation.y += 0.005 <-- not needed

Here's a working example to demonstrate this approach

three.js rotate Object3d around Y axis at it center

Have a look at Object3D's rotateOnAxis(axis, angle) function.
It should be something like:

//declared once at the top of your code
var axis = new THREE.Vector3(0.5,0.5,0);//tilted a bit on x and y - feel free to plug your different axis here
//in your update/draw function
rad += radIncrement;
object.rotateOnAxis(axis,rad);

HTH

Three.js - Rotate 3D model around real axes

This was in fact nothing to do with my code. It was to do with the model's own origin set in the gltf file. To fix, I looked into the file with a text editor and changed the transformation matrix to be centered correctly. After this it rotated perfectly.

Rotating object around object axis THREE.js

Although it's been over a year since this was originally asked and I figured it out, I thought I'd leave my solution here for anyone else with this issue. If you need to reset the origin of an object so that you can rotate it around its own axis instead of the global origin, use this:

object.geometry.computeBoundingBox();

var boundingBox = object.geometry.boundingBox;

position = new THREE.Vector3();
position.subVectors( boundingBox.max, boundingBox.min );
position.multiplyScalar( 0.5 );
position.add( boundingBox.min );
position.applyMatrix4( object.matrixWorld );

object.geometry.applyMatrix(
new THREE.Matrix4()
.makeTranslation(
-(position.x),
-(position.y),
-(position.z)
)
);

object.geometry.verticesNeedUpdate = true;

object.position.x = position.x;
object.position.y = position.y;
object.position.z = position.z;

How to rotate a object on axis world three.js?

UPDATED: THREE - 0.125.2

DEMO: codesandbox.io

const THREE = require("three");

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.z = 5;

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

const geometry = new THREE.BoxGeometry(1, 1, 1, 4, 4, 4);
const material = new THREE.MeshBasicMaterial({
color: 0x628297,
wireframe: true
});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

// select the Z world axis
const myAxis = new THREE.Vector3(0, 0, 1);
// rotate the mesh 45 on this axis
cube.rotateOnWorldAxis(myAxis, THREE.Math.degToRad(45));

function animate() {
// rotate our object on its Y axis,
// but notice the cube has been transformed on world axis, so it will be tilted 45deg.
cube.rotation.y += 0.008;
requestAnimationFrame(animate);
renderer.render(scene, camera);
}

animate();


Related Topics



Leave a reply



Submit