Interaction with 3D stereo interfacesx

rodscarletΛογισμικό & κατασκευή λογ/κού

14 Δεκ 2013 (πριν από 3 χρόνια και 8 μήνες)

71 εμφανίσεις

Interaction with 3D Stereo
Interfaces



Armando de la Re Vega


WGM #41

December 2nd 2011

Introduction



Short

reminder

of

terms
.


Frustum

and

types

of

Stereo

rendering
.



OpenGL

and

GLUT

library
.


OpenSceneGraph

(OSG)
.




2

Stereoscopy



Technique for enhance the illusion of depth in
an image using two offset images separately to
each user eye.



The depth perception is because depth cues.


3

Stereo


Depth cues


Perspective.


Sizes of known objects.


Detail.


Occlusion.


Lighting and shadows.


Relative motion.



Accommodation (focus).


Convergence (rotation).


Binocular disparity (separation).


4

left eye






Screen




Right eye


Parallax (top view)



Stereo

5

left eye






Screen




Right eye

left eye





Screen




Right eye






Positive Parallax








Zero Parallax









Negative Parallax

Stereo


Frustum (or viewing frustum)


Portion of an area, normally cone or pyramid, that
lies between two parallel planes cutting it.


In computer graphics, is the three dimensional
region visible on screen, a clipped pyramid.

6



top


left



right



bottom

Stereo


Frustum

7

glFrustum
(left, right, bottom, top, near, far);


Camera
-
>
setProjectionMatrixAsFrustum
(
left, right, bottom, top, near, far
);

matrix.makeFrustum
(
left, right, bottom, top, near, far
)

camera

Stereo


Frustum (top view)

8

near




far

left








right

glFrustum
(left, right, bottom, top, near, far);


Camera
-
>
setProjectionMatrixAsFrustum
(
left, right, bottom, top, near, far
);

matrix.makeFrustum
(
left, right, bottom, top, near, far
)

camera

Stereo

9

Rendering (
top

view)





camera





Screen

Non
Stereo

Stereo

10

Rendering (
top

view)




left camera








Screen








pi








right camera

Toe
-
in (
incorrect
)

Stereo

11

Rendering (
top

view)








Screen


left camera








right camera

Off
-
axis (Correct)

OpenGL



Needs an OpenGL card and any associated
hardware that supports stereo graphic viewing.



Frame sequential (Quad
-
buffered) stereo reduce
the graphic cards available.



Select appropriate buffer and render the scene
with appropriate projection.


12

OpenGL


An OpenGL application with stereo capabilities
must do following things:


1) Set the geometry for the view from right human eye.


2) Set the right eye rendering buffers.


3) Render the right eye image.


4) Clear Z
-
buffer (if the same Z
-
buffer for left and right
image is used).


5) Set the geometry for the view from left human eye


6) Set the left eye rendering buffers.


7) Render the left eye image.


8) Swap buffers.



13

OpenGL

int

main
(
int

argc
,
char
**
argv
)

{


glutInit
(&
argc
,
argv
);


glutInitDisplayMode
(
GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH |
GLUT_STEREO
);


glutInitWindowSize
(512, 512);


glutInitWindowPosition
(20, 20);


glutCreateWindow
("test
Stereo
");


glutDisplayFunc
(
display
);


glutMainLoop
();


return

0;

}


14

OpenGL


void

display
(
void
)

{


glDrawBuffer
(
GL_BACK_LEFT
);



glClear
(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);




glDrawBuffer
(
GL_BACK_RIGHT
);



glClear
(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);





glutSwapBuffers
();

}


15

glMatrixMode
(GL_PROJECTION);

glLoadIdentity
();

gluPerspective
(camera.aperture,aspectratio,0.1,10000.0);

if

(!
stereo
) {


glMatrixMode
(GL_MODELVIEW);


glDrawBuffer
(GL_BACK);


glClear
(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


glLoadIdentity
();


gluLookAt
(
camera.pos.x

,
camera.pos.y,camera.pos.z
,





camera.dir.x,camera.dir.y,camera.dir.z
,
camera.up.x,camera.up.y,camera.up.z
);


// Create geometry here in convenient model coordinates

}

else

{ //
Symmetric
-

non stereo camera


glMatrixMode
(GL_MODELVIEW);


glDrawBuffer
(GL_BACK_RIGHT);
//
right


glClear
(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


glLoadIdentity
();


gluLookAt
(
camera.pos.x

+
camright.x
,
camera.pos.y

+
camright.y
,
camera.pos.z

+
camright.z
,




camera.pi.x
,
camera.pi.y
,
camera.pi.z
,
camera.up.x
,
camera.up.y
,
camera.up.z
);


// Create geometry here in convenient model coordinates


glMatrixMode
(GL_MODELVIEW);


glDrawBuffer
(GL_BACK_LEFT);
//
left


glClear
(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


glLoadIdentity
();


gluLookAt
(
camera.pos.x

-

camright.x
,
camera.pos.y

-

camright.y
,
camera.pos.z

-

camright.z
,



camera.focus.x
,
camera.focus.y
,
camera.focus.z
,
camera.up.x,camera.up.y,camera.up.z
);


// Create geometry here in convenient model coordinates

}

16

aspectratio

=
windowwidth

/ (double)
windowheight
;

widthdiv2 =
camera.neardist

* tan(
camera.aperture

/ 2); // aperture in radians

camright

=
crossproduct
(
camera.dir,camera.up
); // Each unit vectors

camright.x

*=
camera.eyesep

/ 2.0;

camright.y

*=
camera.eyesep

/ 2.0;

camright.z

*=
camera.eyesep

/ 2.0;


O
penGL

OpenGL

17

Asymmetric frustum


stereoscopic ANAGLYPH

glMatrixMode
(GL_PROJECTION);

glLoadIdentity
();

glClear
(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glColorMask
(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
// Right eye red

glViewport
(0,0,windowwidth,windowheight);

top = widthdiv2; bottom =
-

widthdiv2;

left =
-

aspectratio

* widthdiv2
-

0.5 *
camera.eyesep

*
camera.near

/ camera.fo;

right =
aspectratio

* widthdiv2
-

0.5 *
camera.eyesep

*
camera.near

/ camera.fo;

glFrustum
(
left,right,bottom,top,camera.neardist,camera.fardist
);

glMatrixMode
(GL_MODELVIEW);

glLoadIdentity
();

gluLookAt
(
camera.pos.x

+
camright.x
,
camera.pos.y

+
camright.y
,
camera.pos.z

+
camright.z
,


camera.pos.x+camright.x+camera.dir.x
,
camera.pos.y+camright.y+camera.dir.y
,
camera.pos.z+camright.z+camera.dir.z
,


camera.up.x,camera.up.y,camera.up.z
);

// Create geometry here in convenient model coordinates

glMatrixMode
(GL_PROJECTION);

glLoadIdentity
();

glClear
(GL_DEPTH_BUFFER_BIT);

glColorMask
(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
// Left eye blue

glViewport
(0,0,windowwidth,windowheight);

top = widthdiv2; bottom =
-

widthdiv2;

left =
-

aspectratio

* widthdiv2 + 0.5 *
camera.eyesep

*
camera.near

/ camera.fo;

right =
aspectratio

* widthdiv2 + 0.5 *
camera.eyesep

*
camera.near

/ camera.fo;

glFrustum
(
left,right,bottom,top,camera.neardist,camera.fardist
);

glMatrixMode
(GL_MODELVIEW);

glLoadIdentity
();

gluLookAt
(
camera.pos.x

-

camright.x
,
camera.pos.y

-

right.y
,
camera.pos.z

-

camright.z
,


camera.pos.x
-
camright.x+camera.dir.x
,
camera.pos.y
-
camright.y+camera.dir.y
,
camera.pos.z
-
camright.z+camera.dir.z
,


camera.up.x,camera.up.y,camera.up.z
);

// Create geometry here in convenient model coordinates

aspectratio

=
windowwidth

/ (double)
windowheight
;

widthdiv2 =
camera.neardist

* tan(
camera.aperture

/ 2); // aperture in radians

camright

=
crossproduct
(
camera.dir,camera.up
); // Each unit vectors

camright.x

*=
camera.eyesep

/ 2.0;

camright.y

*=
camera.eyesep

/ 2.0;

camright.z

*=
camera.eyesep

/ 2.0;


OpenGL

18




ANAGLYPH


Color
used

in
Anaglyph
:


glColorMask
(GL_TRUE,GL_FALSE,GL_FALSE,GL_TRUE); //RED


glColorMask
(GL_FALSE,GL_FALSE,GL_TRUE,GL_TRUE); //BLUE


glColorMask
(GL_FALSE,GL_TRUE,GL_TRUE,GL_TRUE); //CYAN


glColorMask
(GL_FALSE,GL_TRUE,GL_FALSE,GL_TRUE); //GREEN

19

Asymmetric frustum


stereoscopic FRAME SEQUENTIAL

glMatrixMode
(GL_PROJECTION);

glLoadIdentity
();

glDrawBuffer
(GL_BACK_RIGHT);
// Right eye

glViewport
(0,0,windowwidth,windowheight);

top = widthdiv2; bottom =
-

widthdiv2;

left =
-

aspectratio

* widthdiv2
-

0.5 *
camera.eyesep

*
camera.near

/ camera.fo;

right =
aspectratio

* widthdiv2
-

0.5 *
camera.eyesep

*
camera.near

/ camera.fo;

glFrustum
(
left,right,bottom,top,camera.neardist,camera.fardist
);

glMatrixMode
(GL_MODELVIEW);

glLoadIdentity
();

gluLookAt
(
camera.pos.x

+
camright.x
,
camera.pos.y

+
camright.y
,
camera.pos.z

+
camright.z
,


camera.pos.x+camright.x+camera.dir.x
,
camera.pos.y+camright.y+camera.dir.y
,
camera.pos.z+camright.z+camera.dir.z
,


camera.up.x,camera.up.y,camera.up.z
);

// Create geometry here in convenient model coordinates

glMatrixMode
(GL_PROJECTION);

glLoadIdentity
();

glDrawBuffer
(GL_BACK_LEFT);
// Left eye

glViewport
(0,0,windowwidth,windowheight);

top = widthdiv2; bottom =
-

widthdiv2;

left =
-

aspectratio

* widthdiv2 + 0.5 *
camera.eyesep

*
camera.near

/ camera.fo;

right =
aspectratio

* widthdiv2 + 0.5 *
camera.eyesep

*
camera.near

/ camera.fo;

glFrustum
(
left,right,bottom,top,camera.neardist,camera.fardist
);

glMatrixMode
(GL_MODELVIEW);

glLoadIdentity
();

gluLookAt
(
camera.pos.x

-

camright.x
,
camera.pos.y

-

right.y
,
camera.pos.z

-

camright.z
,


camera.pos.x
-
camright.x+camera.dir.x
,
camera.pos.y
-
camright.y+camera.dir.y
,
camera.pos.z
-
camright.z+camera.dir.z
,


camera.up.x,camera.up.y,camera.up.z
);

// Create geometry here in convenient model coordinates

aspectratio

=
windowwidth

/ (double)
windowheight
;

widthdiv2 =
camera.neardist

* tan(
camera.aperture

/ 2); // aperture in radians

camright

=
crossproduct
(
camera.dir,camera.up
); // Each unit vectors

camright.x

*=
camera.eyesep

/ 2.0;

camright.y

*=
camera.eyesep

/ 2.0;

camright.z

*=
camera.eyesep

/ 2.0;


OpenGL

OpenGL

20

Asymmetric frustum


stereoscopic SIDE BY SIDE

glMatrixMode
(GL_PROJECTION);

glLoadIdentity
();

glViewport
(
windowwidth
/2,0,windowwidth/2,windowheight);
// Right

top = widthdiv2;

bottom =
-

widthdiv2;

left =
-

aspectratio

* widthdiv2
-

0.5 *
camera.eyesep

*
camera.near

/ camera.fo;

right =
aspectratio

* widthdiv2
-

0.5 *
camera.eyesep

*
camera.near

/ camera.fo;

glFrustum
(
left,right,bottom,top,camera.neardist,camera.fardist
);

glMatrixMode
(GL_MODELVIEW);

glLoadIdentity
();

gluLookAt
(
camera.pos.x

+
camright.x
,
camera.pos.y

+
camright.y
,
camera.pos.z

+
camright.z
,


camera.pos.x+camright.x+camera.dir.x
,
camera.pos.y+camright.y+camera.dir.y
,
camera.pos.z+camright.z+camera.dir.z
,


camera.up.x,camera.up.y,camera.up.z
);

// Create geometry here in convenient model coordinates

glMatrixMode
(GL_PROJECTION);

glLoadIdentity
();

glViewport
(0,0,windowidth/2,windowheight);

// Left

top = widthdiv2;

bottom =
-

widthdiv2;

left =
-

aspectratio

* widthdiv2 + 0.5 *
camera.eyesep

*
camera.near

/ camera.fo;

right =
aspectratio

* widthdiv2 + 0.5 *
camera.eyesep

*
camera.near

/ camera.fo;

glFrustum
(
left,right,bottom,top,camera.neardist,camera.fardist
);

glMatrixMode
(GL_MODELVIEW);

glLoadIdentity
();

gluLookAt
(
camera.pos.x

-

camright.x
,
camera.pos.y

-

camright.y
,
camera.pos.z

-

camright.z
,


camera.pos.x
-
camright.x+camera.dir.x
,
camera.pos.y
-
camright.y+camera.dir.y
,
camera.pos.z
-
camright.z+camera.dir.z
,


camera.up.x,camera.up.y,camera.up.z
);

// Create geometry here in convenient model coordinates

aspectratio

= (
windowwidth

/ (double)
windowheight
)/2;

widthdiv2 =
camera.neardist

* tan(
camera.aperture

/ 2); // aperture in radians

camright

=
crossproduct
(
camera.dir,camera.up
); // Each unit vectors

camright.x

*=
camera.eyesep

/ 2.0;

camright.y

*=
camera.eyesep

/ 2.0;

camright.z

*=
camera.eyesep

/ 2.0;


OpenSceneGraph



Needs an OpenGL card and any associated
hardware that supports stereo graphic viewing.



Frame sequential (Quad
-
buffered) stereo reduce
the graphic cards available.



Easier.


Default Asymmetric Frustum.

21

OpenSceneGraph


Code:


osgViewer
::Viewer
viewer
;



osg
::
DisplaySettings

*
ds

=
osg
::
DisplaySettings
::instance();

ds
-
>
setStereo
(true);

ds
-
>
setStereoMode
(
osg
::
DisplaySettings
::
StereoMode
::QUAD_BUFFER);


viewer.setDisplaySettings
(
ds
);


22

OpenSceneGraph



setEyeSeparation
();
//0.05m



setScreenDistance
();


setScreenHeight
();
//0.5m
image

not

monitor


setScreenWidth
();
//0.26m
image

note monitor



setSplitStereoAutoAdjustAspectRatio
();


setSplitStereoHorizontalEyeMapping
();


setSplitStereoHorizontalSeparation
();


setSplitStereoVerticalEyeMapping
();


setSplitStereoVerticalSeparation
();



viewer.getCamera
()
-
>
setComputeNearFarMode



(
osgUtil
::
CullVisitor
::DO_NOT_COMPUTE_NEAR_FAR
);




23

OpenSceneGraph



ds
-
>
setStereoMode
(
osg
::
DisplaySettings
::
StereoMode
::QUAD_BUFFER);


osg
::
DisplaySettings
::
StereoMode
::QUAD_BUFFER


osg
::
DisplaySettings
::
StereoMode
::ANAGLYPHIC


osg
::
DisplaySettings
::
StereoMode
::HORIZONTAL_SPLIT


osg
::
DisplaySettings
::
StereoMode
::VERTICAL_SPLIT


osg
::
DisplaySettings
::
StereoMode
::LEFT_EYE


osg
::
DisplaySettings
::
StereoMode
::RIGHT_EYE


osg
::
DisplaySettings
::
StereoMode
::HORIZONTAL_INTERLACE


osg
::
DisplaySettings
::
StereoMode
::VERTICAL_INTERLACE


osg
::
DisplaySettings
::
StereoMode
::CHECKERBOARD



ds
-
>
setDisplayType
(
osg
::
DisplaySettings
::
DisplayType
::MONITOR);


osg
::
DisplaySettings
::
DisplayType
::MONITOR



-
>
Asymmetric


osg
::
DisplaySettings
::
DisplayType
::POWERWALL



-
>
Asymmetric


osg
::
DisplaySettings
::
DisplayType
::REALITY_CENTER


-
>
Asymmetric


osg
::
DisplaySettings
::
DisplayType
::HEAD_MOUNTED_DISPLAY

-
>
Symmetric


24

References



Paul Burke: information related to Stereographics. Some examples.


http://paulbourke.net/miscellaneous/stereographics/



Tutorial and examples


http://www.gali
-
3d.com/archive/articles/StereoOpenGL/

StereoscopicOpenGLTutorial.php



OpenGL and OSG pages:


http://www.opengl.org/documentation/


http://www.opengl.org/resources/


http://www.openscenegraph.org/projects/osg



When you are lost:


http://www.opengl.org/discussion_boards/


http://forum.openscenegraph.org



25

Thanks


26

openGL

aspectratio

=
windowwidth

/ (double)
windowheight
;

widthdiv2 =
camera.neardist

* tan(
camera.aperture

/ 2); // aperture in radians

cameraright

=
crossproduct
(
camera.dir,camera.up
); // Each unit vectors

camright.x

*=
camera.eyesep

/ 2.0;

camright.y

*=
camera.eyesep

/ 2.0;

camright.z

*=
camera.eyesep

/ 2.0;



if (!stereo) {


glMatrixMode
(GL_PROJECTION);


glLoadIdentity
();





top = widthdiv2;


bottom =
-

widthdiv2;


left =
-

aspectratio

* widthdiv2;


right =
aspectratio

* widthdiv2;


glFrustum
(
left,right,bottom,top,camera.neardist,camera.fardist
);


glMatrixMode
(GL_MODELVIEW);


glDrawBuffer
(GL_BACK);


glClear
(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


glLoadIdentity
();


gluLookAt
(
camera.pos.x

,
camera.pos.y,camera.pos.z
,




camera.dir.x,camera.dir.y,camera.dir.z
,




camera.up.x,camera.up.y,camera.up.z
);


// Create geometry here in convenient model coordinates

}


27

Symmetric
-

non stereo camera

else {


glMatrixMode
(GL_PROJECTION);


glLoadIdentity
();


top = widthdiv2;


bottom =
-

widthdiv2;


left =
-

aspectratio

* widthdiv2;


right =
aspectratio

* widthdiv2;


glFrustum
(
left,right,bottom,top,camera.neardist,camera.fardist
);


glMatrixMode
(GL_MODELVIEW);


glDrawBuffer
(GL_BACK_RIGHT);


glClear
(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


glLoadIdentity
();


gluLookAt
(

camera.pos.x

+
camright.x
,



camera.pos.y

+
camright.y
,



camera.pos.z

+
camright.z
,




camera.dir.x,camera.dir.y,camera.dir.z
,




camera.up.x,camera.up.y,camera.up.z
);


// Create geometry here in convenient model coordinates



glMatrixMode
(GL_PROJECTION);


glLoadIdentity
();


top = widthdiv2;


bottom =
-

widthdiv2;


left =
-

aspectratio

* widthdiv2;


right =
aspectratio

* widthdiv2;


glFrustum
(
left,right,bottom,top,camera.neardist,camera.fardist
);


glMatrixMode
(GL_MODELVIEW);


glDrawBuffer
(GL_BACK_LEFT);


glClear
(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


glLoadIdentity
();


gluLookAt
(

camera.pos.x

-

camright.x
,



camera.pos.y

-

camright.y
,



camera.pos.z

-

camright.z
,




camera.dir.x,camera.dir.y,camera.dir.z
,




camera.up.x,camera.up.y,camera.up.z
);


// Create geometry here in convenient model coordinates


}


glMatrixMode
(GL_PROJECTION);

glLoadIdentity
();

gluPerspective
(camera.aperture,aspectratio,0.1,10000.0);