From e7214d78eef4c87cd042bc29ec322ad6a2d1509b Mon Sep 17 00:00:00 2001 From: Terry Jia Date: Fri, 29 May 2026 03:06:00 -0400 Subject: [PATCH] feat: add model_info output to Load3D node (#14144) --- comfy_api/latest/_io.py | 13 +++++++++++++ comfy_extras/nodes_load_3d.py | 4 +++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/comfy_api/latest/_io.py b/comfy_api/latest/_io.py index fed8dc7f0..19d8176b0 100644 --- a/comfy_api/latest/_io.py +++ b/comfy_api/latest/_io.py @@ -777,6 +777,17 @@ class Load3DCamera(ComfyTypeIO): Type = CameraInfo +@comfytype(io_type="LOAD3D_MODEL_INFO") +class Load3DModelInfo(ComfyTypeIO): + class Model3DTransform(TypedDict): + # Coordinate system: right-handed, Y-up, world space + position: dict[str, float | int] # scene units + quaternion: dict[str, float | int] # normalized, dimensionless; world rotation + scale: dict[str, float | int] # dimensionless multiplier + + Type = list[Model3DTransform] + + @comfytype(io_type="LOAD_3D") class Load3D(ComfyTypeIO): """3D models are stored as a dictionary.""" @@ -786,6 +797,7 @@ class Load3D(ComfyTypeIO): normal: str camera_info: Load3DCamera.CameraInfo recording: NotRequired[str] + model_3d_info: NotRequired[list[Load3DModelInfo.Model3DTransform]] Type = Model3DDict @@ -2298,6 +2310,7 @@ __all__ = [ "FlowControl", "Accumulation", "Load3DCamera", + "Load3DModelInfo", "Load3D", "Load3DAnimation", "Photomaker", diff --git a/comfy_extras/nodes_load_3d.py b/comfy_extras/nodes_load_3d.py index 9c27c0191..6f05f050e 100644 --- a/comfy_extras/nodes_load_3d.py +++ b/comfy_extras/nodes_load_3d.py @@ -47,6 +47,7 @@ class Load3D(IO.ComfyNode): IO.Load3DCamera.Output(display_name="camera_info"), IO.Video.Output(display_name="recording_video"), IO.File3DAny.Output(display_name="model_3d"), + IO.Load3DModelInfo.Output(display_name="model_3d_info"), ], ) @@ -73,7 +74,8 @@ class Load3D(IO.ComfyNode): if model_file and model_file != "none": file_3d = Types.File3D(folder_paths.get_annotated_filepath(model_file)) mesh_path = model_file - return IO.NodeOutput(output_image, output_mask, mesh_path, normal_image, image['camera_info'], video, file_3d) + model_3d_info = image.get('model_3d_info', []) + return IO.NodeOutput(output_image, output_mask, mesh_path, normal_image, image['camera_info'], video, file_3d, model_3d_info) process = execute # TODO: remove