Python: Geometry: create GeometrySet wrapper for Python
In Geometry Nodes a geometry is represented by a `GeometrySet`. This is a container that can contain one geometry of each of the supported types (mesh, curves, volume, grease pencil, pointcloud, instances). It's possible for a `GeometrySet` to contain e.g. a mesh and a point cloud. This patch creates a Python wrapper for the built-in `GeometrySet`. For now, it's main purpose is to consume the complete evaluated geometry of an object without having to go through complex hoops via `depsgraph.object_instances`. It also also allows retrieving instances that have been created with legacy instancing systems such as dupli-verts or particles. In the future, the `GeometrySet` API could also be used for more kinds of geometry processing from Python, similar to how we use `GeometrySet` internally as generic geometry storage. Since we can't really have constness guarantees in Python currently, it's enforced that the `GeometrySet` wrapper always has its own copy of each geometry type (so e.g. it does not share a `Mesh` data-block pointer with any other place in Blender). Without the copy, changes to the mesh in the geometry set would also affect the evaluated geometry that Blender sees. The copy has a small cost, but typically the overhead should be low, because attributes and other run-time data can still be shared. This should be entirely thread-safe, assuming that no code modifies implicitly shared data, which is forbidden. For historic reasons there are still cases like #132423 where this assumption does not hold in all cases. Those cases should be fixed. To my knowledge, this patch does not introduce any new such issues or makes existing issues worse. Pull Request: https://projects.blender.org/blender/blender/pulls/135318
This commit is contained in:
53
doc/python_api/examples/bpy.types.GeometrySet.py
Normal file
53
doc/python_api/examples/bpy.types.GeometrySet.py
Normal file
@@ -0,0 +1,53 @@
|
||||
"""
|
||||
Accessing Evaluated Geometry
|
||||
++++++++++++++++++++++++++++
|
||||
"""
|
||||
import bpy
|
||||
|
||||
# The GeometrySet can only be retrieved from an evaluated object. So one always
|
||||
# needs a depsgraph that has evaluated the object.
|
||||
depsgraph = bpy.context.view_layer.depsgraph
|
||||
ob = bpy.context.active_object
|
||||
ob_eval = depsgraph.id_eval_get(ob)
|
||||
|
||||
# Get the final evaluated geometry of an object.
|
||||
geometry = ob_eval.evaluated_geometry()
|
||||
|
||||
# Print basic information like the number of elements.
|
||||
print(geometry)
|
||||
|
||||
# A geometry set may have a name. It can be set with the Set Geometry Name node.
|
||||
print(geometry.name)
|
||||
|
||||
# Access "realized" geometry components.
|
||||
print(geometry.mesh)
|
||||
print(geometry.pointcloud)
|
||||
print(geometry.curves)
|
||||
print(geometry.volume)
|
||||
print(geometry.grease_pencil)
|
||||
|
||||
# Access the mesh without final subdivision applied.
|
||||
print(geometry.mesh_base)
|
||||
|
||||
# Accessing instances is a bit more tricky, because there is no specific
|
||||
# mechanism to expose instances. Instead, two accessors are provided which
|
||||
# are easy to keep working in the future even if we get a proper Instances type.
|
||||
|
||||
# This is a pointcloud that provides access to all the instance attributes.
|
||||
# There is a point per instances. May return None if there is no instances data.
|
||||
instances_pointcloud = geometry.instances_pointcloud()
|
||||
|
||||
if instances_pointcloud is not None:
|
||||
# This is a list containing the data that is instanced. The list may contain
|
||||
# None, objects, collections or other GeometrySets. If the geometry does not
|
||||
# have instances, the list is empty.
|
||||
references = geometry.instance_references()
|
||||
|
||||
# Besides normal generic attributes, there are also two important
|
||||
# instance-specific attributes. "instance_transform" is a 4x4 matrix attribute
|
||||
# containing the transforms of each instance.
|
||||
instance_transforms = instances_pointcloud.attributes["instance_transform"]
|
||||
|
||||
# ".reference_index" contains indices into the `references` list above and
|
||||
# determines what geometry each instance uses.
|
||||
reference_indices = instances_pointcloud.attributes[".reference_index"]
|
||||
Reference in New Issue
Block a user