无法使用 Three.js 加载从搅拌机导出的纹理 Collada

Unable to load textured Collada exported from blender using Three.js

我正在使用 Three.js、版本 71。我正在使用 Blender,版本 2.73

我使用 Blender 创建了一个带纹理的 collada 对象(.dae 文件),现在我想将它加载到我的 three.js 场景中。到目前为止,我只能加载从搅拌机导出的没有纹理的模型。

下面是我创建纹理 collada 对象的方法:
在搅拌机中,我只是使用默认的立方体。使用右侧的设置,我将纹理添加到立方体。这是我放在立方体上的纹理(注意:它是 2048 X 2048,所以它是 2 的幂):

这是渲染模式下的立方体图像,以证明纹理在其上:

以下是我从 Blender 将立方体导出为 collada 时使用的导出设置:

这是我用来尝试加载纹理 collada 的一些代码:

var loader = new THREE.ColladaLoader();
var localObject;
loader.options.convertUpAxis = true;
loader.load( './models/test_texture.dae', function ( collada ) {
  localObject = collada.scene;
  localObject.scale.x = localObject.scale.y = localObject.scale.z = 32;
  localObject.updateMatrix();
  game.scene.add(localObject);
} );

这是我得到的错误:

[.WebGLRenderingContext]GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 2

然后我用谷歌搜索了该错误消息,有人说我需要计算切线。这是我的尝试和我得到的错误:

var loader = new THREE.ColladaLoader();
var localObject;
loader.options.convertUpAxis = true;
loader.load( './models/test_texture.dae', function ( collada ) {
  localObject = collada.scene;
  localObject.scale.x = localObject.scale.y = localObject.scale.z = 32;
  localObject.updateMatrix();

  for (var i = collada.scene.children.length - 1; i >= 0; i--) {
    var child = collada.scene.children[i];

    // child.children[0] will give us the THREE.Mesh of the collada
    if ( child.colladaId == "Cube" ) {

      // ATTEMPT 1: Just tried computing tangets based on answer from neoRiley here: 
      // child.children[0].geometry.computeTangents();

      // ATTEMPT 2: Got this suggestion from Popov here: 
      // child.children[0].geometry[ 0 ][ 0 ].computeTangents();
      // child.children[0].geometry[ 1 ][ 0 ].computeTangents();

      // ATTEMPT 3: Tried setting some update flags based on answer from Sayris here: 
      // child.children[0].geometry.buffersNeedUpdate = true;
      // child.children[0].geometry.uvsNeedUpdate = true;
      // child.children[0].material.needsUpdate = true;
      // child.children[0].geometry.computeTangents();
    }
  };
  game.scene.add(localObject);
} );

尝试 1 错误:

Uncaught TypeError: Cannot read property '0' of undefined
// Stack trace
three.js:9935 handleTriangle
three.js:9974 THREE.Geometry.computeTangents
myCode.js:116 (anonymous function)
ColladaLoader.js:204 parse
ColladaLoader.js:84 request.onreadystatechange

尝试 2 错误:

Uncaught TypeError: Cannot read property '0' of undefined

这来自自己的代码。我没想到 THREE.Mesh 的几何是二维的,但我还是试了一下。

尝试 3 错误:(与尝试 1 错误相同)

Uncaught TypeError: Cannot read property '0' of undefined
// Stack trace
three.js:9935 handleTriangle
three.js:9974 THREE.Geometry.computeTangents
myCode.js:116 (anonymous function)
ColladaLoader.js:204 parse
ColladaLoader.js:84 request.onreadystatechange

我决定改用 JSON 加载器,因为我无法让 collada 工作。我做的第一件事是将 JSON exporter 插件安装到 Blender 中。我从 three.js 下载的 .zip 文件中获得了插件。在里面 three.js-r71/utils/exporters/blender/addons 叫做io_three。您只需要复制该文件夹并将其粘贴到 Blender Foundation/Blender/2.73/scripts/addons.

中的 Blender 安装目录中

然后您必须在 Blender 中启用它。为此:

  1. 单击文件->用户首选项...
  2. 单击加载项
  3. 在搜索字段中输入 three
  4. 一路向右,点击复选框启用
  5. 点击左下角的保存用户设置,这样您就不需要再次执行此操作。如果在单击 File->Export 时看到 Three.js (.json),则表明它正在运行。

我遵循了该站点的大部分说明来帮助我创建和导出模型:http://graphic-sim.com/B_basic_export.html

这是我用来创建和导出模型的步骤(我从网站上稍微调整了一下)

  1. 启动 Blender。
  2. 查看属性编辑器(右侧)。
  3. World 上下文按钮。在 World 面板中单击 Ambient Color 并将其从黑色更改为中灰色。
  4. Material 上下文按钮。在 Diffuse 面板上将 Intensity 更改为 1.0。在 Specular 面板上执行相同的操作。在 Shading 面板中勾选 Shadeless 框。
  5. Textures 上下文按钮。在 Type 下拉框的顶部附近,select Image or Movie。在 Image 面板中,浏览到您的图片(确保图片的尺寸为 2 的幂)。
  6. 选择 UV 编辑 屏幕布局(顶部帮助菜单右侧的下拉框)。
  7. 在 3D 编辑器中使用鼠标光标,进入编辑模式(Tab 键)。
  8. 展开(按 U 键)。选择智能 UV 项目。单击 确定 接受默认值。
  9. 在 UV 编辑屏幕中,select 您的图像使用左下角的菜单(见屏幕截图)
  10. Select 图像->另存为图像。此图片需要位于您要导出的 JSON 文件旁边。
  11. 点击文件->导出->Three.js (.json).
  12. 在左侧,select 几个导出选项(请参阅我使用的截图,这是我通过反复试验找到的)。我想我只添加了 Face MaterialsMaterialsTextures.然后您还可以单击 保存设置 来保存这些设置。
  13. 将您之前保存的 JSON 文件和图像文件放入您的项目文件夹中。
  14. 使用以下代码加载它:

    var object;
    var loader = new THREE.JSONLoader();          
    loader.load( "./models/test_texture.json", function(geometry, materials) {
      object = new THREE.Mesh(geometry, materials[0]);
      object.scale.set(32, 32, 32);
      game.scene.add(object);
    });