Load binary PLY/Collada/glb from string

Hi! I’m running in the following issue: I load geometry from different formats in a threejs viewer. The geometry is coming from a database that can only store unicode values. It is possible to directly load OBJ and ascii PLY strings coming from the database by using the following functions:

    function loadThisOBJString( data ){
    	var loader = new THREE.OBJLoader();
    	myObject = loader.parse(data);
    	scene.add (myObject);
    }

    function loadThisPLYString( data ){
    	var loader = new THREE.PLYLoader();
    	myGeometry = loader.parse(data);
    	var plyMaterial = new THREE.MeshStandardMaterial( { color: 0xFFA500 } );
    	var plyMesh = new THREE.Mesh ( plyGeometry , plyMaterial );
    	scene.add (plyMesh);
    }
  1. If I try this for binary PLY (which was base64 encoded in the database, and decoded using atob) however, using the last function (which works for loading ascii PLY as string), nothing is rendered and I get the following error:

THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The “position” attribute is likely to have NaN values.

Might this has something to do with the fact that binary PLY still has an ascii header? The binary PLY is little endian.

  1. Similar as in part 1, I want to load a Collada from a string, similar as OBJ and ascii PLY. I tried the following function:
    function loadThisColladaString( data ){
    	var loader = new THREE.ColladaLoader();
    	//myObject = loader.parse(data, './'); // does not help
    	myObject = loader.parse (data);
    	scene.add(myObject.scene);
    }

which resulted in the following error and nothing being rendered:

TypeError: Cannot read property ‘getAttribute’ of undefined
at THREE.ColladaLoader.parse (ColladaLoader.js:3807)
at loadThisColladaString (three-ld.js:613)
at switchGeometryType (three-ld.js:278)
at three-ld.js:71
at Array.forEach ()
at fetch.then.then.res (three-ld.js:70)

By looking at the code of the Collada loader, I’ve seen that the parse function needs two arguments: text and path. I don’t know what to add for path as it doesn’t have a path (it’s just a string coming from a database).

P.S. All geometries are tested and load from a file using the ‘normal’ way of working, so I guess the actual geometry is OK.

Can you please share one of your PLY and Collada files for testing?

Sure! Thanks for looking into this :slight_smile: I also tested it on a .gltf 2.0 file (embedded geometry), and that one also does not load from string using a similar approach. The received error:

Uncaught (in promise) TypeError: onLoad is not a function
at GLTFLoader.js:235
at GLTFLoader.js:1721

column1-base-embedded.gltf (83.1 KB)
column1-capital.dae (439.9 KB)
column1-capital-binary2.ply (238.8 KB)

I guess I’ll have to make changes to the original loaders, but I would of course be happy if I don’t have to go down that road :slight_smile: Maybe some of the developers of those loaders can tell me if there’s another way to load Collada/gltf/binaryPLY from string? Or at least give hints on where to start? @Mugen87 @donmccurdy

You can use the following fiddle as a starter template: https://jsfiddle.net/f2Lommf5/16343/

It shows how you can use GLTFLoader.parse() without loading the object from a backend. I would not care about PLY and Collada if possible since glTF is the 3D format you should actually use (it’s the recommended format of three.js).

Just keep in mind to embed all resources (like buffers or textures) into the glTF file.

Hi! Thanks, that will help me forward! This should also work with a .glb file?

I think so. Just give it a try :wink:

I got it working for .gltf with embedded geometry (just an empty string for the path was enough apparently). It doesn’t work for .glb though, as it’s no json string what the parse function of gltfloader seems to expect. I get the following error:

SyntaxError: Unexpected token g in JSON at position 0

I decoded from base64 using atob().column1-base-binary.glb (59.8 KB)

No, it should also work if you pass in an object of type ArrayBuffer.

Right, .glb is binary and would need to be stored in your database as bytes. .gltf will be a JSON string. The JSON could technically contain utf8 characters, but that’s unlikely unless you’re deliberately giving nodes utf8 names. .glb will always have its resources embedded, whereas .gltf may or may not. If you need to re-pack an existing gltf file in a different format, or ensure its resources are embedded, use https://github.com/AnalyticalGraphicsInc/gltf-pipeline.

Thanks, loading via ArrayBuffer was the solution! Thanks :slight_smile: