POV-Ray : Newsgroups : povray.general : What to do with the pixel in the middle Server Time: 19 Feb 2019 23:31:24 GMT
 What to do with the pixel in the middle (Message 1 to 10 of 13)
 From: ingo Subject: What to do with the pixel in the middle Date: 1 Feb 2019 21:34:36 Message:
```Tinkering with various user defined cameras I often seem to run into the
following; using select in a function you either select bigger smaller or
bigger and equal or smaller:

from a stereo cam:
#local D2_X_Fn = function(u,v){
select(
(u<=0),   //u<0????
-1,
D1R_X_Fn((u/AspectU*image_width)-0.25,v),
D1L_X_Fn((u/AspectU*image_width)+0.25,v)
)
};

the alternative is select only smaller or bigger resulting in a pixel wide
black line.

So, what to do with the pixel in the middle? Another select with u=0?

ingo
```
 From: Bald Eagle Subject: Re: What to do with the pixel in the middle Date: 1 Feb 2019 22:05:01 Message:
```ingo <ing### [at] tagpovrayorg> wrote:

> from a stereo cam:
> #local D2_X_Fn = function(u,v){
>   select(
>     (u<=0),   //u<0????
>     -1,
>     D1R_X_Fn((u/AspectU*image_width)-0.25,v),
>     D1L_X_Fn((u/AspectU*image_width)+0.25,v)
>   )
> };
>
> the alternative is select only smaller or bigger resulting in a pixel wide
> black line.
>
> So, what to do with the pixel in the middle? Another select with u=0?

Well, that's a pretty interestingly constructed select() function.

I would have done away with the Boolean operator and the semicolon.
I don't think the one you're using ever results in a <0 value for select() to
operate on, since the boolean operator only returns 0 or 1.
So just to keep myself sane during debugging, I'd write it like:

#local D2_X_Fn = function(u,v){
select (u,
D1L_X_Fn ((u/AspectU*image_width)+0.25,v))  // u <  0
D1R_X_Fn ((u/AspectU*image_width)-0.25,v))  // u >= 0
)
}

I guess if you wanted that one-pixel wide strip at the center to use the other
function, then you'd use the 4-argument version and repeat the first function
for the u = 0 case.

Hopefully at some point you can share some of your understanding of the
user-defined camera with a few simple explanatory examples / tutorials.
```
 From: ingo Subject: Re: What to do with the pixel in the middle Date: 1 Feb 2019 23:15:37 Message:
```in news:web.5c54c166738ba468765e06870@news.povray.org Bald Eagle wrote:

> I guess if you wanted that one-pixel wide strip at the center to use
> the other function, then you'd use the 4-argument version and repeat
> the first function for the u = 0 case.
>

Bill,
on an almost "aside way" you explain me that things can be done simpler

> Hopefully at some point you can share some of your understanding of
> the user-defined camera with a few simple explanatory examples /
> tutorials.

in the land of 'nikked' eagles one feather ain't king ;)

but seriously, I almost exclusivly use the 4 term select as:
select(query, ignore(=-1), true, false)

Regarding the pixel in the middle, where does it belong ??? In case of a
stereo cam, the left or right side of the image, there is no in between?

User defined cameras are great, just starting to explore them, but ...

they are indeed rather under documented. It's hard to understand what
exactly happens, but once I get it I'm willing to do a write up (to be
corrected by the ones that realy understand). An other thing is that they
seem to be "verbose". When I try to reimplement an existing 10 line of c++
code cam it seems I need at least 5 times more space. It requires a lot of
trials and mostley errors as I have a hard time wrapping my brain around
some things and my brain isn't very structured, more intuitive.

User defined cameras are great, just starting to explore them, but ...

Ray tracing is about rays, objects an cameras and I realy think POV-Ray
deserves a whealthy choise of ready made cameras. Paul Bourke has defined
a very nice set of stereo cameras a decade ago that I.M.H.O would be very
welcome in an official distribution. Le Forgeron, as I discovered today,
has made a set of _/incredible and bewildering/_ set of 'planet mapping'
camera's. The https://www.cartographersguild.com would love them (/him for
that), they do not seem to have discovered them yet. Let's not forget
Fabrizio's (Clodi) OSD camera.

ingo
```
 From: ingo Subject: Re: What to do with the pixel in the middle Date: 1 Feb 2019 23:33:31 Message:
```in news:XnsA9EA2A6B5B0Dseed7@news.povray.org ingo wrote:

> they seem to be "verbose"

A dense stereo cam file for example. Sanity check before serious use,

ingo

---%<------%<------%<---
#version 3.8;
global_settings{ assumed_gamma 1.0 }

#include "math.inc"
#include "transforms.inc"
//#include "udCameras.inc"

#macro udcLookAtTransform(
D0_X_Fn, D0_Y_Fn, D0_Z_Fn,
pLocation, pLookAt, Angle,
optional Roll, optional vDirection,
optional vRight, optional vUp
)
/*==
Transforms the direction function of a user defined camera to look into
the
pLookAt direction from the camera location.

Code base by: Tor Olav Kristensen, http://subcube.com
This macro is intended to be used in user defined cameras.
For example use, see udcPerspective().

D0_X_Fn, D0_Y_Fn, D0_Z_Fn (function): the original camera direction
functions.
pLocation  (vec) : the location of the camera
pLookAt    (vec) : the point to look at
Angle    (float) : horizontal field of view o view angle
Roll     (float) : optional, defaults to 0.
Roll, a.k.a. banking, rotates the camera around the
view
direction vector.
vDirection (vec) : optional, defaults to +z.
vRigth     (vec) : optional, defaults to
<image_width/image_height,0,0>.
vUp        (vec) : optional, defaults to +y.
*/
#ifndef(local.Roll)
#local Roll = 0;
#end
#ifndef(local.vDirection)
#local vDirection = +1*z;
#end
#ifndef(local.vRight)
#local vRight = +image_width/image_height*x;
#end
#ifndef(local.vUp)
#local vUp = +1*y;
#end
#local vLookAt = pLookAt - pLocation;
#local LookAtTransform = transform{
Reorient_Trans(z, vLookAt)
Axis_Rotate_Trans(vLookAt, Roll)
}
#local vDirection_1 = vtransform(vDirection, LookAtTransform);
#local vRight_1 = vtransform(vRight, LookAtTransform);
#local vUp_1 = vtransform(vUp, LookAtTransform);
#local <X1_X, X1_Y, X1_Z> = vtransform(x, LookAtTransform);
#local <Y1_X, Y1_Y, Y1_Z> = vtransform(y, LookAtTransform);
#local <Z1_X, Z1_Y, Z1_Z> = vtransform(z, LookAtTransform);
#local D1_X_Fn = function(u,v){
0
+ X1_X*D0_X_Fn(u,v)
+ Y1_X*D0_Y_Fn(u,v)
+ Z1_X*D0_Z_Fn(u,v)
};
#local D1_Y_Fn = function(u,v){
0
+ X1_Y*D0_X_Fn(u, v)
+ Y1_Y*D0_Y_Fn(u, v)
+ Z1_Y*D0_Z_Fn(u, v)
};
#local D1_Z_Fn = function(u,v){
0
+ X1_Z*D0_X_Fn(u, v)
+ Y1_Z*D0_Y_Fn(u, v)
+ Z1_Z*D0_Z_Fn(u, v)
};
(D1_X_Fn, D1_Y_Fn, D1_Z_Fn)
#end

#macro udcStereo(pLocation,pLookAt,Angle,FocalDist)
//http://paulbourke.net/stereographics/stereorender/
#local EyeSep = FocalDist/30;
#local Delta  = (image_width*EyeSep)/(2*FocalDist*tand(Angle/2));
#local Angle1 = 2*atand((image_width+Delta)*tand(Angle/2)/image_width);
#local AspectU = image_width+Delta+Delta;
#local AspectV = image_height;
#local vMovement  = EyeSep/2*vnormalize(vcross(pLookAt-pLocation,
<0,1,0>));
#local pLocationL = pLocation+vMovement;
#local pLocationR = pLocation-vMovement;
#local <LocationXL, LocationYL, LocationZL> = pLocationL;
#local <LocationXR, LocationYR, LocationZR> = pLocationR;
#local LocationX = function(u){select((u<=0),-1, LocationXR,
LocationXL)};
#local LocationY = function(u){select((u<=0),-1, LocationYR,
LocationYL)};
#local LocationZ = function(u){select((u<=0),-1, LocationZR,
LocationZL)};
#local D0_X_Fn = function(u,v){u*AspectU};
#local D0_Y_Fn = function(u,v){v*AspectV};
#local D0_Z_Fn = function(u,v){AspectU/2/tand(Angle/2)};
#local pLookAtL = pLookAt+vMovement;
#local pLookAtR = pLookAt-vMovement;
#local(D1L_X_Fn, D1L_Y_Fn, D1L_Z_Fn) = udcLookAtTransform(
D0_X_Fn, D0_Y_Fn, D0_Z_Fn, pLocationL, pLookAtL, Angle1,,,,
);
#local(D1R_X_Fn, D1R_Y_Fn, D1R_Z_Fn) = udcLookAtTransform(
D0_X_Fn, D0_Y_Fn, D0_Z_Fn, pLocationR, pLookAtR, Angle1,,,,
);
#local D2_X_Fn = function(u,v){select(
(u<=0),
-1,
D1R_X_Fn((u/AspectU*image_width)-0.25,v),
D1L_X_Fn((u/AspectU*image_width)+0.25,v)
)};
#local D2_Y_Fn = function(u,v){select((u<=0),-1, D1R_Y_Fn(u-0.25,v),
D1L_Y_Fn(u+0.25,v))};
#local D2_Z_Fn = function(u,v){select((u<=0),-1, D1R_Z_Fn(u-0.25,v),
D1L_Z_Fn(u+0.25,v))};
camera {
user_defined
location {
function {LocationX(u)}
function {LocationY(u)}
function {LocationZ(u)}
}
direction {
function {D2_X_Fn(u,v)}
function {D2_Y_Fn(u,v)}
function {D2_Z_Fn(u,v)}
}
}
#end

#declare ZeroParallax = 3;
udcStereo(<0,0,-ZeroParallax>,<0,0,0>,55,ZeroParallax)
light_source{< 1000,1000,-1000>, rgb 1}
light_source{<-1000,1000,-1000>, rgb .3}
difference{
box{-0.5,0.5 pigment{rgb 1}}
box{-0.5,0.5 scale <0.97,0.97,1.20>}
box{-0.5,0.5 scale <0.97,1.20,0.97>}
box{-0.5,0.5 scale <1.20,0.97,0.97>}
}
sphere{<0,-0.2,-1>,0.035 pigment{rgb z}}
sphere{<0,0.2,10>,0.03 pigment{rgb 1}}
plane{y,-1.5 pigment{checker}}
plane{z,20 pigment{function{abs(y)} scale 12 translate<0,-1.5,0>}}
sphere{<0, 0.0, 0>,0.03 pigment{rgb y}}
```
 From: Bald Eagle Subject: Re: What to do with the pixel in the middle Date: 2 Feb 2019 01:40:01 Message:
```ingo <ing### [at] tagpovrayorg> wrote:
> in news:web.5c54c166738ba468765e06870@news.povray.org Bald Eagle wrote:
>
> > I guess if you wanted that one-pixel wide strip at the center to use
> > the other function, then you'd use the 4-argument version and repeat
> > the first function for the u = 0 case.
> >
>
> Bill,
> on an almost "aside way" you explain me that things can be done simpler

Well, it's not "simpler" - it's just more straightforward for the easily
confused such as me.   :P

> but seriously, I almost exclusivly use the 4 term select as:
> select(query, ignore(=-1), true, false)

Well, whatever works for you, if you use it consistently without problems - go
for it.

> Regarding the pixel in the middle, where does it belong ??? In case of a
> stereo cam, the left or right side of the image, there is no in between?

Nope.  I suppose you could do the calculations and find out where to shift the
camera so that it's "1 pixel" over one way or the other, and then adjust for
that...
Can you check and see if abs (u) > epsilon so that you can filter out a lot of
"0" results...?

> they are indeed rather under documented. It's hard to understand what
> exactly happens, but once I get it I'm willing to do a write up (to be
> corrected by the ones that realy understand).

Sure, I think the idea is to just post some reasonably well commented code, that
we can look at when we want to implement a similar camera structure, and if
necessary, supplement with some renders, drawings, etc.

> An other thing is that they
> seem to be "verbose". When I try to reimplement an existing 10 line of c++
> code cam it seems I need at least 5 times more space. It requires a lot of
> trials and mostley errors as I have a hard time wrapping my brain around
> some things and my brain isn't very structured, more intuitive.

I seem to be able to teach myself what I need to know faster when I try to
explain the problem I'm having, or when I try to condense it down into a macro
or a formula.

> Ray tracing is about rays, objects an cameras and I realy think POV-Ray
> deserves a whealthy choise of ready made cameras. Paul Bourke has defined
> a very nice set of stereo cameras a decade ago that I.M.H.O would be very
> welcome in an official distribution.

I think there's a LOT of Bourke's work that ought to be readily available and
used a lot more, and even implemented under the hood in C++ so that it's not
stuck in super-slow SDL.

> Le Forgeron, as I discovered today,
> has made a set of _/incredible and bewildering/_ set of 'planet mapping'
> camera's.

Jerome is a really intelligent, inventive, and hard-working guy, and I wish I
had more time to sit down and play with all of the goodies he has coded up over
the years.

> The https://www.cartographersguild.com would love them (/him for
> that), they do not seem to have discovered them yet.

Yet another forum to advertise the wonders of POV-Ray in   :)

> Let's not forget
> Fabrizio's (Clodi) OSD camera.

I have not (yet) heard of that.
Aha -

(Clodo)
```
 From: clipka Subject: Re: What to do with the pixel in the middle Date: 2 Feb 2019 02:21:14 Message: <5c54fe9a\$1@news.povray.org>
```Am 02.02.2019 um 00:15 schrieb ingo:

> Regarding the pixel in the middle, where does it belong ??? In case of a
> stereo cam, the left or right side of the image, there is no in between?

That is a fundamental problem - but if you think about it, it's not
specific to user-defined stereo cameras, but to stereo images with an
odd number of pixels.

An even-numbered pixel image does not have any pixel at the center - it
has a _pixel border_ at the center.
```
 From: ingo Subject: Re: What to do with the pixel in the middle Date: 2 Feb 2019 08:08:57 Message:
```in news:5c54fe9a\$1@news.povray.org clipka wrote:

The back pixel in the middle makes sense,

thanks,

ingo
```
 From: ingo Subject: Re: What to do with the pixel in the middle Date: 2 Feb 2019 08:15:34 Message:
```in news:web.5c54f447738ba468765e06870@news.povray.org Bald Eagle wrote:

> I seem to be able to teach myself what I need to know faster when I
> try to explain the problem I'm having, or when I try to condense it
> down into a macro or a formula.
>

"literate programming" (http://www.literateprogramming.com/)

snippets of code and slowly condense the story into code.

ingo
```
 From: Tor Olav Kristensen Subject: Re: What to do with the pixel in the middle Date: 2 Feb 2019 18:35:00 Message:
```ingo <ing### [at] tagpovrayorg> wrote:
> in news:5c54fe9a\$1@news.povray.org clipka wrote:
>
>
> The back pixel in the middle makes sense,

To achieve this you can make the camera look another way when u equals zero,
e.g. like this:

direction {
function {
select(
u,
D1L_X_Fn(u*image_width/AspectU + 0.25, v),
0,
D1R_X_Fn(u*image_width/AspectU - 0.25, v)
)
}
function {
select(
u,
D1L_Y_Fn(u + 0.25, v),
1,
D1R_Y_Fn(u - 0.25, v)
)
}
function {
select(
u,
D1L_Z_Fn(u + 0.25, v),
0,
D1R_Z_Fn(u - 0.25, v)
)
}
}

- and then place something small with a black pigment, no_shadow and
no_reflection close to the camera in that direction (e.g. right above the
camera).

--
Tor Olav
http://subcube.com
```
 From: Tor Olav Kristensen Subject: Re: What to do with the pixel in the middle Date: 2 Feb 2019 19:45:00 Message:
```ingo <ing### [at] tagpovrayorg> wrote:
> in news:XnsA9EA2A6B5B0Dseed7@news.povray.org ingo wrote:
>...
> #macro udcLookAtTransform(
>     D0_X_Fn, D0_Y_Fn, D0_Z_Fn,
>     pLocation, pLookAt, Angle,
>     optional Roll, optional vDirection,
>     optional vRight, optional vUp
>   )
>   /*==
>   Transforms the direction function of a user defined camera to look into
> the
>   pLookAt direction from the camera location.
>
>   Code base by: Tor Olav Kristensen, http://subcube.com
>   This macro is intended to be used in user defined cameras.
>   For example use, see udcPerspective().
>
>   D0_X_Fn, D0_Y_Fn, D0_Z_Fn (function): the original camera direction
> functions.
>   pLocation  (vec) : the location of the camera
>   pLookAt    (vec) : the point to look at
>   Angle    (float) : horizontal field of view o view angle
>   Roll     (float) : optional, defaults to 0.
>                      Roll, a.k.a. banking, rotates the camera around the
> view
>                      direction vector.
>   vDirection (vec) : optional, defaults to +z.
>   vRigth     (vec) : optional, defaults to
> <image_width/image_height,0,0>.
>   vUp        (vec) : optional, defaults to +y.
>   */
>   #ifndef(local.Roll)
>     #local Roll = 0;
>   #end
>   #ifndef(local.vDirection)
>     #local vDirection = +1*z;
>   #end
>   #ifndef(local.vRight)
>       #local vRight = +image_width/image_height*x;
>   #end
>   #ifndef(local.vUp)
>     #local vUp = +1*y;
>   #end
>   #local vLookAt = pLookAt - pLocation;
>   #local LookAtTransform = transform{
>     Reorient_Trans(z, vLookAt)
>     Axis_Rotate_Trans(vLookAt, Roll)
>   }
>   #local vDirection_1 = vtransform(vDirection, LookAtTransform);
>   #local vRight_1 = vtransform(vRight, LookAtTransform);
>   #local vUp_1 = vtransform(vUp, LookAtTransform);
>   #local <X1_X, X1_Y, X1_Z> = vtransform(x, LookAtTransform);
>   #local <Y1_X, Y1_Y, Y1_Z> = vtransform(y, LookAtTransform);
>   #local <Z1_X, Z1_Y, Z1_Z> = vtransform(z, LookAtTransform);
>   #local D1_X_Fn = function(u,v){
>     0
>     + X1_X*D0_X_Fn(u,v)
>     + Y1_X*D0_Y_Fn(u,v)
>     + Z1_X*D0_Z_Fn(u,v)
>   };
>   #local D1_Y_Fn = function(u,v){
>     0
>     + X1_Y*D0_X_Fn(u, v)
>     + Y1_Y*D0_Y_Fn(u, v)
>     + Z1_Y*D0_Z_Fn(u, v)
>   };
>   #local D1_Z_Fn = function(u,v){
>     0
>     + X1_Z*D0_X_Fn(u, v)
>     + Y1_Z*D0_Y_Fn(u, v)
>     + Z1_Z*D0_Z_Fn(u, v)
>   };
>   (D1_X_Fn, D1_Y_Fn, D1_Z_Fn)
> #end
>
> #macro udcStereo(pLocation,pLookAt,Angle,FocalDist)
>   //http://paulbourke.net/stereographics/stereorender/
>   #local EyeSep = FocalDist/30;
>   #local Delta  = (image_width*EyeSep)/(2*FocalDist*tand(Angle/2));
>   #local Angle1 = 2*atand((image_width+Delta)*tand(Angle/2)/image_width);
>   #local AspectU = image_width+Delta+Delta;
>   #local AspectV = image_height;
>   #local vMovement  = EyeSep/2*vnormalize(vcross(pLookAt-pLocation,
> <0,1,0>));
>   #local pLocationL = pLocation+vMovement;
>   #local pLocationR = pLocation-vMovement;
>   #local <LocationXL, LocationYL, LocationZL> = pLocationL;
>   #local <LocationXR, LocationYR, LocationZR> = pLocationR;
>   #local LocationX = function(u){select((u<=0),-1, LocationXR,
> LocationXL)};
>   #local LocationY = function(u){select((u<=0),-1, LocationYR,
> LocationYL)};
>   #local LocationZ = function(u){select((u<=0),-1, LocationZR,
> LocationZL)};
>   #local D0_X_Fn = function(u,v){u*AspectU};
>   #local D0_Y_Fn = function(u,v){v*AspectV};
>   #local D0_Z_Fn = function(u,v){AspectU/2/tand(Angle/2)};
>   #local pLookAtL = pLookAt+vMovement;
>   #local pLookAtR = pLookAt-vMovement;
>   #local(D1L_X_Fn, D1L_Y_Fn, D1L_Z_Fn) = udcLookAtTransform(
>     D0_X_Fn, D0_Y_Fn, D0_Z_Fn, pLocationL, pLookAtL, Angle1,,,,
>   );
>   #local(D1R_X_Fn, D1R_Y_Fn, D1R_Z_Fn) = udcLookAtTransform(
>     D0_X_Fn, D0_Y_Fn, D0_Z_Fn, pLocationR, pLookAtR, Angle1,,,,
>   );
>   #local D2_X_Fn = function(u,v){select(
>     (u<=0),
>     -1,
>     D1R_X_Fn((u/AspectU*image_width)-0.25,v),
>     D1L_X_Fn((u/AspectU*image_width)+0.25,v)
>   )};
>   #local D2_Y_Fn = function(u,v){select((u<=0),-1, D1R_Y_Fn(u-0.25,v),
> D1L_Y_Fn(u+0.25,v))};
>   #local D2_Z_Fn = function(u,v){select((u<=0),-1, D1R_Z_Fn(u-0.25,v),
> D1L_Z_Fn(u+0.25,v))};
>   camera {
>     user_defined
>     location {
>       function {LocationX(u)}
>       function {LocationY(u)}
>       function {LocationZ(u)}
>     }
>     direction {
>       function {D2_X_Fn(u,v)}
>       function {D2_Y_Fn(u,v)}
>       function {D2_Z_Fn(u,v)}
>     }
>   }
> #end

Note that vDirection_1, vRight_1 and vUp_1 are calculated in your
udcLookAtTransform macro, but not used for anything. So I suggest that you
remove them, and also vDirection, vRight and vUp, as you you will not be able to
change the default direction vectors for the user defined camera.

Further, I assume that you are implementing "Off-axis" stereo camera pairs. If
so then the corresponding direction vectors for both cameras will all be
parallel. (But their position and field of view will be different.) Therefore
you do not need to create two different direction function sets for them. You
can create a common set based on the initial pLocation and pLookAt positions.

--
Tor Olav
http://subcube.com
```