Accessing an Entity’s three.js Objects

Every A-Frame entity (e.g., <a-entity>) has its own
THREE.Object3D, more specifically a THREE.Group that
contains different types of Object3Ds. The root THREE.Group of an entity is
accessed via .object3D:

document.querySelector('a-entity').object3D; // THREE.Group

Entities can be composed of multiple types of Object3Ds. For example,
an entity can be both a THREE.Mesh and a THREE.Light by having both
a geometry component and light component:

<a-entitygeometrylight></a-entity>

Components add the mesh and light under the entity’s root THREE.Group.
References to the mesh and light are stored as different types of three.js
objects in the entity’s .object3DMap.

Setting an Object3D on an Entity

Setting an Object3D on an entity adds the Object3D to the entity’s Group,
which makes the newly set Object3D part of the three.js scene. We set the
Object3D with the entity’s .setObject3D(name) method where the name
denotes the Object3Ds purpose.

We set the light with the name light. To later access it, we can use the
entity’s .getObject3D(name) method as described before:

entityEl.getObject3D('light');

And when we set a three.js object on an A-Frame entity, A-Frame will set a
reference to the A-Frame entity from the three.js object via .el:

entityEl.getObject3D('light').el; // entityEl

There’s also a .getOrCreateObject3D(name, constructor) method for creating
and setting an Object3D if one has not been set with the name. This is
commonly used in the case of THREE.Mesh when both the geometry and material
components need to get or create a mesh. Whichever component gets initialized
first creates the mesh, then the other component gets the mesh.

Removing an Object3D From an Entity

To remove an Object3D from an entity, and consequently the three.js scene, we
can use the entity’s .removeObject3D(name) method. Going back to our example
with the point light, we remove the light when the component is detached:

Transforming Between Coordinate Spaces

Every object and the scene (world) in general has their own coordinate space. A
parent object’s position, rotation, and scale transformations are applied to
its children’s position, rotation, and scale transformations. Consider this scene:

From the world’s reference point, foo has position (1,2,3) and bar has position
(3, 5, 7) since foo’s transformations apply onto bar’s. From foo’s reference
point, foo has position (0, 0, 0) and bar has position (2, 3, 4).

Often we will want to transform between these reference points and coordinate
spaces. Above was a simple example, but we might want to do operations such as
finding the world-space coordinate of bar’s position, or translate an arbitrary
coordinate into foo’s coordinate space. In 3D programming, these operations are
accomplished with matrices, but three.js provides helpers to make them easier.

Local to World Transforms

Normally, we’d need to call .updateMatrixWorld () on parent Object3Ds, but
three.js defaults Object3D.matrixAutoUpdate to true. We can use three.js’s
.getWorldPosition () and .getWorldRotation ().