【问题标题】:Change the texture of an existing model in google model-viewer using an image file使用图像文件更改谷歌模型查看器中现有模型的纹理
【发布时间】:2022-07-12 01:35:03
【问题描述】:

我是一名学生,即将使用 Google 的模型查看器在用户的墙上使用 AR 渲染海报。我有一个使用three.js 在线编辑器制作的简单、无纹理、单面的平面,它位于我的项目目录中。我正在尝试实现一个系统,可以将该平面的纹理设置为图像以模拟海报/绘画/等。

Google 的 model-viewer documentation 有一个示例(带有橡皮鸭的示例),其中模型具有从引用的图像文件创建和设置的纹理,我尝试使用平面和各种图像最终实现它用不同类型代替他们的例子,但我无法让它工作。

我一直在网上寻找可能的解决方案,但没有真正的进展,所以我想是时候自己问这个问题了。文档使这看起来很简单,很清楚,我误解了一些东西。

这是模型查看器文档中修改后的代码:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Model-Viewer Test</title>
  <script type="module" src="https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js"></script>
  <style>
    model-viewer {
      width: 400px;
      height: 600px;
    }
  </style>
</head>

<body>
  <model-viewer id="plane" camera-controls src="assets/blank.glb" ar ar-modes="webxr">
    <div class="controls">
      <p>Textures</p>
      <select id="normals2">
        <option>None</option>
        <option value="assets/planet.jpeg">Forbidden Planet</option>
        <option value="assets/retro.jpg">Retro Camera</option>
        <option value="assets/movie.png">Movie Poster</option>
      </select>
    </div>
  </model-viewer>
  <script type="module">
    const modelViewerTexture = document.querySelector("model-viewer#plane");

    modelViewerTexture.addEventListener("load", () => {

      const material = modelViewerTexture.model.materials[0];

      const createAndApplyTexture = async (channel, event) => {

        if (event.target.value == "None") {
          // Clears the texture.
          material[channel].setTexture(null);
        } else if (event.target.value) {
          // Creates a new texture.
          const texture = await modelViewerTexture.createTexture(event.target.value);
          // Set the texture name
          texture.name = event.target.options[event.target.selectedIndex].text.replace(/ /g, "_").toLowerCase();
          // Applies the new texture to the specified channel.
          material[channel].setTexture(texture);
        }
      }

      document.querySelector('#normals2').addEventListener('input', (event) => {
        createAndApplyTexture('normalTexture', event);
      });
    });
  </script>
</body>

</html>

在选择器中选择选项时我得到的唯一响应是错误消息:

Uncaught (in promise) TypeError: Cannot set property name of #<xy> which has only a getter
    at createAndApplyTexture

指的是第 46 行:

texture.name = event.target.options[event.target.selectedIndex].text.replace(/ /g, "_").toLowerCase();

否则,什么都不会发生。飞机本身的渲染没有问题。我尝试过同时使用 .gltf 和 .glb 模型。

我不打算像我在这里所做的那样抄袭 Google 关于实际项目的文档,我只是想看看我是否可以让动态纹理提前工作并立即碰壁。

感谢所有看到或回复此内容的人。

【问题讨论】:

    标签: javascript 3d texture-mapping gltf model-viewer


    【解决方案1】:

    这对你的学校项目来说可能已经太晚了,但我很长一段时间以来都对纹理交换感到头疼。我也恰好是一名学生:D。这是我写的一个例子:https://pastebin.com/d0enJ11Z。我使用下拉列表来选择材料,但如果不需要,您可以进一步简化代码。 最重要的代码就在这里。

    const material = speaker.model.materials[0];
    
    //Get current text value (name) of selected option
    var e = document.getElementById("color-controls");
    var finishName = e.options[e.selectedIndex].text;
    material.pbrMetallicRoughness['baseColorTexture'].texture.source.setURI(e.value);
    

    我不确定finishName 是否有任何作用,但我害怕删除它并破坏一切。理论上,你所需要的只是

    const material = speaker.model.materials[0];
    material.pbrMetallicRoughness['baseColorTexture'].texture.source.setURI("https://thereisatexturefilehere.com");
    

    这将选择材质索引中的第一个材质,然后在 baseColorTexture 通道中设置该索引的纹理。我希望这会有所帮助!

    附:它是 setURI,而不是 setURL

    【讨论】:

      猜你喜欢
      • 2021-04-29
      • 2020-08-06
      • 1970-01-01
      • 2022-07-26
      • 1970-01-01
      • 2016-08-03
      • 1970-01-01
      • 2019-03-04
      • 1970-01-01
      相关资源
      最近更新 更多