2

This particular project has a non-canvas fallback routine which also utilizes the preloading routine. The images add and load appropriately, however I cannot figure out how to use them in THREE.js because THREE.js will use its own image loader to essentially re-load the images.

** Here's the JS **

function MAIN_PRELOAD() {

 var Preload_List = [];
 var Preload_Loaded = 0;
 var Preload_Errors = 0;

 function preload_scene() {

  // Skip Empty List...
  if(SceneAssets.length < 1) return;
  for(var i in SceneAssets) {

   // Skip Blanks...
   if(SceneAssets[i]['material']['map'].length < 1) continue;

   // Skip Repeats...
   if(Preload_List.indexOf(SceneAssets[i]['material']['map']) >= 0) continue;

   // Add to list...
   console.log('Image added to preloader: '+SceneAssets[i]['material']['map']);
   Preload_List[Preload_List.length] = SceneAssets[i]['material']['map'];

  }
 }

 function preload_masks() {

  // Skip Empty List...
  if(MaskLayer['textures'].length < 1) return;
  for(var i in MaskLayer['textures']) {

   // Skip Blanks...
   if(MaskLayer['textures'][i].length < 1) continue;

   // Skip Repeats...
   if(Preload_List.indexOf(MaskLayer['textures'][i]) >= 0) continue;

   // Add to list...
   console.log('Image added to preloader: '+MaskLayer['textures'][i]);
   Preload_List[Preload_List.length] = MaskLayer['textures'][i];

  }
 }

 function preload_finished() {

  console.log('Preloading has finished!');
  // NYI: Hide the loading overlay...
  init();
  animate();

 }

 function preload_init() {

  // Preload Assets...
  preload_scene();
  preload_masks();

  // Finish if empty...
  if(Preload_List.length < 1) {
   preload_finished();
   return;
  }

  // Iterate if filled...
  for(var i in Preload_List) {

   // Enclosure for event trapping...
   (function(i) {

    var imageElement = document.createElement('img');

    imageElement.onload = function() {
     console.log('Image "'+Preload_List[i]+'" done loading!');
     Preload_Loaded ++;
     if(Preload_Loaded + Preload_Errors == Preload_List.length) {
      preload_finished();
     }
    };

    imageElement.onerror = function() {
     console.log('Image "'+Preload_List[i]+'" failed to load...');
     Preload_Errors ++;
     if(Preload_Loaded + Preload_Errors == Preload_List.length) {
      preload_finished();
     }
    };

    imageElement.src = Preload_List[i];

   })(i);

  }

 }
 preload_init();

}

MAIN_PRELOAD();

Currently not yet implemented is a solid overlay that masks everything until the presentation preload completes.

To be clear, both parts of my application work fine on their own, however there exists a big processing stutter at the beginning when everything is loading and being added to the scene which is detrimental to the overall user experience.

There's also periodic stutters in the presentation when it loads masking layers as needed, and each time it does, it does so from a new HTTP request instead of from the browser cache via THREE.ImageUtils.loadTexture().

My best guess is that I have to somehow use the unappended img element created in the preloader as a replacement for the THREE.ImageUtils.loadTexture(), I just can't find anyone doing the same thing anywhere and I think this would be a great way to cache scene assets for THREE.js if I can get it to work.

Alternative methods to solving this problem will also be considered.

Using THREE.js r70

MLK.DEV
  • 453
  • 7
  • 31
  • what are you sending to `THREE.ImageUtils.loadTexture()` ? – 2pha Feb 25 '15 at 02:11
  • Currently its using the relative path to the image, so it's logical that it's loading the image from a new HTTP request. I'd like to use the image cached version though instead. – MLK.DEV Feb 25 '15 at 14:59
  • Why wouldn't you create the texture when the preloader loads it? – 2pha Feb 25 '15 at 15:01
  • That's my question. The preloader uses an `img` element to load the image, my question is how do I use that preloader `img` element as the source for the texture WITHOUT invoking another HTTP request (otherwise preloading is worthless). – MLK.DEV Feb 25 '15 at 16:07
  • answer added with example. – 2pha Feb 26 '15 at 04:59

1 Answers1

4
var texture;
var imageElement = document.createElement('img');
imageElement.onload = function(e) {
    texture = new THREE.Texture( this );
    texture.needsUpdate = true;
    init();
};
imageElement.src = "myimage.png";

init() {
    material = new THREE.MeshPhongMaterial( { map : texture } );
}

Here is a fiddle to demonstrate.
NOTE: in the fiddle I use an image dataUrl, this is just so I can use the image as a texture without getting a CORS error. On a site you should be able to just set the image src to the file path as per normal.

2pha
  • 9,798
  • 2
  • 29
  • 43