0

Question:

Why isn't the 3D graphic rendering?

Details:

I am trying to load the json format of this graphic in the loading.component.ts file. I am using Angular 2 and Three.js. I've looked at several examples, but cannot find what I did wrong. This is my first time trying to load a 3D image. Any help appreciated. The entire project can be found here.

Console Error:

core.es5.js:1084 ERROR TypeError: Cannot read property 'scene' of undefined
    at loading.component.ts:46
    at ObjectLoader.parse (three.module.js:33413)
    at three.module.js:33372
    at XMLHttpRequest.<anonymous> (three.module.js:29460)
    at ZoneDelegate.invokeTask (polyfills.bundle.js:3132)
    at Object.onInvokeTask (core.es5.js:4119)
    at ZoneDelegate.invokeTask (polyfills.bundle.js:3131)
    at Zone.runTask (polyfills.bundle.js:2899)
    at XMLHttpRequest.ZoneTask.invoke (polyfills.bundle.js:3194)

loading.component.ts

import { Component, OnInit } from '@angular/core';
import * as THREE from 'three'
declare var require: any;

@Component({
  selector: 'app-loading',
  templateUrl: './loading.component.html',
  styleUrls: ['./loading.component.css']
})
export class LoadingComponent implements OnInit {
  "use strict";

  scene = new THREE.Scene();
  renderer = new THREE.WebGLRenderer();
  light = new THREE.AmbientLight(0xffffff);
  camera;
  box;
  renderCallback;

  constructor() { }

  ngOnInit() {
    // size of content 
    this.renderer.setSize( window.innerWidth, window.innerHeight);
    // where to render content 
    document.getElementById("webgl-container").appendChild(this.renderer.domElement);

    this.scene.add(this.light);

    this.camera = new THREE.PerspectiveCamera(
      35, // Field of view (FOV) from top to bottom. 
      window.innerWidth / window.innerHeight, // boundries of image 
      1, 
      1000
    );

    this.camera.position.set(0, 0, 5);
    this.scene.add(this.camera);

    var loader = new THREE.ObjectLoader();

    loader.load('assets/img/pac-man-threejs/pac-man.json', function (obj) {
      this.scene.add(obj);
    })

    // this.render();
    this.renderCallback = {
      callRender: (this.render).bind(this)
    };
    this.renderCallback.callRender();
  }

  render() { 
    this.renderer.render(this.scene, this.camera);
    // requestAnimationFrame(this.render);
    requestAnimationFrame(this.renderCallback.callRender);
  }
}
2
  • Have you used the debugger to try to figure out which of the 4 instances of this.scene is not working? Commented May 24, 2017 at 20:58
  • Btw the question isnt why isn't my graphics rendering but why isn't my async javascript working. This more or less has nothing to do with three.js Commented May 24, 2017 at 21:01

2 Answers 2

2

You don't have the correct this inside the loader.load() callback, which is exactly what the browser is telling you.

var _this = this
loader.load(..., function(obj){ _this.scene.add(obj })

or bind it.

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

2 Comments

Thank the graphic is displayed now!
To be more precise, your JavaScript works now :), you barely made it to the graphics part. You may have rendered frames and ran the loop before this callback fired but then js scope crashed your app.
0

Thats why you need arrow functions:

import { Component, OnInit } from '@angular/core';
import * as THREE from 'three'
declare var require: any;

@Component({
  selector: 'app-loading',
  templateUrl: './loading.component.html',
  styleUrls: ['./loading.component.css']
})
export class LoadingComponent implements OnInit {
  "use strict";

  scene = new THREE.Scene();
  renderer = new THREE.WebGLRenderer();
  light = new THREE.AmbientLight(0xffffff);
  camera;
  box;
  renderCallback;

  constructor() { }

  ngOnInit() {
    // size of content 
    this.renderer.setSize( window.innerWidth, window.innerHeight);
    // where to render content 
    document.getElementById("webgl-container").appendChild(this.renderer.domElement);

    this.scene.add(this.light);

    this.camera = new THREE.PerspectiveCamera(
      35, // Field of view (FOV) from top to bottom. 
      window.innerWidth / window.innerHeight, // boundries of image 
      1, 
      1000
    );

    this.camera.position.set(0, 0, 5);
    this.scene.add(this.camera);

    var loader = new THREE.ObjectLoader();

    loader.load('assets/img/pac-man-threejs/pac-man.json', (obj) => {
      this.scene.add(obj);
    })

    // this.render();
    this.renderCallback = {
      callRender: (this.render).bind(this)
    };
    this.renderCallback.callRender();
  }

  render() { 
    this.renderer.render(this.scene, this.camera);
    // requestAnimationFrame(this.render);
    requestAnimationFrame(this.renderCallback.callRender);
  }
}

1 Comment

You haven't really explained why. I've no experience with typescript, so i'm not sure if arrow functions are even available. Furthermore his error mentions es5 in the file, which adds to my confusion. Is it just the fact that this code has imports, that an assumption can be made that arrow functions are available? We should probably mark this as a duplicate, i'm sure there is an answer here about this topic with thousands of upvotes :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.