Skip to content

Commit

Permalink
Enhance MeshObjectUtility.py with type hints and docstrings
Browse files Browse the repository at this point in the history
- Added return type hints to several methods for clarity.
- Improved docstrings to include return descriptions.
- Reformatted method signatures for consistency.
- Updated primitive creation method to include UV_SPHERE.
  • Loading branch information
hummat committed Dec 12, 2024
1 parent 22f9fb6 commit f1b024b
Showing 1 changed file with 31 additions and 16 deletions.
47 changes: 31 additions & 16 deletions blenderproc/python/types/MeshObjectUtility.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def new_material(self, name: str) -> Material:
""" Creates a new material and adds it to the object.
:param name: The name of the new material.
:return: The new material.
"""
new_mat = MaterialLoaderUtility.create(name)
self.add_material(new_mat)
Expand Down Expand Up @@ -311,7 +312,7 @@ def mesh_as_bmesh(self, return_copy=False) -> bmesh.types.BMesh:
bm = bmesh.from_edit_mesh(self.get_mesh())
return bm

def update_from_bmesh(self, bm: bmesh.types.BMesh, free_bm_mesh=True) -> bmesh.types.BMesh:
def update_from_bmesh(self, bm: bmesh.types.BMesh, free_bm_mesh=True):
""" Updates the object's mesh based on the given bmesh.
:param bm: The bmesh to set.
Expand Down Expand Up @@ -377,8 +378,10 @@ def create_bvh_tree(self) -> mathutils.bvhtree.BVHTree:
bm.free()
return bvh_tree

def position_is_above_object(self, position: Union[Vector, np.ndarray],
down_direction: Union[Vector, np.ndarray] = None, check_no_objects_in_between=True):
def position_is_above_object(self,
position: Union[Vector, np.ndarray],
down_direction: Union[Vector, np.ndarray] = None,
check_no_objects_in_between=True) -> bool:
""" Make sure the given position is straight above the given object.
If check_no_objects_in_between is True, this also checks that there are no other objects in between.
Expand All @@ -404,7 +407,7 @@ def position_is_above_object(self, position: Union[Vector, np.ndarray],
world2local.to_3x3() @ Vector(down_direction))
return hit

def ray_cast(self, origin: Union[Vector, list, np.ndarray], direction: Union[Vector, list, np.ndarray],
def ray_cast(self,origin: Union[Vector, list, np.ndarray], direction: Union[Vector, list, np.ndarray],
max_distance: float = 1.70141e+38) -> Tuple[bool, np.ndarray, np.ndarray, int]:
""" Cast a ray onto evaluated geometry, in object space.
Expand Down Expand Up @@ -442,8 +445,11 @@ def add_uv_mapping(self, projection: str, overwrite: bool = False):
f"'smart' or 'sphere'.")
self.object_mode()

def has_uv_mapping(self):
""" Returns whether the mesh object has a valid uv mapping. """
def has_uv_mapping(self) -> bool:
""" Returns whether the mesh object has a valid uv mapping.
:return: True if the object has a valid uv mapping.
"""
if len(self.blender_obj.data.uv_layers) > 1:
raise Exception("This only support objects which only have one uv layer.")
for layer in self.blender_obj.data.uv_layers:
Expand Down Expand Up @@ -478,6 +484,7 @@ def add_displace_modifier(self, texture: bpy.types.Texture, mid_level: float = 0
:param min_vertices_for_subdiv: Checks if a subdivision is necessary. If the vertices of a object are less than
'min_vertices_for_subdiv' a Subdivision modifier will be add to the object.
:param subdiv_level: Numbers of Subdivisions to perform when rendering. Parameter of Subdivision modifier.
:return: The added displace modifier.
"""
# Add a subdivision modifier, if the mesh has too few vertices.
if not len(self.get_mesh().vertices) > min_vertices_for_subdiv:
Expand All @@ -491,6 +498,7 @@ def add_modifier(self, name: str, **kwargs) -> bpy.types.Modifier:
:param name: The name/type of the modifier to add.
:param kwargs: Additional attributes that should be set to the modifier.
:return: The added modifier.
"""
# Create the new modifier
with bpy.context.temp_override(object=self.blender_obj):
Expand All @@ -506,18 +514,23 @@ def get_modifiers(self) -> Dict[str, bpy.types.Modifier] | List[bpy.types.Modifi
""" Returns all modifiers of the object.
Note: The actual type is `bpy_prop_collection` but it is not directly accessible in the Blender API.
:return: The modifiers of the object.
"""
return self.blender_obj.modifiers

def get_modifier(self, name: str) -> bpy.types.Modifier:
""" Returns the modifier with the given name.
:param name: The name of the modifier.
:return: The modifier.
"""
return self.get_modifiers().get(name)

def add_geometry_nodes(self) -> bpy.types.GeometryNodeTree:
""" Adds a new geometry nodes modifier to the object.
:return: The node group of the added geometry nodes modifier.
"""
# Create the new modifier
with bpy.context.temp_override(object=self.blender_obj):
Expand All @@ -531,6 +544,7 @@ def add_auto_smooth_modifier(self, angle: float = 30.0) -> bpy.types.Modifier:
This replaces the 'Auto Smooth' behavior available in Blender before 4.1.
:param angle: Maximum angle (in degrees) between face normals that will be considered as smooth.
:return: The added smooth-by-angle modifier.
"""
# The bpy.ops.object.modifier_add_node_group doesn't work in background mode :(
# So we load the node group and create the modifier ourselves.
Expand Down Expand Up @@ -595,13 +609,13 @@ def mesh_as_trimesh(self) -> Trimesh:

return Trimesh(vertices=verts, faces=faces)

def clear_custom_splitnormals(self) -> None:
def clear_custom_splitnormals(self):
""" Removes custom split normals which might exist after importing the object from file. """

with bpy.context.temp_override(object=self.blender_obj):
bpy.ops.mesh.customdata_custom_splitnormals_clear()

def create_from_blender_mesh(blender_mesh: bpy.types.Mesh, object_name: str = None) -> "MeshObject":
def create_from_blender_mesh(blender_mesh: bpy.types.Mesh, object_name: str = None) -> MeshObject:
""" Creates a new Mesh object using the given blender mesh.
:param blender_mesh: The blender mesh.
Expand All @@ -615,7 +629,7 @@ def create_from_blender_mesh(blender_mesh: bpy.types.Mesh, object_name: str = No
return MeshObject(obj)


def create_with_empty_mesh(object_name: str, mesh_name: str = None) -> "MeshObject":
def create_with_empty_mesh(object_name: str, mesh_name: str = None) -> MeshObject:
""" Creates an object with an empty mesh.
:param object_name: The name of the new object.
:param mesh_name: The name of the contained blender mesh. If None is given, the object name is used.
Expand All @@ -629,7 +643,7 @@ def create_from_point_cloud(points: np.ndarray,
object_name: str,
add_geometry_nodes_visualization: bool = False,
point_size: float = 0.015,
point_color: Tuple[float, float, float] = (1, 0, 0)) -> "MeshObject":
point_color: Tuple[float, float, float] = (1, 0, 0)) -> MeshObject:
""" Create a mesh from a point cloud.
The mesh's vertices are filled with the points from the given point cloud.
Expand Down Expand Up @@ -672,12 +686,13 @@ def create_from_point_cloud(points: np.ndarray,
return point_cloud


def create_primitive(shape: Literal["CUBE", "CYLINDER", "CONE", "PLANE", "SPHERE", "MONKEY"], **kwargs) -> "MeshObject":
def create_primitive(shape: Literal["CUBE", "CYLINDER", "CONE", "PLANE", "SPHERE", "UV_SPHERE", "ICO_SPHERE", "MONKEY"],
**kwargs) -> MeshObject:
""" Creates a new primitive mesh object.
:param shape: The name of the primitive to create. Available: ["CUBE", "CYLINDER", "CONE", "PLANE",
"SPHERE", "MONKEY"]
:return: The newly created MeshObject
:return: The newly created MeshObject.
"""
if shape == "CUBE":
bpy.ops.mesh.primitive_cube_add(**kwargs)
Expand All @@ -687,10 +702,10 @@ def create_primitive(shape: Literal["CUBE", "CYLINDER", "CONE", "PLANE", "SPHERE
bpy.ops.mesh.primitive_cone_add(**kwargs)
elif shape == "PLANE":
bpy.ops.mesh.primitive_plane_add(**kwargs)
elif "SPHERE" in shape:
if "ICO" in shape:
bpy.ops.mesh.primitive_ico_sphere_add(**kwargs)
elif shape in ["SPHERE", "UV_SPHERE"]:
bpy.ops.mesh.primitive_uv_sphere_add(**kwargs)
elif shape == "ICO_SPHERE":
bpy.ops.mesh.primitive_ico_sphere_add(**kwargs)
elif shape in ["MONKEY", "SUZANNE"]:
bpy.ops.mesh.primitive_monkey_add(**kwargs)
else:
Expand Down Expand Up @@ -782,7 +797,7 @@ def compute_poi(objects: List[MeshObject]) -> np.ndarray:

def scene_ray_cast(origin: Union[Vector, list, np.ndarray], direction: Union[Vector, list, np.ndarray],
max_distance: float = 1.70141e+38) -> Tuple[
bool, np.ndarray, np.ndarray, int, MeshObject, np.ndarray]:
bool, np.ndarray, np.ndarray, int, MeshObject, np.ndarray]:
""" Cast a ray onto all geometry from the scene, in world space.
:param origin: Origin of the ray, in world space.
Expand Down

0 comments on commit f1b024b

Please sign in to comment.