[REQ] Proper render mesh getter

@stevebaer @dale @pascal guys i’d like to submit a request for proper mesh getter this what I have to do in RhinoCommon becomes total nonsense to get just the render mesh could somebody tighten up some method to actually give the final render mesh of object?

Tell me guys why CreateMeshes can end up without any mesh to avoid it i went using GetRenderPrimitiveList to receive meshes after displacement but even if in v5 this works in v6 when i try to force make them RhinoViewport.DisplayMode.ShadedPipelineRequired has to be true but in v6 display modes are null and again need to look for them elsewhere and there’s no guarantee that user has Shaded mode so i can get crash and i can’t make it on my own since it needs object on C++ side and DisplayModeDescription constructor is private.

Would someone in your team be so kind to create straight forward method to get RhinoObject mesh with 100% success rate - I mean if there’s no render mesh make it and make it with modifiers like most of using people using this method would expect from render mesh - full finished render mesh without making 20 workarounds to be sure that i will end up with Mesh[] of object not null?

Works without having ever been to a shadede or rendered mode.

Here a quick Python script:

import scriptcontext as sc
import Rhino

ml = list()

for o in sc.doc.Objects:
	p = o.GetRenderMeshParameters()
	obrefs = Rhino.DocObjects.RhinoObject.GetRenderMeshes([o], True, True)
	mainmesh = Rhino.Geometry.Mesh()
	for obref in obrefs:
		obm = obref.Mesh()

for m in ml:

If you have meshable objects that RhinoObject.CreateMeshes fails on, then please post the geometry, along with code that shows the meshing parmeters being used, and we’ll be happy to have a look at it.

If this were possible, we would. That said, you should always do your due diligence and validate the results of any function you call, not just RhinoObject.CreateMeshes.

– Dale

Sure @dale as soon I’ll catch it I’ll drop it for you. My issues pop mostly where I create an instance from object then I get that instance and traverse down recursively trying to get those meshes for most of the situations it worked, later I tried with @andy work out a different approach based on doc primitive list to be sure what I get but it was very reliable but had bad performance.

Now trying to load my objects from the archive and trying to recreate its dependencies it showed me that DisplayMode for viewport could not be set to shaded since it was null at this stage still so it’s like a dead-end for me.

@nathanletwory um it was there like for always ??? can’t believe it works in all situations i spend so much time on this that it had to fail somewhere but can’t recall now where however without doubt ill try to use it again maybe I used it wrong earlier… Anyway thanks for reminder here!

@nathanletwory Nope. Displacement isn’t aplied to it so that was the reason i didnt used it. Yup exactly in both v5 and v6 same result.

Visual proof (purple spheres should be those blobs - this is displaced sphere so only basic shape was read):

And here’s the result how it should look like:

But during file loading in v6 i can’t force display mode to require shading since as i said display modes are null and DisplayModeDescription class has a private constructor and even if i would do a workaround to get it via reflection it won’t help since native code won’t use it since it doesn’t even know anything about its existence…

Hmm, missed the part about modifiers. Can’t you just switch active viewport to Shader or Rendered mode using RunScript?

I’d like to do anything but during archive reading there is no ActiveDoc.Views - those are just null so i need to make own vp and set it to shaded but when you’ll call vp.DisplayModes it is null - the only way around to do it is assigning those like vp.DisplayMode = Rhino.Display.DisplayModeDescription.GetDisplayModes().Where(i => i.EnglishName == "Shaded").FirstOrDefault() but you end with magic string …

Right, here a version that does work. No need to switch display modes.

import scriptcontext as sc
import Rhino

ml = list()

for o in sc.doc.Objects:
	vpi = Rhino.DocObjects.ViewportInfo(sc.doc.Views.ActiveView.ActiveViewport)
	rpl = o.GetRenderPrimitiveList(vpi, None)
	if rpl:
		meshes = rpl.ToMeshArray()
		mainmesh = Rhino.Geometry.Mesh()
		for m in meshes:

for m in ml:

To do display mode switching though you need to do it differently - not use the GUID, but the actual DisplayModeDescription that you get.

import scriptcontext as sc
import Rhino

shaded = None

def shaded_mode():
	global shaded
	if not shaded:
		dmds = Rhino.Display.DisplayModeDescription.GetDisplayModes();	
		for dmd in dmds:
			if 'Shaded' in dmd.EnglishName:
				shaded = dmd


old_mode = sc.doc.Views.ActiveView.ActiveViewport.DisplayMode
sc.doc.Views.ActiveView.ActiveViewport.DisplayMode = shaded

# do stuff here

sc.doc.Views.ActiveView.ActiveViewport.DisplayMode = old_mode

But as said, you don’t need to switch modes to get the meshes with applied modifiers.

Yup, exactly what i’m doing but during loading file there’s no ActiveDoc.Views and Shaded is a magic string not guaranteed to appear if someone will highly customize viewports.

Only way to be safe would be creating own DisplayModeDescription what can’t be done via RhinoCommon

Shaded will always be there, since it is a built-in display mode. Not sure what you mean by magic string, if not the Guid…

Why is there no Views table for you to use?

Looks like more context is needed to understand what you are doing.

What I just showed works in a regular Rhino 6 with any file.

Umm… nope ?

Why? I guess that’s not a question to me I’m just reading data from the file and recreate needed dependencies of it. Put in protected override void ReadDocument single line Rhino.RhinoDoc.ActiveDoc.Views and you will get null. If you will create own vp like var vp = new Rhino.Display.RhinoViewport(); and try getting vp.DisplayMode you will also get null.

It’s the same as magic number but string in this case “Shaded”.

It would be great and probably during normal operation time when everything is loaded yes but when loading file no.

Sure you can press delete. It’ll be ‘gone’ for a moment. But the moment you request the display modes list you’ll have it again… It is built in.

The second snippet I showed you gives you the DisplayModeDescription for Shaded. But you don’t need that.

Never, ever use ActiveDoc. Especially not when you have a RhinoDoc handed to you in that function…

You mean ReadDocument doc arg will have Views - thats funny since i would have to write whole bunch of methods just for reading including bunch of helpers besides how i should get doc if not through ActiveDoc? Not mentioning that v5 Views are not null there for ActiveDoc.

For example i want to search for ObjectId in one of my own methods ? Let’s say user clicked my own UI button so i won’t get doc as arg and i want to select item in doc? For me it should be Rhino.RhinoDoc.ActiveDoc.Objects.Select(ids) but it seems i’m wrong.

Yes, i need it because when i want to make own viewport the vp.DisplayMode is null so i have to set it in order to proceed.

I’ll take your word for it. :crossed_fingers:

@nathanletwory Regarding your comment:

Just checked that out and doc.Views provided via ReadDocument provide only one main viewport which is not shaded and its DisplayMode is also null so RequireShading can’t be set so your theory about it breaks apart here. OFC table ActiveView prop is null also.

If you need a complete, valid RhinoDoc to work with as part of file loading you should use the static RhinoDoc.EndOpenDocument event.

Again, for getting the rendermeshes that have all modifiers applied you don’t need to muck around with display atrributes or display modes, as I have shown.

Not during loading file as i already explained and as i said i’ll take your word for “Shaded” being built-in. :crossed_fingers:

Sounds reasonable!

You don’t need to switch modes anywhere, or fiddle with existing modes, nor create new ones, to get render meshes that have the modifiers applied.

Please put this in ReadDocument and check it on your own if you will succeed I will be pleased to see the example of it. In RhinoDoc.EndOpenDocument and later it shouldn’t be needed as you said.

You don’t even need the document for getting a ViewportInfo, since you can give the GetRenderPrimitiveList any ViewportInfo. As long as you are not relying on a custom rendermesh provider to generate render meshes based on viewport (camera), then below code should work just fine.

import scriptcontext as sc
import Rhino

ml = list()

# create a dummy viewport info. As long
# as the rendermeshes generated aren't
# depending on camera this doesn't matter
# at all.
rv = Rhino.Display.RhinoViewport()
vpi = Rhino.DocObjects.ViewportInfo(rv)

for o in sc.doc.Objects:
	# pass some random ViewportInfo
	# and None (null in C#). In doing so
	# _all_ custom rendermesh providers
	# will be called, since the None signals
	# that this is for a modal rendering.
	# This will generate rendermeshes regardless
	# of display mode.
	rpl = o.GetRenderPrimitiveList(vpi, None)
	if rpl:
		meshes = rpl.ToMeshArray()
		if meshes.Count>0:
			# lets combine all submeshes of this
			# object into one.
			mainmesh = Rhino.Geometry.Mesh()
			for m in meshes:

# now that we've meshed all objects
# we can add the meshes to the document
# or do anything else we want to
for m in ml:

I don’t think there is a need for doing that. The above code uses only the Objects table. I don’t have a plug-in set-up here, so it is better you do the testing. Transforming from Python to C# is a nice additional excercise.

@nathanletwory don’t get me wrong but i sometimes feel like you don’t read what I wrote - I am using it exactly like that but when you put vpi which doesn’t require shaded somewhere beneath it won’t return those.

That’s why you think what you think and pretend to explain to me something else than I see in IDE during debugging…

Anyway code which goes with “Shaded” magic string works for everything as i see so far:

using (var vp = new Rhino.Display.RhinoViewport())
                        if (vp.DisplayMode == null)
                            vp.DisplayMode = Rhino.Display.DisplayModeDescription.GetDisplayModes().Where(i => i.EnglishName == "Shaded").FirstOrDefault();
                            vp.DisplayMode.ShadedPipelineRequired = true;

                        using (var vpi = new ViewportInfo(vp))

And due to original topic you have to admit that its rather far from straight use to get “the final” RenderMeshes :wink:

@nathanletwory i just wonder could it be we both get different results since i use sth what could be moved as obsolete for v6 - since i still use v5 RhCommon as a base. That would mean that i also shouldn’t have to call CreateMeshes at all ?