Camera

동일한 장면이라도 카메라의 위치나 각도에 따라 다르게 보일 수 있다.

일반적으로 Perspective(원근감을 제공), Orthographic(원근감이 없음) 을 많이 사용한다.

camera

Perspective - 인간의 시선

Orthographic - 설계도

절두체(Frustum)


두 카메라 모두 절두체라는 개념이 존재한다.

위 그림에서의 Far clip plane과 Near clip plane 까지의 육면체 영역을 절두체라고 한다.

절두체 영역에 있는 것만 렌더링된다.

카메라 생성을 위한 파라메터


camera2

카메라 생성을 위한 파라메터는 절두체를 정의하기 위한 값과 같다.

이전에 만든

<Canvas
  camera={{
    fov: 75,
    position: [7, 7, 0],
  }}
>
  <Light />
</Canvas>

여기서 기본적으로 만드는 카메라는 perspective camera이다.

R3F에서는 Aspect를 Canvas가 렌더링되는 영역의 비율로 자동으로 세팅해준다.

따라서 Fovy, zNear, zFar 만 신경쓰면 된다.

perspective


fov값이 75도라는 것은 화각이 75도라는 것. 단위는 radian이 아닌 degree

화각이 커질 수록 장면이 작게 렌더링된다.(더 멀어진다.)

0에서 180 사이의 값을 가진다.

<Canvas
  camera={{
    fov: 80,
    near: 1,
    far: 20,
    position: [7, 7, 0],
  }}
>
  <Light />
</Canvas>

zNear, zFar 까지 적용하면 이러한 형태이다.

<Canvas
  camera={{
    fov: 80,
    near: 9,
    far: 20,
    position: [7, 7, 0],
  }}
>
  <Light />
</Canvas>

처럼 near값이 커서 물체의 시작 z값보다 뒤로 가게되면 앞부분이 잘리고

반대로 far값이 작아서 물체의 끝 z값보다 앞으로 오게되면 뒷부분이 잘린다.

position


카메라의 위치는 position으로 변경할 수 있고 카메라가 바라보는 위치는 기본적으로 원점이지만 lookAt 메서드로 변경할 수 있다.

const { camera } = useThree();

useControls({
  positionZ: {
    value: 0,
    min: -10,
    max: 10,
    step: 0.1,
    onChange: (v) => (camera.position.z = v),
  },
  targetZ: {
    value: 0,
    min: -10,
    max: 10,
    step: 0.1,
    onChange: (v) => camera.lookAt(0, 0, v),
  },
});

이때 OrbitControls는 카메라를 내부적으로 관리하기 때문에 지워주어야 한다.


카메라의 위치를 움직이는 구에 위치시키기 위해


useFrame에

const target = new THREE.Vector3();
smallSpherePivot.children[0].getWorldPosition(target);
state.camera.position.copy(target);

를 추가한다.

smallSpherePivot.children0의 getWorldPosition(월드 좌표계)를 target에 저장한다.

이때 console.log(target)을 해보면

기본적으로 console.log(target)는 Vector3 {x: 0, y: 0, z: 0} 의 좌표값을 가지지만

smallSpherePivot.children[0].getWorldPosition(target)를 추가하면 {x: -1.1298855050791705, y: 0.5, z: 2.779093151625542}, {x: -1.1051038648272704, y: 0.5, z: 2.7890402377778325}… 으로 프레임마다 구의 좌표을 찍는다.

이후 state.camera.position.copy(target)로 카메라의 position에 복사함으로 카메라의 포지션을 실시간으로 위치가 변하는 구에 위치시킬 수 있다.

카메라가 바라보는 방향을 구가 움직이는 방향으로 바꾸기 위해


구가 이동할 다음 위치를 가져와야하기 때문에 객체를 만들어 준다.

<group name="ghostSpherePivot">
  <object3D position={[3, 0.5, 0]} />
</group>

이때 포지션은 구와 동일해야한다.

또한, useFrame에

const ghostSpherePivot = state.scene.getObjectByName("ghostSpherePivot");
ghostSpherePivot.rotation.y = THREE.MathUtils.degToRad(time * 50 + 35);
ghostSpherePivot.children[0].getWorldPosition(target);
state.camera.lookAt(target);

를 추가한다.

  1. 추가한 객체를 가져오고 const ghostSpherePivot = state.scene.getObjectByName("ghostSpherePivot")
  2. ghostSpherePivot.rotation.y = THREE.MathUtils.degToRad(time * 50 + 35) 구의 움직임과 동일하게 설정하지만 + 35를 해서 각도로를 수정해준다. + 35를 하지 않으면 정면만 보고 구를 따라가기 때문에, 이때 *를 하면 속도가 빨라지고 +를 하면 각도가 달라진다. 이건 무슨 원리인가
  3. ghostSpherePivot.children[0].getWorldPosition(target); ghostSpherePivot의 Vector3 좌표를 가져와서
  4. state.camera.lookAt(target) lookAt 메서드로 바라보는 뱡향을 설정해준다.

이때 앞부분이 좀 잘리는데 near값을 조절하면 된다.

fov를 조절해서 더 넓은 장면이 보이게 할 수 있다.(원룸 크게보이려고 찍은 것같이 됨)



orthographic


  1. 절두체의 너비값을 정의하기 위한 xLeft, xRight
  2. 절두체의 높이값을 정의하기 위한 yTop, yBottom
  3. 절두체의 깂이값을 정의하기 위한 Near, Far
    • Naer은 카메라에서 절두체의 앞부분까지의 거리
    • Far는 카메라에서 절두체의 뒷부분까지의 거리

화면을 벗어나면 렌더링되지 않는다.

R3F에서는 orghographic의 xLeft, xRight, yTop, yBottom을 3차원 장면이 렌더링될 영역에 맞게 자동적으로 설정해준다.

<Canvas
  orthographic
  camera={{
    near: 0.1,
    far: 20,
    zoom: 20,
    position: [7, 7, 0],
  }}
>
  <Light />
</Canvas>

하지만 객체가 너무 멀리보인다. xLeft, xRight, yTop, yBottom를 조절할 수 없으니 zoom이라는 속성을 이용하면된다.

댓글남기기