How to iterate over all VRayMesh objects and execute "restore mesh from proxy"?

Hi,

I’d like to iterate over all VRayMesh objects in a scene and execute the “create a mesh from this proxy” button for each one.

I have:

for object in cmds.ls(type='VRayMesh'):
    cmds.setAttr(object + '.reassignShaders', 1)
    # Push the button here

Can I push that button via code, somehow?

Ah, figured it out via echo all commands … :slight_smile: should’ve tried that prior to posting, heh.

for object in cmds.ls(type='VRayMesh'):
    cmds.setAttr(object + '.reassignShaders', 1)
    mel.eval('vray restoreMesh object;')

Hm … no, actually, that places the restored mesh in origo. So, my initial question kind of still stands…

Hm. I just noticed now that when I click the “restore a mesh from this proxy”, the restored mesh ends up in origo too. So perhaps there’s a bug with the “restoreMesh” command?

What is origo?

X,Y,Z coordinates 0,0,0; middle of scene.

A restored mesh ends up in the middle of the scene, even if the vraymesh/shape was sitting (translated to) somewhere else.

I think that’s the intended behavior. Otherwise we had many issues when the mesh ended up in the same place as the proxy where users would either not notice it there and click on the button multiple times, or forget to delete the proxy etc. You can always manually or through MEL/Python translate the imported mesh where it needs to be.

Best regards,
Vlado

Ok, cheers. I made a script which puts the object into place and deletes the proxy/shape.

But, I stumbled upon a new issue. When I loop through all VRayMesh nodes in the scene and restore its mesh, I’m noticing a memory leak (at least that’s what I believe it is).

I have a car, where basically all individual pieces were made into a proxy (jeez…) and now I have to undo that (oh my god!) for annoying reasons. But for each restored mesh, the memory is not released and I’ve maxed out a 72 GB RAM machine here after having restored some ~30 proxies (of 2800) into mesh. Hm… could it be possible I’m dealing with a memory leak here or is something funky going on with mel.eval() … ?

Here’s my long and somewhat convoluted code:

import maya.cmds as cmds
import maya.mel as mel

def set_selected_geotype(n):
    """ Source this function in Maya, then run one of the following:
    set_selected_geotype(n=0)  # Placeholder
    set_selected_geotype(n=1)  # Bounding box
    set_selected_geotype(n=2)  # Preview
    set_selected_geotype(n=3)  # Maya mesh
    set_selected_geotype(n=4)  # GPU Cache
    """
    for proxy in cmds.ls(sl=True, long=True):
        relatives = cmds.listRelatives(proxy, fullPath=True)
        if not isinstance(relatives, type(None)):
            for relative in relatives:
                connections = cmds.listConnections(relative, type='VRayMesh')
                if not isinstance(connections, type(None)):
                    for obj in connections:
                        cmds.setAttr(obj+'.geomType', n)

def get_shapes(obj):
    cmds.select(obj)  # for show only
    shapes = cmds.listConnections(obj, type='shape')
    if not isinstance(shapes, type(None)):
        shapes = list(set(shapes))
    else:
        shapes = []
    return shapes

def get_parent_transforms(shape):
    parent_transforms = cmds.listRelatives(shape, parent=True, fullPath=True)
    if not isinstance(parent_transforms, type(None)):
        parent_transforms = list(set(parent_transforms))
    else:
        parent_transforms = []
    return parent_transforms

# --- Make all vrmeshes into placeholders first (save memory) ---
for vrmesh in cmds.ls(type='VRayMesh', long=True):
    cmds.select(vrmesh)
    set_selected_geotype(n=0)
cmds.refresh()

# --- START RESTORE ---
total = len(cmds.ls(type='VRayMesh'))
count = 1
new_shapes = []
constraints = []
for vrmesh in cmds.ls(type='VRayMesh', long=True):
    print 'Analyzing', vrmesh, count, '/', total
    shapes = get_shapes(vrmesh)
    for shape in shapes:
        parent_transforms = get_parent_transforms(shape)
        for parent_transform in parent_transforms:
            cmds.refresh()
            cmds.setAttr(vrmesh + '.reassignShaders', 1)
            print 'Converting', vrmesh

            # Make vrmesh into Maya mesh (for accurate constraining, I guess?)
            cmds.select(vrmesh)
            set_selected_geotype(n=3)  # Maya mesh

            new = mel.eval('vray restoreMesh ' + vrmesh + ';')  # RESTORE MESH!

            new_shape_name = cmds.ls(sl=True, long=True)  # Restored object is selected automatically after conversion
            # Parent in under vrmesh tranform
            new_parent_transforms = get_parent_transforms(new_shape_name)
            for new_parent_transform in new_parent_transforms:
                print 'Parenting...'
                cmds.parent(new_parent_transform, parent_transform)
                new_shape_name = cmds.ls(sl=True, long=True)
                new_shapes.append(new_shape_name)
                # Parent constrain
                print 'Parent constrainting...'
                constraint = cmds.parentConstraint(shape,
                                                   new_shape_name,
                                                   maintainOffset=False)
                constraints.append(constraints)

                # Make vrmesh into locator (save memory)
                cmds.select(vrmesh)
                set_selected_geotype(n=0)

            cmds.refresh()
        count += 1

# Clean up
# to do: delete constraints
# to do: delete vrmesh nodes

Maybe stuff gets saved into Maya’s Undo queue; you might also need to turn off the caching of the proxy geometry viewport preview (or at least, clean the cache up).

Best regards,
Vlado

Aah… Many thanks for those suggestions. I thought you had it nailed down to the geometry caching there… but I’m now performing cmds.flushUndo() and cmds.clearCache(all=True) as well as setting the cacheGeometry attribute on all vrmesh objects to 0 prior to restoring to mesh. I even delete the vrmesh after mesh restoration and again perform the undo flush and cache clearing after having restored the mesh. The machine still runs out of RAM and these proxies are not individually that huge.

So, this still doesn’t make Maya release memory after a restoration.

You can easily repro this by opening a scene which contains a fairly heavy vrproxy, represented as geometry type “bounding box”:

(1. Take a note of the memory usage, e.g. via Task Manager on Windows)
2. Disable geometry caching on the proxy
3. Enable re-application of shaders of the proxy (this is the default)
4. Restore to mesh by clicking the "restore … " button on the vrmesh node
(5. See how memory usage increases during restoration process)
6. Delete the restored mesh
(7. See how memory usage is unchanged from step 5.)
8. Repeat these instructions from step 1, and eventually see your machine using up 100% of your RAM

I tried perforing the above in legacy viewport as well as viewport 2.0. Still results, maxing out all of my RAM.

This is on Windows 10 64-bit, Maya 2015 Extension 1 Service Pack 5, V-Ray 3.30.02 stable build

EDIT: I’m using Viewport 2.0…

Hm… it seems that if I start Maya up with legacy viewport (never loading viewport 2.0) I’m not seeing the same huge increase in RAM usage when batching this…

Managed to restore all meshes when using legacy viewport and hiding all polygons.

I suspect something’s fishy with VP2.0 …

Actually, no. It’s all about not showing polygons (viewport menu → show-> None) while batching. VP2.0 is fine. If polygons are visible in the viewport while I batch through it all, Maya will experience a RAM leak, it seems.