POV-Ray : Newsgroups : povray.advanced-users : A macro I'm proud of I think (public Beta) : A macro I'm proud of I think (public Beta) Server Time
29 Jul 2024 18:30:04 EDT (-0400)
  A macro I'm proud of I think (public Beta)  
From: Dan Johnson
Date: 30 Apr 2001 05:14:33
Message: <3AEE7E92.6963DACB@hotmail.com>
A while ago I was working on a big complicated image, and I wanted to
make a precise plane intersection shape far away from the origin.  I
quickly realized that although I knew exact locations, planes are
described around the origin.  It only takes three points to define a
plane, but for use in plane intersections there is an inside and an
outside, so I decided to use a fourth point to decide witch side of the
plane is inside.  I thought I could write a macro to do it in 15
minutes, I was very wrong.  I think it finally works now, but I thought
that a few days ago before I found some huge bugs.  If you find any bugs
or have suggestions, please comment.


///////////////////////////////////////////////////////////////////
//
//  Four_point_plane support functions
//

#macro Proj (U,V)  // projection of U onto V
        (V*(vdot(U,V)/vdot(V,V)))
#end
#macro Same_test (Vector1,Vector2) //tests if two vectors are the same
returns boolean
        (vdot((Vector1 = Vector2),<1,1,1>) = 3)
#end
#macro Collinear_test (Vector1,Vector2,Vector3)  //tests if three points
are on the same line
        #local U = (Vector1-Vector2);
        #local V = (Vector1-Vector3);
        (abs(vdot(U,V)/(vlength(U)*vlength(V))) = 1)
#end
#macro On_plane_test (Point_on_plane,Normal,Test_point)     //  Uses a
point on the plane, and normal vector to test if Test_point
        (vlength(Proj (Point_on_plane-Test_point,Normal)) = 0)  // is on
the plane, returns boolean.
#end
#macro Same_direction_test (Vector1,Vector2) // Tests if two vectors
point in same direction.  If either point is the zero vector,
        (2*(vdot(Vector1,Vector2)/(vlength(Vector1)*vlength(Vector2)) =
1)-1) // you will get a divide by zero error.
#end
// Returns positive or negative 1.

#macro Same_side_test (Point_on_plane,Normal,Test_point1,Test_point2)
//  Tests if both test points are on same side of plane.
        #local Vec1 = Proj(Test_point1-Point_on_plane,Normal);
//  If either test point is in the plane you will get a
        #local Vec2 = Proj(Test_point2-Point_on_plane,Normal);
//  divide by zero error.  Returns positive or negative 1.
        Same_direction_test (Vec1,Vec2)
#end
//
//  End support functions
//
////////////////////////////////////////////////////////////////

// Four_point_plane
// In povray everything on one side of the plane is considered inside
the plane object
// Vector1, Vector2, and Vector3 are points on the plane, none of these
points can be the same as any other,
// and they can't be in a strait line.  Inside point is a control point
to determine witch side of the plane
// is considered inside.  Originally all of the error tests were just
going to be warning messages, but
// in testing I found that all of the errors the error trapping codes
are used to find would cause something
// like a divide by zero error before the warning message was
displayed.  I decided then that it would be better
// to give a usefull error, and halt the render process, because the
render would be halted regardless.
#macro Four_point_plane (Vector1,Vector2,Vector3,Inside_point)
        #if (Same_test (Vector1,Vector2))
        #error "Vector1 = Vector2" #end
        #if (Same_test (Vector1,Vector3))
        #error "Vector1 = Vector3" #end
        #if (Same_test (Vector3,Vector2))
        #error "Vector2 = Vector3" #end
        #if (Collinear_test (Vector1,Vector2,Vector3))
        #error "All vectors on same line" #end
        #local Cross =
vnormalize(vcross(Vector1-Vector2,Vector3-Vector2));
        #if (On_plane_test(Vector1,Cross,Inside_point))
        #error "Inside_point is on plane"#end
        #if (On_plane_test(Vector1,Cross,<0,0,0>))
           #local Distance_from_origin = 0;
           #local Normal_vector = -Same_side_test
(Vector1,Cross,Cross,Inside_point)*Cross;
           // If Cross vector points to the same side of the plane that
the inside point is on, inverts Cross to create normal vector.
        #else
           #local Test_n = Same_direction_test
(Cross,Proj(Vector1,Cross));
           #local Test_o = Same_side_test
(Vector1,Cross,<0,0,0>,Inside_point);
           #local Normal_vector = Test_n * Test_o * Cross;
           #local Distance_from_origin = Test_o *
vlength(Proj(Vector1,Normal_vector));
        #end
        plane {Normal_vector, Distance_from_origin}
#end
//  Three_point_plane assumes that the origin is in the object.
#macro Three_point_plane (Vector1,Vector2,Vector3)
        Four_point_plane (Vector1,Vector2,Vector3,<0,0,0>) // lazy way
to do things
#end

/////////////////////////////////////////
//                                     //
//  More macros I have been working on //
//                                     //
/////////////////////////////////////////

#macro Array_plane (Array)    // creates a plane from data points stored
in an array
        plane {<Array[1],Array[2],Array[3]>,Array[4]}
#end
#macro Inclusion (Object1,Object2)     // Cuts a hole in an object and
fills it.
        union
{difference{object{Object1}object{Object2}}object{Object2}}
#end
#macro Sign (X)    //Positive or negative 1 depending on the sign of X
        (X/abs(X))
#end
#macro Angle_between_vectors(U,V)
        (degrees (acos(vdot(U,V)/(vlength(U)*vlength(V)))))
#end
#macro Three_Point_Angle (Vector1,Vector2,Vector3)   //measures an angle
defined by three points the middle point is
        Angle_between_vectors((Vector1-Vector2),(Vector3-Vector2))
//the vertex.
#end

////////////////////////////////////////



--
Dan Johnson

http://www.geocities.com/zapob


Post a reply to this message

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