FormaAI-Web / static /index.html
1xCode's picture
Upload 216 files
0a4881d verified
Raw
History Blame Contribute Delete
18.3 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FormaAi Studio</title>
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;800;900&family=Inter:wght@300;400;500;700&display=swap" rel="stylesheet">
<!-- Main Stylesheet -->
<link rel="stylesheet" href="/static/style.css">
<!-- Google Model Viewer -->
<script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/3.5.0/model-viewer.min.js"></script>
</head>
<body>
<div class="glow-bg"></div>
<div class="container">
<!-- Top Bar with Language Switcher -->
<div class="top-bar">
<div class="lang-switcher">
<button class="lang-btn active" id="lang-en-btn" aria-label="Switch to English">
<svg viewBox="0 0 36 36" width="16" height="16" xmlns="http://www.w3.org/2000/svg" style="vertical-align: middle;"><clipPath id="circle-clip"><circle cx="18" cy="18" r="18"/></clipPath><g clip-path="url(#circle-clip)"><rect width="36" height="36" fill="#fff"/><path d="M0 0h36v2.77H0zm0 5.54h36v2.77H0zm0 11.08h36v2.77H0zm0 5.54h36v2.77H0zm0 5.54h36v2.77H0zm0 5.54h36v2.77H0zm0 11.08h36v2.77H0zm0 5.54h36v2.77H0z" fill="#B22234"/><rect width="16" height="19.38" fill="#3C3B6E"/><g fill="#fff"><circle cx="3" cy="3" r="0.8"/><circle cx="7" cy="3" r="0.8"/><circle cx="11" cy="3" r="0.8"/><circle cx="15" cy="3" r="0.8"/><circle cx="5" cy="7" r="0.8"/><circle cx="9" cy="7" r="0.8"/><circle cx="13" cy="7" r="0.8"/><circle cx="3" cy="11" r="0.8"/><circle cx="7" cy="11" r="0.8"/><circle cx="11" cy="11" r="0.8"/><circle cx="15" cy="11" r="0.8"/><circle cx="5" cy="15" r="0.8"/><circle cx="9" cy="15" r="0.8"/><circle cx="13" cy="15" r="0.8"/></g></g></svg>
<span>EN</span>
</button>
<button class="lang-btn" id="lang-ru-btn" aria-label="Переключить на русский">
<svg viewBox="0 0 36 36" width="16" height="16" xmlns="http://www.w3.org/2000/svg" style="vertical-align: middle;"><clipPath id="russia-clip"><circle cx="18" cy="18" r="18"/></clipPath><g clip-path="url(#russia-clip)"><rect width="36" height="12" fill="#fff"/><rect y="12" width="36" height="12" fill="#0039A6"/><rect y="24" width="36" height="12" fill="#D52B1E"/></g></svg>
<span>RU</span>
</button>
</div>
</div>
<!-- Header -->
<header class="header">
<h1 class="header-title" data-i18n="header_title">FormaAi Studio</h1>
<p class="header-subtitle" data-i18n="header_subtitle">Unified Hybrid 3D Generation Pipeline (Mesh + Gaussians)</p>
</header>
<!-- Main Workspace -->
<div class="workspace">
<!-- Left Side: Controls -->
<div class="controls-panel glass-panel">
<!-- Dropzone Section -->
<div class="panel-section">
<h2 class="section-title">
<span class="icon">
<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>
</span>
<span data-i18n="input_image">1. Input Image</span>
</h2>
<div class="dropzone" id="dropzone">
<input type="file" id="file-input" accept="image/*" style="display: none;">
<div class="dropzone-empty" id="dropzone-empty">
<svg class="upload-icon" viewBox="0 0 24 24" width="48" height="48">
<path fill="currentColor" d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"/>
</svg>
<p class="upload-text">
<span data-i18n="upload_text">Drag & drop image here or </span>
<span data-i18n="upload_browse" style="color: var(--neon-indigo); font-weight: 600;">choose file</span>
</p>
<p class="upload-hint" data-i18n="upload_hint">Supports PNG, JPG, JPEG</p>
</div>
<div class="dropzone-preview" id="dropzone-preview" style="display: none;">
<img id="image-preview" src="" alt="Preview">
<button class="remove-btn" id="remove-img-btn" type="button">
<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 4px; vertical-align: middle;"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
<span data-i18n="remove_btn">Delete</span>
</button>
</div>
</div>
</div>
<!-- Parameters Section -->
<div class="panel-section">
<div class="accordion">
<div class="accordion-header" id="accordion-basic-btn">
<h2 class="section-title">
<span class="icon">
<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83 2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
</span>
<span data-i18n="gen_params">2. Generation Settings</span>
</h2>
<span class="arrow"></span>
</div>
<div class="accordion-content" id="accordion-basic-content">
<!-- Basic fields -->
<div class="form-group">
<label for="seed-input" data-i18n="seed_label">Random Seed</label>
<input type="number" id="seed-input" value="42" min="0">
</div>
<div class="form-group">
<label><span data-i18n="stage1_steps">Sparse Structure Steps (Stage 1):</span> <span id="ss-steps-val" class="badge">12</span></label>
<input type="range" id="ss-steps-input" min="4" max="30" step="1" value="12">
</div>
<div class="form-group">
<label><span data-i18n="stage1_cfg">Sparse Structure CFG (Guidance):</span> <span id="ss-cfg-val" class="badge">7.5</span></label>
<input type="range" id="ss-cfg-input" min="1" max="15" step="0.5" value="7.5">
</div>
<div class="form-group">
<label><span data-i18n="stage2_steps">Structured Latent Steps (Stage 2):</span> <span id="slat-steps-val" class="badge">12</span></label>
<input type="range" id="slat-steps-input" min="4" max="30" step="1" value="12">
</div>
<div class="form-group">
<label><span data-i18n="stage2_cfg">Structured Latent CFG (Guidance):</span> <span id="slat-cfg-val" class="badge">3.0</span></label>
<input type="range" id="slat-cfg-input" min="1" max="10" step="0.5" value="3.0">
</div>
</div>
</div>
</div>
<!-- Postprocessing Section -->
<div class="panel-section">
<div class="accordion">
<div class="accordion-header" id="accordion-post-btn">
<h2 class="section-title">
<span class="icon">
<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>
</span>
<span data-i18n="postprocess_title">3. Postprocessing & AI Upscaling</span>
</h2>
<span class="arrow"></span>
</div>
<div class="accordion-content" id="accordion-post-content">
<!-- Checkbox -->
<div class="form-group checkbox-group">
<input type="checkbox" id="refine-gs-input">
<label for="refine-gs-input" data-i18n="refine_gs_label">Refine 3D Gaussians (Differentiable Refinement)</label>
</div>
<div class="form-group" id="refine-steps-group">
<label><span data-i18n="refine_steps_label">Optimization Steps:</span> <span id="refine-steps-val" class="badge">100</span></label>
<input type="range" id="refine-steps-input" min="20" max="300" step="10" value="100">
</div>
<div class="form-group">
<label data-i18n="mesh_upscaling">Mesh Texture Scaling (AI Super Resolution)</label>
<div class="radio-group">
<label class="radio-label">
<input type="radio" name="upscale-factor" value="1">
<span data-i18n="upscale_off">Off</span>
</label>
<label class="radio-label">
<input type="radio" name="upscale-factor" value="2" checked>
<span>2K (Swin2SR x2)</span>
</label>
<label class="radio-label">
<input type="radio" name="upscale-factor" value="4">
<span>4K (Swin2SR x4)</span>
</label>
</div>
</div>
<div class="form-group">
<label data-i18n="upscale_device">Upscaling Device</label>
<div class="radio-group device-radio">
<label class="radio-label">
<input type="radio" name="upscale-device" value="GPU">
<span data-i18n="device_gpu">GPU (Fast)</span>
</label>
<label class="radio-label">
<input type="radio" name="upscale-device" value="CPU">
<span data-i18n="device_cpu">CPU (No OOM)</span>
</label>
<label class="radio-label">
<input type="radio" name="upscale-device" value="Auto-Fallback" checked>
<span data-i18n="device_auto">Auto-Fallback</span>
</label>
</div>
</div>
</div>
</div>
</div>
<!-- Submit Button -->
<button class="btn-primary" id="generate-btn" data-i18n="generate_btn">Generate 3D Object</button>
<!-- Status & Logger Box -->
<div class="status-box" id="status-box" style="display: none;">
<div class="status-header">
<span class="status-label"><span data-i18n="status_label">Status:</span> <strong id="status-text">Pending...</strong></span>
<span class="status-percent" id="status-percent">0%</span>
</div>
<div class="progress-bar-container">
<div class="progress-bar" id="progress-bar"></div>
</div>
<div class="log-output" id="log-output">
<div class="log-line text-cyan">> Initializing interface...</div>
</div>
</div>
</div>
<!-- Right Side: Preview & Viewer -->
<div class="preview-panel glass-panel">
<h2 class="section-title">
<span class="icon">
<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
</span>
<span data-i18n="result_title">4. Generation Result</span>
</h2>
<!-- 3D Viewport -->
<div class="viewport-container">
<div class="viewport-placeholder" id="viewport-placeholder">
<svg class="placeholder-icon" viewBox="0 0 24 24" width="64" height="64">
<path fill="currentColor" d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/>
</svg>
<p data-i18n="viewport_placeholder">GLB 3D model will appear here after generation completes</p>
</div>
<model-viewer id="model-viewer"
src=""
alt="FormaAi Generated 3D Model"
auto-rotate
camera-controls
shadow-intensity="1"
exposure="1"
style="display: none; width: 100%; height: 100%;">
</model-viewer>
</div>
<!-- Tabbed Additional Previews -->
<div class="tabs-container">
<div class="tabs-header">
<button class="tab-btn active" data-tab="images-tab" data-i18n="tab_preview">Add. Preview</button>
<button class="tab-btn" data-tab="files-tab" id="downloads-tab-btn" data-i18n="tab_downloads" disabled>Downloads</button>
</div>
<div class="tabs-content">
<!-- Images Preview Tab -->
<div class="tab-pane active" id="images-tab">
<div class="gallery">
<div class="gallery-item">
<h3 data-i18n="mask_title">Image Mask (Rembg)</h3>
<div class="gallery-image-box">
<div class="img-placeholder" id="mask-placeholder" data-i18n="mask_placeholder">Waiting for generation...</div>
<img id="mask-preview" src="" alt="Mask Preview" style="display: none;">
</div>
</div>
<div class="gallery-item">
<h3 data-i18n="render_title">3D Gaussians Render (Front View)</h3>
<div class="gallery-image-box">
<div class="img-placeholder" id="render-placeholder" data-i18n="render_placeholder">Waiting for generation...</div>
<img id="render-preview" src="" alt="Gaussian Preview" style="display: none;">
</div>
</div>
</div>
</div>
<!-- Downloads Tab -->
<div class="tab-pane" id="files-tab">
<div class="files-list" id="files-list">
<p class="text-gray" id="downloads-empty-text" data-i18n="downloads_empty">Result files not generated.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Frontend Script -->
<script src="/static/app.js"></script>
</body>
</html>