|
|
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
|
|