Create three.js mesh from rhino with vertex colors

Hello all!

I’m trying to use rhino.compute and rhino3dm.js to create a three.js mesh from a rhino mesh. This works fine, but I haven’t figured out how to include the materials from the rhino mesh to the three mesh yet.
Here is the relevant part of the code that I’m using at the moment:

    _threeMaterial = new THREE.MeshNormalMaterial() //basic material 
    let mesh = rhino.DracoCompression.decompressBase64String(data) //data is the draco compressed mesh

    let threeMesh = meshToThreejs(mesh, _threeMaterial)

    //conversion function
    function meshToThreejs (mesh, material) {
    let loader = new THREE.BufferGeometryLoader()
    var geometry = loader.parse(mesh.toThreejsJSON())
    return new THREE.Mesh(geometry, material
    }

As I see it there’s two parts to the equation here.

  1. To acquire the color information from the rhino mesh in the js environment
  2. To convert the rhino mesh material (rgb values in my case) into THREE.MeshBasicMaterials() or similar and apply it to the mesh.

For the first part I’ve tried to store the data in the compressed mesh, but it seems like some of the color information gets lost in the process even when I’m using IncludeVertexColors = true in the DracoCompressionOptions when compressing the mesh. For certain colors it works but other times it is completely off (see image below).

image

So I was thinking that maybe it could be a good idea to just output the list of vertex colors as a RH_OUT: parameter instead of saving it as part of the compressed mesh. Is this a good idea or am I missing something?

For the second part I have no clue how to do it. My initial ideas was to just loop through every item in the list of vertex colors and create a ‘new THREE.MeshBasicMaterials(vertexColors[i])’ from it that I then apply to the mesh. Do you have any suggestions here?

Thank you!
Best regards,
Erik

Hey,
don’t know if it really helps but I have looked into the compute samples on github last week and maybe there is something that can help you. Check these two examples here if you have not already:

Hope it helps.
Regards

1 Like

This looks like it might be a bug in the implementation of Draco compression. I’ve logged it as RH-63277.

Here’s a quick example that shows the same Rhino mesh imported into a three.js scene – the one on the right was compressed using Draco.

A much more comprehensive way to import geometry into three.js is to use the Rhino3dmLoader. This is what is used in the examples above.

1 Like

RH-63277 is fixed in the latest Rhino 7 Service Release Candidate

1 Like

Hey, thanks for your reply! I’ll definitely have a look at those!

Hello Will! Thank you for your reply. I started to look into this but I haven’t done much js before so I’m a bit confused by the syntax and how everything is built up. Will this work directly for converting a regular rhino mesh object with vertex colors set in gh or do I need to do something more with it (I mean part from compressing/decompressing it)?

All you need to do is use a material with vertexColors turned on.

https://gist.github.com/pearswj/ae6e6483107e1a246a5deeec0e78ce89#file-index-html-L23

The mesh’s toThreejsJSON() method (in the meshToThreejs() helper function) takes care of the rest.

By the way, the bug in the draco decompression has been fixed in Rhino, but the fix hasn’t yet made it into a release of rhino3dm.js.

Hi again Will,

Thanks a lot, that’s really useful. I’ll try this!!

Hello Again Will!

The project that I’m working on at the moment is using rhino3dm.js and we are trying to solve the conversion issue with the meshes decoded with the draco compression. I did a workaround for this just for now where I output the vertex colors of the mesh separately and apply them to the mesh in the following way:

function meshToThreejs (mesh, colors) { 
let loader = new THREE.BufferGeometryLoader()
let geometry = loader.parse(mesh.toThreejsJSON())

const colorsAttr = geometry.attributes.position.clone(); //I'm using the position attribute to get the correct object type and data structure. 
colorsAttr.array = colors //colors here is a array of rgb values stored one by one

geometry.setAttribute('color', colorsAttr);
const material = new THREE.MeshPhongMaterial({
vertexColors: THREE.VertexColors
});
return new THREE.Mesh(geometry, material);
} 

This works but it’s a bit messy so I was just wondering if you have any idea how long it usually takes before the js libraries gets updated with bug fixes like this. Thanks again!

Br
Erik

Can you test this for me? If it fixes the problem for you I’ll publish a new release.

rhino3dm-f105e9b.zip (939.0 KB)

Hello again Will!

Thanks for sharing this! We’ve tried it and it works well for us. Great work!

Could you send me a message when this is released so we can use the hosted version instead of including it in the project?

BR
Erik

1 Like

@will @brian

Hi again guys,

I think I found another issue with the draco compression, so I wanted to see if it’s already known or if it is something that needs to be fixed. It’s super small so don’t panic. :slight_smile:

Basically what it is about is that if the mesh that is converted is completely transparent with alpha=0, after compression/decompression (not sure where the issue is), it instead gets completely opaque. I’ll attach a file where I show what I mean so that it is a bit easier to understand the issue. Hope this helps!

Best,
Erik
transparentMeshDraco.gh (15.8 KB)

Hello @erikforsberg95 I am not sure if this has to do with Draco Compression, as the same behavior happens without passing it through compression. We’re looking into it…

Ah alright, just thought it was the compression because of the previous bug. I should of course have checked that first.

Best,
Erik

1 Like

This is an issue with how our legacy materials handle alpha values. Unfortunately this is already a workaround to the limitations of this older material style and isn’t something we will fix. In the future we will look to replace this use of legacy materials in the display pipeline.