Aven in stereoscopic 3D
Olly Betts
olly at survex.com
Wed Feb 7 03:36:35 GMT 2018
On Mon, Feb 05, 2018 at 12:39:03PM +0000, Pedro Silva Pinto wrote:
> Because Survex already relies on OpenGL to render the 3D window, I
> think little work is needed to make it possible.
I suspect the changes needed aren't extensive, but they're hard to
make without access to suitable hardware to test them on so it's
good you're up for a bit of coding.
> For what I was able to find out, OpenGL is implemented in Survex using
> the wxGLCanvas and wxGLContext classes. From their documentation it
> seems that stereoscopy is supported. To move from a plain 3D
> implementation to full stereoscopic 3D, a few things are needed:
> - correctly set up the canvas for 3D stereo: easy enough done by
> adding the WX_GL_STEREO property to the window attributes array
> (gla-gl.cc and aven.cc);
Yes - this should then mean you have four buffers (front and back
buffers for each eye) instead of two (front and back). Assuming
double buffering in each case that is, which is the norm.
With double buffering we draw into the back buffer while the front
buffer is shown on the screen, and then call SwapBuffers() to swap which
buffer is front and which back, thus actually displaying what we just
drew. Then we draw the next frame into the new back buffer, and so on.
Because the drawing happens out of sight this gives smoother update.
With double-buffered stereo, you'll want to draw the new frame into
the back buffer for each eye and then swap the buffers together
(which I'd expect SwapBuffers() does in this case).
> - introduce a loop to run the drawing sequence twice - one for each
> eye - between the StartDrawing and FinishDrawing calls (gla-gl.cc);
You also need to arrange to select the appropriate left or right eye's
buffers to draw into before drawing for that eye. It looks like
glDrawBuffer(GL_BACK_LEFT) and glDrawBuffer(GL_BACK_RIGHT) do that:
https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawBuffer.xhtml
And also only call SwapBuffers() once you've done the drawing for both
eyes. It is not really clear to me if it's better to keep
StartDrawing() and FinishDrawing() as being called once per frame or to
call them once per eye per frame.
> - alter the math for the lr variable to account for the parallax (eye
> separation) for the glFrustum function call. Not sure if the math for
> the glOrtho function call needs to be changed too.
The glOrtho case in SetDataTransform() is Aven's standard view, which
isn't a perspective view. Historically that was because drawing a
non-perspective view was faster on computers in the 1990s, but it also
works better for a plan view as it means points align in the plot when
(and only when) they're vertically above each other.
I'm not sure how well giving each eye a non-perspective view from a
slightly different angle works - I suspect it'll be OK as the brain is
quite good at coping, but it might just give the viewer a headache.
You might need to do something about SetIndicatorTranform() too - this
ortho projection is used for the "indicators" (scale bar, colour key,
compass, and clino), and also for some other things - station labels,
the measuring line, and sometimes for blobs and/or station names (how
these are drawn depends on what the OpenGL implementation in use
supports). You might find it's simplest just to disable anything
which uses this projection to start with. Or perhaps just specify
glDrawBuffer(GL_BACK) in SetIndicatorTranform() so that at least this
is drawn for both eyes.
Cheers,
Olly
More information about the Survex
mailing list