Command Palette

Search for a command to run...

Hectal
Course outline
Topic 3.4Beginner ~18 min · step 4 of 7

Object3D and Transforms

In one line

Meshes, lights, cameras and groups are all Object3Ds with a position, rotation, scale and visibility. You learn add, remove, traverse and getObjectByName, and what happens when an object is hidden, scaled to 0, placed behind the camera or added twice.

0/7 · 0%

Think of it like this

Every item in a shop has a label with the same fields: where it is, which way it faces, how big, and whether it is on display. A lamp, a chair and a shelf are different things, but the label is the same. In three.js that label is Object3D.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

Object3D
The base class of everything in a scene. It has a position, rotation, scale, visibility, a name, a parent and children.
Group
An Object3D that draws nothing itself. It exists to carry children so they move, turn and scale together.
parent / child
An object inside another. Its position is measured from its parent's origin, and it moves with the parent.
traverse
Visit an object and all its descendants, calling a function on each.

Step by step

01Make and place an object

const mesh = new THREE.Mesh(geometry, material); mesh.position.set(1, 0.3, 0); mesh.rotation.y = Math.PI / 4; mesh.scale.set(1, 2, 1). scene.add(mesh) puts it in the tree.

02Give it a name

mesh.name = "orange" costs nothing and lets you find it: scene.getObjectByName("orange"). The scene inspector under each canvas also shows names.

03Hide it, remove it, or scale it

visible = false keeps it in the tree and skips drawing; remove takes it out; scale = 0 still draws it, invisibly. The first example prints the draw calls for each.

04Visit everything

scene.traverse((o) => ...) visits the scene, then every object below it. The example counts six: the scene, two lights and three boxes. Lights are objects too.

Try it yourself

  1. 1

    Remove instead of hiding

    In the first example replace b.visible = false; with scene.remove(b);. The draw calls are the same (2) and scene still holds it prints false. But a later line, scene.getObjectByName("blue").visible, fails with Uncaught TypeError: Cannot read properties of undefined (reading 'visible'), because the name finds nothing. Hidden objects stay in the tree; removed ones leave it.

  2. 2

    Add the same box twice

    Add scene.add(a); console.log("children:", scene.children.length); just before function draw(label) {. It prints children: 5: the second add did nothing. Now try scene.add(scene);: the console logs THREE.Object3D.add: object can't be added as a child of itself. followed by a dump of the scene, and the picture is unchanged.

Code & diagrams

Hide it, shrink it, put it behind the camera New tab

The status bar shows the draw calls too. Scale 0 still costs a draw call; a hidden object and an object behind the camera cost none.

idle

Console

Run the scene to see its console.

Expected console output

three boxes                | draw calls: 3 | triangles: 36
blue.visible = false       | draw calls: 2 | triangles: 24
  scene still holds it: true
grey.scale = 0             | draw calls: 2 | triangles: 24
orange.position.z = 10     | draw calls: 1 | triangles: 12
  found by name: false | missing name gives: undefined
traverse visits 6 objects (the scene itself, 2 lights, 3 boxes)
One parent only: add, add twice, attach, remove New tab

No canvas needed: these are facts about the tree. Positions come from `getWorldPosition` after `updateMatrixWorld()`.

idle

Console

Run the scene to see its console.

Expected console output

in left: left has 1 | right has 0 | world x = -1.5
added to right: left has 0 | right has 1 | world x = 2.5
added twice to right: right has 1 child
moved to scene: local x stays 0.5 | world x = 0.5 (its local number now means something else)
right.attach(wheel): local x = -1.5 | world x = 0.5
after remove: parent is null | right has 0 children
scene children: left, right

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Add something that is not there

Add scene.add(undefined); before the first draw(...) in the first example.

terminal
$ Run
── what you'll see ──
THREE.Object3D.add: object not an instance of THREE.Object3D. undefined
A console error (red), not an uncaught exception. The scene still draws the three boxes, so the picture does not warn you.

Myth vs fact

Myth

scale.set(0, 0, 0) removes an object from the work.

Fact

It is still sent to the GPU (the example's draw call count stays at 2). Use visible = false to skip it.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    visible = false on a parent hides the whole subtree, so its children cost nothing either: the cheapest way to hide ten parts.

  • ▸

    Culling uses a bounding sphere, computed from the geometry on the first render. If you change vertices yourself, update it (Topic 4.5), or the object can vanish at the screen edge while still on screen.

Remember this

  1. 1

    The problem this solves: you need one way to place, turn, hide, find and group anything in a scene. Without it each kind of object would need its own commands.

  2. 2

    **Every scene object extends Object3D**: Mesh, Group, lights, cameras, even Scene. Main fields: position, rotation (Euler, radians), quaternion (the same turn, kept in sync: Topic 2.6), scale, visible, name, parent and children.

  3. 3

    **add and remove** build the tree; parent.add(a, b) adds several. An object has one parent: adding it elsewhere first removes it from the old one (it moves, it is not copied: second example). Adding it twice to the same parent does nothing. remove sets parent to null but frees nothing: geometry and material stay on the GPU until disposed (Phase 17).

  4. 4

    **A wrong argument to add.** undefined or a non-Object3D logs THREE.Object3D.add: object not an instance of THREE.Object3D.; adding an object to itself logs THREE.Object3D.add: object can't be added as a child of itself. Both are console errors, not exceptions, so the scene runs on without the object. A model that failed to load is the usual cause.

  5. 5

    Local numbers, world meaning. position is measured from the parent (Topic 2.4). Moving an object to another parent with add keeps its local numbers and changes its world position; parent.attach(child) keeps the world position and rewrites the local numbers instead.

  6. 6

    **visible = false, scale 0 and a position behind the camera** all hide an object at different costs (first example). visible = false skips the object and its subtree: no draw call. scale.set(0, 0, 0) still sends a draw call. Behind the camera or outside the frustum, culling skips the draw call, but matrices are still updated.

  7. 7

    **traverse and getObjectByName.** traverse(fn) calls fn on an object and every descendant. getObjectByName("front-wheel") returns the first match or undefined; names are not checked for uniqueness. Name the parts you will look for, as the course does from Phase 4.

Explain it without notes

01

What is the difference between visible = false, scene.remove(obj) and scale.set(0, 0, 0)?

02

What happens if you add the same mesh to two different groups?

Practice

01

Write a function findAll(root, namePrefix) that returns every object whose name starts with a prefix.

02

A model's parent is scene. Write the line that moves it to rack but keeps it where it is on screen.

Done when you can

  • Place, turn, scale, hide and name an object

  • Say what visible, remove and scale 0 each cost

  • Use traverse and getObjectByName

  • Explain why an object has only one parent and when to use attach