0
votes

I have an OBJ file generated dynamically by a server on a separate domain. It has some materials and texture JPG files.

I load this OBJ file with a simple php proxy (fileProxy.php):

<?php
 header('Access-Control-Allow-Origin: *');
 header("Access-Control-Allow-Credentials: true"); 
 header('Access-Control-Allow-Headers: X-Requested-With');
 header('Access-Control-Allow-Headers: Content-Type');
 header('Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT'); // http://stackoverflow.com/a/7605119/578667
 header('Access-Control-Max-Age: 86400');

//Check if this is an image. if So print coorect header.
if (strpos($_REQUEST['fileToProxy'],'jpg') !== false) {

     header('Content-Type: image/jpeg');

}


$proxyFile = (isset($_REQUEST['fileToProxy'])? $_REQUEST['fileToProxy'] : null);

if ( isset($proxyFile)){
  // the files sent to us aren't properly url encoded
  $proxyFile = str_replace(' ', '+', $proxyFile);

  $content = file_get_contents($proxyFile);

  print($content);
}
else {
  echo "ERROR: no file to proxy";
}



?>

Loading the OBJ files works like a charm

BUT, i cant load the JPG textures embeded in the MTL file. Single colored shaders all work fine, but loading images i get errors.

I get the following error in chrome:

Uncaught SecurityError: Failed to execute 'texImage2D' on 'WebGLRenderingContext': the cross-origin image at http://ec2-54-201-204-177.us-west-2.compute.amazonaws.com/fileProxy.php?fil…est-2.compute.amazonaws.com/3DModels/435639/DonutFullBread.jpg&timtest=115 may not be loaded.

The address of the texture file is fed correctly into my proxy: http://ec2-54-201-204-177.us-west-2.compute.amazonaws.com/fileProxy.php?fileToProxy=http://ec2-54-201-204-177.us-west-2.compute.amazonaws.com/3DModels/435639/DonutFullBread.jpg&timtest=115

Now after checking my Network monitor, i realise that the Jpg Image is successfully downloaded and the correct CORS headers are all in place. But webgl/three.js still spits out the errors and does not display my model.

SO this seems like a WEBGL bug. But i get security erros in all browsers. I have tested this on my localhost and on my server. Same problem.

Any solutions?

UPDATE Here's how i load the OBJ/MTL files with three.js: (Only cross domain textures fail)

var loader = new THREE.OBJMTLLoader( manager);

///////////////////LOAD MDOEL////////////////////
 loader.load( 'http://ec2-54-201-204-177.us-west-2.compute.amazonaws.com/fileProxy.php?fileToProxy=' + obj.file, 'http://ec2-54-201-204-177.us-west-2.compute.amazonaws.com/fileProxy.php?fileToProxy=' + obj.material, function ( object ) {                                              
//if loaded, do some stuff here.                                                   
}
loadedmodel.add(object);

That's all I do really. The Materials and textures are phrased correctly by the loader. I dont have to set any materials up.

4

4 Answers

4
votes

I just want to put this here for other people. I had a very similar problem when i was trying to load images from static google map images. So here is what i did

THREE.ImageUtils.crossOrigin = "anonymous";

Just before the actual texure is being loaded. Now this got it working and i could load the images without a problem.

3
votes

I know this is old, but I just spent a few hours troubleshooting the same issue, so I thought I'd post an answer here for any future users that run into this. The solution is quite simple, but unfortunately it is not documented anywhere that I could see. I discovered it by pure dumb luck.

var loader = new THREE.OBJMTLLoader( manager);
loader.crossOrigin = ''; //  <-- this is all you need to add!

///////////////////LOAD MDOEL////////////////////
loader.load( 'http://obj_url.com', 'http://mtl_url.com', function ( object ) {                                              
    //if loaded, do some stuff here.                                                   
}
loadedmodel.add(object);

If it's not clear in the code above, the only thing you need to do is to add the line loader.crossOrigin = ''; after declaring the OBJMTLLoader.

I hope this helps someone in the future!

1
votes

You need to set the crossorigin property explicitly for the image. Copying from one of my own examples:

images[id].image = new Image();

images[id].image.crossOrigin = "anonymous";

images[id].image.onload = function() {/* WebGL texture load of file here */}

images[id].image.src = "http://ec2-54-201-204-177.us-west-2.compute.amazonaws.com/fileProxy.php?fileToProxy=http://ec2-54-201-204-177.us-west-2.compute.amazonaws.com/3DModels/435639/DonutFullBread.jpg&timtest=115"

I loaded the image that you have mentioned above, and it works correctly for me in the browser as a texture.

0
votes

I often joke about my projects blowing up because I forgot a semicolon. Well, this time it is no joke. Someone actually forgot a semicolon in the latest revision of ThreeJS. I dug into MTLLoader.js (which is referenced by OBJMTLLoader.js) and found that this line (near the bottom of the MTLLoader prototype constructor) had a semicolon missing:

materialCreator.crossOrigin = this.crossOrigin

That'll kill any cross-site sharing for all materials. I added the semicolon back in...

materialCreator.crossOrigin = this.crossOrigin;

...and all was well with the world again.