Search code examples
javascriptthree.jsaframe

create object from imported model in A-frame


I imported a house model as .gltf. From this house, I would like to retrieve the floor object and convert it into its own a-frame entity so that I can reference it later. I need to reference it in order to tell the aframe-teleport-controls component that it should use the floor as collisionEntity.

This is what I have so far:

AFRAME.registerComponent('floor-test', {
    schema: {
        floorname: {type: 'string', default: "floor"},
    },
    init: function () {
        this.el.addEventListener("model-loaded", (e) => {
            let child = this.el.object3D.getObjectByName(this.data.floorname, true);

            let floor = document.createElement("a-entity");
            floor.setObject3D("Object3D", child)
            floor.setAttribute("id", "floor")
            this.el.appendChild(floor)
        })
    }
});

This is the aframe-teleport-controls entity:

<a-mixin id="teleport" teleport-controls="type: parabolic; cameraRig: #cameraRig; collisionEntities: #floor "></a-mixin>

The object is being created (Not yet in the right position), but the teleport controls don't recognize it as a collision entity.

How can I set the floor from the 3D model as collision entity?

EDIT

Chaning floor.setObject3D("Object3D", child) to floor.setObject3D("mesh", child) fixed the problem of the teleport collision entitys.

But the floor object that is being created does not have the right rotation.

I tried the function entityEl.object3D.getWorldRotation(); in the a-frame docs, but it returns "0 0 0"instead of "0 180 0".

I also tried to use THREE.SceneUtils.detach(child, parent, scene); but the child object didn't show up in the scene.

Here is the current code

AFRAME.registerComponent('floor-test', {
    schema: {
        floorname: {type: 'string', default: "floor"},
    },
    init: function () {
        this.el.addEventListener("model-loaded", (e)=> {
            let parent = this.el.object3D;
            let child = parent.getObjectByName(this.data.floorname, true);

            let floor = document.createElement("a-entity");
            floor.setObject3D("mesh", child)
            floor.setAttribute("id", "floor")
            floor.setAttribute("rotation", child.getWorldRotation())

            this.el.appendChild(floor)
        })
    }
});

Solution

  • I think there is an issue with the timing. When the teleport-controls are attached to the teleport mixin, the #floor is non-existent. Since i don't see any 'refresh' method in the documentation, I can think of two ways of dealing with this:

    1) If the world is non-procedural, add an invisible box where the floor should be and make it Your #floor.

    2) a bit more legit, try adding the teleport-controls when the model is done loading:

    this.el.addEventListener("model-loaded", (e) => {
            let child = this.el.object3D.getObjectByName(this.data.floorname, true);
    
            let floor = document.createElement("a-entity");
            floor.setObject3D("Object3D", child)
            floor.setAttribute("id", "floor")
            this.el.appendChild(floor)
            let teleportEntity = document.querySelector("#teleport");
            teleportEntity.setAtrribute("type", "parabolic");
            teleportEntity.setAttribute("cameraRig", "#cameraRig");
            teleportEntity.setAttribute("collisionEntities", "#floor");
        })
    


    <a-mixin id="teleport"></a-mixin>