Spaces:
Running
Running
UI updates: Pixal3D V1.1 branding, camera settings, readme, ref thumbnail, GPU duration 240s, fix EXR path
Browse files- .gitignore +1 -0
- app.py +5 -4
- autotune_cache.json +0 -0
- index.html +86 -1
.gitignore
CHANGED
|
@@ -17,3 +17,4 @@ outputs*/
|
|
| 17 |
results*/
|
| 18 |
ckpts*/
|
| 19 |
tmp/example.py
|
|
|
|
|
|
| 17 |
results*/
|
| 18 |
ckpts*/
|
| 19 |
tmp/example.py
|
| 20 |
+
tmp/
|
app.py
CHANGED
|
@@ -149,10 +149,11 @@ def init_models():
|
|
| 149 |
moge_model = load_moge_model(device="cuda")
|
| 150 |
|
| 151 |
print("[EnvMap] Loading environment maps...")
|
|
|
|
| 152 |
envmap = {
|
| 153 |
-
'forest': EnvMap(torch.tensor(cv2.cvtColor(cv2.imread('assets/hdri/forest.exr', cv2.IMREAD_UNCHANGED), cv2.COLOR_BGR2RGB), dtype=torch.float32, device='cuda')),
|
| 154 |
-
'sunset': EnvMap(torch.tensor(cv2.cvtColor(cv2.imread('assets/hdri/sunset.exr', cv2.IMREAD_UNCHANGED), cv2.COLOR_BGR2RGB), dtype=torch.float32, device='cuda')),
|
| 155 |
-
'courtyard': EnvMap(torch.tensor(cv2.cvtColor(cv2.imread('assets/hdri/courtyard.exr', cv2.IMREAD_UNCHANGED), cv2.COLOR_BGR2RGB), dtype=torch.float32, device='cuda')),
|
| 156 |
}
|
| 157 |
|
| 158 |
# ============================================================================
|
|
@@ -318,7 +319,7 @@ def generate_3d(
|
|
| 318 |
}
|
| 319 |
|
| 320 |
@app.api()
|
| 321 |
-
@spaces.GPU(duration=
|
| 322 |
def extract_glb_api(state_path: str, decimation_target: int, texture_size: int) -> FileData:
|
| 323 |
init_models()
|
| 324 |
shape_slat, tex_slat, res = unpack_state(state_path)
|
|
|
|
| 149 |
moge_model = load_moge_model(device="cuda")
|
| 150 |
|
| 151 |
print("[EnvMap] Loading environment maps...")
|
| 152 |
+
_base = os.path.dirname(os.path.abspath(__file__))
|
| 153 |
envmap = {
|
| 154 |
+
'forest': EnvMap(torch.tensor(cv2.cvtColor(cv2.imread(os.path.join(_base, 'assets/hdri/forest.exr'), cv2.IMREAD_UNCHANGED), cv2.COLOR_BGR2RGB), dtype=torch.float32, device='cuda')),
|
| 155 |
+
'sunset': EnvMap(torch.tensor(cv2.cvtColor(cv2.imread(os.path.join(_base, 'assets/hdri/sunset.exr'), cv2.IMREAD_UNCHANGED), cv2.COLOR_BGR2RGB), dtype=torch.float32, device='cuda')),
|
| 156 |
+
'courtyard': EnvMap(torch.tensor(cv2.cvtColor(cv2.imread(os.path.join(_base, 'assets/hdri/courtyard.exr'), cv2.IMREAD_UNCHANGED), cv2.COLOR_BGR2RGB), dtype=torch.float32, device='cuda')),
|
| 157 |
}
|
| 158 |
|
| 159 |
# ============================================================================
|
|
|
|
| 319 |
}
|
| 320 |
|
| 321 |
@app.api()
|
| 322 |
+
@spaces.GPU(duration=240)
|
| 323 |
def extract_glb_api(state_path: str, decimation_target: int, texture_size: int) -> FileData:
|
| 324 |
init_models()
|
| 325 |
shape_slat, tex_slat, res = unpack_state(state_path)
|
autotune_cache.json
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
index.html
CHANGED
|
@@ -146,6 +146,7 @@
|
|
| 146 |
align-items: center;
|
| 147 |
justify-content: center;
|
| 148 |
animation: fadeIn 0.4s ease-out;
|
|
|
|
| 149 |
}
|
| 150 |
|
| 151 |
.panel.active {
|
|
@@ -492,6 +493,47 @@
|
|
| 492 |
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 10px; }
|
| 493 |
::-webkit-scrollbar-thumb:hover { background: var(--text-dim); }
|
| 494 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 495 |
</style>
|
| 496 |
</head>
|
| 497 |
<body>
|
|
@@ -504,6 +546,21 @@
|
|
| 504 |
<span>Pixal3D</span>
|
| 505 |
</div>
|
| 506 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 507 |
<div class="sidebar-section">
|
| 508 |
<h3><i data-lucide="sliders-horizontal" style="width: 14px;"></i> Base Settings</h3>
|
| 509 |
<div class="control-group">
|
|
@@ -595,7 +652,7 @@
|
|
| 595 |
</div>
|
| 596 |
</div>
|
| 597 |
<div style="color: var(--text-dim); font-size: 0.8rem; font-weight: 500;">
|
| 598 |
-
|
| 599 |
</div>
|
| 600 |
</header>
|
| 601 |
|
|
@@ -615,6 +672,7 @@
|
|
| 615 |
|
| 616 |
<!-- Panel 2: Multi-frame Preview -->
|
| 617 |
<div class="panel" id="panel-2">
|
|
|
|
| 618 |
<div class="viewer-wrapper">
|
| 619 |
<div id="frame-container">
|
| 620 |
<!-- Injected via JS -->
|
|
@@ -631,10 +689,12 @@
|
|
| 631 |
|
| 632 |
<!-- Panel 3: 3D Result -->
|
| 633 |
<div class="panel" id="panel-3">
|
|
|
|
| 634 |
<div class="viewer-wrapper">
|
| 635 |
<model-viewer id="main-3d-viewer"
|
| 636 |
camera-controls
|
| 637 |
auto-rotate
|
|
|
|
| 638 |
shadow-intensity="1.5"
|
| 639 |
environment-image="neutral"
|
| 640 |
exposure="1.2">
|
|
@@ -662,6 +722,10 @@
|
|
| 662 |
</div>
|
| 663 |
</div>
|
| 664 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 665 |
<div class="status-toast" id="toast">Generation started!</div>
|
| 666 |
|
| 667 |
<script type="module">
|
|
@@ -751,6 +815,13 @@
|
|
| 751 |
img.style.display = 'block';
|
| 752 |
hint.style.display = 'none';
|
| 753 |
document.getElementById('generate-btn').disabled = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 754 |
setStep(1);
|
| 755 |
};
|
| 756 |
reader.readAsDataURL(file);
|
|
@@ -892,6 +963,20 @@
|
|
| 892 |
}
|
| 893 |
|
| 894 |
// Helpers
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 895 |
window.toggleAdvanced = () => {
|
| 896 |
const el = document.getElementById('advanced-settings');
|
| 897 |
const chev = document.getElementById('adv-chevron');
|
|
|
|
| 146 |
align-items: center;
|
| 147 |
justify-content: center;
|
| 148 |
animation: fadeIn 0.4s ease-out;
|
| 149 |
+
position: relative;
|
| 150 |
}
|
| 151 |
|
| 152 |
.panel.active {
|
|
|
|
| 493 |
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 10px; }
|
| 494 |
::-webkit-scrollbar-thumb:hover { background: var(--text-dim); }
|
| 495 |
|
| 496 |
+
/* Reference thumbnail in preview/result panels */
|
| 497 |
+
.ref-thumbnail {
|
| 498 |
+
position: absolute;
|
| 499 |
+
top: 1rem;
|
| 500 |
+
right: 1rem;
|
| 501 |
+
width: 400px;
|
| 502 |
+
height: 400px;
|
| 503 |
+
object-fit: cover;
|
| 504 |
+
border-radius: var(--radius-sm);
|
| 505 |
+
border: 2px solid var(--border);
|
| 506 |
+
z-index: 20;
|
| 507 |
+
display: none;
|
| 508 |
+
box-shadow: 0 4px 12px rgba(0,0,0,0.4);
|
| 509 |
+
cursor: pointer;
|
| 510 |
+
transition: transform 0.2s;
|
| 511 |
+
}
|
| 512 |
+
|
| 513 |
+
.ref-thumbnail:hover {
|
| 514 |
+
transform: scale(1.1);
|
| 515 |
+
}
|
| 516 |
+
|
| 517 |
+
/* Lightbox */
|
| 518 |
+
.lightbox-overlay {
|
| 519 |
+
position: fixed;
|
| 520 |
+
inset: 0;
|
| 521 |
+
background: rgba(0, 0, 0, 0.85);
|
| 522 |
+
z-index: 3000;
|
| 523 |
+
display: none;
|
| 524 |
+
align-items: center;
|
| 525 |
+
justify-content: center;
|
| 526 |
+
cursor: zoom-out;
|
| 527 |
+
backdrop-filter: blur(6px);
|
| 528 |
+
}
|
| 529 |
+
|
| 530 |
+
.lightbox-overlay img {
|
| 531 |
+
max-width: 80%;
|
| 532 |
+
max-height: 80%;
|
| 533 |
+
border-radius: var(--radius-md);
|
| 534 |
+
box-shadow: 0 20px 60px rgba(0,0,0,0.6);
|
| 535 |
+
}
|
| 536 |
+
|
| 537 |
</style>
|
| 538 |
</head>
|
| 539 |
<body>
|
|
|
|
| 546 |
<span>Pixal3D</span>
|
| 547 |
</div>
|
| 548 |
|
| 549 |
+
<div class="sidebar-section" style="margin-bottom: 1.5rem;">
|
| 550 |
+
<p style="font-size: 0.82rem; color: var(--text-dim); line-height: 1.6;">
|
| 551 |
+
Upload an image and click Generate.<br>
|
| 552 |
+
Click Extract GLB to export.<br>
|
| 553 |
+
Download the generated GLB file.
|
| 554 |
+
</p>
|
| 555 |
+
<p style="font-size: 0.72rem; color: var(--text-dim); line-height: 1.5; margin-top: 0.5rem; opacity: 0.7;">
|
| 556 |
+
Note: Camera estimated automatically via MoGe-2.
|
| 557 |
+
</p>
|
| 558 |
+
<a href="https://ldyang694.github.io/projects/pixal3d/" target="_blank" class="btn btn-outline" style="margin-top: 1rem; padding: 0.6rem 1rem; font-size: 0.85rem;">
|
| 559 |
+
<i data-lucide="globe" style="width: 16px;"></i>
|
| 560 |
+
Project Page
|
| 561 |
+
</a>
|
| 562 |
+
</div>
|
| 563 |
+
|
| 564 |
<div class="sidebar-section">
|
| 565 |
<h3><i data-lucide="sliders-horizontal" style="width: 14px;"></i> Base Settings</h3>
|
| 566 |
<div class="control-group">
|
|
|
|
| 652 |
</div>
|
| 653 |
</div>
|
| 654 |
<div style="color: var(--text-dim); font-size: 0.8rem; font-weight: 500;">
|
| 655 |
+
Pixal3D V1.1
|
| 656 |
</div>
|
| 657 |
</header>
|
| 658 |
|
|
|
|
| 672 |
|
| 673 |
<!-- Panel 2: Multi-frame Preview -->
|
| 674 |
<div class="panel" id="panel-2">
|
| 675 |
+
<img id="ref-thumb-2" class="ref-thumbnail" src="" alt="Reference">
|
| 676 |
<div class="viewer-wrapper">
|
| 677 |
<div id="frame-container">
|
| 678 |
<!-- Injected via JS -->
|
|
|
|
| 689 |
|
| 690 |
<!-- Panel 3: 3D Result -->
|
| 691 |
<div class="panel" id="panel-3">
|
| 692 |
+
<img id="ref-thumb-3" class="ref-thumbnail" src="" alt="Reference">
|
| 693 |
<div class="viewer-wrapper">
|
| 694 |
<model-viewer id="main-3d-viewer"
|
| 695 |
camera-controls
|
| 696 |
auto-rotate
|
| 697 |
+
camera-orbit="-180deg 90deg auto"
|
| 698 |
shadow-intensity="1.5"
|
| 699 |
environment-image="neutral"
|
| 700 |
exposure="1.2">
|
|
|
|
| 722 |
</div>
|
| 723 |
</div>
|
| 724 |
|
| 725 |
+
<div class="lightbox-overlay" id="lightbox-overlay" onclick="closeLightbox()">
|
| 726 |
+
<img id="lightbox-img" src="" alt="Enlarged">
|
| 727 |
+
</div>
|
| 728 |
+
|
| 729 |
<div class="status-toast" id="toast">Generation started!</div>
|
| 730 |
|
| 731 |
<script type="module">
|
|
|
|
| 815 |
img.style.display = 'block';
|
| 816 |
hint.style.display = 'none';
|
| 817 |
document.getElementById('generate-btn').disabled = false;
|
| 818 |
+
// Update reference thumbnails
|
| 819 |
+
const thumb2 = document.getElementById('ref-thumb-2');
|
| 820 |
+
const thumb3 = document.getElementById('ref-thumb-3');
|
| 821 |
+
thumb2.src = e.target.result;
|
| 822 |
+
thumb2.style.display = 'block';
|
| 823 |
+
thumb3.src = e.target.result;
|
| 824 |
+
thumb3.style.display = 'block';
|
| 825 |
setStep(1);
|
| 826 |
};
|
| 827 |
reader.readAsDataURL(file);
|
|
|
|
| 963 |
}
|
| 964 |
|
| 965 |
// Helpers
|
| 966 |
+
window.openLightbox = (src) => {
|
| 967 |
+
const lb = document.getElementById('lightbox-overlay');
|
| 968 |
+
document.getElementById('lightbox-img').src = src;
|
| 969 |
+
lb.style.display = 'flex';
|
| 970 |
+
};
|
| 971 |
+
|
| 972 |
+
window.closeLightbox = () => {
|
| 973 |
+
document.getElementById('lightbox-overlay').style.display = 'none';
|
| 974 |
+
};
|
| 975 |
+
|
| 976 |
+
// Thumbnail click to enlarge
|
| 977 |
+
document.getElementById('ref-thumb-2').onclick = (e) => { e.stopPropagation(); openLightbox(e.target.src); };
|
| 978 |
+
document.getElementById('ref-thumb-3').onclick = (e) => { e.stopPropagation(); openLightbox(e.target.src); };
|
| 979 |
+
|
| 980 |
window.toggleAdvanced = () => {
|
| 981 |
const el = document.getElementById('advanced-settings');
|
| 982 |
const chev = document.getElementById('adv-chevron');
|