mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-04-29 10:51:27 +00:00
Compare commits
2 Commits
fix/api-no
...
revert-129
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa24f4ee60 | ||
|
|
e6bb7f03dd |
@@ -1,7 +1,3 @@
|
|||||||
import zipfile
|
|
||||||
from io import BytesIO
|
|
||||||
|
|
||||||
import torch
|
|
||||||
from typing_extensions import override
|
from typing_extensions import override
|
||||||
|
|
||||||
from comfy_api.latest import IO, ComfyExtension, Input, Types
|
from comfy_api.latest import IO, ComfyExtension, Input, Types
|
||||||
@@ -21,10 +17,7 @@ from comfy_api_nodes.apis.hunyuan3d import (
|
|||||||
)
|
)
|
||||||
from comfy_api_nodes.util import (
|
from comfy_api_nodes.util import (
|
||||||
ApiEndpoint,
|
ApiEndpoint,
|
||||||
bytesio_to_image_tensor,
|
|
||||||
download_url_to_bytesio,
|
|
||||||
download_url_to_file_3d,
|
download_url_to_file_3d,
|
||||||
download_url_to_image_tensor,
|
|
||||||
downscale_image_tensor_by_max_side,
|
downscale_image_tensor_by_max_side,
|
||||||
poll_op,
|
poll_op,
|
||||||
sync_op,
|
sync_op,
|
||||||
@@ -43,68 +36,6 @@ def _is_tencent_rate_limited(status: int, body: object) -> bool:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ObjZipResult:
|
|
||||||
__slots__ = ("obj", "texture", "metallic", "normal", "roughness")
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
obj: Types.File3D,
|
|
||||||
texture: Input.Image | None = None,
|
|
||||||
metallic: Input.Image | None = None,
|
|
||||||
normal: Input.Image | None = None,
|
|
||||||
roughness: Input.Image | None = None,
|
|
||||||
):
|
|
||||||
self.obj = obj
|
|
||||||
self.texture = texture
|
|
||||||
self.metallic = metallic
|
|
||||||
self.normal = normal
|
|
||||||
self.roughness = roughness
|
|
||||||
|
|
||||||
|
|
||||||
async def download_and_extract_obj_zip(url: str) -> ObjZipResult:
|
|
||||||
"""The Tencent API returns OBJ results as ZIP archives containing the .obj mesh, and texture images.
|
|
||||||
|
|
||||||
When PBR is enabled, the ZIP may contain additional metallic, normal, and roughness maps
|
|
||||||
identified by their filename suffixes.
|
|
||||||
"""
|
|
||||||
data = BytesIO()
|
|
||||||
await download_url_to_bytesio(url, data)
|
|
||||||
data.seek(0)
|
|
||||||
if not zipfile.is_zipfile(data):
|
|
||||||
data.seek(0)
|
|
||||||
return ObjZipResult(obj=Types.File3D(source=data, file_format="obj"))
|
|
||||||
data.seek(0)
|
|
||||||
obj_bytes = None
|
|
||||||
textures: dict[str, Input.Image] = {}
|
|
||||||
with zipfile.ZipFile(data) as zf:
|
|
||||||
for name in zf.namelist():
|
|
||||||
lower = name.lower()
|
|
||||||
if lower.endswith(".obj"):
|
|
||||||
obj_bytes = zf.read(name)
|
|
||||||
elif any(lower.endswith(ext) for ext in (".png", ".jpg", ".jpeg", ".bmp", ".tiff", ".webp")):
|
|
||||||
stem = lower.rsplit(".", 1)[0]
|
|
||||||
tensor = bytesio_to_image_tensor(BytesIO(zf.read(name)), mode="RGB")
|
|
||||||
matched_key = "texture"
|
|
||||||
for suffix, key in {
|
|
||||||
"_metallic": "metallic",
|
|
||||||
"_normal": "normal",
|
|
||||||
"_roughness": "roughness",
|
|
||||||
}.items():
|
|
||||||
if stem.endswith(suffix):
|
|
||||||
matched_key = key
|
|
||||||
break
|
|
||||||
textures[matched_key] = tensor
|
|
||||||
if obj_bytes is None:
|
|
||||||
raise ValueError("ZIP archive does not contain an OBJ file.")
|
|
||||||
return ObjZipResult(
|
|
||||||
obj=Types.File3D(source=BytesIO(obj_bytes), file_format="obj"),
|
|
||||||
texture=textures.get("texture"),
|
|
||||||
metallic=textures.get("metallic"),
|
|
||||||
normal=textures.get("normal"),
|
|
||||||
roughness=textures.get("roughness"),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def get_file_from_response(
|
def get_file_from_response(
|
||||||
response_objs: list[ResultFile3D], file_type: str, raise_if_not_found: bool = True
|
response_objs: list[ResultFile3D], file_type: str, raise_if_not_found: bool = True
|
||||||
) -> ResultFile3D | None:
|
) -> ResultFile3D | None:
|
||||||
@@ -162,7 +93,6 @@ class TencentTextToModelNode(IO.ComfyNode):
|
|||||||
IO.String.Output(display_name="model_file"), # for backward compatibility only
|
IO.String.Output(display_name="model_file"), # for backward compatibility only
|
||||||
IO.File3DGLB.Output(display_name="GLB"),
|
IO.File3DGLB.Output(display_name="GLB"),
|
||||||
IO.File3DOBJ.Output(display_name="OBJ"),
|
IO.File3DOBJ.Output(display_name="OBJ"),
|
||||||
IO.Image.Output(display_name="texture_image"),
|
|
||||||
],
|
],
|
||||||
hidden=[
|
hidden=[
|
||||||
IO.Hidden.auth_token_comfy_org,
|
IO.Hidden.auth_token_comfy_org,
|
||||||
@@ -221,14 +151,14 @@ class TencentTextToModelNode(IO.ComfyNode):
|
|||||||
response_model=To3DProTaskResultResponse,
|
response_model=To3DProTaskResultResponse,
|
||||||
status_extractor=lambda r: r.Status,
|
status_extractor=lambda r: r.Status,
|
||||||
)
|
)
|
||||||
obj_result = await download_and_extract_obj_zip(get_file_from_response(result.ResultFile3Ds, "obj").Url)
|
|
||||||
return IO.NodeOutput(
|
return IO.NodeOutput(
|
||||||
f"{task_id}.glb",
|
f"{task_id}.glb",
|
||||||
await download_url_to_file_3d(
|
await download_url_to_file_3d(
|
||||||
get_file_from_response(result.ResultFile3Ds, "glb").Url, "glb", task_id=task_id
|
get_file_from_response(result.ResultFile3Ds, "glb").Url, "glb", task_id=task_id
|
||||||
),
|
),
|
||||||
obj_result.obj,
|
await download_url_to_file_3d(
|
||||||
obj_result.texture,
|
get_file_from_response(result.ResultFile3Ds, "obj").Url, "obj", task_id=task_id
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -281,10 +211,6 @@ class TencentImageToModelNode(IO.ComfyNode):
|
|||||||
IO.String.Output(display_name="model_file"), # for backward compatibility only
|
IO.String.Output(display_name="model_file"), # for backward compatibility only
|
||||||
IO.File3DGLB.Output(display_name="GLB"),
|
IO.File3DGLB.Output(display_name="GLB"),
|
||||||
IO.File3DOBJ.Output(display_name="OBJ"),
|
IO.File3DOBJ.Output(display_name="OBJ"),
|
||||||
IO.Image.Output(display_name="texture_image"),
|
|
||||||
IO.Image.Output(display_name="optional_metallic"),
|
|
||||||
IO.Image.Output(display_name="optional_normal"),
|
|
||||||
IO.Image.Output(display_name="optional_roughness"),
|
|
||||||
],
|
],
|
||||||
hidden=[
|
hidden=[
|
||||||
IO.Hidden.auth_token_comfy_org,
|
IO.Hidden.auth_token_comfy_org,
|
||||||
@@ -378,17 +304,14 @@ class TencentImageToModelNode(IO.ComfyNode):
|
|||||||
response_model=To3DProTaskResultResponse,
|
response_model=To3DProTaskResultResponse,
|
||||||
status_extractor=lambda r: r.Status,
|
status_extractor=lambda r: r.Status,
|
||||||
)
|
)
|
||||||
obj_result = await download_and_extract_obj_zip(get_file_from_response(result.ResultFile3Ds, "obj").Url)
|
|
||||||
return IO.NodeOutput(
|
return IO.NodeOutput(
|
||||||
f"{task_id}.glb",
|
f"{task_id}.glb",
|
||||||
await download_url_to_file_3d(
|
await download_url_to_file_3d(
|
||||||
get_file_from_response(result.ResultFile3Ds, "glb").Url, "glb", task_id=task_id
|
get_file_from_response(result.ResultFile3Ds, "glb").Url, "glb", task_id=task_id
|
||||||
),
|
),
|
||||||
obj_result.obj,
|
await download_url_to_file_3d(
|
||||||
obj_result.texture,
|
get_file_from_response(result.ResultFile3Ds, "obj").Url, "obj", task_id=task_id
|
||||||
obj_result.metallic if obj_result.metallic is not None else torch.zeros(1, 1, 1, 3),
|
),
|
||||||
obj_result.normal if obj_result.normal is not None else torch.zeros(1, 1, 1, 3),
|
|
||||||
obj_result.roughness if obj_result.roughness is not None else torch.zeros(1, 1, 1, 3),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -508,8 +431,7 @@ class Tencent3DTextureEditNode(IO.ComfyNode):
|
|||||||
],
|
],
|
||||||
outputs=[
|
outputs=[
|
||||||
IO.File3DGLB.Output(display_name="GLB"),
|
IO.File3DGLB.Output(display_name="GLB"),
|
||||||
IO.File3DOBJ.Output(display_name="OBJ"),
|
IO.File3DFBX.Output(display_name="FBX"),
|
||||||
IO.Image.Output(display_name="texture_image"),
|
|
||||||
],
|
],
|
||||||
hidden=[
|
hidden=[
|
||||||
IO.Hidden.auth_token_comfy_org,
|
IO.Hidden.auth_token_comfy_org,
|
||||||
@@ -558,8 +480,7 @@ class Tencent3DTextureEditNode(IO.ComfyNode):
|
|||||||
)
|
)
|
||||||
return IO.NodeOutput(
|
return IO.NodeOutput(
|
||||||
await download_url_to_file_3d(get_file_from_response(result.ResultFile3Ds, "glb").Url, "glb"),
|
await download_url_to_file_3d(get_file_from_response(result.ResultFile3Ds, "glb").Url, "glb"),
|
||||||
await download_url_to_file_3d(get_file_from_response(result.ResultFile3Ds, "obj").Url, "obj"),
|
await download_url_to_file_3d(get_file_from_response(result.ResultFile3Ds, "fbx").Url, "fbx"),
|
||||||
await download_url_to_image_tensor(get_file_from_response(result.ResultFile3Ds, "texture_image").Url),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -733,7 +654,7 @@ class TencentHunyuan3DExtension(ComfyExtension):
|
|||||||
TencentTextToModelNode,
|
TencentTextToModelNode,
|
||||||
TencentImageToModelNode,
|
TencentImageToModelNode,
|
||||||
TencentModelTo3DUVNode,
|
TencentModelTo3DUVNode,
|
||||||
Tencent3DTextureEditNode,
|
# Tencent3DTextureEditNode,
|
||||||
Tencent3DPartNode,
|
Tencent3DPartNode,
|
||||||
TencentSmartTopologyNode,
|
TencentSmartTopologyNode,
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user