How to get a Mesh's points in world space

Hi everyone!

This seems like it should be easy, but for some reason it’s not. I can get the points from a Mesh like this:

# Load stage
prim = stage.GetPrimAtPath('/asset/geo/body')
mesh = UsdGeom.Mesh(prim)
local_points = mesh.GetPointsAttr().Get()

This is fine if you want the points in local space, but how do you get them in world space?
You can do this:

matrix = mesh.ComputeLocalToWorldTransform(Usd.TimeCode.Default())
world_points = Vt.Vec3fArray([matrix.Transform(p) for p in local_points])

but it’s slow. I also tried converting the matrix and points into numpy types this way:

np_matrix = numpy.matrix(matrix)
np_world_points = numpy.array(world_points)

but because the matrix is 4x4 and each array element is a Vec3f, numpy errors if I try to multiply these because their dimensions don’t align.

So how are we supposed to get the points in world space without a slow Python for loop or list comprehension?

We don’t tend to focus on specialized functions for wrapping all the things that are slow in python, since there are just too many :sweat_smile:

However, I’m not a numpy expert but it looks like you should be able to use the append() method with the axis argument to add a column/row to the array of points?

Thanks for your reply spiff. After discussing it with the team, they found a good way to do this with numpy which is way faster than running [matrix.Transform(p) for p in local_points].

np_matrix = numpy.matrix(matrix)
np_local_points = numpy.array(local_points)
np_world_points = np_local_points.dot(np_matrix[:3, :3]) + np_matrix[3, :3]
world_points = Vt.Vec3fArray.FromNumpy(np_world_points)

Still, I wish Gf.Matrix4d had an overloaded Transform method that could take a Vt.Vec3fArray to avoid having to convert to numpy and back.

That’s fantastic, @erikcarlson - numpy is pretty cool!

What you propose would be nice, but we made the decision that Vt should be “above” Gf in our software stack, so that VtValue and VtArray can support data-transformations between different core datatypes, and the Gf types are among those for which we pre-define transformations. So it’s not clear where such a vectorized matrix-multiply would sensibly be provided.

That’s a fair point. I appreciate your insights.