Begginer - Struggling to understand a concept GLTFLoader

UPDATE: In the interest of clarity I have made a fiddle , using two pre-exsisting fiddles that produces the same problem.

Desired result: I would like the imported object to be targetable in the same way that ‘cube’ is.

Here is the scroll animation fiddle.

Notice how it adresses ‘cube’ in cube.position in the timeline:

timeline.add({
    targets: cube.position,
    x: 100,
    y: 25,
    z: -50,
    duration: 2250,
    update: camera.updateProjectionMatrix()
  })

Here is the object fiddle. - this works as expected.

Here is my mixed fiddle.

In my mixed fiddle - If i try to swap out cube.position for mesh.position in the timeline - it throws an undefined error (in the fiddle you just see a black screen).

This question is now a COPY of THIS question.

I appreciate that this is a three.js forum, and my involves anime.js &or three.js but i didn’t want to leave confusing information up. Even if it goes unsolved.

/сс

PS No worries about cross-posting :slight_smile:

I don’t understand - please explain… are you saying i shouldn’t have asked the question in two places?

It’s okay to ask question at distinct places. However, linking to your other questions is recommended in order to avoid situations where devs provide answers without knowing of existing ones.

Apologies - in which case thankyou @prisoner849 for linking it. I will do the same on the stack question.

In truth i don’t really understand the questions i’m asking, which makes asking the questions even more challenging.

This probably happens because of the asynchronous nature of the loading process. Let me make the error more obvious with this pseudo code:

let logo;

loader.load( function( gltf ) {

    logo = gltf.scene;

} );

console.log( logo );

You will definitely see undefined in the browser console since the glTF scene is assigned to logo at some point in the future (when the asset has been loaded from the backend and successfully parsed). Hence, it’s not correct to directly access logo in the animation loop (or at other places). You have to test if the variable is not undefined like so:

function animate() {

    requestAnimationFrame( animate );

    if ( logo ) logo.rotation.x += 0.01;

}

I’m trying to understand - I read up on async loading… which now somewhat makes sense. So everything inside of the GLTFLoader process gets loaded ‘as and when it can be’ rather than in any order?

So the way i created logo:
logo = gltf.scene;
Is ok? but delaring logo like:
let logo;
before hand is not ok?

I shouldn’t be referencing it in the same way I would reference a div with an id. Instead I should be querying whether ‘logo’ has been defined or not. And if it has been defined → Then do whatever i tell it to do. In your case it’s rotating. - is this correct?

So in my case - the timeline in index.js currently uses ‘target: cube.position’ to give ‘cube’ it’s position at each duration or stage of the timeline:

timeline.add({
    targets: cube.position,
    x: 100,
    y: 25,
    z: -50,
    duration: 2250,
    update: camera.updateProjectionMatrix()
  })

I would presume my version of this would have been ‘targets: logo.position’ - but you said it’s wrong to directly access logo from any other place. Instead am i meant to be using something like your example of

timeline.add({
    targets: if ( logo ) logo.position,
    x: 0,
    y: 0,
    z: 50,
    duration: 2250,
    update: camera.updateProjectionMatrix()
  })

I may have embarassed myself with that last bit :sweat_smile:

Appreciate you’re all busy people - i’ve got some reading to do.

I have changed my code to this:

var loader = new THREE.GLTFLoader();

var logo = null;
var logo2= null;

loader.load(
    '/assets/logotext.glb', function  ( gltf ) {
        // called when the resource is loaded
        var logo = gltf.scene;
        logo.scale.set(20,20,20);
        logo.position.y = 5
        logo.position.z = -100
        scene.add( logo );
        var logoex = document.querySelector( '.logo' )
    },
    
    
    function ( xhr ) {
        // called while loading is progressing
        console.log( ( xhr.loaded / xhr.total * 100 ) + '% + loaded' );
    },
    function ( error ) {
        // called when loading has errors
        console.error( 'An error happened', error );
    },
);

loader.load(
    '/assets/logotext.glb',
    function ( gltf ) {
        // called when the resource is loaded
        var logo = gltf.scene;
        logo2.scale.set(20,20,20);
        logo2.position.y = 5
        logo2.position.z = -100
        scene.add( logo2 );
        var logoex = document.querySelector( '.logo2' )
    },
    
    
    function ( xhr ) {
        // called while loading is progressing
        console.log( ( xhr.loaded / xhr.total * 100 ) + '% + loaded' );
    },
    function ( error ) {
        // called when loading has errors
        console.error( 'An error happened', error );
    },
    
);


function initTimeline() {
  timeline = anime.timeline({
    autoplay: false,
    duration: 4500,
    easing: 'easeOutSine'
  });
  timeline.add({
    targets: 'logo'.position,
    x: 100,
    y: 25,
    z: -50,
    duration: 2250,
    update: camera.updateProjectionMatrix()
  })
  timeline.add({
    targets: 'logo'.position,
    x: 0,
    y: 0,
    z: 50,
    duration: 2250,
    update: camera.updateProjectionMatrix()
  })
  var value = new THREE.Color(0xFFFCFC)
  var initial = new THREE.Color(0x161216)
  timeline.add({
    targets: initial,
    r: [initial.r, value.r],
    g: [initial.g, value.g],
    b: [initial.b, value.b],
    duration: 4500,
    update: () => {
      renderer.setClearColor(initial);
    }
  }, 0);
}

I no longer get any console errors and the logo starts in the same place as the cube. However the logo won’t animate in the same way that the cube does if i swap out logo for cube in cube.position (in the timeline).

I’m not familiar with timeline so somebody else needs to help here, sorry.

@Mugen87 something indirectly related to this topic: I have seen people using the word “mesh” “object” and “model” for an imported “item”. What exactly is it? Are we importing a mesh, an object or a model? :thinking: Or is it that once we import a “model” to 3.js, it becomes an “object”? Excuse me if this is confusing :grimacing:

object or 3D object is usually a generic term to describe any kinds of objects in a scene graph. A mesh is a special type of 3d object similar to point clouds and lines. I personally use the term model to refer to e.g. character models authored in a DCC tool like Blender.

Notice that these are not academic definitions so other developers might refer to the same stuff with different names.

2 Likes

That’s no problem.

I haven’t been able to find a solution yet. And i’m sure it’s a simple thing.

As an update to my question, I created a JSFiddle that combines two working fiddles into one (without my nooby input) and am struggling at the same point.

Half three.js (loading in the object) and half anime.js (creating a timeline) and im just unsure how to make them speak. I will post somewhere more general about this as I understand this is a three.js forum - I just wanted to update the original post for accuracy.

Scroll animation fiddle
GLTFLoader fiddle
My fiddle (mix of the two)

I managed to get it working assigning the mesh to a meshGroup and targeting that: fiddle