I’m currently working on a project that uses rhino3dm.py to read .3dm files and stuff inside.
It looks like I can’t get UVs from SubDs. Only reference to this I could find uses openNurbs: Get UVs from a mesh extracted from SubD - openNURBS - McNeel Forum
Though it looks like this is not exposed in rhino3dm.py
Code for testing:
#!python3
import rhino3dm as r3d
filepath = "test_file.3dm"
model = r3d.File3dm.Read(filepath)
for obj in model.Objects:
geo = obj.Geometry
if geo.ObjectType != r3d.ObjectType.SubD:
continue
mesh = r3d.Mesh.CreateFromSubDControlNet(geo)
print(len(mesh.Vertices))
print(len(mesh.TextureCoordinates))
Digging further into this, I managed to build rhino3dm after fixing a linking issue with the draco lib @fraguada would be great if that can be fixed, might also be an issue with my setup, though most of it was setup from scratch.
Now with the change, using GetControlNetMesh(nullptr, ON_SubDGetControlNetMeshPriority::TextureCoordinates); Does get me the TextureCoordinates, but all faces on the mesh are disconnected / not welded.
It would be great if rhino3dm.py (and with that openNurbs) could provide a method to get the SubD control net mesh with corresponding TextureCoordinates and other features (e.g. edge creasing). I don’t understand, why that doesn’t exist. @pierrec as you answered on the linked topic, could you maybe give some insight on this?
I can add another method that you could pass the ON_SubDGetControlNetMeshPriority, but as you already saw, there are some issues. If you follow the conversation in the linked thread, there are still some underlying issues that prevent the Texture Coordinates being transferred to anything but the unsubdivided subd. I’ll see where we are with that.
@fraguada thanks for your answer. Texture Coordinates for the unsubdivided SubD / ControlNet is what I’m after. I’ve linked the other topic, as that is the only one I could find, which mentions getting texture coordinates for
Here are a few images to show the current possibilities:
SubD in Rhino:
SubD ControlNet read as mesh with rhino3dm and Geometry priority, with subivision modifier applied in blender:
SubD ControlNet read as mesh with rhino3dm and TextureCoordinates priority, with subivision modifier applied in blender:
As you can see, using Geometry priority does bring geometry, with the right topology/connectivity (?) across. Using TextureCoordinates priority brings the UVs across correctly, but all polygons in the mesh are disconnected as vertices are read per polygon (I think).
Personally I don’t see a use case for the second one, I would always want the geometry with correct texture coordinates. Now I haven’t done a lot with openNurbs so far, maybe I’m missing something here.
I can go ahead and weld vertices by distance, which gets me what I want, though that may come with other problems:
Ideally I can read the SubD (/its control net) like this and thinking ahead also crease values. (I can’t test crease values right now as I don’t have access to Rhino 8 yet).
Alright, diving further into this, staying in Rhino.
I’m now trying to figure out how to convert a SubD Control Net to a mesh with UV coordinates. There is ExtractControlPolygon, which doesn’t include texture coordinates.
RhinoCommon provides Mesh.CreateFromSubD, which does generate texture coordinates, but the lowest display level (0) is already one subivision of the control net.
@pierrec am I missing something? Do you have any ideas?
@Jussi_Aaltonen thanks. This does work, but seems it only works with the default UVs. Here is a simple test file with changes UVs (using the Rhino8 unwrapper), where I can’t read the texture coordinates this way: subd_plane_UV.3dm (84.8 KB)
So far I couldn’t figure out how to get the TextureMapping mesh for a mesh with rhino3dm or openNurbs and I assumen, it’s a simliar situation for SubDs.
The control net only has texture coordinates for the standard “surface parameter” mapping. All other mappings define texture coordinates on the limit surface.
Generally if you have access to object’s render mesh and the texture mapping then you can apply that mapping to the render mesh and read out the texture coordinates.
And in case of the custom object mapping you can get the actual mapping primitive mesh from the texture mapping. In openNURBS use ON_TextureMapping::CustomMappingMeshPrimitive.
Thanks for the explanation and hints. Does that mean, unwrapping and discontinuous UVs/texture coordinates on a SubD are set for the limit surface?
What’s the relation for this?
I’m still struggling to understand how this works in Rhino for meshes and SubD and haven’t found a good explanation for it yet.
I’m relating to DCC apps (Blender, Modo, Maya etc.), where there is usually only one mesh with all it’s UVs / texture coordinates and fairly simple ways to access them. Rhino’s way of handling and accessing them is confusing to me.