Three.js 3DM Loader fails to load BREPs

Hi there,

I use the rhino3dm.js library to export geometry to Rhino as NurbsCurves, BREPs, extrusions, …

When I want to re-import the File again with the Three.js 3DM Loader I get this error:

Does someone know what I can do either in the loading or in the export process to make it work?

My export looks like this:

export() {
    this.convert()
    let output = this.doc.toByteArray()
    const date = new Date().getFullYear() + '-' + (new Date().getMonth() + 1) + '-' + new Date().getDate()
    const blob = new Blob([output], { type: 'application/octect-stream' });
    const projectName = this.logic.projectSettings.project.name
    const sketchName = this.logic.projectSettings.sketch.name
    this.logic.emit('download', { blob, name: `${projectName}_${sketchName}_${date}.3dm` })
}

Where convert() calls methods like this:

polylineToRhinoOpenPolysurface(polyine: Polyline, unit: string) {
    const mesh = this.meshFromCurve(polyine)
    const rhinoMesh = this.rhino.Mesh.createFromThreejsJSON({ data: mesh.geometry })
    const brep = this.rhino.Brep.createFromMesh(rhinoMesh, false)
    if (unit === 'millimeter') brep.scale(1000)
    return brep
}
polylineToRhinoBrep(polyine: Polyline, extrusionHeight: number, unit: string) {
    const curvePoints = new this.rhino.Point3dList()
    polyine.pts.forEach(pt => curvePoints.add(pt[0], pt[1], pt[2]))
    const curve = this.rhino.NurbsCurve.create(false, 1, curvePoints)
    const brep = this.rhino.Extrusion.create(curve, extrusionHeight, true).toBrep(false)
    if (unit === 'millimeter') brep.scale(1000)
    return brep
}

The problem happens only on re-imported scenes.
Any help would be more than appreciated! :slight_smile:

Apparently, this mentioned from @fraguada is the problem

Is it possible to adapt the export so I don’t have to manually change to Render/Shaded Mode in Rhino?

Or setting options in the export forcing Rhino to open the document in one of these modes :sweat_smile:

Where are you exporting from? The only software that knows how to generate render meshes for extrusions, breps, and subD is Rhino. You’d have to open the file in Rhino to have it generate render meshes (or script the generation of render meshes from within Rhino).

Alternatively, we could bind the SetMesh method of these types to allow users to add their own render mesh to these geometries from outside of Rhino. (I’ll add this issue to our list).

I export it from a web app using the rhino3dm.js.

We want to include Rhino in our workflow, so import and export to Rhino
I just noticed that I have to open an exported Rhino file in Render or Shaded Mode (Wireframe is not enough) so that it is possible to import it with the Three.js 3DM Loader.

Don’t know if the mentioned approach would help with that

Right. Render meshes are only generated on breps in Rhino itself. What I can do is bind the SetMesh function for BrepFaces and for Extrusions in rhino3dm so that you can push your own meshes to those objects and save them in the 3dm. Does that sound like a solution for your process?

2 Likes

Yes, that would be very helpful!

1 Like

Hello. I’ve wrapped the SetMesh functionality for breps and extrusions. I’d appreciate if you could try it out by downloading the compiled version that can be found here (available for 15 days).

In theory, you should be able to do do the following:


let myRhinoMesh
// create your Rhino mesh

//object is an object from doc.objects()

//for extrusions:
const resultExtrusion = object.geometry().setMesh( myRhinoMesh, rhino.MeshType.Render ); //result is a bool

//for a brepface with index 0 in the brep
const resultBrepFace = object.geometry().faces().get(0).setMesh( myRhinoMesh, rhino.MeshType.Render ) //result is a bool

1 Like

Just tested this very simple example:

//...
const radius = 10
const geometry = new THREE.SphereGeometry( radius, 32, 32 )
const rhinoBrep = rhino.Brep.createFromSphere( new rhino.Sphere( [0,0,0], radius )
const rhinoMesh = rhino.Mesh.createFromThreejsJSON( { data: geometry } )
const result = rhinoBrep.faces().get(0).setMesh( rhinoMesh, rhino.MeshType.Render )

const brep_layer_index = doc.layers().addLayer( 'Breps', { r: 255, g: 255, b: 255, a: 255 } )
const oa_breps = new rhino.ObjectAttributes()
oa_breps.layerIndex = brep_layer_index

doc.objects().add( rhinoBrep, oa_breps )
//...

of course, this is pretty easy because a sphere brep has one face, so we can just put the sphere mesh in there. Stepping through the faces of a Brep and setting the mesh for the face would require quite some logic to get it right.

I was able to save this file and open it in the threejs editor and the meshes came through. I am working on a sample to demonstrate this, but the above code is the main part.

Thank you that’s awesome!
I downloaded the compiled version and will test as as soon as I can get to it.

1 Like

Works fine for extrusions (the boxes):


//...
const geometry = new THREE.BoxGeometry(5, 5, 5, 1, 1, 1)

const rhinoBox = new rhino.Box( new rhino.BoundingBox( [ -2.5, -2.5, -2.5 ], [ 2.5, 2.5, 2.5 ] ) )
const rhinoObject = rhino.Extrusion.createBoxExtrusion( rhinoBox, true )

const rhinoMesh = rhino.Mesh.createFromThreejsJSON( { data: geometry } )
const result = rhinoObject.setMesh( rhinoMesh, rhino.MeshType.Render)

const layer_index = doc.layers().addLayer( 'Breps', { r: 255, g: 255, b: 255, a: 255 } )
const oa = new rhino.ObjectAttributes()
oa.layerIndex = layer_index

doc.objects().add( rhinoObject, oa )

//...

1 Like

Sorry for the late reply
Simple examples worked for me as well!

But it might be more difficult for more complex BREPs - didn’t try this one yet

Will the setMesh() method be accessible in a new release of rhino3dm.js?

yes! We’ll do a beta release to npm soon.

1 Like