如何将 image/video 添加到从 Blender 加载的场景中的特定对象

How to add image/video to a specific object on loaded scene from Blender

我有一个从 Blender 导入的场景。我在场景中有几个屏幕,我想在这些屏幕上添加一个 image/video。

注意:我正在使用 OOP 模型创建应用程序

我已经使用 gltfLoader 导入了场景,我正在等待加载所有资源

 this.resources.on('ready', () => {

            // Setup
            this.controlRoom = new ControlRoom()
            this.tvScreen4x4 = new tvScreen4x4()

        })

ControlRoom 是实际场景,另一个是所有屏幕中的一个网格。

import * as THREE from 'three'
import Experience from "../../Experience.js"

export default class tvScreen4x4 {

    constructor() {
        this.experience = new Experience()
        this.scene = this.experience.scene
        this.resources = this.experience.resources

        // Setup
        this.setTexture()
        this.setMaterial()
        this.updateMesh()
    }

    setTexture() {
        this.texture = {}
        this.texture.normal = this.resources.items.tvScreen4x4
    }

    setMaterial() {
        this.material = new THREE.MeshStandardMaterial({
            map: this.texture.normal
        })
    }

    updateMesh() {

        this.scene.traverse((child) => {
            if (child instanceof THREE.Mesh && child.name === 'tv_4x4_screen') {

                child.material = this.material
                child.material.needsUpdate = true

                console.log(child.material);

            }
        })
    }
}
this.resources.items.tvScreen4x4

正在退回我定制的商品 source.js

export default [
    {
        name: 'controlRoom',
        type: 'gltfModel',
        path: 'models/controlroom.gltf'
    },
    {
        name: 'tvScreen4x4',
        type: 'texture',
        path: 'textures/screen.jpg'
    },
    {
        name: 'tvScreen5x4',
        type: 'texture',
        path: 'textures/screen.jpg'
    },
    {
        name: 'tvScreen6x4',
        type: 'texture',
        path: 'textures/screen.jpg'
    }
]

console.log(child.material)returns如下:

我做错了什么纹理没有显示在那个屏幕上?控制台记录 returns 正确的地图。

加载纹理,将纹理应用到你想要的对象上,然后将模型添加到场景中:

const texture = new THREE.TextureLoader().load(imageUrl);

new GLTFLoader().load(modelUrl, (gltf) => {
  gltf.scene.traverse((object) => {
    if (object.isMesh && object.name === "SCREEN") {
      object.material.map = texture;
    }
  });
  scene.add(gltf.scene);
});

演示:

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

canvas {
  display: block;
}
<script type="module">
  import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.121.1/build/three.module.js";
  import { OrbitControls } from "https://cdn.jsdelivr.net/npm/three@0.121.1/examples/jsm/controls/OrbitControls.js";
  import { GLTFLoader } from "https://cdn.jsdelivr.net/npm/three@0.121.1/examples/jsm/loaders/GLTFLoader.js";
  import { DRACOLoader } from "https://cdn.jsdelivr.net/npm/three@0.121.1/examples/jsm/loaders/DRACOLoader.js";

  const renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  const cameraMin = 0.0001;

  const aspect = window.innerWidth / window.innerHeight;
  const camera = new THREE.PerspectiveCamera(75, aspect, cameraMin, 1000);
  const controls = new OrbitControls(camera, renderer.domElement);

  const scene = new THREE.Scene();

  const model =
    "https://vazxmixjsiawhamofees.supabase.co/storage/v1/object/public/models/iphone-x/model.gltf";

  const image =
    "https://media.istockphoto.com/photos/colorful-umbrellas-for-sale-in-luang-prabang-laos-picture-id918965792";

  const loader = new GLTFLoader();
  const dracoLoader = new DRACOLoader();
  dracoLoader.setDecoderPath(
    "https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/js/libs/draco/"
  );
  loader.setDRACOLoader(dracoLoader);

  const texture = new THREE.TextureLoader().load(image);

  loader.load(model, (gltf) => {
    gltf.scene.traverse((object) => {
      if (!object.isMesh) return;
      if (object.name === "SCREEN") {
        object.material.map = texture;
        // console.log(object);
      }
    });
    const box = new THREE.Box3().setFromObject(gltf.scene);
    const center = box.getCenter(new THREE.Vector3());
    gltf.scene.position.x += gltf.scene.position.x - center.x;
    gltf.scene.position.y += gltf.scene.position.y - center.y;
    gltf.scene.position.z += gltf.scene.position.z - center.z;
    scene.add(gltf.scene);
  });

  camera.position.z = 5;

  const ambientLight = new THREE.AmbientLight();
  scene.add(ambientLight);

  (function animate() {
    requestAnimationFrame(animate);

    renderer.setSize(window.innerWidth, window.innerHeight);
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    controls.update();

    renderer.render(scene, camera);
  })();
</script>

我找到了解决问题的办法。代码是正确的,并且场景已按应有的方式导入。我没有做对的一件事是我如何导出 Blender 场景。

导出场景时,我应该勾选 UV 和几何部分。如下图。

所以这更像是搅拌机的问题,而不是 Three.js