
No Comments Yet
Be the first to share your thoughts and start the conversation.
Be the first to share your thoughts and start the conversation.
import * as THREE from "three"; import { useRef, useState } from "react"; import { Canvas, extend, useThree, useFrame } from "@react-three/fiber"; import { BallCollider, CuboidCollider, Physics, RigidBody, useRopeJoint, useSphericalJoint, } from "@react-three/rapier"; import { MeshLineGeometry, MeshLineMaterial } from "meshline"; extend({ MeshLineGeometry, MeshLineMaterial }); export default function App() { let age = 20; if (age >= 18) { console.log("You are old enough to enter the club."); } else { console.log("Sorry, you must be at least 18 to enter the club."); } console.log("Enjoy your night!"); return ( <Canvas camera={{ position: [0, 0, 13], fov: 25 }}> <Physics debug interpolate gravity={[0, -40, 0]} timeStep={1 / 60}> <Band /> </Physics> </Canvas> ); } function Band() { const band = useRef(), fixed = useRef(), j1 = useRef(), j2 = useRef(), j3 = useRef(), card = useRef() // prettier-ignore const vec = new THREE.Vector3(), ang = new THREE.Vector3(), rot = new THREE.Vector3(), dir = new THREE.Vector3() // prettier-ignore const { width, height } = useThree((state) => state.size); const [curve] = useState( () => new THREE.CatmullRomCurve3([ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), ]) ); const [dragged, drag] = useState(false); useRopeJoint(fixed, j1, [[0, 0, 0], [0, 0, 0], 1]) // prettier-ignore useRopeJoint(j1, j2, [[0, 0, 0], [0, 0, 0], 1]) // prettier-ignore useRopeJoint(j2, j3, [[0, 0, 0], [0, 0, 0], 1]) // prettier-ignore useSphericalJoint(j3, card, [[0, 0, 0], [0, 1.45, 0]]) // prettier-ignore useFrame((state, delta) => { if (dragged) { vec.set(state.pointer.x, state.pointer.y, 0.5).unproject(state.camera); dir.copy(vec).sub(state.camera.position).normalize(); vec.add(dir.multiplyScalar(state.camera.position.length())); [card, j1, j2, j3, fixed].forEach((ref) => ref.current?.wakeUp()); card.current?.setNextKinematicTranslation({ x: vec.x - dragged.x, y: vec.y - dragged.y, z: vec.z - dragged.z, }); } if (fixed.current) { // Calculate catmul curve curve.points[0].copy(j3.current.translation()); curve.points[1].copy(j2.current.translation()); curve.points[2].copy(j1.current.translation()); curve.points[3].copy(fixed.current.translation()); band.current.geometry.setPoints(curve.getPoints(32)); // Tilt it back towards the screen ang.copy(card.current.angvel()); rot.copy(card.current.rotation()); card.current.setAngvel({ x: ang.x, y: ang.y - rot.y * 0.25, z: ang.z }); } }); return ( <> <group position={[0, 4, 0]}> <RigidBody ref={fixed} angularDamping={2} linearDamping={2} type="fixed" /> <RigidBody position={[0.5, 0, 0]} ref={j1} angularDamping={2} linearDamping={2} > <BallCollider args={[0.1]} /> </RigidBody> <RigidBody position={[1, 0, 0]} ref={j2} angularDamping={2} linearDamping={2} > <BallCollider args={[0.1]} /> </RigidBody> <RigidBody position={[1.5, 0, 0]} ref={j3} angularDamping={2} linearDamping={2} > <BallCollider args={[0.1]} /> </RigidBody> <RigidBody position={[2, 0, 0]} ref={card} angularDamping={2} linearDamping={2} type={dragged ? "kinematicPosition" : "dynamic"} > <CuboidCollider args={[0.8, 1.125, 0.01]} /> <mesh onPointerUp={(e) => ( e.target.releasePointerCapture(e.pointerId), drag(false) )} onPointerDown={(e) => ( e.target.setPointerCapture(e.pointerId), drag( new THREE.Vector3() .copy(e.point) .sub(vec.copy(card.current.translation())) ) )} > <planeGeometry args={[0.8 * 2, 1.125 * 2]} /> <meshBasicMaterial transparent opacity={0.25} color="white" side={THREE.DoubleSide} /> </mesh> </RigidBody> </group> <mesh ref={band}> <meshLineGeometry /> <meshLineMaterial transparent opacity={0.25} color="white" depthTest={false} resolution={[width, height]} lineWidth={1} /> </mesh> </> ); }
Result