File size: 14,776 Bytes
0a4881d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>FormaAI TRELLIS 3D Generator</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;500;600;700&family=Plus+Jakarta+Sans:wght@300;400;500;600;700&display=swap" rel="stylesheet">
    <!-- FontAwesome for Icons -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <!-- Custom CSS -->
    <link rel="stylesheet" href="/static/css/style.css">
    <!-- Google <model-viewer> for premium interactive 3D rendering -->
    <script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js"></script>
</head>
<body>
    <!-- Background glow elements -->
    <div class="glow-sphere sphere-1"></div>
    <div class="glow-sphere sphere-2"></div>
    <div class="glow-sphere sphere-3"></div>

    <div class="app-container">
        <!-- Header -->
        <header class="app-header">
            <div class="logo">
                <i class="fa-solid fa-cube logo-icon animate-float"></i>
                <div class="logo-text">
                    <h1>Forma<span>AI</span></h1>
                    <p>TRELLIS 3D Generation Suite</p>
                </div>
            </div>
            <div class="header-status">
                <span class="status-badge"><i class="fa-solid fa-circle status-dot online"></i> GPU Активен</span>
            </div>
        </header>

        <!-- Main Workspace -->
        <main class="app-workspace">
            <!-- Left Panel: Controls & Upload -->
            <section class="workspace-panel panel-left glass">
                <div class="panel-header">
                    <h2><i class="fa-solid fa-cloud-arrow-up"></i> Загрузка изображения</h2>
                </div>
                
                <!-- Dropzone -->
                <div class="upload-zone" id="uploadZone">
                    <input type="file" id="fileInput" accept="image/*" style="display: none;">
                    <div class="upload-content" id="uploadContent">
                        <i class="fa-solid fa-images upload-icon"></i>
                        <p class="upload-title">Перетащите изображение сюда</p>
                        <p class="upload-subtitle">или нажмите для выбора файла</p>
                        <span class="upload-limit">Поддержка PNG, JPG (будет автоматически удален фон)</span>
                    </div>
                    <!-- Preprocessing view -->
                    <div class="preview-container" id="previewContainer" style="display: none;">
                        <img id="imagePreview" src="" alt="Preview">
                        <div class="preview-overlay">
                            <button type="button" class="btn btn-secondary btn-sm" id="btnResetImage">
                                <i class="fa-solid fa-rotate-left"></i> Сбросить
                            </button>
                        </div>
                    </div>
                </div>

                <!-- Parameters Accordion -->
                <div class="parameters-section">
                    <div class="section-title">
                        <h3><i class="fa-solid fa-sliders"></i> Параметры генерации</h3>
                    </div>
                    
                    <form id="generationForm">
                        <input type="hidden" id="sessionId" name="id">
                        
                        <div class="form-group">
                            <label for="seed">Seed (Случайное зерно)</label>
                            <div class="input-with-checkbox">
                                <input type="number" id="seed" name="seed" value="0" class="form-control" disabled>
                                <label class="checkbox-container">
                                    <input type="checkbox" id="randomizeSeed" name="randomize_seed" checked>
                                    <span class="checkmark"></span> Случайно
                                </label>
                            </div>
                        </div>

                        <div class="accordion-item open">
                            <div class="accordion-title">
                                <span>Этап 1: Разреженное облако</span>
                                <i class="fa-solid fa-chevron-down"></i>
                            </div>
                            <div class="accordion-content">
                                <div class="form-group">
                                    <div class="slider-header">
                                        <label>Сила подсказки (CFG)</label>
                                        <span class="slider-val" id="ssGuidanceVal">7.5</span>
                                    </div>
                                    <input type="range" name="ss_guidance_strength" min="1.0" max="15.0" step="0.5" value="7.5" class="slider" oninput="document.getElementById('ssGuidanceVal').innerText=this.value">
                                </div>
                                <div class="form-group">
                                    <div class="slider-header">
                                        <label>Шаги сэмплирования</label>
                                        <span class="slider-val" id="ssStepsVal">12</span>
                                    </div>
                                    <input type="range" name="ss_sampling_steps" min="1" max="50" step="1" value="12" class="slider" oninput="document.getElementById('ssStepsVal').innerText=this.value">
                                </div>
                            </div>
                        </div>

                        <div class="accordion-item open">
                            <div class="accordion-title">
                                <span>Этап 2: Структурированный латент</span>
                                <i class="fa-solid fa-chevron-down"></i>
                            </div>
                            <div class="accordion-content">
                                <div class="form-group">
                                    <div class="slider-header">
                                        <label>Сила подсказки (CFG)</label>
                                        <span class="slider-val" id="slatGuidanceVal">3.0</span>
                                    </div>
                                    <input type="range" name="slat_guidance_strength" min="1.0" max="15.0" step="0.5" value="3.0" class="slider" oninput="document.getElementById('slatGuidanceVal').innerText=this.value">
                                </div>
                                <div class="form-group">
                                    <div class="slider-header">
                                        <label>Шаги сэмплирования</label>
                                        <span class="slider-val" id="slatStepsVal">12</span>
                                    </div>
                                    <input type="range" name="slat_sampling_steps" min="1" max="50" step="1" value="12" class="slider" oninput="document.getElementById('slatStepsVal').innerText=this.value">
                                </div>
                            </div>
                        </div>

                        <button type="submit" class="btn btn-primary btn-block btn-lg" id="btnGenerate" disabled>
                            <span class="btn-text"><i class="fa-solid fa-wand-magic-sparkles"></i> Сгенерировать 3D</span>
                            <span class="spinner" style="display: none;"><i class="fa-solid fa-circle-notch fa-spin"></i> Генерация...</span>
                        </button>
                    </form>
                </div>
            </section>

            <!-- Right Panel: Live Output & 3D Viewer -->
            <section class="workspace-panel panel-right glass">
                <div class="panel-header tabs-header">
                    <button class="panel-tab active" id="tabPreview">
                        <i class="fa-solid fa-play"></i> Видео Превью
                    </button>
                    <button class="panel-tab" id="tab3dViewer" disabled>
                        <i class="fa-solid fa-cube"></i> Интерактивный 3D
                    </button>
                </div>

                <!-- Preview Tab Content -->
                <div class="tab-content" id="contentPreview">
                    <div class="video-placeholder" id="videoPlaceholder">
                        <div class="placeholder-icon-wrap">
                            <i class="fa-solid fa-film placeholder-icon animate-pulse"></i>
                        </div>
                        <h3>Ожидание генерации</h3>
                        <p>Загрузите изображение и нажмите кнопку генерации для создания 3D модели</p>
                    </div>
                    <div class="video-container" id="videoContainer" style="display: none;">
                        <video id="previewVideo" autoplay loop muted playsinline controls></video>
                    </div>
                </div>

                <!-- 3D Viewer Tab Content -->
                <div class="tab-content" id="content3dViewer" style="display: none;">
                    <div class="viewer-container">
                        <model-viewer id="glbViewer" 
                                      alt="3D сгенерированная модель" 
                                      auto-rotate 
                                      camera-controls 
                                      shadow-intensity="1.5" 
                                      shadow-softness="0.8"
                                      exposure="1.0"
                                      environment-image="legacy"
                                      interaction-prompt="auto">
                            <div class="viewer-loading" slot="poster">
                                <i class="fa-solid fa-circle-notch fa-spin"></i> Загрузка 3D модели...
                            </div>
                        </model-viewer>
                    </div>
                </div>

                <!-- Export Controls -->
                <div class="export-controls glass-dark" id="exportControls" style="display: none;">
                    <div class="export-header">
                        <h4><i class="fa-solid fa-file-export"></i> Экспорт и Скачивание</h4>
                    </div>
                    <div class="export-options" id="exportOptions">
                        <div class="glb-baking-config">
                            <div class="config-row">
                                <div class="form-group-inline">
                                    <label for="meshSimplify">Упрощение сетки</label>
                                    <select id="meshSimplify" class="form-control-inline">
                                        <option value="0.90">90% (Детализированная)</option>
                                        <option value="0.95" selected>95% (Оптимальная)</option>
                                        <option value="0.98">98% (Легкая)</option>
                                    </select>
                                </div>
                                <div class="form-group-inline">
                                    <label for="textureSize">Размер текстуры</label>
                                    <select id="textureSize" class="form-control-inline">
                                        <option value="512">512 px</option>
                                        <option value="1024" selected>1024 px (HD)</option>
                                        <option value="2048">2048 px (UHD)</option>
                                    </select>
                                </div>
                            </div>
                            <button class="btn btn-secondary btn-block" id="btnExtractGlb">
                                <span class="btn-text"><i class="fa-solid fa-arrows-to-eye"></i> Извлечь GLB сетку</span>
                                <span class="spinner" style="display: none;"><i class="fa-solid fa-circle-notch fa-spin"></i> Запекание текстур...</span>
                            </button>
                        </div>

                        <div class="download-buttons">
                            <a id="linkDownloadGlb" href="#" download class="btn btn-success btn-download disabled" target="_blank">
                                <i class="fa-solid fa-cube"></i> Скачать GLB
                            </a>
                            <a id="linkDownloadPly" href="#" download class="btn btn-info btn-download" target="_blank">
                                <i class="fa-solid fa-cloud"></i> Скачать PLY (Гауссианы)
                            </a>
                        </div>
                    </div>
                </div>
            </section>
        </main>

        <!-- Generation History Gallery -->
        <section class="history-section glass">
            <div class="section-header">
                <h2><i class="fa-solid fa-clock-rotate-left"></i> История генераций</h2>
                <button class="btn btn-secondary btn-sm" id="btnRefreshHistory">
                    <i class="fa-solid fa-arrows-rotate"></i> Обновить
                </button>
            </div>
            
            <div class="history-gallery" id="historyGallery">
                <!-- Empty State -->
                <div class="gallery-empty" id="galleryEmpty">
                    <i class="fa-regular fa-folder-open"></i>
                    <p>История пуста. Создайте свою первую 3D-модель!</p>
                </div>
            </div>
        </section>
    </div>

    <!-- Toast Notification -->
    <div class="toast-container" id="toastContainer"></div>

    <!-- Custom JS -->
    <script src="/static/js/main.js"></script>
</body>
</html>