react three.js react-three/cannon

해적왕·2022년 8월 26일
1
post-custom-banner

yarn add @react-three/cannon

import { Canvas } from '@react-three/fiber';
import { Physics, useSphere, usePlane, useBox } from '@react-three/cannon';
import { OrbitControls } from "@react-three/drei";
import { useRef, Suspense } from 'react';

const Ball = ({ position }) => {
  const [ballRef] = useSphere(() => ({ mass: 1, position: position }));
  return (
    <mesh ref={ballRef}>
      <sphereGeometry args={[1, 36, 36]} />
      <meshStandardMaterial roughness={0} color="pink" />
    </mesh>
  )
}

const Ground = (props) => {
  const [ref] = usePlane(() => ({ ...props }));
  return (
    <mesh ref={ref}>
      <planeGeometry args={[100, 100]} />
      <meshStandardMaterial color={"#f8f8f8"} />
    </mesh>
  )
}


const Example = () => {
  return (
    <Canvas
      style={{ height: 600, width: 600 }}
      camera={{ position: [0, 10, 5] }}>
      <color attach="background" args={['pink']} />
      <fog attach="fog" args={['red', 60, 100]} />
      <directionalLight
        position={[0, 5, 5]}/>
      <ambientLight intensity={0.1} />
      <Suspense fallback={null}>
        <Physics>
          <Ball position={[0.5, 7, 0]} />
          <Ball position={[0, 5, 0]} />
          <Ball position={[-0.5, 9, 0]} />
          <Ground rotation={[-Math.PI / 2, 0, 0]} />
        </Physics>
      </Suspense>
      <OrbitControls />
    </Canvas>
  )
}

export default Example;

<Physics>로 감싸주어야 한다.

마우스 효과

import { Canvas, useFrame, useThree } from '@react-three/fiber';
import { OrbitControls } from "@react-three/drei";
import { Suspense } from 'react';
import { Physics, usePlane, useSphere } from "@react-three/cannon";


const InstancedSpheres = ({ count = 200 }) => {
  const { viewport } = useThree();
  const [ref] = useSphere((index) => ({ mass: 100, position: [4 - Math.random() * 8, viewport.height, 0, 0], args: [1.2] }))
  return (
    <instancedMesh ref={ref} castShadow receiveShadow args={[null, null, count]}>
      <sphereBufferGeometry args={[1.2, 62, 62]} />
      <meshStandardMaterial color="#ccf0a4" roughness={0}/>
    </instancedMesh>
  )
}

const Borders = () => {
  const { viewport } = useThree();
  return(
    <>
     <Plane position={[0, -viewport.height / 2, 0]} rotation={[-Math.PI / 2, 0, 0]} />
      <Plane position={[-viewport.width / 2 - 1, 0, 0]} rotation={[0, Math.PI / 2, 0]} />
      <Plane position={[viewport.width / 2 + 1, 0, 0]} rotation={[0, -Math.PI / 2, 0]} />
      <Plane position={[0, 0, 1]} rotation={[0, 0, 0]} />
      <Plane position={[0, 0, 12]} rotation={[0, -Math.PI, 0]} />
    </>
  )
}

const Plane = ({ color, ...props }) => {
  usePlane(() => ({ ...props }))
  return null
}

function Mouse() {
  const { viewport } = useThree()
  const [, api] = useSphere(() => ({ type: "Kinematic", args: [6] }))
  return useFrame((state) => api.position.set((state.mouse.x * viewport.width) / 2, (state.mouse.y * viewport.height) / 2, 7))
}


const Rounded = () => {
  return (
    <Canvas shadows gl={{ stencil: false, antialias: false }} camera={{ position: [0, 0, 20], fov: 50, near: 17, far: 40 }}>
      <fog attach="fog" args={["#a2f14a", 25, 35]} />
      <color attach="background" args={["t"]} />
      <ambientLight intensity={1.5} />
      <directionalLight position={[-10, -10, -5]} intensity={0.5} />
      <directionalLight
        castShadow
        intensity={6}
        position={[50, 50, 25]}
        shadow-mapSize={[256, 256]}
        shadow-camera-left={-10}
        shadow-camera-right={10}
        shadow-camera-top={10}
        shadow-camera-bottom={-10}
      />
      <Suspense fallback={null}>
        <Physics gravity={[0, -50, 0]} defaultContactMaterial={{ restitution: 0.5 }}>
          <group position={[0, 0, -10]}>
            <InstancedSpheres />
            <Borders />
            <Mouse />
          </group>
        </Physics>
      </Suspense>
      <OrbitControls />
    </Canvas>
  )
}

export default Rounded;
profile
프론트엔드
post-custom-banner

0개의 댓글