Visitar URL original
setObject3D will give false negatives for CSS3DRenderer when checking whether it's a THREE.Object3D · Issue #5701 · aframevr/aframe · GitHub
Skip to content

setObject3D will give false negatives for CSS3DRenderer when checking whether it's a THREE.Object3D #5701

Open

Description

@ResourceHog

Tried to use https://github.com/mrdoob/three.js/blob/master/examples/jsm/renderers/CSS3DRenderer.js
to embed dom elements in 3D space. However setObject3D will reject it because instanceof is not properly detecting the type.

    setupCss3D(sceneEl: Scene) : void {
        const wrapper = document.createElement('div');
        wrapper.style.position = 'absolute';
        wrapper.style.transformStyle = 'preserve-3d';

        const children = Array.from(this.el.children);
        for(const child of children) {
            
                wrapper.appendChild(child);
            
        }

        this.wrapper = wrapper;
        this.cssObject = new CSS3DObject(wrapper);
        this.cssObject.scale.set(1,1,1);
        this.el.object3D.add(this.cssObject);

        console.log(this.cssObject instanceof THREE.Object3D);
        
        this.el.setObject3D('mesh', this.cssObject);
        console.log(this.el.object3D);

    },

Additional Context:
Object3D provides an "isObject3D" parameter specifically for type checking.
https://github.com/mrdoob/three.js/blob/e3ee9682fb2c776cd77fd8b89f73c321945fa52c/src/core/Object3D.js#L79

Suggested solution:
use a custom type guard to leverage this parameter.


function isObject3D(obj: unknown) is THREE.Object3D {
    return (obj as THREE.Object3D).isObject3D === true;
}

then replace the instanceof check.

...
  setObject3D (type, obj) {
    var oldObj;
    var self = this;

    if (!isObject3D(obj)) {
      throw new Error(
        '`Entity.setObject3D` was called with an object that was not an instance of ' +
        'THREE.Object3D.'
      );
    }
...

Activity

  1. mrxz commented on Apr 6, 2025

    @mrxz
    Contributor

    While the isObject3D property could be checked, the instanceof check should work for Object3D and all derived classes (including CSS3DObject). The fact that it doesn't in your case points towards a problem in your setup. Most likely you have two instances of Three.js loaded.

    This often happens because A-Frame bundles a modified version of Three.js. When loading Three.js addons, these can pull in a different copy of Three.js. Prior to 1.7.0 it was quite tricky to configure build-tools and bundlers to avoid this, but from 1.7.0 onwards there's an ESM module build of A-Frame without three.js making it a lot easier.

    See the importmap example and this FAQ entry https://aframe.io/docs/1.7.0/introduction/faq.html#can-i-load-a-frame-as-an-es-module.

  2. dmarcos commented on Apr 8, 2025

    @dmarcos
    Member

    @ResourceHog Can you share a link to a full example to reproduce? Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions