1

I load a 3D scene in Three.js using the ColladaLoader. I try to create mipmaps images from a mesh object texture image. The problem is that the image isn't completely loaded when I access the image width and height. Both width and height is zero until fully loaded.

When loading the dae file the ColladaLoader trigger the "done" function. I then search the scene for the individual scene objects. One of the mesh object with an image texture needs mipmaps created. The problem is that when I access the image, it's properties are not set. When the scene is rendered, all objects, including the images textures, are rendered perfectly (albeit without the mipmaps). Is there a way for me to add an event handler to the texture/image that is triggered when the image is done loading? If there is such an event (in the Three.js objects), can I then add the mipmaps while the scene is/objects are potentially already rendering? What action must I take to alert the rendering pipeline that the mipmaps are changed?

Example code anybody? Can I precalculate the mipmaps in Blender and save those to the dae file? How do I do that? I'm going to search the Blender docs... Hints are welcome though...

Aycox
  • 136
  • 2
  • 7

1 Answers1

2

You can override THREE.ImageLoader.prototype.load to tap into the texture loading process and do whatever modifications between the time the image is loaded and when it's used by the Renderer.

Put this anywhwere after three.js script tag. The code in this function is exact copy of the three.js original code, except my comment marking the place you could put your mipmap generation or whatever you want.

THREE.ImageLoader.prototype.load = function ( url, image ) {
    var scope = this;
    if ( image === undefined ) image = new Image();
    image.addEventListener( 'load', function () {
                    // DO WHATEVER WITH THE IMAGE HERE
        scope.dispatchEvent( { type: 'load', content: image } );
    }, false );
    image.addEventListener( 'error', function () {
        scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
    }, false );
    if ( scope.crossOrigin ) image.crossOrigin = scope.crossOrigin;
    image.src = url;
}
yaku
  • 3,061
  • 2
  • 19
  • 38
  • BTW. You can use this approach to automatically resize textures in your Collada model to power-of-two (I do exactly that), which might partially answer your other question: http://stackoverflow.com/questions/14224403/how-do-i-avoid-moire-patterns-on-dae-models-in-three-js-loaded-with-colladaloade – yaku Jan 09 '13 at 13:53
  • That seems to be exactly what I'm looking for. – Aycox Jan 09 '13 at 22:45
  • One thing though @yaku; As not to cram too much specialized/application specific code into the Three.js library, is it possible to modify the 'load' event on the line below where you have put the comment. This way the modification of the image can be performed in the application code, not in the Three.js library (not so much code to modify when upgrading to the next version of Three.js. – Aycox Jan 09 '13 at 22:57
  • So... If I add an event handler that listens to the load event of the image in question, and add an 'URL' property to the 'load' event so that I can identify which image is loaded and which objects to modify the UV mapping on. Is it possible to do it this way or is the event model of the DOM message based? I.e. does the event call the event handler synchronously (blocking processing of your code above) or does the processing just continue and the event gets called whenever the 'load' message gets handled????? – Aycox Jan 09 '13 at 22:58
  • Not to pester you or anything, I'm deeply grateful for your answer but I just try to keep the modification of standard libraries to a minimum. Maybe the addition of an identification of URL to the event might be a great modification to Three.js? – Aycox Jan 09 '13 at 22:59
  • You don't need to touch the library code. This will override the library function dynamically on the fly, so you don't need to worry about updating THREE.js. Just make sure to put that piece of code somewhere around the start of YOUR code. – yaku Jan 09 '13 at 23:59