본문 바로가기

[ar.js] 웹캠으로 ar을 시도해보자 1편

by Recstasy 2019. 6. 13.

pc에서는 웹캠, 스마트폰이나 태블릿 pc에서는 카메라만 있으면 ar과 three.js를 활용해서 전시작품을 만들 수 있다. github를 찾아보면 ar.js와 three.js를 동시에 사용한 프로젝트들이 있다. 아래 링크를 들어가서 확인해보자. 상당히 많은 프로젝트들이 three.js와 ar.js 혹은 a-frame, awe.js를 활용해서 진행되고 있다. 


https://jeromeetienne.github.io/AR.js-docs/misc/EXAMPLES.html


위의 링크에서 가장 첫번째 파일, 'basic'을 열어보자. three.js와 ar.js코드가 아래와 같이 섞여 있다. 웹에서 간단하게 ar을 구사하려면 three.js보다 a-frame.js가 훨씬 간단한 느낌이다. 그러나 three.js는 웹에서 3D를 구현하는 기능이 a-frame보다 많기 때문에 미래를 생각한다면, three.js + ar.js 조합이 강력할 것으로 예상한다.


basic씬을 분석해보자.


1 『three.js기본뼈대 생성』


<script>THREEx.ArToolkitContext.baseURL = '../'</script> 

var renderer = new THREE.WebGLRenderer({

antialias: true,

alpha: true

});

// ① WebGL랜더러 설정

renderer.setClearColor(new THREE.Color('lightgrey'), 0)

renderer.setSize( 640, 480 );

renderer.domElement.style.position = 'absolute'

renderer.domElement.style.top = '0px'

renderer.domElement.style.left = '0px'

document.body.appendChild( renderer.domElement );


var onRenderFcts= [];


//② 씬과 카메라 생성

var scene = new THREE.Scene();

var camera = new THREE.Camera();

scene.add(camera);



2 『arToolkitSource객체 생성』

three.js로 기본 랜더러와 씬 그리고 카메라를 설정했다면, arToolkitSource 객체를 생성한다.

ar.js 파일을 조사해보면, arToolkitSource 메서드는 THREEx클래스에 속해 있다.


파라미터값으로 객체를 넣을 수 있으며, 객체에 넣을 수 있는 이미지는 카메라에 비춰진

표식과 교체된다.


//  arToolkitSource 인스턴스 객체 생성

var arToolkitSource = new THREEx.ArToolkitSource({   // 카메라 탐색

sourceType : 'webcam',

// // to read from an image

// sourceType : 'image',

// sourceUrl : THREEx.ArToolkitContext.baseURL + '../data/images/img.jpg',

// to read from a video

// sourceType : 'video',

// sourceUrl : THREEx.ArToolkitContext.baseURL + '../data/videos/headtracking.mp4',

})


arToolkitSource.init(function onReady(){

onResize()

})

// ③디바이스 크기에 맞게 사이즈 조절하는 함수 설정

window.addEventListener('resize', function(){

onResize()

})

function onResize(){

arToolkitSource.onResize()

arToolkitSource.copySizeTo(renderer.domElement)

if( arToolkitContext.arController !== null ){

arToolkitSource.copySizeTo(arToolkitContext.arController.canvas)

}

}



arToolkitSource 객체는 위치추적을 위한 이미지 또는 비디오를 설정한다. 


arToolkitSource 메소드에는 'sourceType(타입)' , 'sourceUrl(경로지정)' 그리고 크기를 지정할 수 있다.  arToolkitSource에서 이미지 파일과 경로를 지정하고, 동영상을 구현하려면 동영상 관련 경로와 타입을 지정한다. 


실험을 해본 결과, arToolkitSource에는 sourceType만 웹캠으로 지정하면 된다. 그 이외의 이미지나 비디오는 '추적 정확도'를 높이는 용도인지 정확히 알 수 없다. 위의 코드처럼 타입으로 웹캠만 지정해주자. 어차피 가장 중요한 메서드는 'arToolkitContext'다.


3 『arToolkitContext객체 생성』

사용설명서(?)에 의하면 'arToolkitContext'객체가 위치추적을 하는 메인 코어이다.  'arToolkitContext'는 이미지 소스에서 마커위치를 찾는 기능을 한다. 따라서 'camera_para.dat'파일의 경로를 정확하게 지정해줘야만 마커의 위치추적을 정확하게 할 수 있다. 'cameraPrametersUrl' 프로퍼티값을 지정해주고, 'mono'로 기본설정을 해보자. 


arToolkitContext.init()매서드는 추적하는 마커의 좌표값을 복사해서 카메라의 좌표 위치에 돌려주는 역할을 한다. ar을 실행하고, 3D 물체를 손으로 가리면 오브젝트가 그대로 사라진다. 마커의 좌표값이 계산되지 않으면(손으로 가려서), 카메라에 해당 좌표값을 전달하지 못해서 3D오브젝트가 사라지기 때문이다.


// arToolkitContext객체 생성하기


var arToolkitContext = new THREEx.ArToolkitContext({

cameraParametersUrl: THREEx.ArToolkitContext.baseURL + '../data/data/camera_para.dat',

detectionMode: 'mono',

})

// initialize it

arToolkitContext.init(function onCompleted(){

// copy projection matrix to camera

camera.projectionMatrix.copy( arToolkitContext.getProjectionMatrix() );

})


// update artoolkit on every frame

onRenderFcts.push(function(){

if( arToolkitSource.ready === false ) return


arToolkitContext.update( arToolkitSource.domElement )

// update scene.visible if the marker is seen

scene.visible = camera.visible

})


'onRenderFcts'는 위에서 배열로 선언했다. onRenderFcts배열에 3D 객체, 씬, 카메라가

들어간다. onRenderFcts배열 속의 객체들은 매프레임마다 실행이 되는데, arToolkitSource의

웹캠이 준비되지 않으면 계속 arToolkitContext.update()를 실행한다. 즉, 카메라를 찾지 못하면

scene자체가 보이지 않는다.(false)

4 『arMakerControls객체 생성』

'arMarkerControls'는 마커의 위치를 제어하는 기능을 담당한다. 기계의 도움을 받지 않는다면 카메라로 마커를 촬영하면서 떨림 증상이 나타난다. 'arMarkerControls'는 마커에 해당되는 위치에 점을 찍고, 마커가 이동할 때마다 점을 추적한다. 그리고 추적한 값에 3D오브젝트를 올려놓으면 마치 3D 오브젝트가 카메라의 특정 위치(마커)에 붙어있는 효과가 나타난다. 


// Create a ArMarkerControls

// init controls for camera

var markerControls = new THREEx.ArMarkerControls(arToolkitContext, camera, {

type : 'pattern',

patternUrl : THREEx.ArToolkitContext.baseURL + '../data/data/patt.hiro',

// patternUrl : THREEx.ArToolkitContext.baseURL + '../data/data/patt.kanji',

// as we controls the camera, set changeMatrixMode: 'cameraTransformMatrix'

changeMatrixMode: 'cameraTransformMatrix'

})

// as we do changeMatrixMode: 'cameraTransformMatrix', start with invisible scene

scene.visible = false



5 『three.js 오브젝트 넣기』

위의 과정까지 진행했다면, three.js 랜더링을 진행한다. three.js로 3D객체들을 랜더링할 때와 ar.js의 차이점은 'onRenderFcts배열'에 있다. 먼저 onRenderFcts배열에 render.render()매서드로 3D 객체들을 몽땅 집어넣는다. 그리고 forEach구문을 사용해서 배열 속에 있는 내용들을 onRenderFct()으로 매프레임 실행한다. 


      var geometry = new THREE.CubeGeometry(1,1,1);

      var material = new THREE.MeshNormalMaterial({

transparent : true,

opacity: 0.5,

side: THREE.DoubleSide

}); 

var mesh = new THREE.Mesh( geometry, material );

    mesh.position.y = geometry.parameters.height/2

    scene.add( mesh );

var geometry = new THREE.TorusKnotGeometry(0.3,0.1,64,16);

var material = new THREE.MeshNormalMaterial(); 

var mesh = new THREE.Mesh( geometry, material );

    mesh.position.y = 0.5

    scene.add( mesh );

onRenderFcts.push(function(delta){

mesh.rotation.x += Math.PI*delta

})


// render the whole thing on the page

// render the scene


onRenderFcts.push(function(){

renderer.render( scene, camera );

})


// run the rendering loop

var lastTimeMsec= null

requestAnimationFrame(function animate(nowMsec){

// keep looping

requestAnimationFrame( animate );

             // measure time

lastTimeMsec = lastTimeMsec || nowMsec-1000/60

var deltaMsec = Math.min(200, nowMsec - lastTimeMsec)

lastTimeMsec = nowMsec


// call each update function

onRenderFcts.forEach(function(onRenderFct){

onRenderFct(deltaMsec/1000, nowMsec/1000)

})

})



ar이 나오는 문양은 아래와 같다. 모니터에 Hiro문양을 띄우거나 인쇄물에 카메라를 가져가면 three.js로 만든 토러스와 박스가 등장한다. 



아래 AR시작 버튼을 클릭해보자. 컴퓨터라면 웹캠이 있어야하고, 폰으로 접속했다면 그대로 볼 수 있다.



댓글

최신글 전체

이미지
제목
글쓴이
등록일