Edupala

Comprehensive Full Stack Development Tutorial: Learn Ionic, Angular, React, React Native, and Node.js with JavaScript

Understanding Object3D in Three.js: The Role of Lights, Cameras, and 3D Objects

Object3D in Three.js:

When diving into the realm of Three.js, you’ll quickly encounter the concept of 3D objects. But what exactly are they, and how do they function within this powerful JavaScript library? Let’s unravel this mystery together.

The Foundation: threejs Object3D base class

At the heart of Three.js lies a fundamental class called Object3D. Think of it as the DNA that all 3D entities in Three.js share. This class bestows upon its children a set of essential properties and methods that allow them to exist and interact within a three-dimensional space. Object3D is the base class for all 3D objects in Three.js. Most objects, including meshes, groups, lines, and points, inherit from Object3D. This gives them properties and methods such as:

What can these object3D in Three.js do?

  1. Position (position.x, position.y, position.z)
  2. Rotation (rotation.x, rotation.y, rotation.z)
  3. Scale (scale.x, scale.y, scale.z)
  4. add() and remove() methods to add or remove child objects.

1. Position: Moving the Object

The position property controls where an object is located in 3D space. It consists of three coordinates: position.x, position.y, and position.z.

  • X-axis:
    • Positive X moves the object to the right.
    • Negative X moves the object to the left.
  • Y-axis:
    • Positive Y moves the object up.
    • Negative Y moves the object down.
  • Z-axis:
    • Positive Z moves the object closer to the camera (towards the viewer).
    • Negative Z moves the object farther away from the camera (into the screen).
object.position.set(10, 5, -15);

This places the object:

  • 10 units to the right (X),
  • 5 units up (Y),
  • 15 units away (Z).

2. The base class object3D Rotation in threejs: Spinning the Object

The rotation property defines how an object is rotated around its X, Y, and Z axes, measured in radians (where 2π radians = 360°).

  • X-axis:
    • Rotating around the X-axis tilts the object up or down (like nodding your head).
    • Positive values spin the object clockwise as viewed from the right side.
    • Negative values spin it counterclockwise.
  • Y-axis:
    • Rotating around the Y-axis turns the object left or right (like shaking your head “no”).
    • Positive values spin the object clockwise as viewed from above.
    • Negative values spin it counterclockwise.
  • Z-axis:
    • Rotating around the Z-axis spins the object like the hands of a clock (like turning a wheel).
    • Positive values spin the object clockwise as viewed from the front.
    • Negative values spin it counterclockwise.

Example:

jsCopy codeobject.rotation.set(Math.PI / 2, 0, Math.PI / 4); // Rotation in radians

This rotates the object:

  • 90° around the X-axis (tilting it up),
  • 0° around the Y-axis (no rotation),
  • 45° around the Z-axis (clockwise spin).

3. Scale: Resizing the Object

The scale property controls how big or small the object is along each axis. The default scale is 1 for all axes (meaning the object is its original size).

  • X-axis:
    • Controls how wide the object is.
    • Values greater than 1 make the object wider; values less than 1 make it narrower.
  • Y-axis:
    • Controls how tall the object is.
    • Values greater than 1 make the object taller; values less than 1 make it shorter.
  • Z-axis:
    • Controls how deep the object is (how far it extends forward/backward).
    • Values greater than 1 make the object thicker; values less than 1 make it thinner.

Example:

jsCopy codeobject.scale.set(2, 0.5, 3);

This scales the object:

  • 2x wider along the X-axis,
  • 0.5x shorter along the Y-axis (half the original height),
  • 3x deeper along the Z-axis.

The Visible and the Invisible

Now, here’s where it gets interesting. In Three.js, not all 3D objects are created equal. Some you can see, others you can’t – but they’re all 3D objects nonetheless.

The Tangible World

First, let’s talk about the objects you can actually see:

  1. Meshes: These are your bread and butter. Cubes, spheres, complex models – if you can see it, it’s probably a mesh.
  2. Lines: Want to draw in 3D space? Lines are your go-to.
  3. Points: Imagine a starfield. Each star? That’s a point.

These visible objects inherit from Object3D, which means they can be moved, rotated, and scaled just like you’d expect in a 3D world.

The Unseen Influencers

But here’s the twist – some of the most important 3D objects in Three.js are ones you can’t see at all:

  1. Lights: These invisible objects bathe your scene in illumination. A PointLight might not have a visible form, but move it around, and watch how it transforms the mood of your entire scene.
  2. Cameras: Think of these as your eyes in the 3D world. They don’t have a physical presence, but their position and orientation determine everything you see.

Both lights and cameras, despite their lack of visible geometry, are full-fledged 3D objects. They can be positioned, rotated, and even scaled (though scaling a camera might lead to some interesting effects).

Bringing It All Together

The beauty of Three.js lies in how it treats all these entities – visible or invisible – as part of the same 3D ecosystem. This unified approach means you can:

  • Group a light with a mesh and move them together
  • Parent a camera to a moving object for a dynamic view
  • Apply the same transformation techniques to everything in your scene.

Lights and Cameras: Direct Inheritors of Object3D

As mentioned in our previous content, both lights and cameras in Three.js do indeed inherit directly from the Object3D class. This inheritance is crucial as it allows these elements to be positioned, rotated, and transformed in 3D space, even though they don’t have visible geometry.

  1. Lights:
    • All light types (PointLight, DirectionalLight, SpotLight, etc.) inherit from Light, which in turn inherits from Object3D.
    • This means you can use methods like position.set() or properties like rotation on any light object.
  2. Cameras:
    • Both perspective and orthographic cameras inherit directly from Object3D.
    • This allows you to move and orient cameras in your scene just like any other 3D object.

Scene: Also an Object3D

The Scene class in Three.js also inherits from Object3D. This might seem surprising at first, but it makes sense when you consider that:

  • A scene can be positioned, rotated, or scaled as a whole.
  • You can add a scene to another scene (though this is rarely done in practice).

The scene’s inheritance from Object3D allows for interesting possibilities, such as having multiple scenes in a single 3D world, each with its own position and orientation.

Group: A Special Kind of Object3D

The Group class in Three.js is essentially a bare-bones Object3D. It doesn’t add any new properties or methods to Object3D, but it serves a crucial purpose:

  • Groups allow you to organize and manipulate multiple objects as a single unit.
  • When you transform a group, all of its children are transformed relative to the group’s coordinates.
  • This is incredibly useful for creating complex, hierarchical structures in your 3D scenes.

Renderer: Not an Object3D

The renderer in Three.js (like WebGLRenderer) does not inherit from Object3D. Here’s why:

  • The renderer is not a 3D object in the scene; it’s the tool that draws the 3D scene onto a 2D canvas.
  • It doesn’t need properties like position or rotation in 3D space.
  • Instead, the renderer has its own set of properties and methods related to how it renders the scene, such as setSize(), render(), etc.

Key Takeaways

  1. Lights, cameras, scenes, and groups all inherit from Object3D, giving them the ability to exist and be manipulated in 3D space.
  2. This shared inheritance is what allows for the flexible and intuitive manipulation of 3D scenes in Three.js.
  3. The renderer, being a tool for drawing rather than an object in the scene, does not inherit from Object3D.

Understanding this inheritance structure is crucial for effectively working with Three.js, as it informs how you can manipulate and organize the various elements in your 3D scenes.

By understanding that everything stems from Object3D, you gain the power to manipulate your 3D world with consistency and flexibility. Whether you’re crafting a visible landscape or setting up the invisible stage that makes it all look stunning, you’re working with the same fundamental tools.

  • Position moves the object in 3D space along the X, Y, and Z axes.
  • Rotation spins the object around its own axes (like rotating around its center).
  • Scale resizes the object along the three dimensions (X for width, Y for height, Z for depth).

Visualization of the Axes:

  • The X-axis is the horizontal line, moving left to right.
  • The Y-axis is the vertical line, moving up and down.
  • The Z-axis is the depth line, moving in and out of the screen.

Example of threejs with object, camera, animation and more.

Let create 3Djs example contating solar system with a sun and a planet. The sun is stationary but rotates, while the planet rotates around its own axis and revolves around the sun. Here’s a breakdown of the code:

  1. We set up the scene, camera, and renderer.
  2. We create a yellow sphere to represent the sun.
  3. We create a blue sphere to represent a planet, positioned away from the sun.
  4. We add ambient light to provide some general illumination.
  5. We add a point light at the center to represent the sun’s light.
  6. In the animation function, we rotate the sun and make the planet both rotate and revolve around the sun.
  7. We handle window resizing to make the scene responsive.
  8. Finally, we start the animation loop.
Threejs example animation

This example demonstrates several Three.js concepts including creating and positioning objects, adding different types of lights, and animating objects in the scene.

import * as THREE from "three";

// Step 1. Create the scene
const scene = new THREE.Scene();

// Step 2. Set up the camera
const camera = new THREE.PerspectiveCamera(
  45,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
camera.position.z = 50;

//Step 3. Set up the renderer
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// Step 4. Create the sun
const sunGeometry = new THREE.SphereGeometry(5, 32, 32);
const sunMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 });
const sun = new THREE.Mesh(sunGeometry, sunMaterial);
scene.add(sun);

// 5. Create a planet
const planetGeometry = new THREE.SphereGeometry(2, 32, 32);
const planetMaterial = new THREE.MeshPhongMaterial({ color: 0x4f4cb0 });
const planet = new THREE.Mesh(planetGeometry, planetMaterial);
planet.position.x = 20; // Position the planet 20 units away from the sun
scene.add(planet);

// 6. Add ambient light
const ambientLight = new THREE.AmbientLight(0xffffff);
scene.add(ambientLight);

// 7. Add a point light (sun light)
const sunLight = new THREE.PointLight(0xffffff, 1, 100);
scene.add(sunLight);

// 8. Animation function
function animate() {
  requestAnimationFrame(animate);

  // Rotate the sun
  sun.rotation.y += 0.005;

  // Rotate and revolve the planet
  planet.rotation.y += 0.01;
  const time = Date.now() * 0.001; // Get the time in seconds
  planet.position.x = Math.cos(time) * 20;
  planet.position.z = Math.sin(time) * 20;

  renderer.render(scene, camera);
}

// 9. Handle window resizing
window.addEventListener("resize", () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

// 10. Start the animation
animate();

To add background color to the scene, you can add this code after creating the scene.

scene.background = new THREE.Color(0x451804);

Example 2 Of threejs

This example creates a simple solar system with a sun, a planet, and a moon. Here’s a breakdown of the key differences and similarities:

  1. Scene Setup: We’re using a 210535 as background to represent space.
  2. Objects: we have a sun (yellow sphere), a planet (blue sphere), and a moon (gray sphere).
  3. Lighting: We’re using both ambient light and a point light to represent the sun’s light.
  4. Orbit Controls: The OrbitControls are implemented similarly to your original code.
  5. Animation: The animation function now handles the rotation and revolution of the planet around the sun, and the moon around the planet.
  6. Responsiveness: We still handle window resizing to keep the scene responsive.

This example demonstrates more complex object relationships (the moon is a child of the planet) and orbital movements, while still using many of the same Three.js concepts as your original code.

Threejs complex example
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";

// Get the canvas element
const canvas = document.getElementById("canvas");

// 1. Create the scene
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x210535);

// 2. Set up the camera
const camera = new THREE.PerspectiveCamera(
  45,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
camera.position.z = 50;

// 3. Create objects: Sun, Planet, and Moon
const sunGeometry = new THREE.SphereGeometry(5, 32, 32);
const sunMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 });
const sun = new THREE.Mesh(sunGeometry, sunMaterial);
scene.add(sun);

const planetGeometry = new THREE.SphereGeometry(2, 32, 32);
const planetMaterial = new THREE.MeshPhongMaterial({
  color: 0x0474fb,
  specular: 0x333333,
  shininess: 5,
  normalScale: new THREE.Vector2(0.5, 0.5),
});
const planet = new THREE.Mesh(planetGeometry, planetMaterial);
planet.position.x = 20;
scene.add(planet);

const moonGeometry = new THREE.SphereGeometry(0.5, 32, 32);
const moonMaterial = new THREE.MeshStandardMaterial({
  color: 0xaaaaaa,
  roughness: 0.8,
  metalness: 0.2,
});
const moon = new THREE.Mesh(moonGeometry, moonMaterial);
moon.position.x = 3;
planet.add(moon); // The moon orbits the planet

// 4. Add lighting
const ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);

const sunLight = new THREE.PointLight(0xffffff, 1, 100);
scene.add(sunLight);

// 5. Set up the renderer
const renderer = new THREE.WebGLRenderer({ canvas });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);

// 6. Add Orbit controls
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.enableZoom = true;
controls.enablePan = true;

// 7. Animation function
const animate = () => {
  requestAnimationFrame(animate);

  // Rotate the sun
  sun.rotation.y += 0.005;

  // Rotate and revolve the planet
  planet.rotation.y += 0.01;
  const time = Date.now() * 0.001;
  planet.position.x = Math.cos(time * 0.3) * 20;
  planet.position.z = Math.sin(time * 0.3) * 20;

  // Rotate and revolve the moon
  moon.rotation.y += 0.02;
  const moonTime = Date.now() * 0.002;
  moon.position.x = Math.cos(moonTime) * 3;
  moon.position.z = Math.sin(moonTime) * 3;

  controls.update();
  renderer.render(scene, camera);
};

// 8. Start the animation
animate();

// 9. Handle window resizing
window.addEventListener("resize", () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

Orbit Controls to allow interact with 3D object

Let’s break down what Orbit Controls are and how they’re implemented in your Three.js scene.

Orbit Controls is a feature in Three.js that allows users to interact with the 3D scene using their mouse or touch input. It enables rotating, zooming, and panning around a target point in the scene, typically the center of the scene or a specific object.

Threejs orbit controls

Step 1: creates a new instance of OrbitControls. It takes two parameters:

  • camera: The camera that OrbitControls will move.
  • renderer.domElement: The DOM element to listen for mouse / touch events.

Step 2 : Configuring the controls:

javascriptCopycontrols.enableDamping = true;
controls.dampingFactor = 0.05;
  • enableDamping: When true, adds inertia to the controls. This means that when you rotate the camera, it will continue to move slightly after you release the mouse, creating a smoother feel.
  • dampingFactor: Controls the inertia. A lower value will make the movement more fluid but slower to stop.
  • Zoom: javascriptCopycontrols.enableZoom = true; This allows the user to zoom in and out using the mouse wheel or pinch gestures on touch devices.
  • javascriptCopycontrols.enablePan = true; This allows the user to pan the camera (move it up, down, left, or right) using the right mouse button or touch gestures.
  • Updating the controls: javascriptCopycontrols.update();

With these controls in place, users can interact with your solar system scene in the following ways:

  • Left-click and drag (or one-finger drag on touch devices) to orbit around the scene.
  • Scroll the mouse wheel (or pinch on touch devices) to zoom in and out.
  • Right-click and drag (or three-finger drag on touch devices) to pan the camera.

These interactions make your 3D scene more engaging and allow users to explore the solar system from different angles and distances. The damping effect makes the interactions feel smoother and more natural.

Conclusion :

So next time you’re building a Three.js project, remember: every entity in your scene, whether you can see it or not, is a 3D object at heart. This shared heritage is what makes Three.js both powerful and intuitive for bringing 3D worlds to life on the web.

Related blog post on nextjs

  1. Comprehensive Guide to Integrating Three.js with Next.js

Understanding Object3D in Three.js: The Role of Lights, Cameras, and 3D Objects

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top