POV-Ray : Newsgroups : povray.tools.general : Norbert Kern's 'Position-Finder' code-- redux Server Time
19 Mar 2024 05:48:31 EDT (-0400)
  Norbert Kern's 'Position-Finder' code-- redux (Message 1 to 10 of 23)  
Goto Latest 10 Messages Next 10 Messages >>>
From: Kenneth
Subject: Norbert Kern's 'Position-Finder' code-- redux
Date: 18 Sep 2018 19:05:00
Message: <web.5ba183edb47e1707a47873e10@news.povray.org>
Back in 2006, Norbert posted a really interesting macro 'tool' -- an object
'position finder' (or 'new object placer' as I call it)--that I've only recently
become aware of. (Thanks, Thomas de Groot.) The code had a few flaws that I
thought I would try and fix, as it's quite magical in what it does.  Norbert
even mentioned at the time that in was not very mature. My own code is below, in
a preliminary form. Currently, it's a stand-alone scene, for testing; I want to
turn it into an include file eventually..

The general idea of his code is to add and place an extra object into your scene
after the fact, purely by choosing  pixel coordinates of a 'visual' point in
the screen preview render (or in a rendered image.) His code returns a rotation
and translation that you then plug into your new object, and it magically shows
up in proper 3D space in your re-rendered scene. (Then, you no longer need the
macro.) As Thomas pointed out elsewhere, this sames gobs of time trying to
'deduce'  the new 3D coordinates that you need. (The scene here already includes
a 'new' test object.)

For all of this to work, a 'surface object' in the scene needs to be
pre-#declared and given to the macro-- usually the ground object in your scene;
that surface is traced automatically (within the macro.) It's a key concept of
Norbert's code. But this 'surface' can actually be a union of *many* objects;
then you can choose a position on any of them.

It's still Norbert's magic; I've just tried to make it more consistent. Many of
my own changes were arrived at experimentally, so the code may not be very
elegant. BTW, I didn't want to amateurishly fumble around with his core math;
that's intact.

Something I didn't understand at first: Of the two transforms that are
returned-- rotate and translate-- the rotation actually aligns the placed object
along the surface normal there. That's a nice Norbert touch (but see below.)

Here's Norbert's original code...
http://news.povray.org/povray.binaries.scene-files/attachment/%3Cweb.4478509041a06b1c9bff7e8b0%40news.povray.org%3E/pos
ition_finder.pov.txt


.... and his initial post about it...
http://news.povray.org/povray.binaries.images/thread/%3Cweb.44784f2141a06b1c9bff7e8b0%40news.povray.org%3E/?ttop=423977
&toff=3700


For picking  the 'point of interest' in the initial preview render (the 2-D x/y
pixel position), Norbert originally chose to use screen *percentages*. I thought
of changing that to the render's actual pixel positions-- but Norbert's idea is
better: the code doesn't depend on the actual size/resolution/aspect ratio of a
render; that's taken care of automatically. (The slight CHANGE I made to that
scheme is, instead of the render percentage going from 0 to 100, it's now 0 to
1000 to get better precision for the point-of-interest-- simply because of the
way POV-ray shows percentages at the upper-left corner of a render preview when
you move your mouse cursor around: like 0.216 for the x-percentage there, which
would then be 216 as used in the code.)

A BIG caveat: I don't like posting code when I know it still has flaws, but
that's the case here, But rather than continuing to work on it for the next
week/month/year(!), I wanted to get it out for testing.  The remaining flaw is
*specific* to chosen points on the 'underside' of objects (like the lower half
of a sphere.) As far as I can tell, the original code was not designed for this
situation. The trouble appears to be when Norm.y goes *negative*, and might also
depend on the camera location vs. the 'point-of-interest' (the vector between
the two.) I think  the code lines that use   vaxis_rotate   and/or   atan2  are
the culprits,   but I don't know how to fix them, try as I might. Some things
need 'flipping' somewhere, when Norm.y goes negative. I tried lots of different
ad-hoc code additions elsewhere-- kludges, really-- which do work in *most*
circumstances but not all. (For example, my experiments worked for the underside
of horizontal cylinders , but not spheres.) For clarity's sake (and sanity!), I
left out all of that stuff.  But if you restrict the point-of-interest to the
'upper surface' of objects, it seems to work consistently.

Also: The found rotation (based on the traced normal of the 'surface') is not
very accurate at times; put another way, the rotation gets better as the traced
normal approaches the  +y direction (and not just 90-degrees orthogonal to any
particular surface, but basically parallel to the sky vector.) I've tried lots
of workarounds for this, but I haven't been able to disentangle all the things
that are going on.  (To see this effect, try some positions on the upper
hemisphere of the large sphere but close to the horizontal mid-line; also move
the camera around.)

HOWEVER, the found *position* always works the way it should. AFAIK!

Some of my changes:
* The macro has its own camera now (temporary, used only when the macro is
actually in use.) It replaces your scene's camera, but uses the same data which
you supply.

* The camera and its look-at point can be anywhere now , with consistent results
(although I haven't tested EVERY possible combination)

* The indicator arrow now remains the same size (more or less), no matter where
it  happens to be in 3D space. IMO, this aids clarity.

* The on-screen text is now fixed in the upper-left of the render. (I used a
matrix to do that, but I can't take credit for it-- it's 'borrowed' from the
original screen.inc file.)

* A strange mirror-flipping behavior (along the x-axis) has been eliminated.

* Note that it only works with a typical perspective camera.

*The code seems to be more precise if, for cam_ang, you use more of a 'zoom'
angle than a wide-angle (i.e., 30 is better than 67, for example.) This would
just be temporary, until the new object is correctly placed and you no longer
need the macro.

---------------- the code ------------
// 9/1-16/18   [Norbet Kern's original code from 2006, with modifications
// by Kenneth Walker]

#version 3.7;  // or 3.71 or 3.8
global_settings{assumed_gamma 1.0}

// definitions (for test scene below) _____________________________________
#declare screen_x_position = 420; // screen percentages X 1000  (0 to 1000)
#declare screen_y_position = 623; // ditto

#declare cam_loc = <2,4,-8>;
#declare lookat  = <.3,-.1,-.2>;
#declare cam_ang = 50; // 36

// [optional origin markers; pointing only in the POSITIVE directions]
union{
cylinder{0,.8*x .03 pigment{rgb 1.5}}     // X-- WHITE
cylinder{0,.8*y .03 pigment{rgb <0,1,0>}} // Y-- GREEN
cylinder{0,.8*z .03 pigment{rgb <0,.2,1>}} // Z-- BLUE
text{ttf "cyrvetic.ttf" "+ X" 0.2, 0 scale .28
     translate <.9,.04,0> pigment{rgb 1.5} no_shadow} // " + X"
text{ttf "cyrvetic.ttf" "+ Y" 0.2, 0 scale .28
     translate <-.2,.9,0> pigment{rgb <0,1,0>} no_shadow} // " + Y"
text{ttf "cyrvetic.ttf" "+ Z" 0.2, 0 scale .28
     translate <-.13,.04,.9> pigment{rgb <0,.2,1>} no_shadow} // "+ Z"
      scale 1.3
      translate .19*y
    }

// [The NEW object you want to place in the scene...]
#declare NEW_OBJECT =
union{
cylinder{0,.6*x .06 pigment {rgb 1.5}} //     WHITE for x-axis
cylinder{0,.6*y .06 pigment {rgb <0,1,0>}} // GREEN for y-axis
cylinder{0,.6*z .06 pigment{rgb <0,.2,1>}} //  BLUE for z-axis
box{0,.3 translate -.15 pigment{rgb <1,.7,0>}} // YELLOW
    scale .7
    translate .15*y
}

#declare SURFACE =
union{
height_field {
    function 500,500 {
            pattern {bozo scale 0.08}
    }
 smooth
 translate <-0.5,0,-0.5>
 scale <7,0.4,7>
 texture {
         pigment{
              average
              pigment_map{
                      [1.0 rgb <0.5,1,0.3>]
                      [0.6 gradient x frequency 8
                           color_map{
                                    [.07 rgb -.3]
                                    [.07 rgb <0.7,1,0.7>]
                                    }
                      ]
                      [0.6 gradient z frequency 8
                           color_map{
                                    [.07 rgb -.3]
                                    [.07 rgb <0.7,1,0.7>]
                                    }
                      ]
                        }
                  }
         finish {ambient 0 diffuse 0.5}
         }
             }
sphere{0,.9
pigment{
        average
        pigment_map{
             [1.0 planar
                  pigment_map{
                    [.5 bumps scale 2]
                    [.5 rgb -.5]
                            }
             ]
             [1.0 planar
                  pigment_map{
                    [.5 bumps scale 2]
                    [.5 rgb -.5]
                            }
                  rotate 90*z
             ]
             [1.0 planar
                  pigment_map{
                    [.5 bumps scale 2]
                    [.5 rgb -.5]
                            }
                  rotate 90*x
             ]
                  }
        scale .03
       }
   translate <-1.8,.85,1.8>
    }
box{0,2 translate -1 rotate 45*x rotate 45*z
pigment{bumps scale .05}
translate <-1.8,-.6,-1.5>
}
union{
cylinder {-1.4*z,1.4*z, .7
pigment{
        average
        pigment_map{
             [1.0 planar
                  pigment_map{
                    [.5 bumps scale 2]
                    [.5 rgb -.1]
                            }
             ]
             [1.0 planar
                  pigment_map{
                    [.5 bumps scale 2]
                    [.5 rgb -.1]
                            }
                  rotate 90*z
             ]
                  }
        scale .03
       }
       translate <1.5,0,0>
    }
cylinder {-1.4*z,1.4*z, .7
pigment{
        average
        pigment_map{
             [1.0 planar
                  pigment_map{
                    [.5 bumps scale 2]
                    [.5 rgb -.1]
                            }
             ]
             [1.0 planar
                  pigment_map{
                    [.5 bumps scale 2]
                    [.5 rgb -.1]
                            }
                  rotate 90*z
             ]
                  }
        scale .03
       }
       rotate -90*y
       translate <2.8,0,1.4>
    }
    rotate 90*y
    translate <1.5,.7,4.0>
    }
} // end of 'SURFACE' union


// creating the macro___________________________________________________
#macro pos_finder (SURFACE, cam_loc, lookat, cam_ang, screen_x_position,
screen_y_position, arrow_scale)
#if(cam_loc.z <= 0)
// do nothing
#else
#local screen_x_position = 1000 - screen_x_position;
#end

#local screen_x_position = screen_x_position/10;
#local screen_y_position = screen_y_position/10;

#local cam_mirror = #if(cam_loc.z < lookat.z) -1; #else 1; #end
#local cam_z = 0.5*image_width/image_height/tan(radians(cam_ang*0.5));
#local cam_a = cam_mirror*image_width/image_height;
#local cam_s = y;
#local cam_d = vnormalize (lookat-cam_loc);
#local cam_r = vnormalize (vcross(cam_s,cam_d));
#local cam_up = vnormalize (vcross(cam_d,cam_r));
#local cam_dir = cam_d*cam_z;
#local cam_right = cam_r*cam_a;

#local TEXT_OBJECT_TRANSFORM =
   transform {
      matrix <
         cam_r.x, cam_r.y, cam_r.z,
         cam_up.x, cam_up.y, cam_up.z,
         cam_d.x, cam_d.y, cam_d.z,
         cam_loc.x, cam_loc.y, cam_loc.z
             >
             }

#local dir_y = vaxis_rotate (lookat-cam_loc,vcross (lookat-cam_loc,cam_up),
(0.5-screen_y_position*0.01)*cam_ang/image_width*image_height);
#local dir_xy = vaxis_rotate (dir_y,cam_up,
(0.5-screen_x_position*0.01)*cam_mirror*cam_ang);

#local Norm = <0,0,0>;
#local Inter = trace (SURFACE,cam_loc,dir_xy,Norm);
#if (vlength (Norm) != 0)
        #local rx = degrees (atan2 (Norm.z,Norm.y + .0001));
        #local rz = -degrees (atan2 (Norm.x,Norm.y + .0001));
        #local precise = 3;

       union{
          cylinder {0.2*y,0.6*y,0.02}
          cone {0,0,0.2*y,0.06}
          text{ttf "cyrvetic.ttf" "POV-Ray" 0.2,
          0 scale .2 translate <-.40,.5,-.02>} // "POV-Ray"
                rotate <rx,0,rz>
                scale arrow_scale*.0040*vlength(cam_loc - Inter)*cam_ang
                texture{
                pigment {color rgb .6*x}
                finish {ambient .15 diffuse .85 specular 0.3 roughness 0.1}
                       }
                translate Inter
                 }
       union{
          text{
              ttf "cyrvetic.ttf"
              concat ("rotate <",str (rx,0,precise-1),",0,",
              str (rz,0,precise-1),">")
              0.02,0
              translate .6*y
              }
       text{
           ttf "cyrvetic.ttf"
           concat ("translate <",str (Inter.x,0,precise),",",
           str (Inter.y,0,precise),",",str (Inter.z,0,precise),">")
           0.02,0
           translate -.6*y
            }
    no_shadow
    scale .025*(cam_ang)/90
    translate <-.38*(cam_ang/90),.32*(image_height/image_width)*
   (cam_ang/90),.5>
    transform{TEXT_OBJECT_TRANSFORM}
    pigment {color rgb z}
    finish {ambient .15 diffuse .85}
         }

#debug concat ("\n","rotate  <",str (rx,0,precise-1),",0,",
str (rz,0,precise-1),">\n")
#debug concat ("\n","translate <",str (Inter.x,0,precise),",",
str (Inter.y,0,precise),",",str (Inter.z,0,precise),">\n\n")
#else
#debug concat ("\n","chosen position not on traced SURFACE, please try
        other screen_x_position or screen_y_position values\n\n")
#end

camera {
        perspective
        location cam_loc
        look_at lookat
        right cam_right
        angle cam_ang
        direction -z
}
#end  // [end of macro]

// test scene __________________________________________________________________

// The macro call
pos_finder (SURFACE, cam_loc, lookat, cam_ang, screen_x_position,
screen_y_position, 1.0)

light_source {0 color rgb .7 translate <-200,200,-200>}
light_source {0 color rgb .7 translate <200,200,200>}

background {color rgb .7}

object {SURFACE}

object{NEW_OBJECT

// rotate ...*y // [optional, in case you don't like the basic x or
// z 'direction' that the new object is pointing in. This needs to come
// BEFORE the following transforms that are returned from the code]

// [the RETURNED on-screen rotation and translation-- replace with the
// new ones, in this order]
rotate    <5.01,0,5.12>

translate <2.844,0.229,-2.911>
}


Post a reply to this message

From: Bald Eagle
Subject: Re: Norbert Kern's 'Position-Finder' code-- redux
Date: 18 Sep 2018 21:55:00
Message: <web.5ba1aba5bb085d6c458c7afe0@news.povray.org>
Nice job, Walker.   :)

Thanks to you, I understand much better what this whole thing is all about.

I'll see if maybe I have some time to sketch it out and run some experiments to
see where the bugs are coming from.   But as we know, I have my good days, and I
have my bad days   ;)

Perhaps the 'surface' ought to be renamed the 'target group' or 'target
object[s]' since it clarifies the use of trace.

I tried the macro with a point not on the 'surface' and just got the macro
message - I'm wondering if instead the macro ought to return a normalized vector
indicating the direction from the camera to that selected pixel.

Then you could translate the object to the camera position, and then some
multiple along that vector, so that you could place things "in the air".

I suppose a vertical semi-transparent plane would work just as well.

I wonder just how much photogrammetry could be developed along these lines...
https://www.popsci.com/technology/article/2011-10/new-program-slips-super-accurate-false-images-existing-photographs


Keep up the good work   :)


Post a reply to this message

From: Kenneth
Subject: Re: Norbert Kern's 'Position-Finder' code-- redux
Date: 19 Sep 2018 01:40:01
Message: <web.5ba1e030bb085d6ca47873e10@news.povray.org>
"Bald Eagle" <cre### [at] netscapenet> wrote:
> Nice job, Walker.   :)

Thanks! I've been *slaving* over this code, day after day. (But I'm still
irritated that I couldn't get it completely worked out. I haven't given up yet!)
You may have already guessed that my recent post about matrix use and transforms
was a last-ditch effort to solve the remaining flaws in this code.

>
> I tried the macro with a point not on the 'surface' and just got the macro
> message - I'm wondering if instead the macro ought to return a normalized vector
> indicating the direction from the camera to that selected pixel.
>
> Then you could translate the object to the camera position, and then some
> multiple along that vector, so that you could place things "in the air".

Like you, I've been wondering how to get such 'in air' positions, which didn't
seem possible with the way the code was constructed. But I tried some more
tests, per your suggestion (going about it the wrong way, naturally), and
realized that your PLANE idea wouldn't need such an arrow...
>
> I suppose a vertical semi-transparent plane would work just as well.
>

That is a brilliant idea! It didn't occur to me at all. And the plane can be
positioned (and rotated if necessary) to get any in-air position anywhere. Add
this code into the SURFACE object-union (and comment it out if it's not
needed)...

plane{z,0  // a transparent plane, for picking positions IN SPACE
     texture {
  pigment{
     average
     pigment_map{
     [0.6 gradient x frequency 8
          color_map{
                  [.07 rgb -.3]
                  [.07 rgbt <1,0,0,.7>]
                  }
     ]
     [0.6 gradient y frequency 8
         color_map{
                  [.07 rgb -.3]
                  [.07 rgbt <1,0,0,.7>]
                  }
     ]
                }
       }
  finish {ambient 0 emission .5 diffuse 0}
     }
  rotate 37   // whatever you want
  translate -1.3*z // wherever you want to put it
    }

BTW: When an in-air POSITION is returned, it's probably best to ignore the found
ROTATION-- as it has no real meaning re: the normal traced on that 'artificial
plane'.


Post a reply to this message

From: Thomas de Groot
Subject: Re: Norbert Kern's 'Position-Finder' code-- redux
Date: 19 Sep 2018 03:05:02
Message: <5ba1f51e$1@news.povray.org>
On 19-9-2018 1:02, Kenneth wrote:
> Back in 2006, Norbert posted a really interesting macro 'tool' -- an object
> 'position finder' (or 'new object placer' as I call it)--that I've only recently
> become aware of. (Thanks, Thomas de Groot.) The code had a few flaws that I
> thought I would try and fix, as it's quite magical in what it does.  Norbert
> even mentioned at the time that in was not very mature. My own code is below, in
> a preliminary form. Currently, it's a stand-alone scene, for testing; I want to
> turn it into an include file eventually..
> 

Well done, sir! I have little time at this particular moment, but be 
sure that I am going to test your code. Just wanted you to know that I 
was aware.

-- 
Thomas


Post a reply to this message

From: Kenneth
Subject: Re: Norbert Kern's 'Position-Finder' code-- redux
Date: 19 Sep 2018 05:40:00
Message: <web.5ba21902bb085d6ca47873e10@news.povray.org>
Thomas de Groot <tho### [at] degrootorg> wrote:

>
> Well done, sir! I have little time at this particular moment, but be
> sure that I am going to test your code. Just wanted you to know that I
> was aware.
>

Many thanks!

NOW, I'm finally going to take a leisurely look at your own code. I was on a
"mission from God" (as the Blues Brothers would say), to see how far I could get
on my own. Wow, did that hurt my brain!! Fun yet frustrating, at the same time.


Post a reply to this message

From: Kenneth
Subject: Re: Norbert Kern's 'Position-Finder' code-- redux
Date: 19 Sep 2018 16:30:00
Message: <web.5ba2b12fbb085d6ca47873e10@news.povray.org>
"Kenneth" <kdw### [at] gmailcom> wrote:

>
> *The code seems to be more precise if, for cam_ang, you use more of a 'zoom'
> angle than a wide-angle (i.e., 30 is better than 67, for example.) This would
> just be temporary, until the new object is correctly placed and you no longer
> need the macro.
>

Hmm. The 2nd part of that little paragraph needs clarifying (only because the
code is presently a self-contained test scene): The accurate placement of an
object *depends* on the camera angle (cam_ang) staying the same. It needs to be
pre-set with whatever value you choose, and NOT changed (at least *while* using
the macro). For example, with a given set of...

cam_loc
lookat
cam_ang

....for the camera, the preview render will look the way you want, and you then
choose a 'point of interest' in the scene. If you then *change* cam_angle, that
chosen point will not be where you thought it would be-- since the essence of
the code is to work solely with the visual on-screen preview (which 'sets' the
point of interest BASED ON the three parameters.) A different cam_angle would
naturally create a different-looking on-screen preview.

Again, this caveat applies only to the current test scene set-up.

BTW, you CAN currently use the macro itself in one of your own scenes, to try it
out. Just make sure the three camera parameters match those of the 'real' camera
in your scene. (And the macro call needs to go somewhere AFTER your own scene
camera; the macro's built-in camera temporarily replaces it.) Once you've placed
your new object, you no longer need the macro, and you can then change your own
camera parameters to whatever you like.


Post a reply to this message

From: Thomas de Groot
Subject: Re: Norbert Kern's 'Position-Finder' code-- redux
Date: 23 Sep 2018 07:27:29
Message: <5ba778a1@news.povray.org>
On 19-9-2018 11:38, Kenneth wrote:
> Thomas de Groot <tho### [at] degrootorg> wrote:
> 
>>
>> Well done, sir! I have little time at this particular moment, but be
>> sure that I am going to test your code. Just wanted you to know that I
>> was aware.
>>
> 
> Many thanks!
> 
> NOW, I'm finally going to take a leisurely look at your own code. I was on a
> "mission from God" (as the Blues Brothers would say), to see how far I could get
> on my own. Wow, did that hurt my brain!! Fun yet frustrating, at the same time.
> 
> 
> 

I like it! I really do, and I shall replace my own version with yours.

-- 
Thomas


Post a reply to this message

From: Kenneth
Subject: Re: Norbert Kern's 'Position-Finder' code-- redux
Date: 23 Sep 2018 15:30:00
Message: <web.5ba7e902bb085d6ca47873e10@news.povray.org>
Thomas de Groot <tho### [at] degrootorg> wrote:
>
> I like it! I really do, and I shall replace my own version with yours.
>

Thanks, glad to hear that it's useful!

I may re-instate my 'kludge' fixes for some of the remaining traced 'normal'
behavior; I found a way to include that stuff in a brute-force kind of way (it's
not very elegant code, but produces results.) I'm currently running more tests,
to see if there are *other* kludges that I need to add ;-)  If it all works out
in a satisfactory way, I'll post the updated macro here.


Post a reply to this message

From: Thomas de Groot
Subject: Re: Norbert Kern's 'Position-Finder' code-- redux
Date: 24 Sep 2018 03:22:24
Message: <5ba890b0$1@news.povray.org>
On 23-9-2018 21:26, Kenneth wrote:
> Thomas de Groot <tho### [at] degrootorg> wrote:
>>
>> I like it! I really do, and I shall replace my own version with yours.
>>
> 
> Thanks, glad to hear that it's useful!
> 
> I may re-instate my 'kludge' fixes for some of the remaining traced 'normal'
> behavior; I found a way to include that stuff in a brute-force kind of way (it's
> not very elegant code, but produces results.) I'm currently running more tests,
> to see if there are *other* kludges that I need to add ;-)  If it all works out
> in a satisfactory way, I'll post the updated macro here.
> 
> 

That would be excellent.

-- 
Thomas


Post a reply to this message

From: Kenneth
Subject: Re: Norbert Kern's 'Position-Finder' code-- redux
Date: 25 Sep 2018 16:15:01
Message: <web.5baa96aebb085d6ca47873e10@news.povray.org>
Thomas de Groot <tho### [at] degrootorg> wrote:

> > I like it! I really do, and I shall replace my own version with yours.

> >
> > I may re-instate my 'kludge' fixes for some of the remaining traced 'normal'
> > behavior...

I've just come across another subtle flaw in the code-- NOT normal-related--
that's probably been there since my *early* experiments. I  may have introduced
it with my own fixes, I don't know. Basically, *sometimes* the arrow or 'new'
object suddenly flips from one side of the preview render to the other. But it
happens only with certain juxtapositions of camera and lookat point, and their
positions relative to the x/y plane at the origin. It's strange that I didn't
see this flaw previously,  even after 100-plus tests of the code! (All my
previsous tests just happened to avoid this situation, amazingly.)

Luckily, I've been able to deduce the 'rules' that govern this behavior, so I'll
add a fix for it-- as soon as I figure out how ;-)


Post a reply to this message

Goto Latest 10 Messages Next 10 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.