8 Commits
Author SHA1 Message Date
Laurent Erignoux 0e4e47a765 Merge pull request #3 from lerignoux/node_publish_ci
Node publish ci
2025-08-02 10:07:38 +08:00
Laurent Erignoux da12e818ff Adding node publication CI-CD 2025-08-02 10:06:21 +08:00
Erignoux Laurent 534c7440f7 Adding linting step in CI-CD 2025-08-02 10:06:19 +08:00
Erignoux Laurent b7f34e5ee7 Adding an example workflow 2025-08-01 15:20:24 +08:00
Erignoux Laurent ebe542ac48 Cleaning dependencies and pyproject 2025-08-01 15:04:43 +08:00
Laurent Erignoux 6a80faf53e Merge pull request #2 from lerignoux/ci_linting
Adding linting step in CI-CD
2025-08-01 15:00:10 +08:00
Erignoux Laurent 6a5279cabc Adding linting step in CI-CD 2025-08-01 14:58:50 +08:00
Laurent Erignoux eaa3b7d597 Merge pull request #1 from lerignoux/draft
First stable 3D Custom node
2025-08-01 14:55:57 +08:00
8 changed files with 430 additions and 20 deletions
+24
View File
@@ -0,0 +1,24 @@
name: Publish to Comfy registry
on:
workflow_dispatch:
push:
branches:
- main
paths:
- "pyproject.toml"
permissions:
issues: write
jobs:
publish-node:
name: Publish Custom Node to registry
runs-on: ubuntu-latest
if: ${{ github.repository_owner == 'lerignoux' }}
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Publish Custom Node
uses: Comfy-Org/publish-node-action@v1
with:
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }} ## Add your own personal access token to your Github Repository secrets and reference it here.
+38
View File
@@ -0,0 +1,38 @@
name: Python Lint Check
on:
push:
branches: [main, master, develop]
pull_request:
branches: [main, master, develop]
jobs:
lint:
runs-on: ubuntu-latest
container:
image: python:3.9-alpine
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
# Update package manager and install required packages
apk update
apk add --no-cache findutils
python -m pip install --upgrade pip
pip install pycodestyle
- name: Show pycodestyle configuration
run: |
echo "Running pycodestyle with setup.cfg configuration:"
echo "- Max line length: 120"
echo "- Excluded directories: Stable3DGen/, __pycache__/"
echo "- Files being checked:"
find . -name "*.py" -not -path "./Stable3DGen/*" -not -path "./__pycache__/*"
- name: Run pycodestyle
run: |
# Run pycodestyle using setup.cfg configuration
pycodestyle .
Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

+324
View File
@@ -0,0 +1,324 @@
{
"id": "a4bc9489-299f-499a-b427-ef84a35c34f6",
"revision": 0,
"last_node_id": 19,
"last_link_id": 35,
"nodes": [
{
"id": 16,
"type": "Stable3DLoadModels",
"pos": [
122.61805725097656,
-337.5390625
],
"size": [
315,
126
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "hi3dgen pipeline",
"type": "HI3DGEN_PIPELINE",
"links": [
31,
33
]
},
{
"name": "Normal predictor",
"type": "STABLE3D_NORMAL",
"links": [
32
]
}
],
"properties": {
"Node name for S&R": "Stable3DLoadModels"
},
"widgets_values": [
"Stable-X/trellis-normal-v0-1",
"Stable-X/yoso-normal-v1-8-1",
"ZhengPeng7/BiRefNet",
null
]
},
{
"id": 13,
"type": "PreviewImage",
"pos": [
989.544677734375,
-49.72162628173828
],
"size": [
210,
222
],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 26
}
],
"outputs": [],
"properties": {
"Node name for S&R": "PreviewImage"
},
"widgets_values": [
null
]
},
{
"id": 12,
"type": "Stable3DPreprocessImage",
"pos": [
535.5403442382812,
-187.32595825195312
],
"size": [
367.79998779296875,
74
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "hi3dgen_pipeline",
"type": "HI3DGEN_PIPELINE",
"link": 33
},
{
"name": "normal_predictor",
"type": "STABLE3D_NORMAL",
"link": 32
},
{
"name": "image",
"type": "IMAGE",
"link": 34
}
],
"outputs": [
{
"name": "normal_images",
"type": "IMAGE",
"links": [
26,
27
]
}
],
"properties": {
"Node name for S&R": "Stable3DPreprocessImage"
},
"widgets_values": [
null
]
},
{
"id": 17,
"type": "LoadImage",
"pos": [
127.95042419433594,
-40.27117919921875
],
"size": [
278,
102
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
34
]
},
{
"name": "MASK",
"type": "MASK",
"links": null
}
],
"properties": {
"Node name for S&R": "LoadImage"
},
"widgets_values": [
"example.png",
"image",
null
]
},
{
"id": 19,
"type": "Preview3D",
"pos": [
1478.064453125,
-362.6379699707031
],
"size": [
400,
526
],
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "camera_info",
"shape": 7,
"type": "LOAD3D_CAMERA",
"link": null
},
{
"name": "model_file",
"type": "STRING",
"widget": {
"name": "model_file"
},
"link": 35
}
],
"outputs": [],
"properties": {
"Node name for S&R": "Preview3D"
},
"widgets_values": [
"",
"",
null
]
},
{
"id": 11,
"type": "Stable3DGenerate3D",
"pos": [
978.2960205078125,
-371.08160400390625
],
"size": [
393,
198
],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"name": "hi3dgen_pipeline",
"type": "HI3DGEN_PIPELINE",
"link": 31
},
{
"name": "normal_images",
"type": "IMAGE",
"link": 27
}
],
"outputs": [
{
"name": "mesh_file_path",
"type": "STRING",
"links": [
35
]
}
],
"properties": {
"Node name for S&R": "Stable3DGenerate3D"
},
"widgets_values": [
1028886841,
"randomize",
3,
50,
3,
6,
null
]
}
],
"links": [
[
26,
12,
0,
13,
0,
"IMAGE"
],
[
27,
12,
0,
11,
1,
"IMAGE"
],
[
31,
16,
0,
11,
0,
"HI3DGEN_PIPELINE"
],
[
32,
16,
1,
12,
1,
"STABLE3D_NORMAL"
],
[
33,
16,
0,
12,
0,
"HI3DGEN_PIPELINE"
],
[
34,
17,
0,
12,
2,
"IMAGE"
],
[
35,
11,
0,
19,
1,
"STRING"
]
],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1.3310000000000004,
"offset": [
-48.53984360644931,
424.3690096481302
]
},
"frontendVersion": "1.23.4"
},
"version": 0.4
}
+10 -4
View File
@@ -1,13 +1,19 @@
[project]
dependencies = [
"scikit-image~=0.25",
"spconv-cu120==2.3.6",
"torch==2.5.1",
"torchaudio==2.5.1",
"torchsde==0.2.6",
"torchvision==0.20.1",
"trimesh~=4.7",
"xformers~=0.0",
"diffusers~=0.28",
"accelerate~=1.9",
"triton~=3.2",
"triton=~3.1",
"kornia~=0.8",
"timm~=0.6",
"transformers~=4.46",
"trimesh~=4.7",
"scikit-image~=0.25",
"transformers~=4.46"
]
+11 -12
View File
@@ -1,20 +1,19 @@
--extra-index-url https://download.pytorch.org/whl/cu124
scikit-image~=0.25
spconv-cu120==2.3.6
torch==2.5.1
torchaudio==2.5.1
torchsde==0.2.6
torchvision==0.20.1
trimesh~=4.7
xformers~=0.0
# For StableNormal
diffusers~=0.28
accelerate~=1.9
triton
triton~=3.1
# For BirefNet
kornia~=0.8
timm~=0.6
transformers~=4.46
trimesh~=4.7
scikit-image~=0.25
xformers~=0.0
torch==2.5.1
torchaudio==2.5.1
torchvision==0.20.1
torchsde
spconv-cu120==2.3.6
transformers~=4.46
+5
View File
@@ -0,0 +1,5 @@
[pycodestyle]
max-line-length = 120
exclude = Stable3DGen/,__pycache__/
statistics = True
count = True
+18 -4
View File
@@ -11,7 +11,7 @@ from transformers import AutoModelForImageSegmentation
import folder_paths
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Stable3DGen'))
from hi3dgen.pipelines import Hi3DGenPipeline
from hi3dgen.pipelines import Hi3DGenPipeline # noqa E402
log = logging.getLogger(__name__)
MAX_SEED = numpy.iinfo(numpy.int32).max
@@ -95,7 +95,11 @@ class Stable3DLoadModels:
log.info(f"Already cached at: {local_path}")
return local_path
log.info(f"Downloading and caching model: {model_id} to trellis model folder")
local_path = snapshot_download(repo_id=model_id, local_dir=os.path.join(self.models_path, model_id), force_download=False)
local_path = snapshot_download(
repo_id=model_id,
local_dir=os.path.join(self.models_path, model_id),
force_download=False
)
return local_path
@set_spconv_algo
@@ -112,7 +116,13 @@ class Stable3DLoadModels:
loaded_models.append(self.download_model(model_id))
# Loads yoso pedictor model to ~/models/trellis and StableNormal_turbo predictor library to ~/.cache/torch/hub/
yozo_model_folder = os.path.join(self.models_path, "Stable-X")
normal_predictor = torch.hub.load("hugoycj/StableNormal", "StableNormal_turbo", trust_repo=True, yoso_version='yoso-normal-v1-8-1', local_cache_dir=yozo_model_folder)
normal_predictor = torch.hub.load(
"hugoycj/StableNormal",
"StableNormal_turbo",
trust_repo=True,
yoso_version='yoso-normal-v1-8-1',
local_cache_dir=yozo_model_folder
)
# download dinov2 feature detection model and library to ~/.cache/torch/hub/
torch.hub.load('facebookresearch/dinov2', 'dinov2_vitl14_reg', pretrained=True)
@@ -319,6 +329,10 @@ class Stable3DGenerate3D:
return (filename,)
@classmethod
def IS_CHANGED(s, images, seed, ss_guidance_strength, ss_sampling_steps, slat_guidance_strength, slat_sampling_steps):
def IS_CHANGED(
s, images, seed,
ss_guidance_strength, ss_sampling_steps,
slat_guidance_strength, slat_sampling_steps
):
# FIXME We should properly handle re-generation depending on the input parameters.
return float("NaN")