derOtterDieb
derOtterDieb

Reputation: 565

Three.js and Angular 6 not rendering an object from JSON file

I'm trying for the first time to render 3D things on my browser. Here's few informations about my app :

I get a 3D model on clara.io (https://clara.io/view/1a03ac6b-d6b5-4c2d-9f1a-c80068311396) and downloaded it as JSON and as .obj (I wanted to try both ways), but I fail to render it on my screen.

Here's some code :

fox.component.html :

<div id="rendu"></div>

fox.component.ts :

import { Component, OnInit, ElementRef, ViewChild } from '@angular/core';
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { JhiEventManager } from 'ng-jhipster';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { Detector } from 'detector-js';
const raf = require('raf');
import { LoginModalService, Principal, Account } from 'app/core';

import * as THREE from 'three-full';

@Component({
    selector: 'jhi-poc',
    templateUrl: './fox.component.html',
    styleUrls: ['fox.component.scss']
})
export class FoxComponent implements OnInit {
    @ViewChild('rendu') rendererContainer: ElementRef;
    camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera();
    scene: THREE.Scene = new THREE.Scene();
    renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer();
    geometry: THREE.Geometry = new THREE.Geometry();
    material: THREE.MeshBasicMaterial = new THREE.MeshBasicMaterial();
    mesh: THREE.Mesh = new THREE.Mesh();

    constructor(private http: HttpClient) {}

    ngOnInit() {
        const _this = this;

        _this.camera = new THREE.PerspectiveCamera(75, (window.innerWidth * 3 / 4) / (window.innerHeight * 3 / 4), 0.01, 1000);
        _this.camera.position.z = 5;

        _this.scene = new THREE.Scene();

        _this.renderer = new THREE.WebGLRenderer({ alpha: true });
        _this.renderer.setSize(window.innerWidth * 3 / 4, window.innerHeight * 3 / 4);
        _this.renderer.setClearColor(new THREE.Color(0.7, 0.7, 0.7);
        const loader = new THREE.OBJLoader2();
        const url = '3D/fox.json';
        loader.load(url, function(obj) {
            _this.scene.add(obj.detail.loaderRootNode);
            console.log(obj);
        });

        const light = new THREE.AmbientLight(0.7, 0.7, 0.7);
        _this.scene.add(light);
        document.getElementById('rendu').appendChild(this.renderer.domElement);
        _this.renderer.render( _this.scene, _this.camera );
    }
}

You can download json or .obj files from the link I gave above.

Problem is, weither I try with .obj or .json, I only get a gray empty canvas. No error in console, so I'm a bit lost about what I do wrong here. I displayed the result of the load() function in console :

{detail: {…}}
    detail:
        instanceNo: 0
        loaderRootNode: Group
            castShadow: false
            children: []
            frustumCulled: true
            layers: Layers {mask: 1}
            matrix: Matrix4 {elements: Array(16)}
            matrixAutoUpdate: true
            matrixWorld: Matrix4 {elements: Array(16)}
            matrixWorldNeedsUpdate: false
            name: ""
            parent: Scene {uuid: "066CCCF6-B0DE-42FA-AA60-9679BFB688E3", name: "", type: "Scene", parent: null, children: Array(2), …}
            position: Vector3 {x: 0, y: 0, z: 0}
            quaternion: Quaternion {_x: 0, _y: 0, _z: 0, _w: 1, onChangeCallback: ƒ}
            receiveShadow: false
            renderOrder: 0
            rotation: Euler {_x: 0, _y: 0, _z: 0, _order: "XYZ", onChangeCallback: ƒ}
            scale: Vector3 {x: 1, y: 1, z: 1}
            type: "Group"
            up: Vector3 {x: 0, y: 1, z: 0}
            userData: {}
            uuid: "C98D648A-6929-4EFA-AF62-7C27270F5D4E"
            visible: true
            id: 24
            modelViewMatrix: Matrix4 {elements: Array(16)}
            normalMatrix: Matrix3 {elements: Array(9)}
            __proto__: Object3D
        modelName: ""
        __proto__: Object
    __proto__: Object

Seems like the object is properly read to me. Don't hesitate to ask if you need anything else, I'm not familiar with three.js or 3D in general.

UPDATE :

Upvotes: 0

Views: 1326

Answers (2)

derOtterDieb
derOtterDieb

Reputation: 565

Alright, I found few things.

First of all, I ended using GLTF files, and GLTFLoader as recommended. Then, I started over, using this example : https://github.com/makimenko/angular-three-examples/blob/master/src/app/scene/scene.component.ts

I don't really know if using <canvas> instead of <div> in .html is what I missed, but it might be. I used all the code from the link I gave and only changed one part :

private createScene() {
    this.scene = new THREE.Scene();
    const loader = new THREE.GLTFLoader();
    loader.load('3D/fox.gltf', this.onModelLoadingComplete);
}

Works perfectly fine now. This code uses more options for the rendering part, and use AfterViewInit (I was trying to do it in OnInit), and canvas as I said. That's the big differences I saw. Anyway, it works now.

Upvotes: 0

Mugen87
Mugen87

Reputation: 31076

 const loader = new THREE.OBJLoader2();
 const url = '3D/fox.json';
 loader.load(url, function(obj) {

You can't load JSON files with OBJLoader2 which is exclusively intended for OBJ files. Try it with THREE.ObjectLoader instead.

three.js R104

Upvotes: 1

Related Questions