Panolens ipd 설정

IPD…그리고

panolens에서 IPD를 따로 설정해 주는 부분이 없다. 깃허브에도 따로 언급된 부분도 없다.

간단하게 눈사이의 거리를 담당하는 변수가 따로 있고, 이 변수의 크기만 조절하면 될 것 같다는 생각을 했다. 일단 VR Mode로 화면을 전환하는 부분에서 부터 코드 역추적을 시작했다.

StereoEffect

stereo 소스에서 Stereoscopic으로 검색을 해서 따라가니 PANOLENS.Modes를 확인할 수 있었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**        
 * @memberOf PANOLENS
 * @enum {number}
 */
PANOLENS.Modes = {
    /** Unknown */
    UNKNOWN: 0,
    /** Normal */
    NORMAL: 1,
    /** Google Cardboard*/
    CARDBOARD: 2,
    /** Stereoscopic **/
    STEREO: 3
};
cs

설정 화면에서 선택하면 각각 0, 1, 2, 3으로 설정된다.

또 Stereoscopic 관련 부분을 찾을 수 있었는데 enableEffect 함수와 연결되어 있었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    title: 'Mode'
    subMenu: [ 
        { 
            title: 'Normal',
            handler: handler( 'disableEffect' )
        }, 
        { 
            title: 'Cardboard',
            handler: handler( 'enableEffect', PANOLENS.Modes.CARDBOARD )
        },
        { 
            title: 'Stereoscopic',
            handler: handler( 'enableEffect', PANOLENS.Modes.STEREO )
        }
    ]
}
cs

enableEffect

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
PANOLENS.Viewer.prototype.enableEffect = function ( mode ) {
 
    if ( this.mode === mode ) { return; }
    if ( mode === PANOLENS.Modes.NORMAL ) { this.disableEffect(); return; }
    else { this.mode = mode; }
 
    var fov = this.camera.fov;
 
    switch( mode ) {
 
        case PANOLENS.Modes.CARDBOARD:
 
            this.effect = this.CardboardEffect;
            this.enableReticleControl();
 
            break;
 
        case PANOLENS.Modes.STEREO:
 
            this.effect = this.StereoEffect;
            this.enableReticleControl();
            
            break;
 
        default:
 
            this.effect = null;
            this.disableReticleControl();
 
            break;
 
    }
 
    this.activateWidgetItem( undefined, this.mode );
 
    /**
     * Dual eye effect event
     * @type {object}
     * @event PANOLENS.Viewer#panolens-dual-eye-effect
     * @event PANOLENS.Infospot#panolens-dual-eye-effect
     * @property {PANOLENS.Modes} mode - Current display mode
     */
    this.dispatchEventToChildren( { type: 'panolens-dual-eye-effect', mode: this.mode } );
 
    // Force effect stereo camera to update by refreshing fov
    this.camera.fov = fov + 10e-3;
    this.effect.setSize( this.container.clientWidth, this.container.clientHeight );
    this.render();
    this.camera.fov = fov;
 
};
cs

함수는 위와가 같이 작성이 되어 있었고 StereoEffect, CardboardEffect 단어가 눈에 들어왔다. 다시 CardboardEffect으로 검색하니 PANOLENS.Viewer의 생성자에서 찾을 수 있엇다.

StereoEffect

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
THREE.StereoEffect = function ( renderer ) {
 
    var _stereo = new THREE.StereoCamera();
    _stereo.aspect = 0.5;
 
    this.setEyeSeparation = function ( eyeSep ) {
 
        _stereo.eyeSep = eyeSep;
 
    };
 
    this.setSize = function ( width, height ) {
 
        renderer.setSize( width, height );
 
    };
 
    this.render = function ( scene, camera ) {
 
        scene.updateMatrixWorld();
 
        if ( camera.parent === null ) camera.updateMatrixWorld();
 
        _stereo.update( camera );
 
        var size = renderer.getSize();
 
        if ( renderer.autoClear ) renderer.clear();
        renderer.setScissorTest( true );
 
        renderer.setScissor( 00, size.width / 2, size.height );
        renderer.setViewport( 00, size.width / 2, size.height );
        renderer.render( scene, _stereo.cameraL );
 
        renderer.setScissor( size.width / 20, size.width / 2, size.height );
        renderer.setViewport( size.width / 20, size.width / 2, size.height );
        renderer.render( scene, _stereo.cameraR );
 
        renderer.setScissorTest( false );
 
    };
 
};
cs

쭉~ 코드를 읽어 가다가 setEyeSeparation? EyeSeparation을 set하는 함수인데 EyeSeparation가 뭐지? eyeSeparation 번역을 해보니 눈 분리!!! _stereo.eyeSep 값이 얼마로 설정되어 있는지 확인하니 _stereo는 three.js 의 new THREE.StereoCamera 였다.

new THREE.StereoCamera

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
THREE.StereoEffect = function ( renderer ) {
 
    var _stereo = new THREE.StereoCamera();
    _stereo.aspect = 0.5;
 
    this.setEyeSeparation = function ( eyeSep ) {
 
        _stereo.eyeSep = eyeSep;
 
    };
 
    this.setSize = function ( width, height ) {
 
        renderer.setSize( width, height );
 
    };
 
    this.render = function ( scene, camera ) {
 
        scene.updateMatrixWorld();
 
        if ( camera.parent === null ) camera.updateMatrixWorld();
 
        _stereo.update( camera );
 
        var size = renderer.getSize();
 
        if ( renderer.autoClear ) renderer.clear();
        renderer.setScissorTest( true );
 
        renderer.setScissor( 00, size.width / 2, size.height );
        renderer.setViewport( 00, size.width / 2, size.height );
        renderer.render( scene, _stereo.cameraL );
 
        renderer.setScissor( size.width / 20, size.width / 2, size.height );
        renderer.setViewport( size.width / 20, size.width / 2, size.height );
        renderer.render( scene, _stereo.cameraR );
 
        renderer.setScissorTest( false );
 
    };
 
};
cs

여기서 보니 eyeSep 값이 0.064로 내가 알고 있던 ipd의 평균 수치 (60mm~65mm)의 값과 근사해서 혹시나 싶었다. panolens의 기본 예제에서 증가버튼, 감소버튼, eyeSep 출력을 추가하고 eyeSep 을 조절하면 KRpano의 IPD 설정과 똑같이 동작하는지 확인했다.

KRPANO IPD

eyeSeparation

구현물

eyeSeparation

결과

코딩 결과를 비교해서 보니 동작하는 모습이 비슷해보였다. 실제로 IPD의 값이 안맞은 예제나 핸드폰이 있으면 가지고 테스트할 가치가 있다.