Load .STL model provided by .net api

Hi there,

i want to load .STL model provided by my .net api but i receive such error

image

my .net api:

    [HttpGet]
    [EnableCors("AllowOrigin")]
    public IActionResult GetFile()
    {
        try
        {
            var bytes = System.IO.File.ReadAllBytes(_settings.TestPath);
            return File(bytes, GetContentType(_settings.TestPath), "A-0006801.STL");
        }
        catch
        {
            return StatusCode(500, new { StatusMessage = "Internal server error" });
        }
    }
    private string GetContentType(string path)
    {
        var provider = new FileExtensionContentTypeProvider();
        string contentType;
        if (!provider.TryGetContentType(path, out contentType))
        {
            contentType = "application/octet-stream";
        }
        return contentType;
    }

in my .ts file im using SceneLoader as follows:

public createScene(): void {
var canvas = document.getElementById(‘rendererCanvas’) as HTMLCanvasElement;
var engine = new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true });
var scene = new BABYLON.Scene(engine);

scene.createDefaultCameraOrLight(true, true, true);
scene.createDefaultEnvironment();

BABYLON.SceneLoader.ImportMesh("", "http://localhost:8002/api/test", "", scene, function (scene) {
});

engine.runRenderLoop(function () {
  if (scene) {
    scene.render();
  }
});

}

my imports are:

import { SceneLoader, Scene, Engine, FreeCamera, Mesh, Camera, FilesInput } from ‘babylonjs’;
import 'babylonjs-loaders

every suggestions welcome.

Looks like you are missing the file name in here. the 3rd double quote should contain the filename.stl

Thank you for your answer @sebavan, but my api method GetFile(), for test purposes, takes no arguments and returns only one specific file. Therefore address http://localhost:8002/api/test is valid to obtain that .STL file and in this case third optional argument of BABYLON.SceneLoader.ImportMesh() may be empty.

You can try :

BABYLON.SceneLoader.ImportMesh("", "http://localhost:8002/api/", "test",
    undefined, 
    undefined,
    undefined,
    undefined,
    ".stl")

To force the stl loader :slight_smile:

I changed the function call to BABYLON.SceneLoader.ImportMesh("", “http://localhost:8002/api/”, “test”, scene, undefined, undefined, undefined, “.STL”); but recived same error message image

Can you check if the stl loader is present?

Run console.log(SceneLoader._getPluginForExtension(".stl")) right before the import - does it output anythying?

Thank you for your answer @RaananW, yes it does, the output is:

Will it be possible to see your code? what version of babylon are you using?

The stl extension is there, you are setting the plugin extension correctly (seems to be, at least), but still - the .babylon file loader is triggered.

a repro in the playground is the key as always!

https://doc.babylonjs.com/resources/external_pg_assets

That is, if he can get his .net server deployed online somehow :slight_smile:

Wouldn’t the file name be “A-0006801.stl” ?

What happens if you try

BABYLON.SceneLoader.ImportMesh("", "http://localhost:8002/api/test", "A-0006801.stl",
    undefined, 
    undefined,
    undefined,
    undefined,
    ".stl")

Hi there,
sorry for not answering to this topic earlier, I was involved in other project. I still haven’t found sollution to this problem. Here is what I want to achieve: https://www.babylonjs-playground.com/#8LFTCH#250, in this playground i used my .stl model hosted on dropbox and it works as should. At this moment i am unable to deploy online my .net api but code of TestController is as follows

[Route("api/test")]
[ApiController]
public class TestController : Controller
{
    private readonly Settings _settings;

    public TestController(IOptions<Settings> settings)
    {
        _settings = settings.Value;
    }

    [HttpGet]
    [EnableCors("AllowOrigin")]
    public IActionResult GetFile()
    {
        try
        {
            var bytes = System.IO.File.ReadAllBytes(_settings.TestPath);
            return File(bytes, GetContentType(_settings.TestPath), "A-0006801.STL");
        }
        catch
        {
            return StatusCode(500, new { StatusMessage = "Internal server error" });
        }
    }
    private string GetContentType(string path)
    {
        var provider = new FileExtensionContentTypeProvider();
        string contentType;
        if (!provider.TryGetContentType(path, out contentType))
        {
            contentType = "application/octet-stream";
        }
        return contentType;
    }

    [HttpGet("alien")]
    [EnableCors("AllowOrigin")]
    public IActionResult GetAlien()
    {
        try
        {
            var bytes = System.IO.File.ReadAllBytes(@"wwwroot/database/test/alien.glb");

            return File(bytes, "model/gltf-binary", "alien.glb");

        }
        catch
        {
            return StatusCode(500, new { StatusMessage = "Internal server error" });
        }
    }
}

}

My Angular client - package.json

{
  "name": "client-app",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~9.0.6",
    "@angular/common": "~9.0.6",
    "@angular/compiler": "~9.0.6",
    "@angular/core": "~9.0.6",
    "@angular/forms": "~9.0.6",
    "@angular/platform-browser": "~9.0.6",
    "@angular/platform-browser-dynamic": "~9.0.6",
    "@angular/router": "~9.0.6",
    "babylonjs": "^4.1.0",
    "babylonjs-loaders": "^4.1.0",
    "rxjs": "~6.5.4",
    "tslib": "^1.10.0",
    "zone.js": "~0.10.2"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.900.6",
    "@angular/cli": "~9.0.6",
    "@angular/compiler-cli": "~9.0.6",
    "@angular/language-service": "~9.0.6",
    "@types/node": "^12.11.1",
    "@types/jasmine": "~3.5.0",
    "@types/jasminewd2": "~2.0.3",
    "codelyzer": "^5.1.2",
    "jasmine-core": "~3.5.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~4.3.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage-istanbul-reporter": "~2.1.0",
    "karma-jasmine": "~2.0.1",
    "karma-jasmine-html-reporter": "^1.4.2",
    "protractor": "~5.4.3",
    "ts-node": "~8.3.0",
    "tslint": "~5.18.0",
    "typescript": "~3.7.5"
  }
}

My Angular client component

import { Component, OnInit } from '@angular/core';
import { SceneLoader, Scene, Engine, FreeCamera, Vector3, HemisphericLight, Mesh, Camera, FilesInput } from 'babylonjs';
import 'babylonjs-loaders';
import { CanvasService } from 'src/app/services/canvas.service';
import { Customer } from 'src/app/model/Customer';
import { HttpEventType } from '@angular/common/http';
import { STLFileLoader } from 'babylonjs-loaders';

@Component({
  selector: 'app-canvas',
  templateUrl: './canvas.component.html',
  styleUrls: ['./canvas.component.css']
})

export class CanvasComponent implements OnInit {

  constructor(private canvasService: CanvasService) { }

  ngOnInit(): void {  
    this.byDropboxLink();
  }

  byDropboxLink(){
    var canvas = document.getElementById('rendererCanvas') as HTMLCanvasElement;
    var engine = new Engine(canvas);
    var scene = new Scene(engine); 
    SceneLoader.ImportMesh(
        "",
       //"https://dl.dropbox.com/s/oo64nfczss2xrz2/A-0006801.STL",
            "http://localhost:8002/api/test",
        undefined,
        scene,
        function (meshes) {          
            scene.createDefaultCameraOrLight(true, true, true);
            scene.createDefaultEnvironment();
            engine.runRenderLoop(function () { scene.render(); });
        }
    );
  }
}

Still wandering what may be the difference between using file hosted in dropbox which works fine and my .net api that gives this error
image

This is impossible to troubleshoot without a repro at this point :frowning: so either you do not have the loaders referenced in your page or the model does not load from the server.

I have the same error on Svelte.

The problem is that there’s no documentation available on how to use FileLoaders via npm. There’s this: babylonjs-loaders - npm

But it doesn’t show any examples of how to actually use (e.g.) the stlFileLoader. It just shows how to import it and configure it.

When I do as shown in the NPM readme then use the importer:

BABYLON.SceneLoader.ImportMesh(null, "src/assets/3dmodels/", "modem", scene, function (meshes, particleSystems, skeletons) {
          console.log("meshes", meshes);
    });

I get the same error:

BJS - [13:43:46]: Unable to import meshes from src/assets/3dmodels/model.stl: importMesh of undefined from undefined version: undefined, exporter version: undefinedimportMesh has failed JSON parse

The end of the page here describes what you are probably referring to:

You just need to import the right loader from the @babylonjs/loaders library.
Make sure you are using the same version for both the core and loaders packages

I managed to get it working. The key for me was that Babylon must be imported after the DOM has mounted, while babylonjs-loaders can be imported normally. E.g.

<script>
  import 'babylonjs-loaders';
  let BABYLON: typeof import('babylonjs');
  onMount() {
     const babylonjs = await import('babylonjs');
     BABYLON = babylonjs.default;
  }
</script>

I would very much suggest you to use the es66 packages instead of the UMD packages if you want it to work better. The UMD packages are great if you want to use them as a script in your HTML page. the es6 modules (the page I linked) would be much better if you are working with bundlers

1 Like

@RaananW I don’t understand. The page you linked doesn’t seem to tell me anything related. Have I linked to UMD packages in my example?

I linked the ES6 support page. Here are the available packages:

Babylon.js ES6 support with Tree Shaking | Babylon.js Documentation (babylonjs.com)

any package that doesn’t start with @babylonjs is a UMD package.

2 Likes