Как применить текстуру SVG к файлу OBJ в Three.js

Я использую Threejs для своего проекта, я визуализирую объектный файл с помощью загрузчика OBJ, и он отображает объект на экране. Но я не знаю, как сопоставить изображение SVG с этим объектом, как применить текстуру к этому объектному файлу. пожалуйста, помогите мне, это мой текущий код. Я новичок в этой платформе и мало что знаю о THREE.js. Я видел несколько примеров, но у меня это не сработало. Один человек в моем недавнем посте рассказал мне, как наносить материал на объект, но у меня это не сработало.

При применении материала возникает эта ошибка. ERROR TypeError: Cannot set property 'map' of undefined

Вот мой полный файл кода.

import { Component, AfterViewInit, ViewChild, Input, ElementRef } from '@angular/core';
import * as THREE from 'three';
import { OrbitControls } from '@avatsaev/three-orbitcontrols-ts';
import {OBJLoader} from 'three-obj-mtl-loader';
import { TextureLoader } from 'three';



@Component({
  selector: 'app-scene',
  templateUrl: './scene.component.html',
  styleUrls: ['./scene.component.css']
})
export class SceneComponent implements AfterViewInit {
  @Input() name: string;
  @ViewChild('canvas', {static:true}) canvasRef: ElementRef;


  renderer = new THREE.WebGLRenderer;
  scene = null;
  camera = null;
  controls = null;
  mesh = null;
  light = null;
  loader;
  svgLoader;
  private calculateAspectRatio(): number {
    const height = this.canvas.clientHeight;
    if (height === 0) {
      return 0;
    }
    return this.canvas.clientWidth / this.canvas.clientHeight;
  }

  private get canvas(): HTMLCanvasElement {
    return this.canvasRef.nativeElement;
  }

  constructor() {
    // this.loader = new OBJLoader();
    this.scene = new THREE.Scene();
    this.loader = new OBJLoader();

    this.camera = new THREE.PerspectiveCamera(15, window.innerWidth / window.innerHeight, 0.1, 1000)
  }

  ngAfterViewInit() {
    this.configScene();
    this.configCamera();
    this.configRenderer();
    this.configControls();
    this.createLight();
    this.createMesh();
    this.animate();
  }

  configScene() {
    // this.scene.background = new THREE.Color( 0xdddddd );
  }

  configCamera() {
    this.camera.aspect = this.calculateAspectRatio();
    this.camera.updateProjectionMatrix();
      this.camera.position.set( 0, 0, 3 );
      this.camera.lookAt( this.scene.position );
  }

  configRenderer() {
    this.renderer = new THREE.WebGLRenderer({
      canvas: this.canvas,
      antialias: true,
      alpha: true
    });
    this.renderer.setPixelRatio(devicePixelRatio);

    // setClearColor for transparent background
    // i.e. scene or canvas background shows through
    this.renderer.setClearColor( 0x000000, 0 );
    this.renderer.setSize((window.innerWidth/2), (window.innerHeight/2));
    window.addEventListener('resize', ()=>{
      this.renderer.setSize((window.innerWidth/2), (window.innerHeight)/2);
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
    })
    console.log('clientWidth', this.canvas.clientWidth);
    console.log('clientHeight', this.canvas.clientHeight);
  }

  configControls() {
    this.controls = new OrbitControls(this.camera);
    this.controls.autoRotate = false;
    this.controls.enableZoom = false;
    // this.controls.maxDistance = 5;
    // this.controls.minDistance = 10;
    this.controls.enablePan = false;
    this.controls.update();
  }


  createLight() {
    this.light = new THREE.PointLight( 0xffffff );
      this.light.position.set( -10, 10, 10 );
      this.scene.add( this.light );
  }

  createMesh() {
      const url ='../../../../assets/abc.svg';


        this.loader.load('../../../../assets/nonunified.obj', (object)=>{

            object.traverse( function ( child ) {
              if ( child instanceof THREE.Mesh ) {
                  child.geometry.center();
              }
            } );
            object.material.map = new TextureLoader().load(url)
            this.scene.add(object)
          },
            // called when loading is in progresses
            function (xhr) {

            console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

          },
        // called when loading has errors
            function ( error ) {
            console.log( 'An error happened' );

          }
        )}

  animate() {
    window.requestAnimationFrame(() => this.animate());
    this.controls.update();
    this.renderer.render(this.scene, this.camera);
  }

}


person Tayyab Arif    schedule 05.12.2019    source источник


Ответы (1)


Вы не создали материал. Если вы выполните console.log(object.material); он покажет неопределенное. Сначала нужно создать материал. Пожалуйста, ознакомьтесь с документацией threejs, чтобы узнать о различных материалах, которые можно использовать. В этом примере я использую MeshPhongMaterial. Итак, ваша функция createMesh будет выглядеть так.

createMesh() {
        const url = '../../../../assets/abc.svg';

        this.loader.load('../../../../assets/nonunified.obj', (object) => {

            object.traverse(function (child) {
                if (child instanceof THREE.Mesh) {
                    child.geometry.center();
                }
            });

            const material = new THREE.MeshPhongMaterial({
                map: new TextureLoader().load(url)
            });

            object.material = material;

            this.scene.add(object)
        },
            // called when loading is in progresses
            function (xhr) {

                console.log((xhr.loaded / xhr.total * 100) + '% loaded');

            },
            // called when loading has errors
            function (error) {
                console.log('An error happened');

            }
        )
    }

Это должно работать.

person Aniket Betkikar    schedule 10.12.2019