+
SIH Cam
Another project related to the Smart India Hackathon.
@@ -331,12 +357,13 @@
SIH Cam
@@ -728,10 +755,147 @@
Let's work together
});
}
+ // --- 3D Thumbnail Generator for Project/Demo Cards ---
+ function createThumb3D(container, shapeType, accentColor) {
+ if (!container) return;
+
+ const width = container.clientWidth;
+ const height = container.clientHeight;
+
+ // Scene
+ const scene = new THREE.Scene();
+
+ // Camera - adjusted FOV for better fit
+ const camera = new THREE.PerspectiveCamera(50, width / height, 0.1, 1000);
+ camera.position.z = 4;
+
+ // Renderer
+ const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
+ renderer.setSize(width, height);
+ renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
+ container.appendChild(renderer.domElement);
+
+ // Colors - Metallic palette with neon accents
+ const accentHex = accentColor === 'pink' ? 0xec4899 : 0x3b82f6;
+ const metallicColor = 0x9ca3af; // Silver/gray
+
+ // Geometry creation based on shape type
+ let geometry;
+ const scale = 1.2; // Base scale for all objects
+
+ switch(shapeType) {
+ case 'trophy':
+ geometry = new THREE.ConeGeometry(0.8 * scale, 1.4 * scale, 6);
+ break;
+ case 'torus':
+ geometry = new THREE.TorusGeometry(0.7 * scale, 0.25 * scale, 16, 50);
+ break;
+ case 'robot':
+ geometry = new THREE.BoxGeometry(1 * scale, 1.2 * scale, 0.8 * scale);
+ break;
+ case 'octahedron':
+ geometry = new THREE.OctahedronGeometry(0.9 * scale, 0);
+ break;
+ case 'dodecahedron':
+ geometry = new THREE.DodecahedronGeometry(0.85 * scale, 0);
+ break;
+ case 'icosahedron':
+ geometry = new THREE.IcosahedronGeometry(0.9 * scale, 0);
+ break;
+ case 'torusKnot':
+ geometry = new THREE.TorusKnotGeometry(0.5 * scale, 0.18 * scale, 80, 12);
+ break;
+ case 'gear':
+ geometry = new THREE.CylinderGeometry(0.8 * scale, 0.8 * scale, 0.3 * scale, 12);
+ break;
+ default:
+ geometry = new THREE.IcosahedronGeometry(0.9 * scale, 0);
+ }
+
+ // Metallic material for the main object
+ const mainMaterial = new THREE.MeshStandardMaterial({
+ color: metallicColor,
+ metalness: 0.7,
+ roughness: 0.2
+ });
+ const mainMesh = new THREE.Mesh(geometry, mainMaterial);
+ mainMesh.position.set(0, 0, 0);
+ scene.add(mainMesh);
+
+ // Wireframe overlay with accent color
+ const wireframeMaterial = new THREE.MeshBasicMaterial({
+ color: accentHex,
+ wireframe: true,
+ transparent: true,
+ opacity: 0.4
+ });
+ const wireframeMesh = new THREE.Mesh(geometry, wireframeMaterial);
+ wireframeMesh.position.set(0, 0, 0);
+ scene.add(wireframeMesh);
+
+ // Lighting setup
+ const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
+ scene.add(ambientLight);
+
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
+ directionalLight.position.set(2, 3, 4);
+ scene.add(directionalLight);
+
+ // Colored rim light for glow effect
+ const rimLight = new THREE.PointLight(accentHex, 0.6, 10);
+ rimLight.position.set(-2, 1, 2);
+ scene.add(rimLight);
+
+ // Second accent light
+ const secondLight = new THREE.PointLight(accentColor === 'pink' ? 0x3b82f6 : 0xec4899, 0.3, 8);
+ secondLight.position.set(2, -1, 1);
+ scene.add(secondLight);
+
+ // Animation
+ let animationId;
+ function animate() {
+ animationId = requestAnimationFrame(animate);
+ mainMesh.rotation.x += 0.005;
+ mainMesh.rotation.y += 0.008;
+ wireframeMesh.rotation.x += 0.005;
+ wireframeMesh.rotation.y += 0.008;
+ renderer.render(scene, camera);
+ }
+ animate();
+
+ // Store reference for resize handling
+ container._thumbData = { camera, renderer, scene, mainMesh, wireframeMesh };
+ }
+
+ // --- Initialize all 3D Thumbnails ---
+ function initThumbnails() {
+ const thumbContainers = document.querySelectorAll('.threejs-thumb');
+ thumbContainers.forEach(container => {
+ const shape = container.dataset.shape || 'icosahedron';
+ const accent = container.dataset.accent || 'blue';
+ createThumb3D(container, shape, accent);
+ });
+
+ // Handle resize for all thumbnails
+ window.addEventListener('resize', () => {
+ thumbContainers.forEach(container => {
+ if (container._thumbData) {
+ const { camera, renderer } = container._thumbData;
+ const width = container.clientWidth;
+ const height = container.clientHeight;
+ camera.aspect = width / height;
+ camera.updateProjectionMatrix();
+ renderer.setSize(width, height);
+ }
+ });
+ });
+ }
+
// Start everything
initAboutCanvas(); // Initialize the new canvas
initTypingAnimation(); // Start the typing effect
initMobileMenu(); // Initialize the mobile menu
+ initThumbnails(); // Initialize 3D thumbnails
});
From e36332e37af936b0f1a03146859c5d1e68f27beb Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 29 Nov 2025 14:54:59 +0000
Subject: [PATCH 3/4] Address code review: use Map for thumbnail data, add
cleanup function
Co-authored-by: DEFAULTE-R <215202484+DEFAULTE-R@users.noreply.github.com>
---
index.html | 37 ++++++++++++++++++++++++++++++-------
1 file changed, 30 insertions(+), 7 deletions(-)
diff --git a/index.html b/index.html
index e803d52..0941b0f 100644
--- a/index.html
+++ b/index.html
@@ -755,9 +755,12 @@
Let's work together
});
}
+ // --- 3D Thumbnail Data Storage ---
+ const thumbnailDataMap = new Map();
+
// --- 3D Thumbnail Generator for Project/Demo Cards ---
function createThumb3D(container, shapeType, accentColor) {
- if (!container) return;
+ if (!container) return null;
const width = container.clientWidth;
const height = container.clientHeight;
@@ -851,9 +854,12 @@
Let's work together
secondLight.position.set(2, -1, 1);
scene.add(secondLight);
- // Animation
- let animationId;
+ // Animation with cleanup capability
+ let animationId = null;
+ let isAnimating = true;
+
function animate() {
+ if (!isAnimating) return;
animationId = requestAnimationFrame(animate);
mainMesh.rotation.x += 0.005;
mainMesh.rotation.y += 0.008;
@@ -863,8 +869,24 @@
Let's work together
}
animate();
- // Store reference for resize handling
- container._thumbData = { camera, renderer, scene, mainMesh, wireframeMesh };
+ // Cleanup function to stop animation and dispose resources
+ function cleanup() {
+ isAnimating = false;
+ if (animationId !== null) {
+ cancelAnimationFrame(animationId);
+ }
+ geometry.dispose();
+ mainMaterial.dispose();
+ wireframeMaterial.dispose();
+ renderer.dispose();
+ thumbnailDataMap.delete(container);
+ }
+
+ // Store reference in Map for resize handling
+ const thumbData = { camera, renderer, scene, mainMesh, wireframeMesh, cleanup };
+ thumbnailDataMap.set(container, thumbData);
+
+ return thumbData;
}
// --- Initialize all 3D Thumbnails ---
@@ -879,8 +901,9 @@
Let's work together
// Handle resize for all thumbnails
window.addEventListener('resize', () => {
thumbContainers.forEach(container => {
- if (container._thumbData) {
- const { camera, renderer } = container._thumbData;
+ const thumbData = thumbnailDataMap.get(container);
+ if (thumbData) {
+ const { camera, renderer } = thumbData;
const width = container.clientWidth;
const height = container.clientHeight;
camera.aspect = width / height;
From 2523ca78add52e48d18a156985e849d8b11f73d6 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 29 Nov 2025 14:56:24 +0000
Subject: [PATCH 4/4] Add debounced resize handler for better performance
Co-authored-by: DEFAULTE-R <215202484+DEFAULTE-R@users.noreply.github.com>
---
index.html | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/index.html b/index.html
index 0941b0f..b217639 100644
--- a/index.html
+++ b/index.html
@@ -898,8 +898,9 @@
Let's work together
createThumb3D(container, shape, accent);
});
- // Handle resize for all thumbnails
- window.addEventListener('resize', () => {
+ // Debounced resize handler for performance
+ let resizeTimeout;
+ function handleResize() {
thumbContainers.forEach(container => {
const thumbData = thumbnailDataMap.get(container);
if (thumbData) {
@@ -911,6 +912,11 @@
Let's work together
renderer.setSize(width, height);
}
});
+ }
+
+ window.addEventListener('resize', () => {
+ clearTimeout(resizeTimeout);
+ resizeTimeout = setTimeout(handleResize, 150);
});
}