POV-Ray : Newsgroups : povray.newusers : TRACE returns a unit-length NORMAL vector : TRACE returns a unit-length NORMAL vector Server Time
29 Jul 2024 14:22:04 EDT (-0400)
  TRACE returns a unit-length NORMAL vector  
From: Kenneth
Date: 3 Oct 2005 18:25:01
Message: <web.4341aa9daf8295c7b55189fe0@news.povray.org>
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

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