|
![](/i/fill.gif) |
To those of you who are new to the TRACE operation, here's a tip that I had
to find out on my own, as I could not locate this particular info anywhere
in the POV manuals, nor on any of the support websites I've been to.
TRACE, which can be a three-OR-four component operation, will, if you ask it
to, return (give back) the NORMAL vector found at an intersection point.
That's very useful for ALIGNING attached objects to a main object or
heightfield. What's missing in the TRACE tutorials I've seen is the fact
that this NORMAL vector is always 1 POV unit in length. Meaning, the
normal's <x,y,z> vector values, no matter what they are, always produce a
vector LENGTH of 1. This was never very clear
to me, so I constructed a small scene file to "prove" it to myself. (If
anyone can point me to a good explanation of this
in the POV docs, I would be very appreciative.)
Here's my simple (??) scene for creating a sphere, TRACED with (imaginary)
rays that
"orbit" the sphere. This scene graphically demonstrates how the <x,y,z>
components of the NORMAL vector go about creating a unit-length. (Actually,
the demo shows only the x and y components; I left the z direction out for
clarity. In this demo, the z-axis contributes nothing anyway.) The white
lines are the unit-length vector itself, the green
lines represent the x-axis component, and the red lines represent the y-axis
component.
In the following code, I make use of "dot operators," such as BLAH.X If
you're not familiar with this syntax, it just means that you can extract a
SINGLE value from a 3,4, or 5 component vector. I.e., if BLAH = <3,27,19>,
then BLAH.X = 3. Very simple.
BTW, I left the lights out of the code, so be sure to add in a few!
global_settings {
assumed_gamma 1.8
}
#include "math.inc"
// ----------------------------------------
camera {
perspective
location <3.5, 4, -200>
look_at <3.5, 4, 0>
right x*image_width/image_height
angle 5
}
sky_sphere {
pigment {
gradient y
color_map {
[0.0 rgb <0.6,0.7,1.0>*.5]
[0.05 rgb 0]
}
}
}
#declare test_sphere =
object{
sphere{0,8
texture{
pigment {color rgb <.6,.8,1>}
finish{
ambient .1
diffuse .5
}
}
}
}
object {test_sphere}
// ---------------------------
#declare norm = <0,0,0>; // just to initialize this (any arbitrary values
// will do, as it will be changed below.)
#declare theta_angle = 0; // as rotated about the z axis, in degrees.
#while (theta_angle <= 120)
// The following use trig functions inside "MATH.INC"...
// SIND and COSD use degrees instead of radians, which is
// easier to understand.
#declare x_component = cosd (theta_angle);
#declare y_component = sind (theta_angle);
#declare shoot_from_x = 100*x_component;
#declare shoot_from_y = 100*y_component;
#declare surface_point =
trace( // a four-component operation here...
test_sphere, // object to trace
<shoot_from_x, shoot_from_y, 0>, // shoot-from point
<-x_component, -y_component, 0>, // direction of trace ray
norm // gives back the NORMAL vector found at that point
);
#if(norm.x = 0 & norm.y = 0 & norm.z = 0)
// A safety measure, to determine IF a trace ray actually hits the sphere.
// Uses the Boolean "AND" symbol. When a ray misses the object, TRACE
// returns <0,0,0> for the NORM value. So if this is TRUE, do
// NOTHING. I.e., make NO objects.
#else
// LINE drawn from surface intersection point, the exact length
// of the normal, aligned along the composite normal vector...
object {
cylinder{surface_point, surface_point + norm, .035
pigment {color rgb 1} // WHITE
finish{
ambient 1
diffuse 0
}
}
}
// LINE drawn from surface intersection point, the exact length of
// the x-axis part of the normal, aligned along the x-axis.
// (The .00001 addition is just to keep any "degenerate cylinders"
// from being made, which produce an error message.)
object {
cylinder{surface_point, surface_point + <norm.x + .00001, 0, 0> .03
pigment {color rgb <.3,1,.3>} // GREEN
finish{
ambient .7
diffuse 0
}
}
}
// LINE drawn from surface intersection point, the exact length of
// the y-axis part of the normal, aligned along the y-axis...
object {
cylinder{surface_point, surface_point + <0, norm.y + .00001, 0> .03
pigment {color rgb <1,.3,.3>} // RED
finish{
ambient 1
diffuse 0
}
}
translate norm.x*x // to make each right triangle visually clearer
}
#end // of #IF block
#declare theta_angle = theta_angle + 9;
#end
Post a reply to this message
|
![](/i/fill.gif) |