Last active
July 23, 2025 05:40
-
-
Save kiritocode1/20fdf85eac388f8d785770d7e3716b69 to your computer and use it in GitHub Desktop.
3d scene in VR
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use client"; | |
import React, { useRef, useState, useMemo } from "react"; | |
import { Canvas, useFrame } from "@react-three/fiber"; | |
import { XR, VRButton, useXR, createXRStore } from "@react-three/xr"; | |
import { OrbitControls, Text } from "@react-three/drei"; | |
import { Mesh } from "three"; | |
// Animated cube component | |
function AnimatedCube({ position, color = "orange" }: { position: [number, number, number]; color: string }) { | |
const meshRef = useRef<Mesh>(null); | |
const [hovered, setHovered] = useState(false); | |
const [clicked, setClicked] = useState(false); | |
useFrame((state, delta) => { | |
if (meshRef.current) { | |
meshRef.current.rotation.x += delta * 0.5; | |
meshRef.current.rotation.y += delta * 0.3; | |
meshRef.current.scale.setScalar(clicked ? 1.5 : hovered ? 1.2 : 1); | |
} | |
}); | |
return ( | |
<mesh | |
ref={meshRef} | |
position={position} | |
onPointerOver={() => setHovered(true)} | |
onPointerOut={() => setHovered(false)} | |
onClick={() => setClicked(!clicked)} | |
> | |
<boxGeometry args={[1, 1, 1]} /> | |
<meshStandardMaterial color={hovered ? "hotpink" : color} /> | |
</mesh> | |
); | |
} | |
// Interactive sphere component | |
function InteractiveSphere({ position }: { position: [number, number, number] }) { | |
const [color, setColor] = useState("lightblue"); | |
const colors = ["lightblue", "lightgreen", "lightyellow", "lightcoral", "lightpink"]; | |
const changeColor = () => { | |
const randomColor = colors[Math.floor(Math.random() * colors.length)]; | |
setColor(randomColor); | |
}; | |
return ( | |
<mesh | |
position={position} | |
onClick={changeColor} | |
> | |
<sphereGeometry args={[0.8, 32, 32]} /> | |
<meshStandardMaterial color={color} /> | |
</mesh> | |
); | |
} | |
// VR Scene component | |
function VRScene() { | |
const { session } = useXR(); | |
return ( | |
<> | |
{/* Lighting */} | |
<ambientLight intensity={0.5} /> | |
<pointLight position={[10, 10, 10]} /> | |
<directionalLight | |
position={[-10, -10, -5]} | |
intensity={0.5} | |
/> | |
{/* Interactive objects */} | |
<AnimatedCube | |
position={[-2, 0, -2]} | |
color="orange" | |
/> | |
<AnimatedCube | |
position={[2, 0, -2]} | |
color="purple" | |
/> | |
<InteractiveSphere position={[0, 2, -3]} /> | |
{/* Ground plane */} | |
<mesh | |
rotation={[-Math.PI / 2, 0, 0]} | |
position={[0, -2, 0]} | |
> | |
<planeGeometry args={[20, 20]} /> | |
<meshStandardMaterial color="lightgray" /> | |
</mesh> | |
{/* Welcome text */} | |
<Text | |
position={[0, 3, -4]} | |
fontSize={0.5} | |
color="white" | |
anchorX="center" | |
anchorY="middle" | |
> | |
Welcome to Next.js XR! | |
</Text> | |
<Text | |
position={[0, 2.5, -4]} | |
fontSize={0.3} | |
color="lightblue" | |
anchorX="center" | |
anchorY="middle" | |
> | |
{session ? "You are in VR mode!" : "Click VR button to enter VR"} | |
</Text> | |
{/* VR Controllers */} | |
{/* <Controllers /> */} | |
{/* Desktop orbit controls (disabled in VR) */} | |
{!session && <OrbitControls />} | |
</> | |
); | |
} | |
// Main XR App component | |
export default function XRApp() { | |
const store = useMemo(() => createXRStore(), []); | |
return ( | |
<div style={{ width: "100vw", height: "100vh", background: "#1a1a1a" }}> | |
{/* VR Button */} | |
<div | |
style={{ | |
position: "absolute", | |
top: "20px", | |
left: "20px", | |
zIndex: 100, | |
color: "white", | |
fontFamily: "Arial, sans-serif", | |
}} | |
> | |
<h2>Next.js XR Demo</h2> | |
<p>Use mouse to look around, click objects to interact</p> | |
<VRButton | |
store={store} | |
style={{ | |
background: "#6366f1", | |
color: "white", | |
border: "none", | |
padding: "12px 24px", | |
borderRadius: "8px", | |
cursor: "pointer", | |
fontSize: "16px", | |
fontWeight: "bold", | |
}} | |
/> | |
</div> | |
{/* Instructions */} | |
<div | |
style={{ | |
position: "absolute", | |
bottom: "20px", | |
left: "20px", | |
color: "white", | |
fontFamily: "Arial, sans-serif", | |
fontSize: "14px", | |
maxWidth: "300px", | |
}} | |
> | |
<p> | |
<strong>Desktop:</strong> Click and drag to orbit, scroll to zoom | |
</p> | |
<p> | |
<strong>VR:</strong> Use controllers to interact with objects | |
</p> | |
<p> | |
<strong>Interactions:</strong> Click cubes to scale, click sphere to change color | |
</p> | |
</div> | |
{/* Canvas with XR support */} | |
<Canvas camera={{ position: [0, 0, 5], fov: 60 }}> | |
<XR store={store}> | |
<VRScene /> | |
</XR> | |
</Canvas> | |
</div> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
package.json