URLs that lack extensions

Hi all, first post here - I’m trying to port a content mgmt system (https://servicemedia.net) to support BabylonJS in which all the content (pics, audio, gltfs, etc) is provisioned via signed URLs from AWS, so none of the urls have extensions. I’ve found some posts that show forcing the loader type for models, but is it possible to force the loader types for textures/audio/video, when the urls lack extensions? Thanks!

1 Like

You should be able to set the Content-Type on a per-object basis in S3 and get that back as a response header, then use that to switch on type.

In which function do you have a problem when loading digital assets with no extension? As you say - when loading models it is important to provide the extension, but then loading images they are practically auto-detected. But you might have found a spot where they aren’t :slight_smile:

Thanks! Loading a skybox doesn’t seem to work with a no-extension url:
BABYLON.EquiRectangularCubeTexture(‘https://mysignedurlwithnoext’, scene, 512);

Again, I need to load EVERYTHING this way.

Thanks - I believe the content type is being returned in the header already, but my understanding is that Babylon only looks at the extension of the url to determine content type. Is that not the case?

You can also force it manually in most of the apis like on import mesh or texture creation you can manually specify the file type to use.

Latest parameter of ImportMesh is actually the pluginExtension and the format parameter of the texture constructor could be used for the same result.

Oh, cube texture is an interesting one.

The code is actually rather straight-forward - create an image object )native, browser, image object), set its src to the URL, and load fill the buffer. Unless the image is not supported, it should work.

I can see how it won’t work with a regular cube texture, which expects the files to be structured in a certain order, but this can be overriden during construction.

Would you be able to show a (non-working) example where it doesn’t work?

Thanks - @RaananW I was with you until “load fill the buffer”? How does one do that? Here’s a demo scene babylonTest Regular textures seem to work fine, but I’m stuck on making the cubemap with an equirect, it always gives me the “Uncaught DOMException: Failed to execute ‘getImageData’ on 'CanvasRenderingContext2D’The canvas has been tainted by cross-origin data.” error, although I think the CORS stuff is correct.

I also have the 6 cubemap pics that are generated from the equirect, but I don’t see a way to load them individually. I see how you can point to a folder that has the pics, or create a dds or env, but is there a programmatic way of creating the cubemap by giving it the individual pictures? I’ll be happy if I can get the equirect version to work, though…

To load a cube texture you will need to define the extensions array when creating the cube texture:

https://github.com/BabylonJS/Babylon.js/blob/master/src/Materials/Textures/cubeTexture.ts#L146

Extensions is a bit confusing. Those 6 strings will be added to the root URL to load all 6 images. usually it would be:

root: https://www.example.com/cube/file
extensions: ["_px.jpg", "_py.jpg", "_pz.jpg", "_nx.jpg", "_ny.jpg", "_nz.jpg"]

in this case 6 files will be loaded. the first would be - https://www.example.com/cube/file_px.jpg and so on.

Typo… load filE from buffer (sorry, my bad!). The browser’s Image object takes care of identifying the image for you. if it is an image that the browser supports (jpg, png, etc’), the image will be automatically loaded. I don’t see why it wouldn’t work in this case:

https://github.com/BabylonJS/Babylon.js/blob/master/src/Materials/Textures/equiRectangularCubeTexture.ts#L41

The URL will be used to load the image, using native browser functionality

Regarding loading the cube texture that makes sense - except my files are not in a folder, and the urls do not have extensions - they’re all signed urls from s3. AFrame has a similar approach (put the cubemap pics in a folder with the right extensions), but ThreeJS allows you to pass in an array of individual urls. But if that’s not possible here, OK. Regarding the option of using the equirect, as I say, regular textures work fine, but declaring the equirect CubeTexture always gives a cors error. And I don’t see any params in the equiRectangularCubeTexture there that allow forcing the mimetype or passing in something other than a url.

It’s weird that cubemaps are still such a pain. Local cubemaps look promising for cheap, accurate reflections, but having to cook the things with a third party app or photoshop plugin makes me sad. I could probably stick the pics together into the proper cubemap layout, but how would I convert that to a dds or env?

Thanks for your help!

Oh, they don’t have to be in the same folder :slight_smile: Base URL can be empty, and the array can contain 6 different URLs.

There is no way to set mime, but the browser’s image loader is using the mime type sent from the server, so it should work. Would be great to see a non-working example, if you have one

When you do a GET request on your object what are the response headers? It sounds to me based on @RaananW’s comment about using the mime type that your objects are not setting it correctly or the header is getting stripped out.

@RaananW so I put the 6 extensionless urls in the extensions parameter? Like this?

skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture(‘’, scene, [“https://archive1.s3.amazonaws.com/staging/5150540ab038969c24000008/cubemaps/5ec5b00adeebe2158fcba60a_1.jpg?AWSAccessKeyId=1G198RB42M1G51PMNA02&Expires=1592599568&Signature=kNxf2yEz9XCbnQ3dp0kyIuYE%2Bz8%3D",“https://archive1.s3.amazonaws.com/staging/5150540ab038969c24000008/cubemaps/5ec5b00adeebe2158fcba60a_2.jpg?AWSAccessKeyId=1G198RB42M1G51PMNA02&Expires=1592599568&Signature=FbLaSvvWpkcVc55FyZIwb6qyqio%3D”,“https://archive1.s3.amazonaws.com/staging/5150540ab038969c24000008/cubemaps/5ec5b00adeebe2158fcba60a_3.jpg?AWSAccessKeyId=1G198RB42M1G51PMNA02&Expires=1592599568&Signature=utseJzi%2BDVYk5CyPDIhulE1c22U%3D”,“https://archive1.s3.amazonaws.com/staging/5150540ab038969c24000008/cubemaps/5ec5b00adeebe2158fcba60a_4.jpg?AWSAccessKeyId=1G198RB42M1G51PMNA02&Expires=1592599568&Signature=3VAeqf4pOdhuAFvqgax2%2F6Twq5E%3D”,“https://archive1.s3.amazonaws.com/staging/5150540ab038969c24000008/cubemaps/5ec5b00adeebe2158fcba60a_5.jpg?AWSAccessKeyId=1G198RB42M1G51PMNA02&Expires=1592599568&Signature=9FYUacyLpNf9z8PqV%2B%2B3Z6HQCzs%3D”,"https://archive1.s3.amazonaws.com/staging/5150540ab038969c24000008/cubemaps/5ec5b00adeebe2158fcba60a_6.jpg?AWSAccessKeyId=1G198RB42M1G51PMNA02&Expires=1592599568&Signature=D6s2dOyfTwAqmiOiOocUkeDA9Qc%3D”]);

When I do that, it hangs at “loading assets” in the playground, i.e. https://www.babylonjs-playground.com/#UU7RQ#631

You don’t pass the array to the right parameter of the constructor:

https://www.babylonjs-playground.com/#UU7RQ#633

1 Like

Also your URLs do have extensions, it’s just that there are query parameters after the object path extension.

Here is your URL: https://archive1.s3.amazonaws.com/staging/5150540ab038969c24000008/cubemaps/5ec5b00adeebe2158fcba60a_1.jpg

Here are the query parameters that S3 parses to accept the request:

?AWSAccessKeyId=1G198RB42M1G51PMNA02&Expires=1592599568&Signature=kNxf2yEz9XCbnQ3dp0kyIuYE%2Bz8%3D

Insofar as extensions are semantic (which apparently they are not), you should be good.

1 Like

ahh, thanks that was it, just needed to match the constructor.

2 Likes