3DMLoader for Three.js

Hi @Willem - thanks for your reply. No not yet because there appears to be quite a few methods that sounded similar. Here are the methods that I was going to experiment with:

  • RhinoObject
    .CreateMeshes()
    .GetMeshes()
    .GetRenderMeshes()
    .GetRenderMeshesWithUpdatedTCs()
    .GetRenderPrimitiveList()
    .MeshObjects()

  • RenderPrimitive.Mesh()

  • RhinoDoc
    .GetRenderPrimitives()
    .GetRenderPrimitiveList()

First I will try RhinoDoc.GetRenderPrimitiveList() since I guess this will enumerate all the objects in the document calling RhinoObject.GetRenderPrimitiveList on each one. I don’t know if that is identical to RhinoObject.CreateMeshes() but i’ll try both. Maybe these all do the same thing?

cheers
dan.

If you know the object is a brep, then you can use the Mesh.CreateFromBrep() method. Something like this:

var rhinoObjs = doc.Objects.FindByObjectType(ObjectType.Brep);
var meshedbreps = new List<Mesh>();
foreach (var item in rhinoObjs) 
{
	var brep = item.Geometry as Brep;
    var mesh = Mesh.CreateFromBrep(brep); //optionally set meshing parameters
    meshedbreps.Add(mesh);
        

}

...

Hi @fraguada

Currently we are working only with breps but I wanted to leave the door open for future other object types.

So yes at the moment I could use Mesh.CreateFrom…() methods in c# and send only mesh objects to my threeJs scene but I was hoping to be future proof and send entire 3dm document to the threejs scene relying on your 3DMLoader.js class to convert every type of meshable object that it can to threejs. --That way as you mature your 3DMLoader.js class (perhaps texture/material support etc) i would get the improvements too :slight_smile:

So i think for now I would like to call RhinoDoc.GetRenderPrimitiveList() on my c# side for the entire document so that all objects have a rendermesh present – then I’ll send the entire doc to JS and rely on your 3DMLoader class to convert to threejs.

Unless performance of 3DMLoader.js is much worse than using Mesh.CreateFromBreps() on only the breps - so I’ll test and compare.

Sounds like a decent plan!

Calling the RhinoObject.CreateMeshes() method server-side (c# Compute plugin) hasn’t worked for me. :frowning:

The breps are still being reported by 3DMLoader.js as having no render meshes.
Perhaps this is because I am calling .CreateMeshes() in Compute which is headless.
Perhaps the brep.EnsurePrivateCopy() or brep.Compact() steps are removing the rendermeshes from the breps.
For now I have run out of time with this approach.

Instead I will take @fraguada suggestion and instead of sending breps to the webpage i’ll create mesh objects directly with Mesh.CreateFrom…() methods and send these meshes to the Javascript and convert them to threejs using:

    const loader = new THREE.BufferGeometryLoader()
    const geometry = loader.parse(mesh.toThreejsJSON())
    return new THREE.Mesh(geometry, material)

I’ll try all of this out and see where it might be failing.

I try to load Annotations via threejs and get “THREE.3DMLoader: Conversion not implemented for ObjectType_Annotation”, type: “not implemented”

the message is clear but i like to know if someone do have some nice workaround to get the informations of the annotations like startpoint and endpoints or length inside the 3dmLoader?

We don’t have much in openNURBS to deal with annotations and since openNURBS is the basis for rhino3dm, there isn’t much in rhino3dm. I will see what we can do to make some of that info public.

Hi,
Is there any news about this topic ( supporting annotations?)
Thank you!

What is it that you would like to do with annotations?

Hi Luís,

My application displays 3DM Models using R3F + Rhino3dmjs and in the models we have measurements (quotas) and the measurements are text type objects.

At the moment the text objects are not rendered.

In the browser console I get the following warning:
THREE.3DMLoader: Conversion not implemented for ObjectType_Annotation

I’m assuming this has to due with the fact that the object is Type Text. I can’t recognized them on the 3DMLoader (just looping the model children and output to console > “child.Type”)

PS: The models are generated through Grasshopper.

Thank you!

For now I would recommend exploding the annotations, or creating some sort of customized data structure from within GH to help you visualize this information on the front end.

Each object type requires a conversion to a three.js type. Meshes in Rhino have a specific data structure that we need to convert to the three.js mesh data structure. Same for curves. There is no three.js Annotation object, so we’d need to develop something that can represent an Annotation in three.js. This is not a trivial task, hence why we’ve not done it.

In any case, I will take a look at what other Annotation data we can make accessible via rhino3dm.

Hi,

Thank you for your reply!

For now, and to get around this issue, we’re changing the model objets to TextDots (they’re supported by 3DMLoader) and converting them into Sprites.

But it would be useful to have some kind of direct conversion :slight_smile: (if possible, of course).

Thank you very much!

I totally agree. I’ll keep thinking about this.

Hi, any update on Annotations?
I have been looking at the code and I was able to sort of get it to work by just copying what TextDot does, except the annotation doesn’t have any location information that I can find.

@Jesse_Pascoe, the location is available, it is just not where TextDot keeps it. A Text annotation inherits from AnnotationBase, so its position comes from its plane: use annotation.plane.origin for the insertion point, and annotation.plainText (or richText) for the string. That should be enough to place a sprite the same way you did for TextDot.

For dimensions there is more: they expose getDisplayLines(dimStyle) and points, so you can draw the actual dimension geometry as line segments.

The remaining gap is on the three.js side: the 3DMLoader has no conversion case for annotations yet, which is why you see the “not implemented” warning and have to roll your own. I have logged that as an enhancement so we can add a built-in Text/annotation conversion. In the meantime the plane-origin approach above is the way to go.

Thanks for the update, that sounded promising. I got a local copy of the threejs 3DMLoader so I could try and add this, but I can’t seem to fine a plane anywhere on the annotation, I found this in the code,

      } else {

        // these are functions that could be called to extract more data.

        //console.log( `${property}: ${object[ property ].constructor.name}` );

      }

but couldn’t find any useful function in there via debugging. Nor anything else in function extractProperties(object) {

If you’ve got an idea where to look I’d be greatful.
Edit:
Of course, as soon as I posted I thought to update to the latest https://www.npmjs.com/package/rhino3dm
Which has what I needed.

OK, I’ve got annotations parsing in a local fork of the three.js 3DMLoader now, using rhino3dm 8.32.2.

What’s working:

  • position/orientation from the annotation plane (origin + axes)
  • the string from plainText
  • bold/italic/underline/strikethrough/font from the RTF
  • textHeight treated as cap height.

What’s still missing is per-object overrides. In this file every dimstyle reports textHeight = 1, no field overrides, not a child style, and every annotation points at the document style.
Rhino’s properties panel still shows height and model space scale, but I can’t seem to access them.
Two labels that Rhino draws at different sizes look identical through rhino3dm. Same style id, same everything except the text and the object id.

Looks like the bits we need are the ones sitting commented out in bnd_annotationbase.h.
DimStyle also doesn’t expose model space scale, and getBoundingBox on annotations come back invalid, so there’s nothing to measure from.

Any chance those could get wired up?
Until then I’m just sizing everything from the drawing extents, which is readable but obviously not what the file says.

I will log this and take a look.

@Jesse_Pascoe

I have prepared a js beta with expanded annotation support. https://www.npmjs.com/package/rhino3dm/v/8.35.0-beta1

I won’t update the 3dmloader just yet, but the following should now be possible:

const parent = doc.dimstyles().findId(annotation.dimensionStyleId)
const style  = annotation.getDimensionStyle(parent)   // parent + per-object overrides

const height = annotation.getTextHeight(parent)        // effective cap height
const scale  = annotation.getDimensionScale(parent)    // "model space scale" from the panel
const renderedHeight = height * scale                   // what Rhino actually draws

// the two same-size-in-Rhino labels now differ correctly:
annotation.hasPropertyOverrides                         // bool
annotation.isPropertyOverridden(rhino.DimensionStyleField.TextHeight)

Please let me know if you are still having issues with this.