Spaces:
Running
Running
cool it's working but we need to generate model with https://huggingface.co/spaces/ilcve21/Sparc3D. model - Initial Deployment
d76ea03 verified | <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>3D Model Generator with Sparc3D</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| .model-container { | |
| width: 100%; | |
| height: 400px; | |
| background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); | |
| border-radius: 12px; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .model-placeholder { | |
| animation: pulse 2s infinite; | |
| } | |
| @keyframes pulse { | |
| 0% { opacity: 0.5; } | |
| 50% { opacity: 0.8; } | |
| 100% { opacity: 0.5; } | |
| } | |
| .loading-spinner { | |
| width: 50px; | |
| height: 50px; | |
| border: 5px solid rgba(255,255,255,0.3); | |
| border-radius: 50%; | |
| border-top-color: #4f46e5; | |
| animation: spin 1s ease-in-out infinite; | |
| } | |
| @keyframes spin { | |
| to { transform: rotate(360deg); } | |
| } | |
| .model-view { | |
| width: 100%; | |
| height: 100%; | |
| object-fit: contain; | |
| } | |
| .history-item { | |
| transition: all 0.3s ease; | |
| } | |
| .history-item:hover { | |
| transform: scale(1.02); | |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 min-h-screen"> | |
| <div class="container mx-auto px-4 py-8"> | |
| <!-- Header --> | |
| <header class="mb-10 text-center"> | |
| <h1 class="text-4xl md:text-5xl font-bold text-indigo-800 mb-3">3D Model Generator</h1> | |
| <p class="text-lg text-gray-600 max-w-2xl mx-auto"> | |
| Create stunning 3D models from text prompts using the power of Sparc3D's AI technology | |
| </p> | |
| </header> | |
| <!-- Main Content --> | |
| <div class="flex flex-col lg:flex-row gap-8"> | |
| <!-- Generation Panel --> | |
| <div class="lg:w-2/3"> | |
| <div class="bg-white rounded-xl shadow-lg p-6"> | |
| <h2 class="text-2xl font-semibold text-gray-800 mb-6">Generate New Model</h2> | |
| <!-- Prompt Input --> | |
| <div class="mb-6"> | |
| <label for="prompt" class="block text-sm font-medium text-gray-700 mb-2">Describe your 3D model</label> | |
| <div class="flex gap-2"> | |
| <input | |
| type="text" | |
| id="prompt" | |
| placeholder="e.g. A futuristic spaceship with glowing engines" | |
| class="flex-1 px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none transition" | |
| > | |
| <button id="generate-btn" class="px-6 py-3 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition flex items-center gap-2"> | |
| <i class="fas fa-magic"></i> Generate | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Advanced Options (Collapsible) --> | |
| <div class="mb-6"> | |
| <button id="advanced-toggle" class="flex items-center text-indigo-600 hover:text-indigo-800 transition mb-3"> | |
| <i class="fas fa-cog mr-2"></i> | |
| Advanced Options | |
| <i class="fas fa-chevron-down ml-2 text-sm transition-transform" id="advanced-arrow"></i> | |
| </button> | |
| <div id="advanced-options" class="hidden bg-gray-50 p-4 rounded-lg space-y-4"> | |
| <div> | |
| <label for="style" class="block text-sm font-medium text-gray-700 mb-1">Style</label> | |
| <select id="style" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500"> | |
| <option value="realistic">Realistic</option> | |
| <option value="cartoon">Cartoon</option> | |
| <option value="low-poly">Low Poly</option> | |
| <option value="scifi">Sci-Fi</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label for="quality" class="block text-sm font-medium text-gray-700 mb-1">Quality</label> | |
| <select id="quality" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500"> | |
| <option value="low">Low (Faster)</option> | |
| <option value="medium" selected>Medium</option> | |
| <option value="high">High (Slower)</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label for="color" class="block text-sm font-medium text-gray-700 mb-1">Primary Color</label> | |
| <input type="color" id="color" value="#4f46e5" class="h-10 w-10 cursor-pointer"> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Model Display --> | |
| <div class="model-container mb-6"> | |
| <div id="model-placeholder" class="model-placeholder text-center p-6"> | |
| <i class="fas fa-cube text-6xl text-gray-400 mb-4"></i> | |
| <p class="text-gray-500">Enter a prompt and click Generate to create your 3D model</p> | |
| </div> | |
| <div id="loading-indicator" class="hidden absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center"> | |
| <div class="loading-spinner"></div> | |
| <p class="ml-3 text-white font-medium">Generating your 3D model...</p> | |
| </div> | |
| <iframe id="model-view" class="model-view hidden" frameborder="0"></iframe> | |
| <iframe id="sparc3d-iframe" src="https://ilcve21-sparc3d.hf.space" class="hidden w-full h-full"></iframe> | |
| </div> | |
| <!-- Action Buttons --> | |
| <div class="flex flex-wrap gap-3"> | |
| <button id="download-btn" class="px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition flex items-center gap-2 disabled:opacity-50" disabled> | |
| <i class="fas fa-download"></i> Download | |
| </button> | |
| <button id="share-btn" class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition flex items-center gap-2 disabled:opacity-50" disabled> | |
| <i class="fas fa-share-alt"></i> Share | |
| </button> | |
| <button id="regenerate-btn" class="px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition flex items-center gap-2"> | |
| <i class="fas fa-sync-alt"></i> Regenerate | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- History Panel --> | |
| <div class="lg:w-1/3"> | |
| <div class="bg-white rounded-xl shadow-lg p-6 h-full"> | |
| <div class="flex justify-between items-center mb-6"> | |
| <h2 class="text-2xl font-semibold text-gray-800">Your History</h2> | |
| <button id="clear-history" class="text-sm text-red-500 hover:text-red-700 flex items-center gap-1"> | |
| <i class="fas fa-trash"></i> Clear | |
| </button> | |
| </div> | |
| <div id="history-list" class="space-y-3 max-h-[600px] overflow-y-auto pr-2"> | |
| <!-- History items will be added here --> | |
| <div class="text-center py-10 text-gray-400" id="empty-history-message"> | |
| <i class="fas fa-history text-4xl mb-3"></i> | |
| <p>Your generated models will appear here</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Info Section --> | |
| <div class="mt-12 bg-indigo-50 rounded-xl p-6"> | |
| <h3 class="text-xl font-semibold text-indigo-800 mb-3">About Sparc3D</h3> | |
| <p class="text-gray-700 mb-4"> | |
| This app uses <a href="https://lizhihao6.github.io/Sparc3D/" target="_blank" class="text-indigo-600 hover:underline">Sparc3D</a>, a free AI-powered 3D model generator that creates high-quality 3D assets from text descriptions. | |
| </p> | |
| <div class="grid md:grid-cols-3 gap-4"> | |
| <div class="bg-white p-4 rounded-lg shadow"> | |
| <i class="fas fa-bolt text-indigo-500 text-2xl mb-2"></i> | |
| <h4 class="font-medium text-gray-800">Fast Generation</h4> | |
| <p class="text-sm text-gray-600">Create 3D models in minutes instead of hours</p> | |
| </div> | |
| <div class="bg-white p-4 rounded-lg shadow"> | |
| <i class="fas fa-paint-brush text-indigo-500 text-2xl mb-2"></i> | |
| <h4 class="font-medium text-gray-800">Customizable</h4> | |
| <p class="text-sm text-gray-600">Control style, quality and colors of your models</p> | |
| </div> | |
| <div class="bg-white p-4 rounded-lg shadow"> | |
| <i class="fas fa-download text-indigo-500 text-2xl mb-2"></i> | |
| <h4 class="font-medium text-gray-800">Free to Use</h4> | |
| <p class="text-sm text-gray-600">Download your creations without any cost</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // Listen for messages from the Sparc3D iframe | |
| window.addEventListener('message', (event) => { | |
| if (event.origin !== 'https://ilcve21-sparc3d.hf.space') return; | |
| if (event.data.type === 'model-ready') { | |
| const modelUrl = event.data.url; | |
| document.getElementById('model-view').src = modelUrl; | |
| document.getElementById('sparc3d-iframe').classList.add('hidden'); | |
| document.getElementById('model-view').classList.remove('hidden'); | |
| } | |
| if (event.data.type === 'generation-error') { | |
| console.error('Generation error:', event.data.error); | |
| // Show error message to user | |
| } | |
| }); | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // DOM Elements | |
| const promptInput = document.getElementById('prompt'); | |
| const generateBtn = document.getElementById('generate-btn'); | |
| const regenerateBtn = document.getElementById('regenerate-btn'); | |
| const downloadBtn = document.getElementById('download-btn'); | |
| const shareBtn = document.getElementById('share-btn'); | |
| const advancedToggle = document.getElementById('advanced-toggle'); | |
| const advancedOptions = document.getElementById('advanced-options'); | |
| const advancedArrow = document.getElementById('advanced-arrow'); | |
| const modelPlaceholder = document.getElementById('model-placeholder'); | |
| const loadingIndicator = document.getElementById('loading-indicator'); | |
| const modelView = document.getElementById('model-view'); | |
| const historyList = document.getElementById('history-list'); | |
| const emptyHistoryMessage = document.getElementById('empty-history-message'); | |
| const clearHistoryBtn = document.getElementById('clear-history'); | |
| // Toggle advanced options | |
| advancedToggle.addEventListener('click', function() { | |
| advancedOptions.classList.toggle('hidden'); | |
| advancedArrow.classList.toggle('rotate-180'); | |
| }); | |
| // Generate model function using Sparc3D Hugging Face Space | |
| async function generateModel(prompt, style = 'realistic', quality = 'medium', color = '#4f46e5') { | |
| if (!prompt.trim()) { | |
| alert('Please enter a description for your 3D model'); | |
| return; | |
| } | |
| // Show loading state | |
| modelPlaceholder.classList.add('hidden'); | |
| loadingIndicator.classList.remove('hidden'); | |
| modelView.classList.add('hidden'); | |
| try { | |
| // Show the Sparc3D iframe | |
| const sparc3dIframe = document.getElementById('sparc3d-iframe'); | |
| sparc3dIframe.classList.remove('hidden'); | |
| // Wait for iframe to load | |
| await new Promise(resolve => { | |
| sparc3dIframe.onload = resolve; | |
| }); | |
| // Send message to iframe with prompt | |
| sparc3dIframe.contentWindow.postMessage({ | |
| type: 'generate', | |
| prompt: prompt, | |
| style: style, | |
| quality: quality, | |
| color: color | |
| }, 'https://ilcve21-sparc3d.hf.space'); | |
| // Hide loading indicator | |
| loadingIndicator.classList.add('hidden'); | |
| // Enable download and share buttons | |
| downloadBtn.disabled = false; | |
| shareBtn.disabled = false; | |
| // Add to history | |
| addToHistory(prompt, 'https://ilcve21-sparc3d.hf.space'); | |
| } catch (error) { | |
| console.error('Error generating model:', error); | |
| loadingIndicator.classList.add('hidden'); | |
| modelPlaceholder.classList.remove('hidden'); | |
| // Create and show error message | |
| const errorElement = document.createElement('div'); | |
| errorElement.className = 'bg-red-50 border-l-4 border-red-500 p-4 mb-4'; | |
| errorElement.innerHTML = ` | |
| <div class="flex"> | |
| <div class="flex-shrink-0"> | |
| <i class="fas fa-exclamation-circle text-red-500"></i> | |
| </div> | |
| <div class="ml-3"> | |
| <p class="text-sm text-red-700"> | |
| Failed to generate model. Please try again later. | |
| </p> | |
| </div> | |
| </div> | |
| `; | |
| // Insert error message above the model container | |
| modelContainer.insertAdjacentElement('beforebegin', errorElement); | |
| // Remove error after 5 seconds | |
| setTimeout(() => { | |
| errorElement.remove(); | |
| }, 5000); | |
| } | |
| } | |
| // Add generated model to history | |
| function addToHistory(prompt, modelUrl) { | |
| // Remove empty message if it's the first item | |
| if (emptyHistoryMessage) { | |
| emptyHistoryMessage.remove(); | |
| } | |
| const historyItem = document.createElement('div'); | |
| historyItem.className = 'history-item bg-gray-50 rounded-lg p-4 cursor-pointer hover:bg-indigo-50 border border-gray-200'; | |
| historyItem.innerHTML = ` | |
| <div class="flex items-start gap-3"> | |
| <div class="bg-indigo-100 p-2 rounded-lg"> | |
| <i class="fas fa-cube text-indigo-600"></i> | |
| </div> | |
| <div class="flex-1"> | |
| <h4 class="font-medium text-gray-800 line-clamp-1">${prompt}</h4> | |
| <p class="text-xs text-gray-500 mb-2">Just now</p> | |
| <div class="flex gap-2"> | |
| <button class="view-btn text-xs px-3 py-1 bg-indigo-100 text-indigo-700 rounded hover:bg-indigo-200 transition"> | |
| <i class="fas fa-eye mr-1"></i> View | |
| </button> | |
| <button class="download-btn text-xs px-3 py-1 bg-green-100 text-green-700 rounded hover:bg-green-200 transition"> | |
| <i class="fas fa-download mr-1"></i> Download | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| // Add click handlers | |
| const viewBtn = historyItem.querySelector('.view-btn'); | |
| const downloadBtn = historyItem.querySelector('.download-btn'); | |
| viewBtn.addEventListener('click', (e) => { | |
| e.stopPropagation(); | |
| modelPlaceholder.classList.add('hidden'); | |
| modelView.classList.remove('hidden'); | |
| modelView.src = modelUrl; | |
| }); | |
| downloadBtn.addEventListener('click', (e) => { | |
| e.stopPropagation(); | |
| downloadModel(modelUrl, prompt); | |
| }); | |
| historyItem.addEventListener('click', () => { | |
| modelPlaceholder.classList.add('hidden'); | |
| modelView.classList.remove('hidden'); | |
| modelView.src = modelUrl; | |
| }); | |
| // Add to top of history | |
| historyList.insertBefore(historyItem, historyList.firstChild); | |
| } | |
| // Download model function | |
| async function downloadModel(url, prompt) { | |
| try { | |
| const response = await fetch(url); | |
| if (!response.ok) { | |
| throw new Error('Failed to download model'); | |
| } | |
| const blob = await response.blob(); | |
| const downloadUrl = window.URL.createObjectURL(blob); | |
| const link = document.createElement('a'); | |
| link.href = downloadUrl; | |
| link.download = `3d-model-${prompt.substring(0, 20).toLowerCase().replace(/\s+/g, '-')}.glb`; | |
| document.body.appendChild(link); | |
| link.click(); | |
| // Clean up | |
| setTimeout(() => { | |
| document.body.removeChild(link); | |
| window.URL.revokeObjectURL(downloadUrl); | |
| }, 100); | |
| } catch (error) { | |
| console.error('Error downloading model:', error); | |
| alert('Failed to download model. Please try again.'); | |
| } | |
| } | |
| // Share model function | |
| function shareModel() { | |
| if (navigator.share) { | |
| navigator.share({ | |
| title: 'Check out this 3D model I created', | |
| text: `I created a 3D model of "${promptInput.value}" using Sparc3D`, | |
| url: window.location.href, | |
| }) | |
| .catch(err => { | |
| console.error('Error sharing:', err); | |
| }); | |
| } else { | |
| // Fallback for browsers that don't support Web Share API | |
| alert('Web Share API not supported in your browser. Copy this link to share: ' + window.location.href); | |
| } | |
| } | |
| // Get model container element | |
| const modelContainer = document.querySelector('.model-container'); | |
| // Event listeners | |
| generateBtn.addEventListener('click', function() { | |
| // Clear any previous errors | |
| const existingError = document.querySelector('.bg-red-50'); | |
| if (existingError) { | |
| existingError.remove(); | |
| } | |
| const prompt = promptInput.value; | |
| const style = document.getElementById('style').value; | |
| const quality = document.getElementById('quality').value; | |
| const color = document.getElementById('color').value; | |
| generateModel(prompt, style, quality, color); | |
| }); | |
| regenerateBtn.addEventListener('click', function() { | |
| if (!promptInput.value.trim()) { | |
| alert('Please enter a description first'); | |
| return; | |
| } | |
| const prompt = promptInput.value; | |
| const style = document.getElementById('style').value; | |
| const quality = document.getElementById('quality').value; | |
| const color = document.getElementById('color').value; | |
| generateModel(prompt, style, quality, color); | |
| }); | |
| downloadBtn.addEventListener('click', function() { | |
| if (modelView.src) { | |
| const prompt = promptInput.value || 'my-3d-model'; | |
| downloadModel(modelView.src, prompt); | |
| } | |
| }); | |
| shareBtn.addEventListener('click', shareModel); | |
| clearHistoryBtn.addEventListener('click', function() { | |
| if (confirm('Are you sure you want to clear your generation history?')) { | |
| historyList.innerHTML = ` | |
| <div class="text-center py-10 text-gray-400" id="empty-history-message"> | |
| <i class="fas fa-history text-4xl mb-3"></i> | |
| <p>Your generated models will appear here</p> | |
| </div> | |
| `; | |
| } | |
| }); | |
| // Load any saved history from localStorage | |
| function loadHistory() { | |
| // In a real app, you would load from localStorage or a backend | |
| // This is just a placeholder | |
| } | |
| loadHistory(); | |
| // Allow pressing Enter in the prompt input to generate | |
| promptInput.addEventListener('keypress', function(e) { | |
| if (e.key === 'Enter') { | |
| generateBtn.click(); | |
| } | |
| }); | |
| }); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=blacksiders/3dgen" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |