Meshes

How do I get a CLxUser_Mesh from a mesh item?

There are two meshes you can get. If you want the base mesh – the mesh that the user edits – then you need to use the form of GetChannels which specifies the action layer, and use LXs_ACTIONLAYER_EDIT. This allows you to read the mesh channel from the action directly:

C++

unsigned                 index;
CLxUser_Scene            scene;
CLxUser_ChannelRead      rchan;
CLxUser_Mesh             umesh;

if (LXx_OK(item.ChannelLookup (LXsICHAN_MESH_MESH, &index))) {
        item.GetContext (scene);
        scene.GetChannels (rchan, LXs_ACTIONLAYER_EDIT); // this version is crucial here!!!
        if (rchan.Object (itm, index, umesh))
                np = umesh.NPoints ();
}

Python

item = lxu.object.Item()   # given
scene = item.Context()
rchan = scene.Channels(lx.symbol.s_ACTIONLAYER_EDIT, 0.0)
index = item.ChannelLookup(lx.symbol.sICHAN_MESH_MESH)
meshChanVal = rchan.ValueObj(item, index)
umesh = lxu.object.Mesh(meshChanVal)
np = umesh.PointCount()

If you want to access the mesh after deformation, then you want to read from the evaluated mesh channel. This is done by specifying the time at which you want to evaluate. You can then read the channel as a MeshFilter Interface which can be evaluated:

C++

unsigned                 index;
CLxUser_Scene            scene;
CLxUser_ChannelRead      rchan;
CLxUser_MeshFilter       mfilt;
CLxUser_Mesh             umesh;

if (LXx_OK(item.ChannelLookup (LXsICHAN_MESH_MESH, &index))) {
        scene.from (item);
        scene.GetChannels (rchan, 0.0); // read the deformed mesh at time zero
        if (rchan.Object (itm, index, mfilt)) {
                if (mfilt.GetMesh (umesh))
                        np = umesh.NPoints ();
        }
}

Python

item = lxu.object.Item()   # given
scene = item.Context()
rchan = scene.Channels(None, 0.0)
index = item.ChannelLookup(lx.symbol.sICHAN_MESH_MESH)
meshChanVal = rchan.ValueObj(item, index)
mfilt = lxu.object.MeshFilter(meshChanVal)
umesh = mfilt.Generate()
np = umesh.PointCount()

Note that the channel is a Mesh Object in one case and a EvaluationStack Object in the other. You have to know the source of your ChannelRead Object to know which one you will get. Alternately you could query for the different interface types to probe the object as runtime.

The MeshFilter is also what you get from a modifier. You’d specify the mesh channel as an input and store its attribute index. During evaluation you’d read the channel as a MeshFilter:

C++

CLxUser_MeshFilter       mfilt;
CLxUser_Mesh             mesh;

if (m_attr.ObjectRO (i_mesh, mfilt)) {
        if (mfilt.GetMesh (mesh))
                np = mesh.NPoints ();
}

How do I get the bounding box of a mesh with the Python API?

There are a couple of ways to do this, assuming you have the mesh as an item object, one is by using the “Surface” interface:

Python

chan_eval = scene.Channels(None, 0.0)
surfItem = lxu.object.SurfaceItem(item)
surf = surfItem.GetSurface(chan_eval, 0)
bbox = surf.GetBBox()

Or alternatively you can cast the mesh item as a Mesh object and query it’s BoundingBox:

Python

chan_read = scene.Channels(lx.symbol.s_ACTIONLAYER_EDIT, lx.service.Selection().GetTime())
mesh_chan = chan_read.ValueObj(mesh, mesh.ChannelLookup(lx.symbol.sICHAN_MESH_MESH))
mesh_obj = lx.object.Mesh(mesh_chan)
bbox = mesh_obj.BoundingBox(lx.symbol.iMARK_ANY)

A mesh object can be retrieved via a layer scan or mesh channel - what method is preferred?

The preferred way of editing a mesh is by using a layer scan. The mesh channel object does not internally store deltas and thus does not support undoing edits. The mesh channel object is rather useful to evaluate a deformed mesh at an arbitrary time from animation.

How do I get the primary mesh layer item?

The best way to get the primary mesh layer item is using the layer service. This will allocate a layer scan for the primary layer, and then lookup the mesh item.

Python

lyr_svc = lx.service.Layer ()
scan = lx.object.LayerScan (lyr_svc.ScanAllocate (lx.symbol.f_LAYERSCAN_PRIMARY))
if scan.Count () > 0:
        item = scan.MeshItem (0)
scan.Apply ()