I am using obj loader, but my obj can not be displayed at all

myown.obj.zip (2.5 MB) Hi, I want to play the attached obj file using threejs, what I did is to modify the webgl_loader_obj.html directly by pointing to this obj, using below:

loader.load( ‘models/obj/myown.obj’, function ( obj ) {
object = obj;
});

But when I refresh the page, the whole page is empty.
I am very new at using threejs, and do not know how to debug and find error, I don’t see any error in the console either.
can you please help to tell me the error here?
Thanks in advance

Try it with this code:

import * as THREE from '../build/three.module.js';

import { OBJLoader } from './jsm/loaders/OBJLoader.js';
import { OrbitControls } from './jsm/controls/OrbitControls.js';

var container;

var camera, scene, renderer;

init();
animate();


function init() {

	container = document.createElement( 'div' );
	document.body.appendChild( container );

	camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.01, 10 );
	camera.position.z = 5;

	// scene

	scene = new THREE.Scene();

	var ambientLight = new THREE.AmbientLight( 0xcccccc, 0.4 );
	scene.add( ambientLight );

	var pointLight = new THREE.PointLight( 0xffffff, 0.8 );
	camera.add( pointLight );
	scene.add( camera );

	// model

	var loader = new OBJLoader();

	loader.load( 'models/obj/myown.obj', function ( obj ) {

		// center asset

		var box = new THREE.Box3().setFromObject( obj );
		var center = new THREE.Vector3();
		box.getCenter( center );
		obj.position.sub( center );

		// add to scene

		scene.add( obj );

	} );

	//

	renderer = new THREE.WebGLRenderer();
	renderer.setPixelRatio( window.devicePixelRatio );
	renderer.setSize( window.innerWidth, window.innerHeight );
	container.appendChild( renderer.domElement );

	var controls = new OrbitControls( camera, renderer.domElement );

	//

	window.addEventListener( 'resize', onWindowResize, false );

}

function onWindowResize() {

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

	renderer.setSize( window.innerWidth, window.innerHeight );

}

//

function animate() {

	requestAnimationFrame( animate );
	render();

}

function render() {

	renderer.render( scene, camera );

}

The original OBJ model has a far bigger scale than your book. The above code has optimized camera settings for your use case. It also uses OrbitControls which is more appropriate for a model viewer.

However, the colors of your book are messed up because there is a bug in OBJLoader. I’m going to fix this and link the PR here.

2 Likes

Fixed with the next release R109.

2 Likes

very good help, thanks!

1 Like

Hi, I was wondering how to dynamically decide the best z value of camera position? Also I tries the change z value like below:

camera.position.set(-2, 2, 2);
setTimeout(()={
camera.position.z=6;
});

It seemed the object just moved to the corner of the canvas, I want to have the z value changed only and the whole object still located at same place.

Thanks

You can use the code from gltf-viewer for centering your object and an optimal camera configuration:

The variable object represents your loaded asset.

Thanks,
I used the logic, but found that initially the book does not show, only after I clicked the canvas and then it appeared.

const box = new THREE.Box3().setFromObject(obj);
const size = box.getSize(new THREE.Vector3()).length();
const center = box.getCenter(new THREE.Vector3());
this.controls.reset();

        obj.position.x += (obj.position.x - center.x);
        obj.position.y += (obj.position.y - center.y);
        obj.position.z += (obj.position.z - center.z);
        this.controls.maxDistance = size * 10;
        this.camera.near = size / 100;
        this.camera.far = size * 100;
        this.camera.updateProjectionMatrix();

        this.camera.position.copy(center);
        this.camera.position.x += size / 2.0;
        this.camera.position.y += size / 5.0;
        this.camera.position.z += size / 2.0;

        this.camera.lookAt(center);
        this.scene.add(obj);

what might be the cause for that?

Not sure. Can you please share your whole code?

This is the whole code using angular 6:

export class ThreeDPlayerComponent {

@Input() threeDPath: string;
@Input() darkMode: boolean;

loaderType: string; // OBJ | 3MF

nativeElement: any;
comp: any;
object: any;

renderer: any;
camera: any;
scene: any;
controls: any;

constructor(el: ElementRef) {
    this.nativeElement = el.nativeElement;
    setTimeout(() => {
        this.loaderType = this.threeDPath.substr(this.threeDPath.lastIndexOf('.') + 1);
        this.play3D();
        this.animate();
    });
    this.render = this.render.bind(this);
    this.onWindowResize = this.onWindowResize.bind(this);
    this.onProgress = this.onProgress.bind(this);
    this.animate = this.animate.bind(this);

    this.darkMode = true;
}

animate() {
    requestAnimationFrame(this.animate);
    this.render();
}
play3D() {
    const domElement = this.nativeElement.children[0];
    domElement.innerHTML = '';
    this.renderer = new THREE.WebGLRenderer({
        antialias: true,
        preserveDrawingBuffer: true
    });
    this.renderer.setPixelRatio(window.devicePixelRatio);
    // this.renderer.setSize(domElement.offsetWidth, domElement.offsetWidth / window.devicePixelRatio);
    this.renderer.setSize(domElement.offsetWidth, domElement.offsetHeight);

    domElement.appendChild(this.renderer.domElement);

    this.scene = new THREE.Scene();
    if (this.darkMode) {
        this.scene.background = new THREE.Color(0x000000);
    } else {
        this.scene.background = new THREE.Color(0xffffff);
    }
    this.scene.add(new THREE.AmbientLight(0xcccccc, 0.4));
    this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
    // this.camera.position.set(-2, 2, 2); // z - to control if this is too small

    // this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
    // this.camera.position.set(-2, 2, 250);

    this.camera.add(new THREE.PointLight(0xffffff, 0.8));

    this.scene.add(this.camera);

    this.controls = new OrbitControls(this.camera, this.renderer.domElement);
    const loader = new OBJLoader();

    loader.load(this.threeDPath, obj => {
        // center asset
        // const box = new THREE.Box3().setFromObject(obj);
        // const center = new THREE.Vector3();
        // box.getCenter(center);
        // obj.position.sub(center);
        // this.scene.add(obj);

        const box = new THREE.Box3().setFromObject(obj);
        const size = box.getSize(new THREE.Vector3()).length();
        const center = box.getCenter(new THREE.Vector3());
        this.controls.reset();

        obj.position.x += (obj.position.x - center.x);
        obj.position.y += (obj.position.y - center.y);
        obj.position.z += (obj.position.z - center.z);
        this.controls.maxDistance = size * 10;
        this.camera.near = size / 100;
        this.camera.far = size * 100;
        this.camera.updateProjectionMatrix();

        this.camera.position.copy(center);
        this.camera.position.x += size / 2.0;
        this.camera.position.y += size / 5.0;
        this.camera.position.z += size / 2.0;

        this.camera.lookAt(center);
        this.scene.add(obj);

    }, this.onProgress);

    window.addEventListener('resize', this.onWindowResize, false);
}
onProgress(xhr) {
    if (xhr.lengthComputable) {
        const percentComplete = xhr.loaded / xhr.total * 100;
        console.log('model ' + percentComplete + '% downloaded');
    }
}

onWindowResize() {
    const domElement = this.nativeElement.children[0];
    this.camera.aspect = domElement.offsetWidth / domElement.offsetHeight;
    this.camera.updateProjectionMatrix();
    this.renderer.setSize(domElement.offsetWidth, domElement.offsetHeight);
}
render() {
    this.renderer.render(this.scene, this.camera);
}

}

for this, initialy, the book is not there, only after I click on canvas and move, then the book appeared.

Any idea?

I can’t see something obvious in your code. Any chances to share a live example with your code? It’s also a good option to share a repository so I can debug the code on my computer.

BTW: Any reasons for setting preserveDrawingBuffer to true. Unless you don’t do stuff like synchronous drawing buffer access (e.g. via toDataURL()), it’s better to not set this flag to true. Otherwise you might have significant performance loss on some platforms.

Thanks Michael,
This is the repo for the testing code:

git clone https://hexufeng@bitbucket.org/hexufeng/my_threed_test.git

You need to npm install and then ng serve

Need to be in latest node version

You can see the code inside app.component.ts

when you first run, you can see the obj is loaded, but if you use the commented out code, then the book does not appear until you click the canvas. I think something is wrong in my code, but I do not know where.

Also for the current code, if you zoom the obj, the book is cut off from half, no idea why.

Hope to hear your advice soon

Thanks

It should work if you call this.controls.update(); at the end of the onLoad() callback (right after this.scene.add(obj);).

1 Like

Thanks Michael, it worked!
Appreciate it very much.

Have a good day.

1 Like

Hey man,
It’s my first time creating account here and it’s all because of you. I’ve just started learning threejs and been struggling with loading stl file for a while. Some of the lightning codes in the script above helps me while I couldn’t find my model on the canvas.

Thanks, man.

I still got some questions to ask though.

1 Like