How can I get the texture information of a Material from a loaded model?

textures
loaders

#1

Hi all,

I want to get the texture after loaded a model, but I found it is always undefined when I tried to get it, can it be read?

var fbxloader = new THREE.FBXLoader();
fbxloader.load('any-model-with-material-info.fbx', function(object){ //model format can be anyone with material info
  object.traverse( function ( child ) {
    if ( child instanceof THREE.Mesh ) {
        if(child.material){
          if(child.material.length > 1){
            if(child.material[0].isMeshPhongMaterial){
              console.log("material map is ", child.material[0].map); //can get map but its image is undefined
              console.log("material map image is ", child.material[0].map.image); //material map image is  undefined
            }
          }else if(child.material.isMeshPhongMaterial){
            console.log("material map is ", child.material.map); //can get map but its image is undefined
            console.log("material map image is ", child.material.map.image); //material map image is  undefined
          }
        }
      }
    }
  });
});

the above is the basic step I tried, is there any error? Hope anyone can help me on it, or give me some clue to have a try, thanks in advance!


#2

The image property of a texture object is only set when the texture has fully loaded. This is not necessarily the case when the onLoad() callback of FBXLoader.load() fires. Use loading manager instead. Try something like this:

var object;

var manager = new THREE.LoadingManager( function() {
   object.traverse( function ( child ) {
      if ( child.isMesh ) {
        var material = child.material;
          if ( Array.isArray( material ) ) {
            if ( material[ 0 ].isMeshPhongMaterial ) {
              console.log( "material map is ", material[ 0 ].map ); //can get map but its image is undefined
              console.log( "material map image is ", material[ 0 ].map.image ); //material map image is  undefined
            }
          } else if ( material.isMeshPhongMaterial ) {
            console.log( "material map is ", material.map ); //can get map but its image is undefined
            console.log( "material map image is ", material.map.image ); //material map image is  undefined
          }
        }
      }
    }
  });
} );

var fbxloader = new THREE.FBXLoader( manager );

fbxloader.load( 'any-model-with-material-info.fbx', function( scene ) {
   object = scene;
} );

#3

@Mugen87 cool! it works! thanks for your clear explanation! I forgot that the texture is loaded async…


#4

@Mugen87 sorry to disturb you again, but for the fbx model which has no texture itself, the callback defined in the LoadingManager will not be called any more, so is there any methods can be used for models with or without textures? Or before the callback called, can I know whether a fbx model has/hasn’t textures?


#5

I don’t think that is not correct. The onLoad() callback of LoadingManager always fires. It does not matter whether the model has textures or not.


#6

@Mugen87 yes, you are right, if use FBXLoader.load(), the onLoad callback should be called. I am sorry that I forgot to change the method from FBXLoader.load() to FBXLoader.parse() in at the first time, just because the data I got is just an arraybuffer. So when I tried to use FBXLoader.parse() to parse the arraybuffer things I mentioned will happen and I don’t know how to make them(models with/without texture(s)) both work.


#7

FBXLoader.parse() returns the parsed scene graph. Why not just doing something like this:

var scene = new THREE.FBXLoader().parse( buffer );
scene.traverse( function( object ) {
   // 
} );

#8

eh, I want to make them work together, because I don’t know whether the model has texture or not.

currently, if the model has textures, then after run parse() function, the map info has not been assigned, so I need the way you told to me to get the texture information;

but if the model has no textures, actually the callback in LoadingManger will not be called any more.

so there are two entry(exit) to use the parsed object, but I have not found a good way to make them work together.

Hope you can understand what I am confused, and thank you very much on this topic.