diff --git a/src/app/gym-3d/page.tsx b/src/app/gym-3d/page.tsx new file mode 100644 index 0000000..aba90f0 --- /dev/null +++ b/src/app/gym-3d/page.tsx @@ -0,0 +1,424 @@ +"use client"; + +import React, { useEffect, useRef, useState } from 'react'; +import * as THREE from 'three'; +import NavbarLayoutFloatingOverlay from '@/components/navbar/NavbarLayoutFloatingOverlay/NavbarLayoutFloatingOverlay'; +import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider"; +import { Zap } from 'lucide-react'; +import Input from '@/components/form/Input'; +import ButtonElasticEffect from '@/components/button/ButtonElasticEffect/ButtonElasticEffect'; + +interface FormData { + name: string; + email: string; + phone: string; + message: string; +} + +export default function Gym3DPage() { + const canvasRef = useRef(null); + const [formData, setFormData] = useState({ + name: '', + email: '', + phone: '', + message: '' + }); + const [submitted, setSubmitted] = useState(false); + + useEffect(() => { + if (!canvasRef.current) return; + + // Scene setup + const scene = new THREE.Scene(); + scene.background = new THREE.Color(0x0a0a0a); + + const camera = new THREE.PerspectiveCamera( + 75, + canvasRef.current.clientWidth / canvasRef.current.clientHeight, + 0.1, + 1000 + ); + camera.position.set(0, 5, 15); + + const renderer = new THREE.WebGLRenderer({ + canvas: canvasRef.current, + antialias: true, + alpha: true, + }); + renderer.setSize(canvasRef.current.clientWidth, canvasRef.current.clientHeight); + renderer.setPixelRatio(window.devicePixelRatio); + renderer.shadowMap.enabled = true; + + // Lighting + const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); + scene.add(ambientLight); + + const directionalLight = new THREE.DirectionalLight(0xffff00, 1); + directionalLight.position.set(10, 20, 10); + directionalLight.castShadow = true; + directionalLight.shadow.mapSize.width = 2048; + directionalLight.shadow.mapSize.height = 2048; + scene.add(directionalLight); + + const pointLight = new THREE.PointLight(0xff6b00, 0.8); + pointLight.position.set(-10, 10, -10); + scene.add(pointLight); + + // Gym floor + const floorGeometry = new THREE.PlaneGeometry(40, 40); + const floorMaterial = new THREE.MeshStandardMaterial({ + color: 0x1a1a1a, + roughness: 0.8, + metalness: 0.1, + }); + const floor = new THREE.Mesh(floorGeometry, floorMaterial); + floor.rotation.x = -Math.PI / 2; + floor.receiveShadow = true; + scene.add(floor); + + // Walls + const wallMaterial = new THREE.MeshStandardMaterial({ + color: 0x1a1a1a, + roughness: 0.9, + }); + + const backWallGeometry = new THREE.PlaneGeometry(40, 20); + const backWall = new THREE.Mesh(backWallGeometry, wallMaterial); + backWall.position.z = -20; + backWall.position.y = 10; + backWall.receiveShadow = true; + scene.add(backWall); + + const leftWallGeometry = new THREE.PlaneGeometry(40, 20); + const leftWall = new THREE.Mesh(leftWallGeometry, wallMaterial); + leftWall.rotation.y = Math.PI / 2; + leftWall.position.x = -20; + leftWall.position.y = 10; + leftWall.receiveShadow = true; + scene.add(leftWall); + + // Power racks + const createPowerRack = (x: number, z: number) => { + const rackGroup = new THREE.Group(); + + const tubeMaterial = new THREE.MeshStandardMaterial({ + color: 0x333333, + metalness: 0.7, + roughness: 0.3, + }); + + // Vertical posts + const postGeometry = new THREE.BoxGeometry(0.1, 3, 0.1); + for (let i = 0; i < 4; i++) { + const post = new THREE.Mesh(postGeometry, tubeMaterial); + const offsetX = i % 2 === 0 ? -0.5 : 0.5; + const offsetZ = i < 2 ? -0.5 : 0.5; + post.position.set(offsetX, 1.5, offsetZ); + post.castShadow = true; + post.receiveShadow = true; + rackGroup.add(post); + } + + // Horizontal bars + const barGeometry = new THREE.BoxGeometry(1.2, 0.08, 1.2); + const bar = new THREE.Mesh(barGeometry, tubeMaterial); + bar.position.y = 2.5; + bar.castShadow = true; + bar.receiveShadow = true; + rackGroup.add(bar); + + rackGroup.position.set(x, 0, z); + return rackGroup; + }; + + scene.add(createPowerRack(-8, -5)); + scene.add(createPowerRack(8, -5)); + scene.add(createPowerRack(-8, 5)); + scene.add(createPowerRack(8, 5)); + + // Dumbbells + const createDumbbell = (x: number, z: number) => { + const group = new THREE.Group(); + const handleMaterial = new THREE.MeshStandardMaterial({ + color: 0xffff00, + metalness: 0.8, + roughness: 0.2, + }); + + const handle = new THREE.Mesh(new THREE.CylinderGeometry(0.05, 0.05, 0.3), handleMaterial); + handle.castShadow = true; + handle.receiveShadow = true; + group.add(handle); + + const weightMaterial = new THREE.MeshStandardMaterial({ + color: 0xff6b00, + metalness: 0.9, + roughness: 0.1, + }); + + const weight1 = new THREE.Mesh(new THREE.SphereGeometry(0.15, 16, 16), weightMaterial); + weight1.position.z = 0.2; + weight1.castShadow = true; + weight1.receiveShadow = true; + group.add(weight1); + + const weight2 = new THREE.Mesh(new THREE.SphereGeometry(0.15, 16, 16), weightMaterial); + weight2.position.z = -0.2; + weight2.castShadow = true; + weight2.receiveShadow = true; + group.add(weight2); + + group.position.set(x, 0.5, z); + return group; + }; + + scene.add(createDumbbell(-12, 0)); + scene.add(createDumbbell(-10, 0)); + scene.add(createDumbbell(10, 0)); + scene.add(createDumbbell(12, 0)); + + // Barbells on stands + const createBarbell = (x: number, z: number) => { + const group = new THREE.Group(); + + const barMaterial = new THREE.MeshStandardMaterial({ + color: 0xffff00, + metalness: 0.9, + roughness: 0.1, + }); + + const bar = new THREE.Mesh(new THREE.CylinderGeometry(0.08, 0.08, 2), barMaterial); + bar.rotation.z = Math.PI / 2; + bar.castShadow = true; + bar.receiveShadow = true; + group.add(bar); + + const plateMaterial = new THREE.MeshStandardMaterial({ + color: 0xff0000, + metalness: 0.7, + roughness: 0.3, + }); + + for (let i = 0; i < 4; i++) { + const plate = new THREE.Mesh(new THREE.CylinderGeometry(0.35, 0.35, 0.05), plateMaterial); + plate.position.z = (i - 1.5) * 0.2; + plate.rotation.z = Math.PI / 2; + plate.castShadow = true; + plate.receiveShadow = true; + group.add(plate); + } + + group.position.set(x, 1, z); + return group; + }; + + scene.add(createBarbell(0, -8)); + scene.add(createBarbell(0, 8)); + + // Rowing machines + const createRowingMachine = (x: number, z: number) => { + const group = new THREE.Group(); + + const frameMaterial = new THREE.MeshStandardMaterial({ + color: 0x333333, + metalness: 0.6, + roughness: 0.4, + }); + + const base = new THREE.Mesh(new THREE.BoxGeometry(0.8, 0.2, 2), frameMaterial); + base.castShadow = true; + base.receiveShadow = true; + group.add(base); + + const seat = new THREE.Mesh(new THREE.BoxGeometry(0.6, 0.3, 0.4), frameMaterial); + seat.position.set(0, 0.5, -0.3); + seat.castShadow = true; + seat.receiveShadow = true; + group.add(seat); + + const handle = new THREE.Mesh(new THREE.BoxGeometry(0.6, 0.1, 0.1), frameMaterial); + handle.position.set(0, 0.7, 0.6); + handle.castShadow = true; + handle.receiveShadow = true; + group.add(handle); + + group.position.set(x, 0, z); + return group; + }; + + scene.add(createRowingMachine(-5, 12)); + scene.add(createRowingMachine(5, 12)); + + // Animation + let animationFrameId: number; + const animate = () => { + animationFrameId = requestAnimationFrame(animate); + + // Rotate scene slightly + scene.rotation.y += 0.0003; + + renderer.render(scene, camera); + }; + + animate(); + + // Handle window resize + const handleResize = () => { + if (!canvasRef.current) return; + const width = canvasRef.current.clientWidth; + const height = canvasRef.current.clientHeight; + camera.aspect = width / height; + camera.updateProjectionMatrix(); + renderer.setSize(width, height); + }; + + window.addEventListener('resize', handleResize); + + return () => { + window.removeEventListener('resize', handleResize); + cancelAnimationFrame(animationFrameId); + renderer.dispose(); + }; + }, []); + + const handleInputChange = (field: keyof FormData, value: string) => { + setFormData(prev => ({ + ...prev, + [field]: value + })); + }; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + console.log('Form submitted:', formData); + setSubmitted(true); + setFormData({ name: '', email: '', phone: '', message: '' }); + setTimeout(() => setSubmitted(false), 3000); + }; + + return ( + + + +
+ {/* 3D Gym Viewer */} +
+
+
+

Tour Our 3D Gym

+

Explore Iron Pulse's state-of-the-art facility

+

Use your mouse to rotate and explore. Scroll to zoom.

+
+ +
+ +
+
+
+ + {/* Contact Form */} +
+
+
+

+ + Contattaci +

+

Siamo pronti a rispondere a tutte le tue domande sulla nostra palestra 3D e i nostri servizi

+
+ +
+
+ + handleInputChange('name', value)} + type="text" + placeholder="Il tuo nome" + required + className="w-full" + /> +
+ +
+ + handleInputChange('email', value)} + type="email" + placeholder="La tua email" + required + className="w-full" + /> +
+ +
+ + handleInputChange('phone', value)} + type="tel" + placeholder="Il tuo numero di telefono" + className="w-full" + /> +
+ +
+ +