Access BABYLON.OBJFileLoader in BJS 4.0.3

Hello all,

I’m now playing with importing some geometry files, and I’ve given some use to the assetsManager and to BABYLON.SceneLoader.Append. However, I’m interested in seeing BABYLON’s capabilities for importing geometries from strings. In order to do so I’ve dived into BABYLON source code (GitHub - BabylonJS/Babylon.js: Babylon.js is a powerful, beautiful, simple, and open, game and rendering engine packed into a friendly JavaScript framework.) and found the lovely OBJFileLoader class:


This class has a method, importMeshAsync that does exactly what I’m looking for, however I’ve been encountering some issues when trying to use it in my code.

I’m a beginner in both web-apps and BJS so my problems might be quite silly. I hope someone can give me some guidance here! :smiley:

First, I found this class in version 4.1.0-alpha.1 This class has an optional parameter for the constructor that gives some settings to the class. I was using some boilerplate I found based on version 3.3.0, and this class did not have constructor available there (I really need to use those settings, so I can’t work with the class available in 3.3.0). So here I go, ready to upgrade my version to the latest released one (4.0.3 in npm) only to find that now, OBJFileLoader is not an available class inside BJS:

Am I doing something terribly wrong and this class should be ready to use somewhere, or I can’t just access it out of the blue? If it is not as easily accesible as I thought, is there some work around importing .stl/.obj files from strings?

Thank you!

I’m not exactly sure how you are pulling in the Babylon code into your project, but most likely you need to pull in the loaders in addition to the core engine. If you are using ES6 modules, see here: ES6 - Babylon.js Documentation and more specifically ES6 - Babylon.js Documentation.

2 Likes

Thank you for your answer! Apparently it is exactly that what I am missing. I’ve read the documentation you sent, implemented it ,and now it does not give any errors. However, when I try to load said .obj from a string, it does nothing apparently. Now, I’m not sure if it’s because I’m not using the method as it should be used, or because the content of the string should be modified beforehand. Maybe someone around here as some experience with this, so I will post my code here to see if someone has any idea that helps :slight_smile:

I’m doing this project in typescript, and these are the two main files:
index.ts

import { Main } from './main';
import 'babylonjs-materials';
import 'babylonjs-loaders';

window.addEventListener('DOMContentLoaded', () => {
    const main = new Main('renderCanvas');
    main.createScene();
    main.useHiddenFunction();
});

main.ts

import * as BABYLON from 'babylonjs';
import { OBJFileLoader } from 'babylonjs-loaders';

export class Main {
    private _canvas: HTMLCanvasElement;
    private _engine: BABYLON.Engine;
    private _scene: BABYLON.Scene;
    private _camera: BABYLON.ArcRotateCamera;
    private _light: any;
    private _my_obj: string;

    constructor(canvasElement: string) {
        // Create canvas and engine
        this._canvas = <HTMLCanvasElement>document.getElementById(canvasElement);
        this._engine = new BABYLON.Engine(this._canvas, true);
    }

    /**
     * Creates the BABYLONJS Scene
     */
    createScene(): void {
        // create a basic BJS Scene object
        this._scene = new BABYLON.Scene(this._engine);
        // create an ArcRotateCamera
        this._camera = new BABYLON.ArcRotateCamera(
            'camera',
            2.127076697832047,
            0.8671560465713813,
            50,
            BABYLON.Vector3.Zero(),
            this._scene
        );
        this._camera.attachControl(this._canvas, true);

        this._light = new BABYLON.HemisphericLight(
            'light',
            new BABYLON.Vector3(0, 1, 0),
            this._scene
        );

        this._engine.runRenderLoop(() => {
            this._scene.render();
        });
    }

    useHiddenFunction(): void {
        const my_obj = https://paste.ee/p/GTN5R;
        const mesh_load_options = {
            ComputeNormals: false,
            ImportVertexColors: false,
            InvertY: false,
            InvertTextureY: true,
            UVScaling: new BABYLON.Vector2(1, 1),
            MaterialLoadingFailsSilently: true,
            OptimizeWithUV: false,
            SkipMaterials: true
        };
        const object_loader = new OBJFileLoader(mesh_load_options);

        var promise_aft = object_loader.importMeshAsync('shark', this._scene, my_obj, '').then(
            (value) => {
                console.log('I passed!');
                console.log(value);
            },
            (error) => {
                console.log('I failed :(');
                console.log(error);
            }
        );
        console.log(promise_aft);
    }

Some notes about index.ts:

  • that url that you can see is not written like that in the code. In the actual code I have the content that is in that pastebin url. I just typed the URL there so that it is cleaner in this post.
  • I’m not very familiar with Promises (yet), but if I understood everything right, if the promise “is accepted” something should come out of it. I would think that it would return the mesh (actually it should return an object that includes the created mesh), but instead it returns said object, with an empty array of meshes.

So I see that my code is not crashing, which is a good sign, but it is not doing anything either, which is not a good sign. Does anybody have any idea why the mesh contained in the string is not imported onto the scene?

Thank you! :slight_smile:

P.D. I included this question as an extra post in my previous question, to keep it all organized. If I should post it as a sepparate question in the forum, please let me know.

P.D.2 I included the code written in the post instead of a PG, because I wanted to show the
import { OBJFileLoader} from 'babylonjs-loaders'
to check that I’m doing everything right. I think this would not show up in a PG

My guess is that the mesh name that you are passing as the first parameter to importMeshAsync isn’t actually the name of any mesh in the obj. It looks like the obj’s mesh name is Shark_01SG1_Untitled and not shark. If you just want to load everything from the obj, pass in empty string or null as the first parameter for importMeshAsync.

If this isn’t the issue, can you put this into a playground?

1 Like

That was it! Eventually I saw that there was some problem with the naming, but I couldn’t find the solution. I actually thought that the mesh name I’m passing to the function is just some name that I want to give to the mesh within Babylon (such as when you create a Mesh), and I didn’t think of passing an empty string. That worked perfectly!

Thanks a lot @bghgary! :smiley:

1 Like