在THREE.JS中加载带纹理的OBJ / MTL文件时出现跨域问题

时间:2014-02-23 08:08:30

标签: three.js textures webgl cors

我有一个由单独域上的服务器动态生成的OBJ文件。它有一些材料和纹理JPG文件。

我用一个简单的php代理(fileProxy.php)加载这个OBJ文件:

<?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";
}



?>

加载OBJ文件就像魅力一样

但是,我无法加载嵌入在MTL文件中的JPG纹理。单色着色器都可以正常工作,但是加载图像会出错。

我在chrome中遇到以下错误:

Uncaught SecurityError:无法在'WebGLRenderingContext'上执行'texImage2D':http://ec2-54-201-204-177.us-west-2.compute.amazonaws.com/fileProxy.php?fil处的跨源图像... est-2.compute.amazonaws.com / 3DModels / 435639 / DonutFullBread.jpg&amp; timtest = 115可能无法加载。

纹理文件的地址正确送入我的代理: 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

现在在检查我的网络监视器后,我意识到Jpg图像已成功下载,并且正确的CORS标头都已到位。但是webgl / three.js仍然会出错并且不会显示我的模型。

所以这看起来像一个WEBGL错误。但我在所有浏览器中都获得了安全错误。 我在我的localhost和我的服务器上测试了这个。同样的问题。

任何解决方案?

更新 这是我如何使用three.js加载OBJ / MTL文件: (只有跨域纹理失败)

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);

这就是我所做的一切。材料和纹理由装载器正确表达。 我没有必要设置任何材料。

4 个答案:

答案 0 :(得分:4)

我只是想把这个放在其他人身上。 当我试图从静态谷歌地图图像加载图像时,我有一个非常类似的问题。 所以这就是我所做的

THREE.ImageUtils.crossOrigin = "anonymous";

在加载实际纹理之前。 现在这让它工作了,我可以毫无问题地加载图像。

答案 1 :(得分:2)

我知道这已经过时了,但我只花了几个小时来解决同样的问题,所以我想我会在这里为任何未来的用户发布一个答案。解决方案非常简单,但不幸的是,我无法在任何地方找到它。我通过纯粹的愚蠢运气发现了它。

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);

如果上述代码中不清楚,您唯一需要做的就是在声明loader.crossOrigin = '';后添加行OBJMTLLoader.

我希望这有助于将来的某个人!

答案 2 :(得分:1)

您需要为图像显式设置crossorigin属性。从我自己的一个例子中复制:

  
    

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

         

images [id] .image.crossOrigin =“anonymous”;

         

images [id] .image.onload = function(){/ *此处文件的WebGL纹理加载* /}

         

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

  

我加载了您上面提到的图片,它在浏览器中作为纹理正常使用。

答案 3 :(得分:0)

我经常开玩笑说我的项目因为忘了分号而爆炸了。好吧,这次不是开玩笑。有人在最新版本的ThreeJS中忘记了分号。我挖到了MTLLoader.js(由OBJMTLLoader.js引用)并发现这一行(靠近MTLLoader原型构造函数的底部)有一个分号丢失:

materialCreator.crossOrigin = this.crossOrigin

这会杀死所有材料的任何跨站点共享。我把分号添加回......

materialCreator.crossOrigin = this.crossOrigin;

......再次与世界相处得很好。