웹개발 자료실/three.js 프론트개발 Code

「three.js」턴테이블 카메라 생성하기

Recstasy 2023. 1. 12. 20:06

 

 

 

 

 

three.js에서 카메라를 빙빙 돌려보자. CG포트폴리오 중에서 3D 모델링을 만들어 카메라를 빙빙 돌리는 작품이 바로 이번 포스팅의 주제다. 

 

 


three.js CG카메라 용어

CG 프로그램에서 카메라 속성에는 ' FOV' , 'Depth of Field' , 'Aspect Ratio' , 'resolution gate' 등.. 과 같은 용어들을 볼 수 있다. 우선 CG에서 가장 기본적으로 알아둬야 할 카메라 용어를 정리해보자.

 

아래 사진을 보면, Field Of View를 볼 수 있다. 줄여서 FOV라고 하며, 쉽게 말해 '시야'라고 이해하면 된다. 필자는 FOV를 단순히 '시야'라고 생각한다. 가령, FOV가 클수록 전방 시야가 넓어지기 때문이다. 실제 구글에는 FOV값에 관한 여러 설명 중, '광각' , '망원' , '어안' 렌즈와 같은 분야까지 나오는데 그냥 무시하자. 

 

 

위의 사진에서 Near의 수치가 작을수록 카메라와 피사체 사이의 거리가 짧아지는 점을 알 수 있다. 즉, 'Near'수치가 작을수록 카메라 바로 앞의 피사체를 촬영할 수 있다. 만일, Near수치를 0.1(Default:1)로 한다면, 일종의 '접사'라 할 수 있다. 반면, Far는 어디까지 촬영할 수 있는지를 알 수 있으며, 이는 '망원'을 의미한다. three.js의 경우, 카메라 파라미터 설정에서 Near와 Far 부분의 값에 따라 카메라의 촬영범위가 결정된다. 

 

Aspect Ratio는 아래 사진처럼 '가로&세로 비율'을 의미한다. 가령, 16:9 , 4:3과 같은 설정값이 Aspect Ratio에 해당한다. 

 

 

Three.js에서 카메라를 설정하는 부분은 간단하다. 아래의 공식에 해당하는 파라미터에 값을 넣으면 카메라의 설정이 마무리된다. 자세한 부분은 threejs.org에서 확인할 수 있다.

 

https://threejs.org/docs/index.html?q=camera#api/en/cameras/PerspectiveCamera

 

 

 

 


| three.js 카메라 회전하기

오브젝트 주변을 빙빙 돌아가는 카메라를 만들어보자. 먼저 간략하게 설계한다. (설계라 할 것까지 없지만) requestAnimationFrame 재귀함수에 cos, sin으로 원회전을 하는 카메라를 업데이트 하는 설정이다.

 

let scene, camera, renderer, light1;
let cylinder,sphere,plane;
let ADD = 0.01, default_value = 0;

let createGeometry = function(){}

let init = function(){}

let render = function(){}

init()
render()

 

 

카메라는 x축과 z축의 값으로 Cos( )함수와 Sin( )함수를 넣으면, 회전 운동을 한다. 아래와 같이 자바스크립트 내장함수인 "Math"를 이용해 Math.Cos(default_value)값을 position.x에 넣고, Math.Sin(default_value)값을 position.y에 넣어준다.

 

 

let render = function(){
    
    camera.lookAt( new THREE.Vector3( 0, 0, 0 ) );
    camera.position.x = 40 * Math.sin( default_value );
    camera.position.z = 40 * Math.cos( default_value );

    default_value += add;

    requestAnimationFrame( render );
    renderer.render( scene, camera );

}

 

 

createGeomtry( )함수는 3D 오브젝트들을 생성하며, 여기서는 plane, sphere, cylinder를 씬에 넣고 있다.

 

 

let createGeometry = function(){

    let geometry = new THREE.CylinderGeometry( 5, 5, 20, 32 )
    let material = new THREE.MeshPhongMaterial({
        color: 0x448844, 
        shininess: 100, 
        side: THREE.DoubleSide 
    });

    cylinder = new THREE.Mesh( geometry, material );
    cylinder.position.set( 6, 0, -2 );
 
    geometry = new THREE.BoxGeometry( 2000, 1, 2000 );
    material = new THREE.MeshPhongMaterial({
        color: 0xabcdef, 
        side: THREE.DoubleSide
    });

    plane = new THREE.Mesh( geometry, material );
    plane.position.y = -1;

    geometry = new THREE.SphereGeometry( 5, 30, 30 );
    material = new THREE.MeshPhongMaterial({
        color: 0x693421, 
        side: THREE.DoubleSide
    });

    sphere = new THREE.Mesh( geometry, material );
    sphere.position.set( -5, 5, 2 );    

    scene.add( cylinder );
    scene.add( plane );
    scene.add( sphere );

}

 

 

위의 구현에서 가장 중요한 부분은 Render() 함수다. 카메라는 계속 중점(0, 0)을 보고 있어야 하는데, 이를 위해 (dummy데이터) 3차원 벡터 오브젝트를 생성해준다. 그리고 다음과 같이 lookAt()메서드에 dummy데이터를 넣는다.

 

 

let render = function() {
        
        camera.lookAt(new THREE.Vector3(0, 0, 0));
        camera.position.x = 40 * Math.sin(default_value);
        camera.position.z = 40 * Math.cos(default_value);
        default_value += add;
        
        renderer.render(scene, camera);
        requestAnimationFrame(render);
    };

 

 

카메라의 x, y위치값이 각각 sin, cos운동을 하므로 원회전이 완성된다.