// Main application logic
document.addEventListener('DOMContentLoaded', function() {
// Style selection
const styleButtons = document.querySelectorAll('.style-btn');
let selectedStyle = 'realistic';
styleButtons.forEach(btn => {
btn.addEventListener('click', () => {
styleButtons.forEach(b => b.classList.remove('active'));
btn.classList.add('active');
selectedStyle = btn.dataset.style;
});
});
// Set default active style
document.querySelector('[data-style="realistic"]').classList.add('active');
// Generate button functionality
const generateBtn = document.getElementById('generate-btn');
const textInput = document.getElementById('text-input');
const progressContainer = document.getElementById('progress-container');
const progressBar = document.getElementById('progress-bar');
const progressPercent = document.getElementById('progress-percent');
const previewContainer = document.getElementById('preview-container');
const canvas = document.getElementById('3d-canvas');
const actionButtons = document.getElementById('action-buttons');
const renderTime = document.getElementById('render-time');
generateBtn.addEventListener('click', async () => {
const text = textInput.value.trim();
if (!text) {
showNotification('Please enter a description for your 3D design', 'warning');
return;
}
// Show progress
progressContainer.classList.remove('hidden');
generateBtn.disabled = true;
generateBtn.classList.add('opacity-50', 'cursor-not-allowed');
// Simulate generation progress
let progress = 0;
const startTime = Date.now();
const progressInterval = setInterval(() => {
progress += Math.random() * 15;
if (progress > 90) progress = 90;
progressBar.style.width = `${progress}%`;
progressPercent.textContent = `${Math.round(progress)}%`;
}, 200);
// Simulate API call
setTimeout(() => {
clearInterval(progressInterval);
progressBar.style.width = '100%';
progressPercent.textContent = '100%';
// Generate 3D visualization
generate3DVisualization(text, selectedStyle);
// Calculate render time
const endTime = Date.now();
const renderDuration = ((endTime - startTime) / 1000).toFixed(1);
renderTime.textContent = `Rendered in ${renderDuration}s`;
// Show result
setTimeout(() => {
progressContainer.classList.add('hidden');
generateBtn.disabled = false;
generateBtn.classList.remove('opacity-50', 'cursor-not-allowed');
actionButtons.classList.remove('hidden');
canvas.classList.remove('hidden');
previewContainer.querySelector('.text-center').classList.add('hidden');
// Add to recent creations
addToRecentCreations(text);
}, 500);
}, 3000);
});
// Enhanced 3D Visualization
function generate3DVisualization(description, style) {
const ctx = canvas.getContext('2d');
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
// Store the visualization data for animation
canvas.dataset.description = description;
canvas.dataset.style = style;
canvas.dataset.rotation = '0';
draw3DModel(ctx, canvas.width, canvas.height, style, 0);
}
function draw3DModel(ctx, width, height, style, rotation) {
// Clear canvas
ctx.clearRect(0, 0, width, height);
// Create gradient background based on style
let gradient;
switch(style) {
case 'cartoon':
gradient = ctx.createLinearGradient(0, 0, width, height);
gradient.addColorStop(0, '#fef3c7');
gradient.addColorStop(0.5, '#fed7aa');
gradient.addColorStop(1, '#fbbf24');
break;
case 'minimalist':
gradient = ctx.createLinearGradient(0, 0, width, height);
gradient.addColorStop(0, '#f3f4f6');
gradient.addColorStop(0.5, '#e5e7eb');
gradient.addColorStop(1, '#d1d5db');
break;
case 'fantasy':
gradient = ctx.createRadialGradient(width/2, height/2, 0, width/2, height/2, width/2);
gradient.addColorStop(0, '#ddd6fe');
gradient.addColorStop(0.3, '#f9a8d4');
gradient.addColorStop(0.6, '#c084fc');
gradient.addColorStop(1, '#818cf8');
break;
default: // realistic
gradient = ctx.createLinearGradient(0, 0, width, height);
gradient.addColorStop(0, '#0f172a');
gradient.addColorStop(0.5, '#1e293b');
gradient.addColorStop(1, '#334155');
}
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, height);
// Add grid for depth perception
ctx.strokeStyle = style === 'minimalist' ? 'rgba(0, 0, 0, 0.1)' : 'rgba(255, 255, 255, 0.05)';
ctx.lineWidth = 1;
const gridSize = 30;
for (let x = 0; x <= width; x += gridSize) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, height);
ctx.stroke();
}
for (let y = 0; y <= height; y += gridSize) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(width, y);
ctx.stroke();
}
const centerX = width / 2;
const centerY = height / 2;
// Main 3D object - More complex and realistic
ctx.save();
ctx.translate(centerX, centerY);
// Rotate the entire scene
ctx.rotate(rotation);
// Draw 3D cube with proper perspective
const size = 100;
const depth = 60;
// Back faces (darker)
ctx.fillStyle = style === 'cartoon' ? 'rgba(251, 191, 36, 0.4)' :
style === 'minimalist' ? 'rgba(156, 163, 175, 0.3)' :
style === 'fantasy' ? 'rgba(168, 85, 247, 0.4)' :
'rgba(14, 165, 233, 0.3)';
ctx.strokeStyle = style === 'cartoon' ? 'rgba(251, 191, 36, 0.8)' :
style === 'minimalist' ? 'rgba(75, 85, 99, 0.8)' :
style === 'fantasy' ? 'rgba(168, 85, 247, 0.8)' :
'rgba(14, 165, 233, 0.8)';
ctx.lineWidth = 2;
// Back face
ctx.beginPath();
ctx.rect(-size/2 - depth/3, -size/2 - depth/3, size, size);
ctx.fill();
ctx.stroke();
// Side faces
ctx.fillStyle = style === 'cartoon' ? 'rgba(251, 191, 36, 0.5)' :
style === 'minimalist' ? 'rgba(156, 163, 175, 0.4)' :
style === 'fantasy' ? 'rgba(236, 72, 153, 0.5)' :
'rgba(217, 70, 239, 0.4)';
// Right face
ctx.beginPath();
ctx.moveTo(size/2, -size/2);
ctx.lineTo(size/2 + depth/3, -size/2 - depth/3);
ctx.lineTo(size/2 + depth/3, size/2 - depth/3);
ctx.lineTo(size/2, size/2);
ctx.closePath();
ctx.fill();
ctx.stroke();
// Top face
ctx.beginPath();
ctx.moveTo(-size/2, -size/2);
ctx.lineTo(-size/2 - depth/3, -size/2 - depth/3);
ctx.lineTo(size/2 - depth/3, -size/2 - depth/3);
ctx.lineTo(size/2, -size/2);
ctx.closePath();
ctx.fill();
ctx.stroke();
// Front face (brightest)
ctx.fillStyle = style === 'cartoon' ? 'rgba(251, 191, 36, 0.7)' :
style === 'minimalist' ? 'rgba(156, 163, 175, 0.6)' :
style === 'fantasy' ? 'rgba(236, 72, 153, 0.7)' :
'rgba(14, 165, 233, 0.6)';
ctx.beginPath();
ctx.rect(-size/2, -size/2, size, size);
ctx.fill();
ctx.stroke();
// Add decorative elements based on style
if (style === 'fantasy') {
// Add sparkles
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
for (let i = 0; i < 5; i++) {
const sparkleX = (Math.random() - 0.5) * size * 1.5;
const sparkleY = (Math.random() - 0.5) * size * 1.5;
const sparkleSize = Math.random() * 3 + 1;
ctx.beginPath();
ctx.arc(sparkleX, sparkleY, sparkleSize, 0, Math.PI * 2);
ctx.fill();
}
} else if (style === 'cartoon') {
// Add cartoon eyes
ctx.fillStyle = 'white';
ctx.beginPath();
ctx.arc(-20, -10, 12, 0, Math.PI * 2);
ctx.arc(20, -10, 12, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = 'black';
ctx.beginPath();
ctx.arc(-20, -10, 6, 0, Math.PI * 2);
ctx.arc(20, -10, 6, 0, Math.PI * 2);
ctx.fill();
}
ctx.restore();
// Add shadow
ctx.save();
ctx.translate(centerX, centerY + 100);
ctx.scale(1, 0.3);
ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';
ctx.beginPath();
ctx.ellipse(0, 0, size/2, size/4, 0, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
// Add text overlay
ctx.fillStyle = style === 'minimalist' ? 'rgba(0, 0, 0, 0.7)' : 'rgba(255, 255, 255, 0.9)';
ctx.font = 'bold 14px sans-serif';
ctx.textAlign = 'center';
ctx.fillText('3D Model Generated!', centerX, height - 20);
}
// Add to recent creations
function addToRecentCreations(description) {
const recentContainer = document.getElementById('recent-creations');
const newItem = document.createElement('div');
newItem.className = 'bg-gray-800/50 rounded-lg overflow-hidden hover:scale-105 transition-transform duration-300 cursor-pointer opacity-0';
const randomSeed = Math.floor(Math.random() * 100);
newItem.innerHTML = `
${description.substring(0, 30)}${description.length > 30 ? '...' : ''}
Just now