Rhino3dm.js fails to write a single cube to a 3dm file

Hi All,

I’ve created a script that does the following:

  • Reads a 3dm file, converts the meshes to three.js json with the toThreejsJSON function.
  • Writes another 3dm file by converting the previous jsons to meshes with the createFromThreejsJSON function.

Now I have three test files created with Rhino 7: one_cube.3dm, two_cubes.3dm, and three_cubes.3dm. I think you can figure out the content of these files. :slight_smile:

My problem is the following: If the original file contains only one cube, the result file can’t be opened in Rhino (… is not a Rhino m_archive). The same happens with two cubes. And here is the interesting part: it works great with three cubes, and I don’t understand why.

I’ve also had success with more complicated models, but somehow I can’t make the export work for only a single cube.

Here is the script I’ve used, and attached the input files as well.

let rhino3dm = require ('rhino3dm.min.js')
let fs = require ('fs');
let path = require ('path');

function GetThreeMeshesFrom3dm (rhino, rhinoFileName)
{
	let inputBuffer = fs.readFileSync (rhinoFileName, null).buffer;
	let inputArray = new Uint8Array (inputBuffer);
	let inputDoc = rhino.File3dm.fromByteArray (inputArray);
	let objects = inputDoc.objects ();
	let threeMeshes = [];
	for (let i = 0; i < objects.count; i++) {
		let mesh = objects.get (i).geometry ();
		if (mesh instanceof rhino.Mesh) {
			threeMeshes.push (mesh.toThreejsJSON ());
		}
	}
	return threeMeshes;
}

function WriteThreeMeshesTo3dm (rhino, threeMeshes, rhinoFileName)
{
	let outputDoc = new rhino.File3dm ();
	for (let i = 0; i < threeMeshes.length; i++) {
		let rhinoMesh = new rhino.Mesh.createFromThreejsJSON (threeMeshes[i]);
		outputDoc.objects ().add (rhinoMesh, null);
	}
	let writeOptions = new rhino.File3dmWriteOptions ();
	writeOptions.version = 6;
	let outputBuffer = outputDoc.toByteArray (writeOptions);
	fs.writeFileSync (rhinoFileName, outputBuffer);
}

function ReadWriteRhinoFile (rhinoIn, rhinoOut, inputRhinoFile, outputRhinoFile)
{
	let threeMeshes = GetThreeMeshesFrom3dm (rhinoIn, inputRhinoFile);
	console.log ('Meshes in ' + inputRhinoFile + ': ' + threeMeshes.length);
	WriteThreeMeshesTo3dm (rhinoOut, threeMeshes, outputRhinoFile);
}

if (!fs.existsSync ('output')){
	fs.mkdirSync ('output');
}

rhino3dm ().then (async function (rhinoIn) {
	rhino3dm ().then (async function (rhinoOut) {
		ReadWriteRhinoFile (rhinoIn, rhinoOut, 'input/one_cube.3dm', 'output/one_cube.3dm');
		ReadWriteRhinoFile (rhinoIn, rhinoOut, 'input/two_cubes.3dm', 'output/two_cubes.3dm');
		ReadWriteRhinoFile (rhinoIn, rhinoOut, 'input/three_cubes.3dm', 'output/three_cubes.3dm');
	});
});

one_cube.3dm (24.9 KB) three_cubes.3dm (26.8 KB) two_cubes.3dm (25.9 KB)

1 Like

My investigation results showed that in case of one and two cubes the start section is invalid. It should contain “3D Geometry File Format       60”, but in the wrong cases it contains some kind of garbage.

Another found that it is reproducible with this example as well:

Just replace Rhino_Logo.obj with the attached cube.obj.
cube.obj (445 Bytes)

I’ve opened a pull request that seems to solve the issue:

1 Like