From 9524e66ac25882138376217809b41afee6340c67 Mon Sep 17 00:00:00 2001 From: bender Date: Wed, 4 Mar 2026 18:42:06 +0000 Subject: [PATCH 1/3] Add src/app/gym-3d/page.tsx --- src/app/gym-3d/page.tsx | 320 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 320 insertions(+) create mode 100644 src/app/gym-3d/page.tsx diff --git a/src/app/gym-3d/page.tsx b/src/app/gym-3d/page.tsx new file mode 100644 index 0000000..b08cdf2 --- /dev/null +++ b/src/app/gym-3d/page.tsx @@ -0,0 +1,320 @@ +"use client"; + +import { useEffect, useRef, useState } from "react"; +import NavbarLayoutFloatingOverlay from '@/components/navbar/NavbarLayoutFloatingOverlay/NavbarLayoutFloatingOverlay'; +import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider"; +import { Mail, Send } from 'lucide-react'; + +declare global { + namespace JSX { + interface IntrinsicElements { + canvas: React.CanvasHTMLAttributes; + } + } +} + +export default function Gym3D() { + const canvasRef = useRef(null); + const [formData, setFormData] = useState({ name: "", email: "", message: "" }); + const [submitted, setSubmitted] = useState(false); + + useEffect(() => { + const loadThree = async () => { + const THREE = (await import("three")).default; + const { GLTFLoader } = await import("three/examples/jsm/loaders/GLTFLoader.js"); + const { OrbitControls } = await import("three/examples/jsm/controls/OrbitControls.js"); + + if (!canvasRef.current) return; + + const scene = new THREE.Scene(); + scene.background = new THREE.Color(0x0a0a0a); + scene.fog = new THREE.Fog(0x0a0a0a, 50, 200); + + const camera = new THREE.PerspectiveCamera( + 75, + canvasRef.current.clientWidth / canvasRef.current.clientHeight, + 0.1, + 1000 + ); + camera.position.set(20, 15, 20); + + const renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize(canvasRef.current.clientWidth, canvasRef.current.clientHeight); + renderer.shadowMap.enabled = true; + canvasRef.current.appendChild(renderer.domElement); + + // Lighting + const ambientLight = new THREE.AmbientLight(0xffff00, 0.6); + scene.add(ambientLight); + + const directionalLight = new THREE.DirectionalLight(0xffff00, 0.8); + directionalLight.position.set(30, 30, 20); + directionalLight.castShadow = true; + directionalLight.shadow.mapSize.width = 2048; + directionalLight.shadow.mapSize.height = 2048; + scene.add(directionalLight); + + // Floor + const floorGeometry = new THREE.PlaneGeometry(50, 50); + const floorMaterial = new THREE.MeshStandardMaterial({ color: 0x1a1a1a }); + const floor = new THREE.Mesh(floorGeometry, floorMaterial); + floor.rotation.x = -Math.PI / 2; + floor.receiveShadow = true; + scene.add(floor); + + // Gym Equipment - Barbells + const barlbellGeometry = new THREE.CylinderGeometry(0.2, 0.2, 2, 16); + const barMaterial = new THREE.MeshStandardMaterial({ color: 0xffff00, metalness: 0.8, roughness: 0.2 }); + const barbell1 = new THREE.Mesh(barlbellGeometry, barMaterial); + barbell1.position.set(-10, 1, 0); + barbell1.rotation.z = Math.PI / 2; + barbell1.castShadow = true; + scene.add(barbell1); + + const barbell2 = new THREE.Mesh(barlbellGeometry, barMaterial); + barbell2.position.set(-5, 1, 0); + barbell2.rotation.z = Math.PI / 2; + barbell2.castShadow = true; + scene.add(barbell2); + + const barbell3 = new THREE.Mesh(barlbellGeometry, barMaterial); + barbell3.position.set(0, 1, 0); + barbell3.rotation.z = Math.PI / 2; + barbell3.castShadow = true; + scene.add(barbell3); + + // Dumbbells + const dumbellBallGeometry = new THREE.SphereGeometry(0.3, 16, 16); + const dumbellMaterial = new THREE.MeshStandardMaterial({ color: 0x1a1a1a, metalness: 0.6 }); + for (let i = 0; i < 6; i++) { + const dumbbell1 = new THREE.Mesh(dumbellBallGeometry, dumbellMaterial); + dumbbell1.position.set(-15 + i * 3, 0.5, -5); + dumbbell1.castShadow = true; + scene.add(dumbbell1); + + const dumbbell2 = new THREE.Mesh(dumbellBallGeometry, dumbellMaterial); + dumbbell2.position.set(-15 + i * 3, 0.5, 5); + dumbbell2.castShadow = true; + scene.add(dumbbell2); + } + + // Pull-up Bar / Rig + const rigFrameGeometry = new THREE.BoxGeometry(15, 0.3, 0.3); + const rigMaterial = new THREE.MeshStandardMaterial({ color: 0xffff00, metalness: 0.7 }); + const rigBar = new THREE.Mesh(rigFrameGeometry, rigMaterial); + rigBar.position.set(0, 10, -8); + rigBar.castShadow = true; + scene.add(rigBar); + + // Supports for rig + const supportGeometry = new THREE.CylinderGeometry(0.2, 0.2, 10, 16); + const support1 = new THREE.Mesh(supportGeometry, rigMaterial); + support1.position.set(-7, 5, -8); + support1.castShadow = true; + scene.add(support1); + + const support2 = new THREE.Mesh(supportGeometry, rigMaterial); + support2.position.set(7, 5, -8); + support2.castShadow = true; + scene.add(support2); + + // Rowing Machine + const rowingBaseGeometry = new THREE.BoxGeometry(2, 0.5, 1); + const rowingMaterial = new THREE.MeshStandardMaterial({ color: 0x333333 }); + const rowingBase = new THREE.Mesh(rowingBaseGeometry, rowingMaterial); + rowingBase.position.set(10, 0.25, 0); + rowingBase.castShadow = true; + scene.add(rowingBase); + + const rowingSeatGeometry = new THREE.BoxGeometry(0.5, 1, 0.8); + const rowingSeat = new THREE.Mesh(rowingSeatGeometry, rowingMaterial); + rowingSeat.position.set(10, 1.3, 0); + rowingSeat.castShadow = true; + scene.add(rowingSeat); + + // Gym Walls + const wallGeometry = new THREE.BoxGeometry(50, 15, 0.5); + const wallMaterial = new THREE.MeshStandardMaterial({ color: 0x2a2a2a }); + + const backWall = new THREE.Mesh(wallGeometry, wallMaterial); + backWall.position.set(0, 7.5, -25); + scene.add(backWall); + + const sideWall = new THREE.Mesh( + new THREE.BoxGeometry(0.5, 15, 50), + wallMaterial + ); + sideWall.position.set(-25, 7.5, 0); + scene.add(sideWall); + + // Controls + const controls = new OrbitControls(camera, renderer.domElement); + controls.enableDamping = true; + controls.dampingFactor = 0.05; + controls.autoRotate = true; + controls.autoRotateSpeed = 2; + + const animate = () => { + requestAnimationFrame(animate); + controls.update(); + renderer.render(scene, camera); + }; + animate(); + + // Handle 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); + canvasRef.current?.removeChild(renderer.domElement); + }; + }; + + loadThree(); + }, []); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + setSubmitted(true); + setFormData({ name: "", email: "", message: "" }); + setTimeout(() => setSubmitted(false), 3000); + }; + + return ( + + + +
+
+
+

Tour Our 3D Gym

+

Explore Iron Pulse's state-of-the-art facility from every angle

+
+ +
+ +
+ +
+
+

Gym Features

+
    +
  • + + Olympic Barbells & Competition Platforms +
  • +
  • + + Complete Gymnastics Rig with Rings & Pull-up Bars +
  • +
  • + + Full Set of Competition Dumbbells (5 lbs to 150 lbs) +
  • +
  • + + Cardio Equipment: Rowing Machines & Bikes +
  • +
  • + + Strength Training: Power Racks & Benches +
  • +
  • + + Climate Controlled & Fully Equipped Locker Rooms +
  • +
+
+ +
+

+ + Contact Us +

+
+
+ + setFormData({ ...formData, name: e.target.value })} + className="w-full bg-black/50 border border-yellow-400/30 rounded px-4 py-2 text-white placeholder-gray-500 focus:outline-none focus:border-yellow-400 transition" + placeholder="Your name" + required + /> +
+
+ + setFormData({ ...formData, email: e.target.value })} + className="w-full bg-black/50 border border-yellow-400/30 rounded px-4 py-2 text-white placeholder-gray-500 focus:outline-none focus:border-yellow-400 transition" + placeholder="your@email.com" + required + /> +
+
+ +