Rotate object on specific axis anywhere in Three.js - including outside of mesh

Asked
Active3 hr before
Viewed126 times

8 Answers

specificobject
90%

Trying to rotate an object around any axis.,For example like a door hinge (on edge of object) or planet around the sun (outside of object).,If you want to rotate an object around an arbitrary line in world space, you can use the following method. The line is specified by a 3D point and a direction vector (axis).,The problem seems to be defining the axis. The below unit vector results in axis remaining on object's origin (centre) therefor identical to standard rotation:

If you want to rotate an object around an arbitrary line in world space, you can use the following method. The line is specified by a 3D point and a direction vector (axis).

THREE.Object3D.prototype.rotateAroundWorldAxis = function() {

   // rotate object around axis in world space (the axis passes through point)
   // axis is assumed to be normalized
   // assumes object does not have a rotated parent

   var q = new THREE.Quaternion();

   return function rotateAroundWorldAxis(point, axis, angle) {

      q.setFromAxisAngle(axis, angle);

      this.applyQuaternion(q);

      this.position.sub(point);
      this.position.applyQuaternion(q);
      this.position.add(point);

      return this;

   }

}();
88%

I've been spending most of the day trying to rotate a mesh on it's Y axis to face a specific Mesh location.,6 Rotate object on specific axis anywhere in Three.js - including outside of mesh,You want to rotate a mesh on its Y axis, but you're actually rotating on its Z axis, so instead of:,So I'm not sure I understeand why the turret wont rotate to face the specific vector position. I also tried this with Euler rotation by using vec1.angleTo(vec2) and rotate the turret to the specified direction but witouth success.

This is what I have.

   var vector = new THREE.Vector3(0, 0, 5);
   var axis = new THREE.Vector3(0, 1, 0);
   turret.quaternion.setFromUnitVectors(axis, vector.clone().normalize());
load more v
72%

A positive translation on the $Z$-axis moves the object out towards you.,A positive translation on the $Y$-axis moves the object up towards the top of your screen.,A positive translation on the $X$-axis moves the object to the right on your screen.,A negative translation on the $Y$-axis moves the object down towards the bottom of your screen.

Our First Scene: main.js
    camera.position.set(0, 0, 10);
load more v
65%

If this is your site, make sure that the filename case matches the URL. For root URLs (like http://example.com/) you must provide an index.html file. , The site configured at this address does not contain the requested file. , Read the full documentation for more information about using GitHub Pages.

The site configured at this address does not contain the requested file.

If this is your site, make sure that the filename case matches the URL.
For root URLs (like http://example.com/) you must provide an index.html file.

http: //example.com/
load more v
75%

Hi, I’m a newbie of three.js.,I want to rotate each roller of the conveyor around each’s own axis, but as you may notice in the screenshot, the roller that I have tried to roll around is rotating around the center of whole object.,Thank you Mugen. Thank you hofk. I have searched on the internet more and found the proper solution to my situation on the stackoverflow. (https://stackoverflow.com/questions/26836065/rotating-object-around-object-axis-three-js),After inspecting your asset in the three.js editor the geometries are indeed not centered. And thus their pivot point is off.

For anyone who has encountered same issue, here is the part of my code.

function loadModel() {
   var position = new THREE.Vector3();
   object.traverse(function(child) {
      if (child.name == "Cylinder") {
         child.geometry.computeBoundingBox();
         var boundingBox = child.geometry.boundingBox;
         position.subVectors(boundingBox.max, boundingBox.min);
         position.multiplyScalar(0.5);
         position.add(boundingBox.min);
         position.applyMatrix4(object.matrixWorld);
         child.geometry.applyMatrix4(
            new THREE.Matrix4()
            .makeTranslation(
               -(position.x),
               -(position.y),
               -(position.z)
            )
         );
         child.verticesNeedUpdate = true;
         child.position.set(position.x, position.y, position.z);
         child.rotation.z = 2 * Math.PI * Math.random();
      }
   });
   scene.add(object);
}
40%

First we'll make a function that creates a new material with the specified color. Then it creates a mesh using the specified geometry and adds it to the scene and sets its X position.,As you can see we have 3 Mesh objects each referencing the same BoxGeometry. Each Mesh references a unique MeshPhongMaterial so that each cube can have a different color.,A Geometry (the shape of the object),Light objects represent different kinds of lights.

First let's load three.js

<script type="module">
   import * as THREE from './resources/threejs/r132/build/three.module.js';
</script>

Next we need is a <canvas> tag so...

<body>
   <canvas id="c"></canvas>
</body>

We will ask three.js to draw into that canvas so we need to look it up.

<script type="module">
import * as THREE from './resources/threejs/r132/build/three.module.js';

+function main() {
+  const canvas = document.querySelector('#c');
+  const renderer = new THREE.WebGLRenderer({canvas});
+  ...
</script>

Next up we need a camera. We'll create a PerspectiveCamera.

const fov = 75;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 5;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);

The camera defaults to looking down the -Z axis with +Y up. We'll put our cube at the origin so we need to move the camera back a little from the origin in order to see anything.

camera.position.z = 2;

Next we make a Scene. A Scene in three.js is the root of a form of scene graph. Anything you want three.js to draw needs to be added to the scene. We'll cover more details of how scenes work in a future article.

const scene = new THREE.Scene();

Next up we create a BoxGeometry which contains the data for a box. Almost anything we want to display in Three.js needs geometry which defines the vertices that make up our 3D object.

const boxWidth = 1;
const boxHeight = 1;
const boxDepth = 1;
const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);

We then create a basic material and set its color. Colors can be specified using standard CSS style 6 digit hex color values.

const material = new THREE.MeshBasicMaterial({
   color: 0x44aa88
});
  1. A Geometry (the shape of the object)
  2. A Material (how to draw the object, shiny or flat, what color, what texture(s) to apply. Etc.)
  3. The position, orientation, and scale of that object in the scene relative to its parent. In the code below that parent is the scene.
const cube = new THREE.Mesh(geometry, material);

And finally we add that mesh to the scene

scene.add(cube);

We can then render the scene by calling the renderer's render function and passing it the scene and the camera

renderer.render(scene, camera);

Here's our loop

function render(time) {
   time *= 0.001; // convert time to seconds

   cube.rotation.x = time;
   cube.rotation.y = time;

   renderer.render(scene, camera);

   requestAnimationFrame(render);
}
requestAnimationFrame(render);

It's a little better but it's still hard to see the 3d. What would help is to add some lighting so let's add a light. There are many kinds of lights in three.js which we'll go over in a future article. For now let's create a directional light.

{
   const color = 0xFFFFFF;
   const intensity = 1;
   const light = new THREE.DirectionalLight(color, intensity);
   light.position.set(-1, 2, 4);
   scene.add(light);
}

We also need to change the material. The MeshBasicMaterial is not affected by lights. Let's change it to a MeshPhongMaterial which is affected by lights.

-
const material = new THREE.MeshBasicMaterial({
   color: 0x44aa88
}); // greenish blue
+
const material = new THREE.MeshPhongMaterial({
   color: 0x44aa88
}); // greenish blue

First we'll make a function that creates a new material with the specified color. Then it creates a mesh using the specified geometry and adds it to the scene and sets its X position.

function makeInstance(geometry, color, x) {
   const material = new THREE.MeshPhongMaterial({
      color
   });

   const cube = new THREE.Mesh(geometry, material);
   scene.add(cube);

   cube.position.x = x;

   return cube;
}

Then we'll call it 3 times with 3 different colors and X positions saving the Mesh instances in an array.

const cubes = [
   makeInstance(geometry, 0x44aa88, 0),
   makeInstance(geometry, 0x8844aa, -2),
   makeInstance(geometry, 0xaa8844, 2),
];

Finally we'll spin all 3 cubes in our render function. We compute a slightly different rotation for each one.

function render(time) {
   time *= 0.001; // convert time to seconds

   cubes.forEach((cube, ndx) => {
      const speed = 1 + ndx * .1;
      const rot = time * speed;
      cube.rotation.x = rot;
      cube.rotation.y = rot;
   });

   ...

es6 modules can be loaded via the import keyword in a script or inline via a <script type="module"> tag. Here's an example of both

<script type="module">
   import * as THREE from './resources/threejs/r132/build/three.module.js';

   ...
</script>

References to the same script will only be loaded once as long as their absolute paths are exactly the same. For three.js this means it's required that you put all the examples libraries in the correct folder structure

someFolder
   |
   ├-build |
   |
   |
   + -three.module.js |
   + -examples |
   + -jsm |
   + -controls |
   |
   |
   + -OrbitControls.js |
   + -TrackballControls.js |
   + -...
   |
   + -loaders |
   |
   |
   + -GLTFLoader.js |
   + -...
   |
   ...

The reason this folder structure is required is because the scripts in the examples like OrbitControls.js have hard coded relative paths like

import * as THREE from '../../../build/three.module.js';

Using the same structure assures then when you import both three and one of the example libraries they'll both reference the same three.module.js file.

import * as THREE from './someFolder/build/three.module.js';
import {
   OrbitControls
} from './someFolder/examples/jsm/controls/OrbitControls.js';

This includes when using a CDN. Be sure your path to three.module.js ends with /build/three.modules.js. For example

import * as THREE from 'https://unpkg.com/[email protected]/build/three.module.js';
import {
   OrbitControls
} from 'https://unpkg.com/[email protected]/examples/jsm/controls/OrbitControls.js';
load more v
22%

Around 2006–2007, Mozilla started work on an experimental 3D canvas implementation. This became WebGL, which gained traction among browser vendors, and was standardized around 2009–2010. WebGL allows you to create real 3D graphics inside your web browser; the below example shows a simple rotating WebGL cube:,This article will focus mainly on 2D canvas, as raw WebGL code is very complex. We will however show how to use a WebGL library to create a 3D scene more easily, and you can find a tutorial covering raw WebGL elsewhere — see Getting started with WebGL.,Let's look at a simple example of how to create something with a WebGL library. We'll choose Three.js, as it is one of the most popular ones. In this tutorial we'll create the 3D spinning cube we saw earlier.,Optimizing animation of graphics is an entire specialty of programming, with lots of clever techniques available. Those are beyond what we need for our example, though!

<canvas width="320" height="240"></canvas>
load more v
60%

Let's take a snowperson as our basic example. A snowperson is a composite object comprised of three or four components: three white spheres and an optional orange cone for the nose. (No, we're not doing anything as complicated as Olaf.) ,If you offset the cone downward by half its height and set the inner rotation to zero, the point of the cone is at the origin of the outer frame, and we can rotate the cone around its apex. Very cool! ,You should usually choose frames for your composite objects that make it easy to position them within your scene (or a larger composite object that they are components of). ,Rotating around something other than the center of an object is very useful. Here's how we might model a jointed leg:

Here is the function that makes the snowperson:

load more v

Other "specific-object" queries related to "Rotate object on specific axis anywhere in Three.js - including outside of mesh"