POV-Ray : Newsgroups : povray.binaries.images : "Position Finder" results : Re: "Position Finder" results Server Time
27 Apr 2024 09:49:07 EDT (-0400)
  Re: "Position Finder" results  
From: Bald Eagle
Date: 3 Oct 2018 15:10:02
Message: <web.5bb513d4813dde7ac437ac910@news.povray.org>
OK, so here's a rudimentary object position / surface normal finding scene I
wrote from scratch, which shows the back-and-forth conversion of screen position
coordinates and 3D scene object coordinates.

Wrote 2 "shotgun" macros to pepper the target object with trace() calls to see
about the "underside" issue.

Play around with it, let me know questions, comments, improvements as always.


########################################################################

#version version;

#global_settings {assumed_gamma 1.0}

#include "colors.inc"

light_source {
 <0.5, 0.5, -1>
 color White
 fade_distance 20
 fade_power 2
}



#declare Default_location = <0, 0, 0>;  // 2.3.1.1.1 Location and Look_At
#declare Default_direction = <0, 0, 1>;  // 2.3.1.1.4 The Direction Vector
#declare Default_right = <1.33, 0, 0>;  // 2.3.1.1.6 Aspect Ratio
#declare Default_up = <0, 1, 0>;   // 2.3.1.1.6 Aspect Ratio
#declare Default_sky = <0, 1, 0>;   // 2.3.1.1.2 The Sky Vector

// When you specify the angle, POV-Ray adjusts the length of the direction
vector accordingly.
// The formula used is direction_length = 0.5 * right_length / tan(angle / 2)
// where right_length is the length of the right vector.
// You should therefore specify the direction and right vectors before the angle
keyword.
#declare Default_angle = 0;
// direction_length = 0.5 * right_length / tan(angle / 2)

// The look_at modifier should almost always be the last item in the camera
statement.
// If other camera items are placed after the look_at vector then the camera may
not continue to look at the specified point.
#declare Default_look_at = <0, 0, 1>;  // 2.3.1.1.1 Location and Look_At

#declare Aspect = image_width/image_height;
#declare A = <Aspect, 1, 1>;

camera {
 location Default_location
 direction Default_direction
 //right Default_right
 right x*image_width/image_height
 up  Default_up
 look_at Default_look_at
}


#declare TopRight = <0.5, 0.5, 1>;
#declare Far = 12;  // the far plane of a defined view frustum
// The diagonal distance from the Image Plane to a Far view frustum corner is
greater than the straight distance
//
#declare DiagonalLength = vlength (<(Far/2)*Aspect, (Far/2), Far> - TopRight);

// Frame the canvas
#declare Corner = array [4] {<-0.5, 0.5, 1>, <0.5, 0.5, 1>, <0.5, -0.5, 1>,
<-0.5, -0.5, 1>}
#declare Frustum = union {
#for (N, 0, 3)
 sphere {Corner [N] * A 0.01 pigment {Gray10}}
 sphere {Corner [N] * A * DiagonalLength 0.01 * DiagonalLength * 1.1 pigment
{Green}}
 // Here you can see that I just multply the sphere center's vector by a scalar:
the DiagonalLength
 // To give the rear sphere the same _apparent_ size (MOA), the radius is
multiplied by the distance
 // (Twice as far away needs to be twice as big to appear the same size)
 // Since you wouldn't be able to see one sphere behind the other, the radius is
increased by a factor of 1.1
#end
}

object {Frustum}


#macro Get3DPosition (Xpos, Ypos, Target, Mark)

 #declare Xpos = (Xpos - 0.5) * Aspect;
 #declare Ypos = -1*(Ypos - 0.5);
 #declare NormalVector = <0, 0, 0>;
 #declare From = <0, 0, 0>;
 #declare TraceThrough = <Xpos, Ypos, 1> - From;

 #declare PositionIn3D = trace (Target, From, TraceThrough, NormalVector);

 #if (vlength (NormalVector) != 0)
  cylinder {PositionIn3D, PositionIn3D+NormalVector, 0.01 pigment {Green}}
 #end

 // Indicate trace point
 #if (Mark)
  sphere {<Xpos, Ypos, 1> 0.005 pigment {Green}}
 #end // end if Mark
#end // end macro

#macro Convert2ScreenPos (Pos3D)
 #declare ScreenPosX = (Pos3D.x / Pos3D.z)/Aspect+0.5;
 #declare ScreenPosY = -1*((Pos3D.y / Pos3D.z)-0.5);
 #declare ScreenPos = <ScreenPosX, ScreenPosY>;
 ScreenPos
#end


// define an object
#declare Radius = 0.25;
#declare Object = sphere {<3, 5, 12> Radius pigment {Red}}

object {Object}

Get3DPosition (0.696, 0.094, Object, yes)


// Find the center of the object
#declare Min = min_extent (Object);
#declare Max = max_extent (Object);
#declare Center = Min + (Max-Min)/2;

#macro CircularShotgun (Target)
 #for (Angle, 0, 2*pi, 2*pi/12)
  #for (Rad, 0.9, 0.1, -0.1)
   #declare Offset = Angle + (2*pi/12 * Rad);
   #declare SP = Convert2ScreenPos (Center+<Rad*Radius*cos(Offset),
Rad*Radius*sin(Offset), 0>);
   #declare SPX = SP.x;
   #declare SPY = SP.y;

   Get3DPosition (SPX, SPY, Target, yes)
  #end
 #end
#end // end macro CircularShotgun

#macro BBShotgun (Target)
 #declare MinT = min_extent (Target);
 #declare MaxT = max_extent (Target);
 #declare Xrange = (MaxT.x - MinT.x);
 #declare Yrange = (MaxT.y - MinT.y);
 #debug concat(str (MinT.x, 0, 5), "\n")
 #debug concat(str (MaxT.x, 0, 5), "\n")
 #debug concat(str (Xrange, 0, 5), "\n")

 #for (Xvals, MinT.x, MaxT.x, Xrange/10)
  #for (Yvals, MinT.y, MaxT.y, Yrange/10)
   #debug concat(str (Xvals, 0, 5), "\n")
   #declare SP = Convert2ScreenPos (<Xvals, Yvals, Center.z>);
   #declare SPX = SP.x;
   #declare SPY = SP.y;

   Get3DPosition (SPX, SPY, Target, no)
  #end
 #end
#end // end macro BBShotgun

//CircularShotgun (Object)

BBShotgun (Object)

// end file


Post a reply to this message

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