Back Send feedback to ilkka.kuivanen@me.com

ThreeJS: Lightweight setup for controlling objects by external updates

I have been thinking about how to structure, organise, type and control objects in ThreeJS scene with comfortable and ergonomic way. The need is to apply external updates to scene. This need can be divided into two parts: 1) finding the correct object from the scene by some external id, 2) controlling that object with desired way. After discussing with a colleague I came into a conclusion that some simple and separate controller object is the way to go. That object would hold the reference to the scene objects and the external id. userData in ThreeJS objects is a good place to store the reference.

Controller class

export class MyDoubleBoxController {
    private obj;

    constructor(obj: THREE.Object3D) {
        this.obj = obj;

        // Example 1: Validating by content
        if (obj.children.length === 2) {
            console.log("Correct source obj: has 2 children!");
        } else {
            console.error("Wait! This is not the correct obj!");
        }

        // Example 2: Validating by custom type
        if (obj.userData["type"] === "MyDoubleBox") {
            console.log("Correct source obj: has type 'MyDoubleBox'!");
        } else {
            console.error("Wait! This is not the correct obj!");
        }
    }

    update() {
        console.log(`Updating... `);
    }
}

Usage

const controllers = new Map<string, MyDoubleBoxController>();

// "box1" and "box2" are defined earlier in the code...
const group = new THREE.Group();
group.add(box1);
group.add(box2);
group.userData["type"] = "MyDoubleBox";
group.userData["externalId"] = "foobar123";

controllers.set(group.userData["externalId"], new MyDoubleBoxController(group));

// External update happens for id "foobar123":
// - Find the object by external id
// - Invoke the method
const controller = controllers.get("foobar123");
if (controller) {
    controller.update();
}

// Update all controllers
controllers.forEach((controller) => controller.update());