
       StereoPOV 0.2

______________________________
POV-ray with STEREO-trace mode

Hermann Vosseler, 4/2002, 2/2003


This patch enables some of the camera types built into POV-ray to
generate real 3D output by generating stereoscopic pairs of images.
In "STEREO-trace"-mode, the width of the output images created will
be double the amount specified, containing left and right view of the
pair side-by-side. There are deliberately, by design decision, no other 
output formats (e.g. anaglyphes, interlaced) available, because creating 
such is the job of a painting or image mounting program, not a raytracer. 

The key feature of this patch is the ability to render the two halfimages
in a single raytracing pass, whilst sharing the results of lighting, texture
and radiosity calculations.
Five built in camera types are "stereoscopically enabeled": perspective, orthogonal,
fisheye, cylindrical and spherical wideangle, the latter beeing a new addition
specifically designed to create full range stereoscopic images of fisheye type.


Syntax: 
Stereoscopy utilizes two almost identical views of a given scene,
one for each eye. The spacing between this two viewpoints is called Stereo Base.
It corresponds to the (average) eye spacing of humans (about 65 mm) but can differ
from this for gaining special effects.
In StereoPOV, the STEREO-trace function is activated by specifying one of the
following stereoscopic parameters in camera definition:
stereo_base <float>       explicitely defines the Stereo Base to be used.
window_distance <float>   places the Stereoscopic Window at the given distance
                          with respect to the cameras location in the scene.
                          If stereo_base is omitted, it will be guessed based
                          on window_distance.
screen_width <float>      declares the width of the screen intended for presentation
                          of the resulting image. Everything is scaled, so the resulting
                          stereoscopic window machtes the given screen width (actually
                          the stereospcopic base is inverse scaled to gain this effect)
Specify only window_distance and let StereoPOV do the rest, if in doubt.
(See "hints on setting up the stereo camera" below)

Output Format: Both halfimages side-by-side in a single output file, left image left.
Alternative Output Format: It is very comon to swap the order of the halfimages in
stereo pairs, thus making them suitable for cross-eyed viewing (i.e. left image at
right side). You can convert this output to .JPEG or .PNG in order to view them with a 
JPS-Viewer in a variety of formats (red/green, red/blue, cross-eyed, wall-eyed, interlaced)

cross_eyed                use this keyword in camera definition to gain cross-eyed output.
                          (inverts the sign of stereo base to achieve the desired result)


Options: for controling the operation modes there are three new .INI Options:

Stereo_Trace=Off     disables STEREO-tracing explicitly.
                     (in contrary, it can be enabled ONLY by adding the stereo_base
                     in camera definition.)
Stereo_Cache=On/Off  Activates (default) or deactivates StereoCache. If deactivated,
                     the calculations for left and right halfimage are performed 
                     interleaved, but independently.
Stereo_Cache_Tolerance=<float> 
                     StereoCache hit tolerance. This value defaults to 1.0, i.e. a 
                     hit occures, if the two found intersections for left and right
                     match to within one Pixel or Subpixel (the latter while AAing).

Please note:
- You need to give the version directive "#version unofficial stereopov 0.2"
- All POV-ray parameters and options defining explicit pixel or column numbers,
  are now to be based on the size of a single half image (and not on the width
  of the image file produced, which is doubled). 
- You can't use Vista buffer while STEREO-tracing.
All the other features of POV-ray are retained unmodified.



________________________________________________________________________________
                 
                 
LEGAL INFORMATION

This is an unofficial patch for the Persistence of Vision Raytracer Ver. 3.5
Use and distribution shall be governed by the rules of POVLEGAL.doc Ver. 3.5
This software is provided "as is" without any warranty or guarantees.

Please feel free to contact me if you have questions, bug reports or
suggestions for future work. I will try my best to answer you, but please
understand that I can not guarantee any response.

Author: Hermann Vosseler
 eMail: Ichthyostega@web.de
 
 
In Order to compile and/or run this software, you will need a copy of
the official POV-Ray distribution and source (Ver. 3.5) available at
http://www.povray.org
________________________________________________________________________________




Why using a built-in stereoscopic camera?
As you probably will know, it is very easy to create steroscopic views with POV-ray. 
Simply render the scene two times while applying a small lateral shift to the
camera position. Using this approach, we will encounter three problems:
 1. The time amount needed will be doubled. With increasing quality demands, Doing more
    sophisticated texturing and modelling, applying more advanced lighting techniques,
    you will soon arrive at rendering times of some hours up to some days anyway. 
    So often we have to do a tradeoff. Very bad, as stereoscopy per se is much more
    quality demanding then "normal" flat imaging.
 2. Any random features used in the raytracing process will show up as image errors
    in stereoscopic view (similar to the problems caused in animations). This is
    especially true for textures with "crand", area ligths with jitter or when 
    using media.
 3. Generally, you can't use special camera types.
Such problems are solved or ameliorated by the patch presented here, as the STEREO-
tracing is built into the core raytracing engine. The use of StereoCache datastructures
allows the two half images to share computations. This alredy in simple scenes decreases 
the time amount needed to create a stereoscopic pair.
And in scenes with some area lights and texturing, typical values range 150% (to be 
compared to 200% time amount for calculating two independent views with camera shift).
The speed gain is especially noticable when using radiosity. Complex ray object inter-
section calculations on the contrary, or the tracing of reflected and refracted rays 
and of media is *not* speeded up. 
StereoCache solves the problems wiht crand and area lights. Jitter appears to be
grainyness on the surface of the objects. On the other hand, media calculations
have to be done twice independently for the two viewing rays in order to gain the
impression of media floating in the air between the visible objects. Here the
jitter problem remains.
As STEREO-tracing is built into the raytracer, it is posible to adjust the geometry
of the camera projection indepently for every pixel in the image. This allows for
camera constructions not to be achieved with real mechanic/optical cameras.



    Some technical details of the implementation.
    
    (You can safely skip this section if not interested)
    Basic adjustments:  Stereo_base added to camera struct. The switch opts.Stereo_trace
    will be activated, when the Frame.camera is stereoscopic. 
    While STEREO-tracing, the width of the image created is twice the number of columns 
    specified. Thus introduced new variable Frame.Output_Screen_Width to be used while
    creating (or re-reading) the output file and for allocating memory for the row 
    buffers. WriteLine will use the width specified while opening the file. When opening
    partial rendered files, the line width may be adjusted downwards to fit into the
    preallocated arrays in order to prevent a crash. Of course, if the image width 
    specified doesn't match the width of the continued render, the output will be
    rubbish, but POV-Ray won't crash.
    The VistaBuffer in it's current form can't be used in STEREO-trace mode. We have
    two centres of projection and, moreover, even in stereoscopic perspective camera
    the "direction" vector is no longer orthogonal to the "up" and "right" vectors.
    (It seemes that with some modifications it would be possible to use the vista
    buffer though -- to bee investigated further).
    The Stereo Cache datastructure is querried *after* doing the ray object intersection
    test. It is utilized only for primary rays, not for transmitted, reflected or re-
    fracted rays. The best new intersection found will be compared with cached inter-
    sections, the latter beeing used if possible and within certain error bounds. If
    no cached intersections were found (maybee because the cached ones were to far off
    the new intersection point), the new intersection will be fed to cache to be used 
    while tracing the other half image. Cached intersections are stored at the predicted 
    location where they could be used, and they are stored only if calculations on the 
    other half image still have to reach this location. This includes calculating
    the stereoscopic deviation based on angle, depth of intersection and projection
    geometry. 
    For every possible sub pixel StereoCache preallocates a slot to hold at most one 
    cache entry. The "best" (i.e. nearest to camera) intersection found is cached.
    So querrying the cache involves only a small number of slots to be tested, according
    to the current pixel or sub pixel size. Adaptive supersampling means that the
    current pixel size is reduced in several recursive steps.
    Each cache entry is dedicated to a single ray object intersection point and
    holds the followin data:
      (a) - Angle of incidence and contribution to the diffuse
            illumination for each light source. ("light list")
      (b) - Radiosity contribution                                          
      (c) - Result of Photon gathering for the intersection point
      (d) - Local pigment and normal values of the textur(es) at this point.
    StereoCache may either be inactive or operates in "put" (insert data) or
    "fetch" (get cached data) mode. The StereoCache system at a whole is inactive for
    all but primary rays. (i.e. it is operative only at trace_level 1). The cached
    light list (a) is used for all lighting calculations at given intersection point.
    The same holds true for the radiosity and photon contribution (b) and (c), wheras 
    pigment and normal values (d) are different for each textue component or layer. 
    As textures may be defined to arbitrary complexity, StereoCache assumes that for a 
    given, fixed intersection point the evaluation and calculation order of the texture 
    functions will be reproducible. Thus it is sufficient to store a flat list of all 
    texture values encountered while recursivly evaluating the textures and retrieving 
    the cached values in same order.            
    As this operation scheme continously creates new data blocks to be hold in cache
    only for a small number of main loop iterations before beeing released, StereoCache
    maintaines a pool of preallocated data blocks to be reused as needed.
    
    
    
    The StereoCache statistics
    
    When StereoCache is used, it will issue some additional statistics after 
    rendering is finished. A typical example:
    ----------------------------------------------------------------------------
    Stereo Cache                    315660          145308     46.03
     Hit vs.new I.                  177516          145308     81.86
     I. fed to cache                170352          155472     91.27
     Cached I. reused               155472          124879     80.32
           reused Intersections avg. 0.93 / 1.16 times (total/succsessfull)
    ----------------------------------------------------------------------------
    The first number is the overall success quote of StereoCache. As the two half
    images are treated strictly symmetrical, this value can (theoretically) be at
    most 50%. 
    If there is a cached intersection found, it has to be compared to the new 
    intersecion and can only be used if it's near enough. The secound number gives 
    the fraction of cached intersections compared and prefered over new ones.
    If there is no cache hit, we try to fed the new intersection to cache. This
    is possible only if there is a chance left, that the calculations on the other 
    half image can use this intersection. (Third number)
    The fourth number counts the cached intersections really reused.
    A cached intersection may be reused several times, especially while anti-aliasing.
    The last number pair keeps track of the average reuse count, the first figure
    based on the total number of Intersections fed to cache, the second figure based
    on the count of intersections succsessfully reused.
    



Stereoscopic Cameras

This POV-Ray Patch defines five camera types able to create stereoscopic images. 
The last two camera types in this list beeing new additions.
 Default POV-Ray camera        "perspective"
 Orthogonal projection         "orthogonal"
 Fisheye lens                  "fisheye"
 Stereo panoramic camera       "cylinder 5 "
 Spherical wide angle camera   "ultra_wide_angle 2 "


 
Image Size and Stereoscopic Window

Much in contrary to common (flat) images, stereoscopic images are dedicated allways 
to a fixed image size. Arbitrary scaling will result in a loss of depth impression,
thus degrading the image quality to some extent. To be more specific: An image
optimally suited for presentation (maybe as anaglyphes) on a 17 inch computer monitor, 
will show up with unnaturally exaggerated depth on the IMAX screen, causing eye strain
and headache or even falling apart. On the contrary, when our image has been targeted
to a slide projection screen of 4m width, it will give an almost flat impression
(as if beeing made out of paper) when viewed on home projection screen or monitor.
This effect may be ameliorated partially by readjusting the stereoscopic pair, but
you won't get optimal results this way. To put it short, stereoscopic images allways 
have to be composed with a certain window size and -location in mind.
Thus all stereoscopic camera types built into StereoPOV were designed to behave
consistently with respect to image size and location of the Stereoscopic Window.
The "up" and "right" vectores not only define the aspect ratio of the image, they also
define the dimensions of the resulting stereoscopic window measured in model units
(POV-Ray scene units). And the "direction" vector not only defines the effective
viewing angle, it at the same time defines the optimal viewing distance for
stereoscopic slide projection or monitor presentation (again measured in POV-Ray
units).
The following example will illustrate this principle:
Let one POV-Ray unit be interpreted as 1 m. Assumed further, the image is designed 
for presentation on 1.80m projection screen (this size is known to be well suited for
small audiences like  stereoscopic camera clubs or meetings of some society and the like).
Then the camera can be defined as

camera{ location <0,0,0>
        direction z * 1.76
        right x * 1.8
        up x * 1.8 * 2/3    // aspect ratio 3:2
        stereo_base 0.065
        translate <....>
        look_at <....>
      }
This will yield a moderate wide angle view (55 deg), 
corresponding to f=35mm for photograpic cameras (KB).
This definition further tells us, the stereoscopic window will be found at 
1.76m distance from assumed camera location, and this means we may start placing 
the nearest objects at this distance. (We indeed should start at this distance and 
group the main objects of the scene near by, in order to achieve a good impression 
of depth) Of course we can leave out the "direction" vector and specify "angle 90" 
instead. StereoPOV will then derive the direction=1.76m . The down side of the latter 
approach is: as the "direction" vector is computed internally, we don't know its exact 
length. 
Specifying the "direction" vector explicitly gives exact control of where the
stereoscopic window will be.

In case of the non-planar camera types (panoramic and fisheye types) the "direction"
vector defines the radius of the image cylinder or sphere as well. But the size of
the stereoscopic window at the same time is defined with respect to the planar image 
"rolled off" the cylinder or sphere.


hints on setting up the stereo camera

Based on this principles, StereoPOV implements some features to aid setting up stereo-
scopic cameras or to help adapting at given scenes. Additionally, before start of rendering, 
the camera parameters to be used are printed, so you can see what actually is going on.

All stereoscopic camera types start out with a window of the dimensions given by
"up" and "right" and located at a distance given by the "direction" vector. (so called
natural window of the camera). StereoPOV allways uses the bare numbers given and never
attempts to apply or transform units of measurement. As a consequence, the effective
units of measurement are those, *you* are using conceptually, so you should be consequent
in this respect.
Now, if the user specifies a certain "window_distance", this denotes a stereoscopic 
window located at the given distance with respect to the camera origin ("location" vector). 
StereoPOV compares this with the current length of "direction" vector in order to derive 
a general scale factor. By applying this scale factor to the camera as a whole, the 
stereoscopic window will be brought to the distance desired. (Aspect ratio and image
angle remaining unmodified).
Nothing has been done to define the stereo base thus far. As allredy stated, stereo base
is the eye separation effective while creating the stereo image, and thus is measured
with respect to the dimensions and objects in the POV-Ray scene to be rendered. If the
user doesn't specify a "stereo_base", StereoPOV guesses the stereoscopic base by applying
a heuristic often referred to as "1:30 rule" (or, more precisely, as "1/f rule"). This
means assuming the picture has to be a "nice picture" or "fine picture", and moreover,
the viewer has to be related to the subject of the picture in a certain, well known
manner. Brought into the context of stereoscopy, this yields a specific geometrical
constellation, which enables us to derive necessary parameters like eye separation
of the viewer with respect to the (virtual) dimensions of the POV-Ray scene.
By applying this rule, we get a camera with a natural window sized aproximately 2 meters.
But what, if the final presentation screen has much differing dimensions (e.g. large scale
slide projection or computer monitor)? A possible solution in this case could be to apply
an appropriate scale factor to the whole scene to let the width of resulting stereoscopic 
window match the desired presentation screen width. By setting "screen_width", you can
tell StereoPOV to do so by inverse scaling the stereo base. Please note, that "screen_width"
is related to dimensions in the real world, much in contrary to "window_distance", which is
related to the dimensions of the scene to be rendered. This third stereo camera parameter
("screen_width") is experimental, in so far its usability still has to be proven.

In order to acchieve good image composition, I saw people taking two very different approaches.
One possibility could be, to arrange and organize objects near the stereoscopic window in a 
tastefull manner. The "window_distance" parameter is intended to support this approach. A good
starting point is to use the distance of the nearest object as "window_distance", thus placing
this object in the window plane. The other possible aproach is to stick to dimensions and
proportions of the real world, using real world measurements as far as possible. In a consequence,
for this approach you define the stereoscopic base to be the average human eye separation (65mm)
and you define the "direction", "up" and "right" vectors of the camera so to match the desired
presentation situation (screen size, intended optimal distance to viewer). (Hint: set up the
camera at origin and then apply a series of rotations and translations to place the camera
as appropriate)




Notes on non-standard Camera Types


With Orthogonal camera, the visual depth extension of a given object has a fixed
value, independent of the object's distance to the camera. As this doesn't correspond
to any real life visual experience, objects will seem to be distorted in depth 
direction when viewed stereoscopically. Another consequence of this is, that you
can't fuse the half images of objects far off, because they are to far apart.
Bottom line is, you can use this projection type only for objects near to the 
image plane, i.e. the stereoscopic window. (Limit in depth direction is two times
the length of the "direction" vector, or the window_distance, if specifyed)

POV-Ray's Fisheye camera creates an image utilizing spherical coordinates commonly
used in mathematics. This implies, that corresponding image elements don't nessesarily
appear at the same height (y) in both half images. (i.e. "height errors"). The resulting
image will cause eye strain; only a small region near the center of the image is usable,
if at all. To cope with this problem, I let the stereo-effect drop off to zero with
increasing angle, so that beyond +-90 deg the output will be mono (flat). An additional
adjustment factor was added to make the flat image region and the circular image border
apear in the stereoscopic window plane. So the image "opens to depth" in the middle,
as if it was a cave. You should consider this implementation as an experimental feature,
I hope, it's of some use. (Note that StereoCache is disabled for Fisheye.)

Stereo Panoramic camera is inspired by some real world panoramic camera constructions
where the whole optical system turnes round at exposure time. Here this means, that
the stereoscopic baseline (the line connecting the two centres of projection) is turned
as well, thus being oriented optimally for every direction. This yields a constant depth
impression over the whole image angle up to 360 deg and more. On the contrary, in 
vertical direction this cylindric projection can be compared with the normal perspective
camere, including the well known degeneration problem produced by perspective camera, 
when the (here: vertical) image angle gets too large.
Like all the other stereoscopic cameras in this patch, the stereo panoramic camera
adheres to the rule, that the "right" vector corresponds to the width of the final
image created (measured in POV-Ray units). Now, as the image is gained by rolling it
off the image cylinder and the radius of this image cylinder is defined by the
"direction" vector of the camera definition, the ("direction","right")-Pair alredy
completely defines the image angle. (If, on the other hand, an angle value is given,
the length of the "direction" vector can be derived).
At the same time, via the "right"/"up" ratio, the vertical image angle is completely
defined, as the stereo panoramic camera always uses the same scale factor in vertical
and horzontal direction (i.e. respects the given aspect ratio). This behaviour of
the "direction", "right" and "up" vectors differs from the one of the "cylinder"
camera types alredy build into POV-Ray. (And for this reason I introduced a new
"cylinder" camera type 5 instead of making "cylinder 1" stereoscopic). As a practical
consequence, if you chose an aspect ratio differing from quadratic image, the vertical
image angle is adjusted to accomodate as well. You should play around a bit with
this behaviour to get a feeling how it works. It may seem strange at a first glance,
but it produces more consistent results with respect to the placement of the 
stereoscopic window for all camera types.

My newly developed Spherical Wide Angle Camera (ultra_wide_angle 2) adheres to
the same rule. "direction" gives the radius of the image sphere, "right" the
width of the final planar image "rolled off" the sphere, image angle and placement
of stereoscopic window will be derived to fit. Or, if you give an angle value,
the "direction" will be adjusted to accomodate.
The chosen type of projection differes significantly form Dan Farmer's ultra wide
angle camera (ultra_wide_angle 1). The latter beeing a fisheye projection sort of 
"streched out diagonally" in order to fill an rectangular image area. This would 
result in the same problems with stereoscopy encountered by the fisheye camerea itself.
My spherical wide angle camera (ultra_wide_angle 2) on the contrary allways retains 
the same height for corresponding image elements in both half images. This is
achieved by rather "rolling off" the image. To be more precise, to a given viewing
ray, the image sphere is first rolled up or down (vertically) starting from the
center of the image region, and then rolled horizontally to yield the position of 
the resulting pixel. Now, as the circumference of a sphere gets smaller and smaller
as we aproach the poles, this causes vertical lines to "fall" towards the (vertical)
middle axis of the image. On a pure empirical base (having a lot of experience in
drawing and painting views with spherical or fisheye type perspectives), I introduced
a variable horizontal stretch/correction factor and accomodated the stereoscopic
imaging accordingly. This gives the vertical lines a more soft slope near the aequator.
The price to pay for this is a rather sudden turn of the vertical lines towards 
converging to the poles at greater vertical angles.
Similar to the stereo panoramic camera, the stereoscopic baseline is turned round,
(oriented towards the ray currently to be traced), thus yielding a constant depth 
impression over the whole image area. At the usual image angles, the whole 
rectangular image area is covered. But enlarging this image area while keeping the 
radius of the sphere ("direction" vector) constant, at some point the curved border 
lines of the projection will show up. This "onion shaped" border lines go curved in 
depth direction as well, running from pole to pole, i.e.
form infinity up above to infinity down below.
      
        


$Id: STEREO-trace.txt,v 1.3.2.1 2003/02/10 02:16:04 HIV Exp $


