# Camera

## Camera

> 3D 객체가 담긴 장면을 바라보는 역할을 담당

```typescript
const camera = new THREE.PerspectiveCamera(fov, aspect ratio, near, far);
```

* **Fov(시야각)**: 값이 클수록 시야각이 커지며 담는 범위가 늘어난다. 일반적으로 사용되는 값은 45 또는 75이다.&#x20;
* **Aspect ratio(종횡비)**: 일반적으로 화면의 너비를 높이로 나누다.
* **Near(가시 근거리)**: 근거리 범위보다 앞에 있는 경우 렌더링 계산이 이루어지지 않음,  일반적으로 0.1 값이 설정된다.
* **Far(가시 원거리)**: 원거리 범위보다 뒤에 있는 경우 렌더링 계산이 이루어지지 않음

{% hint style="warning" %}
3D 객체를 보기에 적합한 각도를 찾는것은 어렵고도 중요한 작업
{% endhint %}

### Method

* **updateProjectionMatrix** → 카메라의 시야각, 종횡비, 줌 등 모든 속성이 변경되면 반드시 해당 메서드를 호출해주어야 반영이 된다.

### Built In Camera

* **PerspectiveCamera** → 사람이의 눈이 바라보는 방식과 비슷하게 원근감을 구현한 카메라, 3D의 대부분은 해당 카메라를 사용한다.&#x20;
* **OrthographicCamera** → `PerspectiveCamera` 와 달리 원근감이 제거된 카메라, 물체와 카메라 사이의 거리에 상관없이 물체의 크기가 동일, 주로 전략시뮬레이션 게임에서 사용된다.
* **ArrayCamera** → 여러 카메라 시점을 렌더링하며, 멀티플레이어 게임과 같이 분할 화면 디스플레이에서 여러 대의 카메라를 보는 것과 비슷하다.
* **StereoCamera** → VR / 3D 안경으로 만 볼 수있는 입체 효과를 가진 장면을 쉽게 렌더링 할 수 있다.
* **CubeCamera** → 현재 보고있는 장면을 실시간으로 6면 이미지로 렌더링하며, 거울과 같은 반사 효과를 만드는데 사용된다.

## Camera Type <a href="#id-3e60" id="id-3e60"></a>

<figure><img src="https://1912740209-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3GVYdZvmqQyBVq29ebqk%2Fuploads%2FVrCunWhsdpVFwztB4Nee%2Fcamera%20type.png?alt=media&#x26;token=7aae3d00-9b7a-42a6-bacf-1eb6241ae06e" alt=""><figcaption></figcaption></figure>

### Perspective Camera <a href="#id-3e60" id="id-3e60"></a>

* 우리가 흔히 생각하는 일반적인 카메라
* 오브젝트들이 원근감있게 표시된다.

### Orthographic Camera

* 오브젝트들이 원근감없이 똑같은 크기로 보이게 된다.
* 화면을 2D 형태로 관찰한다.
* 2D 카메라이기 때문에 각도가 없어 `fov`를 사용하지 않고 `zoom`으로 거리를 조절한다.

## Camera Controls <a href="#id-3e60" id="id-3e60"></a>

> 3D 공간을 탐색하기 위한 카메라를 제어하는 역할  ,각 컨트롤러는 주로 특정한 사용 사례에 맞게 설계됨

### Built In Controls

{% hint style="warning" %}
**`Built In Controls`**&#xB294; 내장 기능이라기보다는 에드온과같은 보조적인 기능으로 별도로 임포트를 추가해줘야 한다.
{% endhint %}

* **ArcballControls** → 객체는 고정된 상태로 마우스 드래그를 통해 카메라를 회전시켜 객체 주변을 다양한 각도로 탐색한다.&#x20;
* **TrackballControls** → `ArcballControls` 와 유사하지만 더 자유롭다. 마우스 드래그를 통해 카메라를 회전 및 이동시켜 3D 공간을 탐색
* **FlyControls** → 이름 그대로 비행 즉, 카메라를 자유롭게 이동하여 탐색
* **FirstPersonControls** → `FlyControls`와 비슷하며, 사람이 움직이는 것과 유사한 효과를 갖는다.
* **PointerLockControls** → 카메라가 FPS 게임처럼 마우스 이동 이벤트를 따라 회전, 1인칭 3D 게임에 적합하다.
* **OrbitControls** → 카메라가 대상 물체의 주변을 궤도를 그려 탐색한다.&#x20;

{% hint style="info" %}
**Controls**에는 camera를 제어하는 것 뿐만 아니라 다양한 인터렉션을 추가할 수 있는 옵션들이 있다. \
ex:**`DragControls`**, **`TransformControls`,  `MapControls`** 등,
{% endhint %}

### Options

* `autoRotate` → 드래그하지 않아도 대상 주변을 자동으로 회전시킨다.&#x20;
* `enableDamping` → 드래그시 회전을 멈추지않고 관성을 유지
* `dampingFactor` → 관성의 정도 값 설정 (defualt: 0.05, 값이 작을수록 관성을 더 오래 유지함)
* `enableZoom` → 카메라 줌인(앞, 뒤) 가능 여부 설정 (default: true)
* `minDistance` → 카메라가 이동할 수 있는 최소 거리 설정
* `maxDistance` → 카메라가 이동할 수 있는 최대 거리 설정
* `enablePan` → 카메라 좌우 이동 가능 여부 설정 (default: true)
* `minPolarAngle` → 카메라를 수직방향으로 회전할 수 있는 최소 각도
* `maxPolarAngle` → 카메라를 수직방향으로 회전할 수 있는 최대 각도
* `minAzimuthAngle` → 카메라를 수평방향으로 회전할 수 있는 최소 각도
* `maxAzimuthAngle` → 카메라를 수평방향으로 회전할 수 있는 최대 각도

{% hint style="danger" %}
**controls** 옵션의 변경시켜 카메라를 제어한다면 애니메이션 루프내에서 **`update`** 메서드를 호출시켜줘야 정상적으로 반영된다.
{% endhint %}

### OrbitControls

> 마우스나 터치로 3D 공간을 회전 및 이동할 수 있게 해주는 컨트롤러

* 현재  카메라를 중심으로 상하좌우로 뷰를 회전하거나, 확대 축소가 가능하다.

### AxisHelper

> 3D 공간에서 좌표축(X, Y, Z)축을 시각적으로 표시

### GridHelper&#x20;

> 3D 공간 바닥에 특정 단위(default Meter)로 정렬된 격자를 표시&#x20;

* 3D 공간에서 객체의 Transform을 시각적으로 파악할 때 유용

{% hint style="info" %}
`axisHelper`, `gridHelper` 를 통해 내가 보고 있는 3D 공간이 얼마만큼의 규격으로 렌더링되고있는지 파악할 수 있다.
{% endhint %}

### GUI Control

> 옵션이나 속성을 변경하고 확인할 때 코드를 직접 수정하고 확인하는 번거로움을 줄이기 위해 GUI 컨트롤 패널을 이용하여 값을 변경해보자.&#x20;

```bash
npm i lil-gui
```

![](https://1912740209-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3GVYdZvmqQyBVq29ebqk%2Fuploads%2FwQ54KPfMrueelkM4aToX%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202023-09-03%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.09.17.png?alt=media\&token=30a3b1c3-f996-4048-a57a-773e6993c156)

```javascript
import GUI from 'lil-gui';

const gui = new GUI();
// 값의 최소, 최대 값을 설정하면 컨트롤러가 슬라이더로 변한다.
gui.add(object, property, min, max, step);
// 변경하고자 하는 객체, 변경하고자 하는 프로퍼티, 값의 최소 범위, 값의 최대 범위, 값 조절 단위
// 메서드 체이닝을 통해 좀 더 읽기 쉬운 코드로 설정 가능
gui.add(cube.position, 'y').min(-3).max(3).step(0.1)
```

{% hint style="info" %}
**`lil-gui`**&#xB294; 프로퍼티 데이터 타입을 보고 적절한 UI 컨트롤러를 알아서 선택한다.
{% endhint %}

#### 색상 팔레트 사용하기

> 머터리얼의 색상을 제어하기 위한 색상 팔레트 컨트롤러를 추가해보자.

![](https://1912740209-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3GVYdZvmqQyBVq29ebqk%2Fuploads%2FIHrYSDK83MVsgXc97buJ%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202023-09-03%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.39.27.png?alt=media\&token=9264686a-7f3d-46ef-8d7e-437e013be33d)

색상은 `hex` 또는 `rgb` 값으로 표현되고, 문자열 타입이기 때문에 `lil-gui`가 이 값을 보고 색상 팔레트 UI를 사용해야하는지 알수가 없어 `add` 함수 대신 **`addColor`** 함수를 사용하여 색상 팔레트를 사용하겠다고 알려야 한다.

\
또한, 머터리얼의 색상 프로퍼티에 저장되는 값은  `hex` 나 `rgb` 값이 아닌 `Built In Color Instance` 로 잡혀있기 때문에 프로퍼티 값을 직접적으로 변경할 수 없어 컬러 옵션 객체를 별도로 선언한 후 주입 해주어야 한다.

```javascript
const options = {
  color: '#0066ff',
}

gui.addColor(options, 'color').onChange((value) => cube.material.color.set(value));
```

{% hint style="info" %}
**`onChage`** 메서드는 색상 팔레트 컨트롤러로 값을 변경시킬 때마다 인자로 넘긴 콜백 함수가 호출되며, 변경한 값을 머터리얼에 반영시키기 위해 사용된다.
{% endhint %}
