0


Im using Three.js in my Angular Application. I try to show a cup (obj file) with a texture on it. It works, but I only can see the texture when I rotate or zoom the object. Before it, the object is totally black.. Object when it doesnt rotate or zoom

export class SceneComponent implements AfterViewInit {

  private renderer: THREE.WebGLRenderer;
  private camera: THREE.PerspectiveCamera;
  private lighting;
  private ambient;
  private cameraTarget: THREE.Vector3;
  public scene: THREE.Scene;

  public fieldOfView: number = 20;
  public nearClippingPane: number = 1;
  public farClippingPane: number = 2000;

  public controls: THREE.OrbitControls;

  constructor(){
    this.render = this.render.bind(this);
    this.onModelLoadingCompleted = this.onModelLoadingCompleted.bind(this);
  }

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

  private createCamera(){
    let aspectRatio = this.getAspectRatio();
    this.camera = new THREE.PerspectiveCamera(
      this.fieldOfView,
      aspectRatio,
      this.nearClippingPane,
      this.farClippingPane
    );

    // Set position and look at
    this.camera.position.y = 1.5;
    this.camera.position.x = 0.1;
    this.camera.position.z = 4.2;
  }

  private createScene(){
    this.scene = new THREE.Scene();
    //this.scene.add(new THREE.AxesHelper(200));
    var loader = new THREE.OBJLoader();
    loader.load('assets/model/test.obj', this.onModelLoadingCompleted);
  }

  private createLight(){
    this.lighting = true;
    this.ambient = new THREE.AmbientLight(0xffffff, 1);
    this.scene.add(this.ambient);
    this.ambient.intensity = 0.5;

    var keyLight = new THREE.DirectionalLight(new THREE.Color(0xf3f3f3), 0.4);
    keyLight.position.set(0, 100, 0);
    this.scene.add(keyLight);

    var fillLight = new THREE.DirectionalLight(new THREE.Color(0xffffff), 0.2);
    fillLight.position.set(100, 0, 100);
    this.scene.add(fillLight);

    var backLight = new THREE.DirectionalLight(0xffffff, 0.5);
    backLight.position.set(-100, 0, -100).normalize();
    this.scene.add(backLight);
  }

  private onModelLoadingCompleted(object) {

    var loader = new THREE.TextureLoader();
    var material = new THREE.MeshPhongMaterial();

    //material.specular = 1;
    material.map = loader.load('assets/textures/y-form.png');

    object.traverse( function ( child ) {
      if ( child instanceof THREE.Mesh ) {
        child.material = material;
      }
    } );

    object.position.y = -.5;

    this.scene.add(object);
    this.render();
    console.log('Texture load complete.');
  }

  private getAspectRatio(): number {
    let height = this.canvas.clientHeight;
    if (height === 0) {
      return 0;
    }
    return this.canvas.clientWidth / this.canvas.clientHeight;
  }

  private startRendering() {
    this.renderer = new THREE.WebGLRenderer({
      canvas: this.canvas,
      antialias: true
    });
    this.renderer.setPixelRatio(devicePixelRatio);
    this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
    this.renderer.setClearColor(0xffffff, 1);

    let component: SceneComponent = this;

    (function render() {
      //requestAnimationFrame(render);
      component.render();
    }());
  }

  public render() {
    this.renderer.render(this.scene, this.camera);
  }

  public addControls() {
    this.controls = new THREE.OrbitControls(this.camera);
    this.controls.enableDamping = true;
    this.controls.dampingFactor = 0.7;
    this.controls.enableZoom = true;
    this.controls.autoRotate = false;
    this.controls.autoRotateSpeed = 0.3;
    this.controls.rotateSpeed = 1.0;
    this.controls.zoomSpeed = 1.2;
    this.controls.addEventListener('change', this.render);
  }

  /* EVENTS */

  public onMouseDown(event: MouseEvent) {
    console.log("onMouseDown");
    event.preventDefault();

    // Example of mesh selection/pick:
    var raycaster = new THREE.Raycaster();
    var mouse = new THREE.Vector2();
    mouse.x = (event.clientX / this.renderer.domElement.clientWidth) * 2 - 1;
    mouse.y = - (event.clientY / this.renderer.domElement.clientHeight) * 2 + 1;
    raycaster.setFromCamera(mouse, this.camera);

    var obj: THREE.Object3D[] = [];
    this.findAllObjects(obj, this.scene);
    var intersects = raycaster.intersectObjects(obj);
    console.log("Scene has " + obj.length + " objects");
    console.log("Camera position " + this.camera.position.x + ", " + this.camera.position.y + ", " + this.camera.position.z);
    console.log(intersects.length + " intersected objects found")
    intersects.forEach((i) => {
      console.log(i.object); // do what you want to do with object
    });

  }

  private findAllObjects(pred: THREE.Object3D[], parent: THREE.Object3D) {
    // NOTE: Better to keep separate array of selected objects
    if (parent.children.length > 0) {
      parent.children.forEach((i) => {
        pred.push(i);
        this.findAllObjects(pred, i);
      });
    }
  }

  public onMouseUp(event: MouseEvent) {
    console.log("onMouseUp");
  }


  @HostListener('window:resize', ['$event'])
  public onResize(event: Event) {
    this.canvas.style.width = "100%";
    this.canvas.style.height = "100%";
    console.log("onResize: " + this.canvas.clientWidth + ", " + this.canvas.clientHeight);

    this.camera.aspect = this.getAspectRatio();
    this.camera.updateProjectionMatrix();
    this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
    this.render();
  }

  @HostListener('document:keypress', ['$event'])
  public onKeyPress(event: KeyboardEvent) {
    console.log("onKeyPress: " + event.key);
  }

  /* LIFECYCLE */
  ngAfterViewInit() {
    this.createScene();
    this.createLight();
    this.createCamera();
    this.startRendering();
    this.addControls();
  }

}

When I remove the Texture the object is shown correctly.. Thanks for help.

1 Answer 1

1

The problem is that you redraw your scene too early. Try to use the onLoad() callback of TextureLoader so you execute this.render(); only when the texture has fully loaded

Alternatively, consider to use THREE.LoadingManager in order to manage requests of multiple loaders.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.