Geometric

From Second Life Wiki
Jump to navigation Jump to search

Note; Currently working on a new design of this page so this page might be rewritten at any moment.


Documentation

Line Functions

Line Nearest Point

Calculates the vector from a point to the closest point on a line <lsl> vector gLXdV(vector O,vector D,vector A){

   return (O-A)-((O-A)*D)*D;}

</lsl>

Input Description
vector O Origin of Line
vector D Direction of Line
vector A Origin of Point
Output Description
return vector gLXdV Returns origin of closest point on Line to Point

Line Nearest Point, Distance

Calculates distance of this vector, but faster on it's own <lsl> float gLXdZ(vector O,vector D,vector A){

   return llSqrt(CP((A-O),D)*CP((A-O),D));}

</lsl>

Input Description
vector O Origin of Line
vector D Direction of Line
vector A Origin of Point
Output Description
return float gLXdZ Returns numerical distance from Line to Point
Requirement
function vector CP(vector A,vector B)

Line and Line, Vector

Shortest vector of two lines <lsl> vector gLLdV(vector O1,vector D1,vector O2,vector D2){

   return Project3D( (O2-O1), CP(D1,D2) );}

</lsl>

Input Description
vector O1 Origin of Line 1
vector D1 Direction of Line 1
vector O2 Origin of Line 2
vector D2 Direction of Line 2
Output Description
return vector gLLdV Returns shortest vector between the two lines
Requirement
function vector Project3D(vector A,vector B)
function vector CP(vector A,vector B)

Line and Line, Distance

Returns the distance between two lines <lsl> float gLLdZ(vector O1,vector D1,vector O2,vector D2){

   vector A = CP(D1,D2);float B = llVecMag(A);A = <A.x/B,A.y/B,A.z/B>;
   return (O2-O1) * A;}

</lsl>

Input Description
vector O1 Origin of Line 1
vector D1 Direction of Line 1
vector O2 Origin of Line 2
vector D2 Direction of Line 2
Output Description
return float gLLdZ Returns numerical distance between the two lines
Requirement
function vector CP(vector A,vector B)

Line and Line, Nearest point

Closest point of two lines <lsl> vector gLLnX(vector O1,vector D1,vector O2,vector D2){

   vector nO1 = < O1*D1, O1*D2, 0>;
   vector nO2 = < O2*D1, O2*D2, 0>;
   vector nD1 = < D1*D1, O1*D2, 0>;
   vector nD2 = < O2*D1, O2*D2, 0>;
   
   float t = ( nD2.x*nD1.y - nD1.x*nD2.y );
   
   t = ( nD2.y*(nO1.x-nO2.x) - nD2.x*(nO1.y-nO2.y) ) / t;
   
   return O1 + D1*t;}

</lsl>

Input Description
vector O1 Origin of Line 1
vector D1 Direction of Line 1
vector O2 Origin of Line 2
vector D2 Direction of Line 2
Output Description
return vector gLLnX Returns closest point between the two lines

Line and Line, two nearest points along both lines

Two closest points of two lines on each line <lsl> vector X1;vector X2; gLLnnXX(vector O1,vector D1,vector O2,vector D2){

   vector nO1 = < O1*D1, O1*D2, 0>;
   vector nO2 = < O2*D1, O2*D2, 0>;
   vector nD1 = < D1*D1, O1*D2, 0>;
   vector nD2 = < O2*D1, O2*D2, 0>;
   
   float t = ( nD2.x*nD1.y - nD1.x*nD2.y );
   
   t = ( nD2.y*(nO1.x-nO2.x) - nD2.x*(nO1.y-nO2.y) ) / t;
   
   X1 = O1 + D1*t;
   X2 = X1 + CP(nD1,nD2);}

</lsl>

Input Description
vector O1 Origin of Line 1
vector D1 Direction of Line 1
vector O2 Origin of Line 2
vector D2 Direction of Line 2
Output Description
vector X1 Closest point on line 1 to line 2
vector X2 Closest point on line 2 to line 1
Requirement
global vector X1
global vector X2
function vector CP(vector A,vector B)

Line and Line, two nearest points with vector and distance

Computes two closest points of two lines, vector and distance <lsl> vector X1;vector X2;vector V1;float Z1; gLLnnXXVZ(vector O1,vector D1,vector O2,vector D2){

   vector nO1 = < O1*D1, O1*D2, 0>;
   vector nO2 = < O2*D1, O2*D2, 0>;
   vector nD1 = < D1*D1, O1*D2, 0>;
   vector nD2 = < O2*D1, O2*D2, 0>;
   
   float t = ( nD2.x*nD1.y - nD1.x*nD2.y );
   
   t = ( nD2.y*(nO1.x-nO2.x) - nD2.x*(nO1.y-nO2.y) ) / t;
   
   X1 = O1 + D1*t;
   X2 = X1 + CP(nD1,nD2);
   V1 = CP(nD1,nD2);
   Z1 = llVecMag(V1);}

</lsl>

Input Description
vector O1 Origin of Line 1
vector D1 Direction of Line 1
vector O2 Origin of Line 2
vector D2 Direction of Line 2
Output Description
vector X1 Closest point on line 1 to line 2
vector X2 Closest point on line 2 to line 1
vector V1 Direction vector of line 1 to line 2
float Z1 Numerical distance of line 1 to line 2
Requirement
global vector X1
global vector X2
global vector V1
global float Z1
function vector CP(vector A,vector B)

Plane Functions

Plane and Point, Distance

Finds distance of a point from a plane <lsl> float gPXdZ(vector Pn,float Pd,vector A){

   return A * Pn + Pd;}

</lsl>

Input Description
vector Pn Normal of Plane
float Pd Distance of Plane
vector A Origin of Point
Output Description
return float gPXdZ Returns Distance between plane and point

Plane and Point, Vector

Finds vector that points from point to nearest on plane <lsl> vector gPXdV(vector Pn,float Pd,vector A){

   return -(Pn * A + Pd)*Pn;}

</lsl>

Input Description
vector Pn Normal of Plane
float Pd Distance of Plane
vector A Origin of Point
Output Description
return vector gPXdV Returns vector from point to closest point on plane

Plane and Point, Nearest point

Finds closest point on plane given point <lsl> vector gPXnX(vector Pn,float Pd,vector A){

   return A - (Pn * A + Pd) * Pn;}

</lsl>

Input Description
vector Pn Normal of Plane
float Pd Distance of Plane
vector A Origin of Point
Output Description
return vector gPXnX Returns vector of a point from closest of point to plane

Plane and Ray, Intersection Distance

Finds distance to intersection of plane along ray <lsl> float gPRxZ(vector Pn,float Pd,vector O,vector D){

   return -( ( (Pn*D)+(Pn*O) ) / (Pn*D) );}

</lsl>

Input Description
vector Pn Normal of Plane
float Pd Distance of Plane
vector O Origin of Ray
vector D Direction of Ray
Output Description
return float gPRxZ Returns float distance of intersection between ray and plane

Plane and Ray, Vector

Finds distance vector along a ray to a plane <lsl> vector gPRdV(vector Pn,float Pd,vector O,vector D){

   return D * gPRxZ(Pn,Pd,O,D);}

</lsl>

Input Description
vector Pn Normal of Plane
float Pd Distance of Plane
vector O Origin of Ray
vector D Direction of Ray
Output Description
return vector gPRdV Returns vector along a ray to a plane

Plane and Ray, Intersection Point

Finds intersection point along a ray to a plane <lsl> vector gPRxX(vector Pn,float Pd,vector O,vector D){

   return O + gPRdV(Pn,Pd,O,D);}

</lsl>

Input Description
vector Pn Normal of Plane
float Pd Distance of Plane
vector O Origin of Ray
vector D Direction of Ray
Output Description
return vector gPRxX Returns vector point of intersection between ray and plane
Requirement
function vector gPRdV(vector Pn,float Pd,vector O,vector D)

Plane and Line, Intersection Point

Finds interesection point of a line and a plane <lsl> vector gPLxX(vector Pn,float Pd,vector O,vector D){

   return O -( (Pn*D)/(Pn*O+Pd) )*D;}

</lsl>

Input Description
vector Pn Normal of Plane
float Pd Distance of Plane
vector O Origin of Line
vector D Direction of Line
Output Description
return vector gPLxX Returns vector point of intersection between line and plane

Plane and Plane, Intersection Line

Finds line of intersection of two planes <lsl> vector oO;vector oD;

gPPxL(vector Pn,float Pd,vector Qn,float Qd){

   oD = CP(Pn,Qn)/llVecMag(CP(Pn,Qn));
   vector Cross = CP(CP(Pn,Qn),Pn);
   vector Bleh = (-Pd*Pn);
   oO = Bleh - (Qn*Cross)/(Qn*Bleh+Qd)*Cross/llVecMag(Cross);}

</lsl>

Input Description
vector Pn Normal of Plane 1
float Pd Distance of Plane 1
vector Qn Origin of Plane 2
float Qd Distance of Plane 2
Output Description
vector oO Intersection Line's origin
vector oD Intersection Line's direction
Requirement
global vector oO
global vector oD
function vector CP(vector A,vector B)

Plane and Ray, Projection

Projects a ray onto a plane <lsl> vector oO;vector oD;

gPRpR(vector Pn,float Pd,vector O,vector D){

   oO = O - (Pn * O + Pd) * Pn;
   vector t = llVecNorm( D - Project3D(D,Pn) );t = <1.0/t.x,1.0/t.y,1.0/t.z>;
   oD = CP(Pn,t);}

</lsl>

Input Description
vector Pn Normal of Plane
float Pd Distance of Plane
vector O Origin of Ray
vector D Direction of Ray
Output Description
vector oO Projected Ray Origin
vector oD Projected Ray Direction
Requirement
global vector oO
global vector oD
function vector Project3D(vector A,vector B)
function vector CP(vector A,vector B)

Sphere Functions

Sphere and Ray, Intersection Point

Finds intersection point of sphere and ray <lsl> vector gSRxX(vector Sp, float Sr, vector Ro, vector Rd){

   float t;Ro = Ro - Sp;
   if(Rd == ZERO_VECTOR) return ZERO_VECTOR;
   
   float a = Rd * Rd;
   float b = 2 * Rd * Ro;
   float c = (Ro * Ro)  - (Sr * Sr);
   
   float disc = b * b - 4 * a * c;
   
   if(disc < 0) return ZERO_VECTOR;
   
   float distSqrt = llSqrt(disc);
   float q;
   
   if(b < 0)
       q = (-b - distSqrt)/2.0;
   else 
       q = (-b + distSqrt)/2.0;
   
   float t0 = q / a;
   float t1 = c / q;
   
   if(t0 > t1){
       float temp = t0;
       t0 = t1;
       t1 = temp;
   }
   
   if(t1 < 0) return ZERO_VECTOR;
   
   if(t0 < 0)
       t = t1;
   else
       t = t0;
   
   return Ro + (t * Rd);

} </lsl>

Input Description
vector Sp Origin of Sphere
float Sr Radius of Sphere
vector Ro Origin of Ray
vector Rd Direction of Ray
Output Description
vector gSRxX Returns intersection point of sphere and ray otherwise ZERO_VECTOR

Sphere and Ray, Intersection Boolean

Finds if there is a intersection of sphere and ray <lsl> integer gSRx(vector Sp, float Sr, vector Ro, vector Rd){

   float t;Ro = Ro - Sp;
   //vector RayOrg = llDetectedPos(x) - llGetPos();
   if(Rd == ZERO_VECTOR) return FALSE;
   
   float a = Rd * Rd;
   float b = 2 * Rd * Ro;
   float c = (Ro * Ro)  - (Sr * Sr);
   
   float disc = b * b - 4 * a * c;
   
   if(disc < 0) return FALSE;
   return TRUE;

} </lsl>

Input Description
vector Sp Origin of Sphere
float Sr Radius of Sphere
vector Ro Origin of Ray
vector Rd Direction of Ray
Output Description
integer gSRx Returns a boolean indicating if there is a valid intersection

Ray Functions

Ray and Point, projected distance

Finds projected distance of a point along a ray <lsl> float gRXpZ(vector O,vector D,vector A){

   return (A-O)*D;}

</lsl>

Input Description
vector O Origin of Ray
vector D Direction of Ray
vector A Origin of Point
Output Description
float gRXpZ Returns projected distance of a point along a ray

Geometric Library Code

Legend

I tried to minimize the script function names to be easily readable. All the geometric function names start with a g. Please note, Nexii Malthus is no maths professor and so one or two functions might not work as expected.

Here is the legend:

Shorthand Name Description
X Point vector defining a point in space
L Line A line has an origin and a direction
R Ray A ray is like a line, except it is more distinct as it can define weather it points forward or back
P Plane A two dimensional doubly ruled surface of infinite size
S Sphere A sphere is defined by origin and radius
d Distance Calculate distance
n Nearest Calculate nearest
p Project Calculates projection
x Intersection Calculates intersection
Z Float Represents that a float is returned
V Vector Represents that a vector is returned
O Origin Represents the Origin of the ray or line
D Direction Direction from the Origin

LSL Script

This is the script in its entirety. <lsl>//===================================================// // Geometric Library 1.0 // // "May 4 2008", "2:24:30" // // Copyright (C) 2008, Nexii Malthus (cc-by) // // http://creativecommons.org/licenses/by/3.0/ // //===================================================//

vector CP(vector A,vector B){

   return A % B;}

vector Project3D(vector A,vector B){

   vector proj;
   proj.x = ( (A*B) / (B.x*B.x + B.y*B.y + B.z*B.z) ) * B.x;
   proj.y = ( (A*B) / (B.x*B.x + B.y*B.y + B.z*B.z) ) * B.y;
   proj.z = ( (A*B) / (B.x*B.x + B.y*B.y + B.z*B.z) ) * B.z;
   return proj;}

// POINT // float gXXdZ(vector A,vector B){

   // Distance P2P.
   return llVecDist(A,B);}

vector gXXdV(vector A,vector B){

   // Vector to move from P2P.
   return A-B;}

// LINE // vector gLXdV(vector O,vector D,vector A){

   // Calculates the vector from a point to the closest point on a line
   return (O-A)-((O-A)*D)*D;}

float gLXdZ(vector O,vector D,vector A){

   // Calculates distance of this vector, but faster on it's own
   return llSqrt(CP((A-O),D)*CP((A-O),D));}

vector gLLdV(vector O1,vector D1,vector O2,vector D2){

   // Shortest vector of two lines
   return Project3D( (O2-O1), CP(D1,D2) );}

float gLLdZ(vector O1,vector D1,vector O2,vector D2){

   // Returns the distance between two lines
   vector A = CP(D1,D2);float B = llVecMag(A);A = <A.x/B,A.y/B,A.z/B>;
   return (O2-O1) * A;}

vector gLLnX(vector O1,vector D1,vector O2,vector D2){

   // Closest point of two lines
   vector nO1 = < O1*D1, O1*D2, 0>;
   vector nO2 = < O2*D1, O2*D2, 0>;
   vector nD1 = < D1*D1, O1*D2, 0>;
   vector nD2 = < O2*D1, O2*D2, 0>;
   
   float t = ( nD2.x*nD1.y - nD1.x*nD2.y );
   
   t = ( nD2.y*(nO1.x-nO2.x) - nD2.x*(nO1.y-nO2.y) ) / t;
   
   return O1 + D1*t;}

vector X1;vector X2;vector V1;float Z1;

gLLnnXX(vector O1,vector D1,vector O2,vector D2){

   // Two closest points of two lines
   vector nO1 = < O1*D1, O1*D2, 0>;
   vector nO2 = < O2*D1, O2*D2, 0>;
   vector nD1 = < D1*D1, O1*D2, 0>;
   vector nD2 = < O2*D1, O2*D2, 0>;
   
   float t = ( nD2.x*nD1.y - nD1.x*nD2.y );
   
   t = ( nD2.y*(nO1.x-nO2.x) - nD2.x*(nO1.y-nO2.y) ) / t;
   
   X1 = O1 + D1*t;
   X2 = X1 + CP(nD1,nD2);}

gLLnnXXVZ(vector O1,vector D1,vector O2,vector D2){

   // Computes two closest points of two lines, vector and distance
   vector nO1 = < O1*D1, O1*D2, 0>;
   vector nO2 = < O2*D1, O2*D2, 0>;
   vector nD1 = < D1*D1, O1*D2, 0>;
   vector nD2 = < O2*D1, O2*D2, 0>;
   
   float t = ( nD2.x*nD1.y - nD1.x*nD2.y );
   
   t = ( nD2.y*(nO1.x-nO2.x) - nD2.x*(nO1.y-nO2.y) ) / t;
   
   X1 = O1 + D1*t;
   X2 = X1 + CP(nD1,nD2);
   V1 = CP(nD1,nD2);
   Z1 = llVecMag(V1);}

// PLANE // float gPXdZ(vector Pn,float Pd,vector A){

   // Finds distance of a point from a plane
   return A * Pn + Pd;}

vector gPXdV(vector Pn,float Pd,vector A){

   // Finds vector that points from point to nearest on plane
   return -(Pn * A + Pd)*Pn;}

vector gPXnX(vector Pn,float Pd,vector A){

   // Finds closest point on plane given point
   return A - (Pn * A + Pd) * Pn;}

float gPRxZ(vector Pn,float Pd,vector O,vector D){

   // Finds distance to intersection of plane along ray
   return -( ( (Pn*D)+(Pn*O) ) / (Pn*D) );}
   //return -( (Pn*D)/(Pn*O+Pd) );}

vector gPRdV(vector Pn,float Pd,vector O,vector D){

   // Finds distance vector along a ray to a plane
   return D * gPRxZ(Pn,Pd,O,D);}
   //return -( (Pn*D)/(Pn*O+Pd) )*D;}

vector gPRxX(vector Pn,float Pd,vector O,vector D){

   // Finds intersection point along a ray to a plane
   return O + gPRdV(Pn,Pd,O,D);}

vector gPLxX(vector Pn,float Pd,vector O,vector D){

   // Finds interesection point of a line and a plane
   return O -( (Pn*D)/(Pn*O+Pd) )*D;}

vector oO;vector oD;

gPPxL(vector Pn,float Pd,vector Qn,float Qd){

   // Finds line of intersection of two planes
   oD = CP(Pn,Qn)/llVecMag(CP(Pn,Qn));
   vector Cross = CP(CP(Pn,Qn),Pn);
   vector Bleh = (-Pd*Pn);
   oO = Bleh - (Qn*Cross)/(Qn*Bleh+Qd)*Cross/llVecMag(Cross);}

gPRpR(vector Pn,float Pd,vector O,vector D){

   // Projects a ray onto a plane
   oO = O - (Pn * O + Pd) * Pn;
   vector t = llVecNorm( D - Project3D(D,Pn) );t = <1.0/t.x,1.0/t.y,1.0/t.z>;
   oD = CP(Pn,t);}

// SPHERE // vector gSRxX(vector Sp, float Sr, vector Ro, vector Rd){

   float t;Ro = Ro - Sp;
   //vector RayOrg = llDetectedPos(x) - llGetPos();
   if(Rd == ZERO_VECTOR) return ZERO_VECTOR;
   
   float a = Rd * Rd;
   float b = 2 * Rd * Ro;
   float c = (Ro * Ro)  - (Sr * Sr);
   
   float disc = b * b - 4 * a * c;
   
   if(disc < 0) return ZERO_VECTOR;
   
   float distSqrt = llSqrt(disc);
   float q;
   
   if(b < 0)
       q = (-b - distSqrt)/2.0;
   else 
       q = (-b + distSqrt)/2.0;
   
   float t0 = q / a;
   float t1 = c / q;
   
   if(t0 > t1){
       float temp = t0;
       t0 = t1;
       t1 = temp;
   }
   
   if(t1 < 0) return ZERO_VECTOR;
   
   if(t0 < 0)
       t = t1;
   else
       t = t0;
   
   return Ro + (t * Rd);

}

integer gSRx(vector Sp, float Sr, vector Ro, vector Rd){

   float t;Ro = Ro - Sp;
   //vector RayOrg = llDetectedPos(x) - llGetPos();
   if(Rd == ZERO_VECTOR) return FALSE;
   
   float a = Rd * Rd;
   float b = 2 * Rd * Ro;
   float c = (Ro * Ro)  - (Sr * Sr);
   
   float disc = b * b - 4 * a * c;
   
   if(disc < 0) return FALSE;
   return TRUE;

}

// RAY // float gRXpZ(vector O,vector D,vector A){

   // Finds projected distance of a point along a ray
   return (A-O)*D;}

vector gRZiX(vector O,vector D,float z){

   return O+z*D;}

// OTHER // vector pN;float pD; gTiP(vector p1,vector p2,vector p3){

   // Turns three vector points in space into a plane
   pN = llVecNorm( CP((p2-p1),(p3-p1)) );
   pD = -p1*pN;}

integer gTXcC(vector p1,vector p2,vector p3,vector x){

   // Can be used to check weather a point is inside a triangle
   gTiP(p1,p2,p3);
   vector Vn;vector En;
       Vn = p1 - x;
       En = CP((p2-p1),pN);
   if( ((p1-x)*CP(p2-p1,pN) >= 0)&&((p2-x)*CP(p3-p2,pN) >= 0)&&((p3-x)*CP(p1-p3,pN) >= 0) ) return TRUE;
   return FALSE;}

integer gTVXcC(vector p1,vector p2,vector p3,vector v,vector x){

   if( ((p1-x)*CP(p2-p1,v) >= 0)&&((p2-x)*CP(p3-p2,v) >= 0)&&((p3-x)*CP(p1-p3,v) >= 0) ) return TRUE;
   return FALSE;}

integer gTRcC(vector p1,vector p2,vector p3,vector O,vector D){

   return gTVXcC(p1,p2,p3,O,D);}

default{state_entry(){}}

</lsl>

Expanded Library

I was informed by Strife that shorthand one/two letter variable names is out of fashion these days, so it's up to the opinion of the reader if they really think this is cleaner and can now choose from two versions.

<lsl> //===================================================// // Geometric Library 1.0 // // "May 4 2008", "2:24:30" // // Copyright (C) 2008, Nexii Malthus (cc-by) // // http://creativecommons.org/licenses/by/3.0/ // //===================================================//

vector CrossProduct(vector Point1,vector Point2){

   return Point1 % Point2;}

vector Project3D(vector A,vector B){

   vector proj;
   proj.x = ( (A*B) / (B.x*B.x + B.y*B.y + B.z*B.z) ) * B.x;
   proj.y = ( (A*B) / (B.x*B.x + B.y*B.y + B.z*B.z) ) * B.y;
   proj.z = ( (A*B) / (B.x*B.x + B.y*B.y + B.z*B.z) ) * B.z;
   return proj;}

// POINT float gPoint2Point_Distance_Float(vector Point1,vector Point2){

   // Distance P2P.
   return llVecDist(Point1,Point2);}

vector gPoint2Point_Distance_Vector(vector Point1,vector Point2){

   // Vector to move from P2P.
   return Point1-Point2;}

// LINE vector gLine2Point_Distance_Vector(vector LineOrigin,vector LineDirection,vector Point){

   // Calculates the vector from a point to the closest point on a line
   return (LineOrigin-Point)-((LineOrigin-Point)*LineDirection)*LineDirection;}

float gLine2Point_Distance_Float(vector LineOrigin,vector LineDirection,vector Point){

   // Calculates distance of this vector, but faster on it's own
   return llSqrt(CrossProduct((Point-LineOrigin),LineDirection)*CrossProduct((Point-LineOrigin),LineDirection));}

vector gLine2Line_Distance_Vector(vector LineOrigin1,vector LineDirection1,vector LineOrigin2,vector LineDirection2){

   // Shortest vector of two lines
   return Project3D( (LineOrigin2-LineOrigin1), CrossProduct(LineDirection1,LineDirection2) );}

float gLine2Line_Distance_Float(vector LineOrigin1,vector LineDirection1,vector LineOrigin2,vector LineDirection2){

   // Returns the distance between two lines
   vector A = CrossProduct(LineDirection1,LineDirection2);float B = llVecMag(A);A = <A.x/B,A.y/B,A.z/B>;
   return (LineOrigin2-LineOrigin1) * A;}

vector gLine2Line_Nearest_Point(vector LineOrigin1,vector LineDirection1,vector LineOrigin2,vector LineDirection2){

   // Closest point of two lines
   vector nearestOrigin1 = < LineOrigin1*LineDirection1, LineOrigin1*LineDirection2, 0>;
   vector nearestOrigin2 = < LineOrigin2*LineDirection1, LineOrigin2*LineDirection2, 0>;
   vector nearestDirection1 = < LineDirection1*LineDirection1, LineOrigin1*LineDirection2, 0>;
   vector nearestDirection2 = < LineOrigin2*LineDirection1, LineOrigin2*LineDirection2, 0>;
   
   float t = ( nearestDirection2.x*nearestDirection1.y - nearestDirection1.x*nearestDirection2.y );
   
   t = ( nearestDirection2.y*(nearestOrigin1.x-nearestOrigin2.x) - nearestDirection2.x*(nearestOrigin1.y-nearestOrigin2.y) ) / t;
   
   return LineOrigin1 + LineDirection1*t;}

vector outPoint1;vector outPoint2;vector outVector1;float outFloat1;

gLine2Line_Nearest_Two_Points(vector LineOrigin1,vector LineDirection1,vector LineOrigin2,vector LineDirection2){

   // Two closest points of two lines
   vector nearestOrigin1 = < LineOrigin1*LineDirection1, LineOrigin1*LineDirection2, 0>;
   vector nearestOrigin2 = < LineOrigin2*LineDirection1, LineOrigin2*LineDirection2, 0>;
   vector nearestDirection1 = < LineDirection1*LineDirection1, LineOrigin1*LineDirection2, 0>;
   vector nearestDirection2 = < LineOrigin2*LineDirection1, LineOrigin2*LineDirection2, 0>;
   
   float t = ( nearestDirection2.x*nearestDirection1.y - nearestDirection1.x*nearestDirection2.y );
   
   t = ( nearestDirection2.y*(nearestOrigin1.x-nearestOrigin2.x) - nearestDirection2.x*(nearestOrigin1.y-nearestOrigin2.y) ) / t;
   
   outPoint1 = LineOrigin1 + LineDirection1*t;
   outPoint2 = outPoint1 + CrossProduct(nearestDirection1,nearestDirection2);}

gLine2Line_Nearest_Two_Points_Vector_Distance(vector LineOrigin1,vector LineDirection1,vector LineOrigin2,vector LineDirection2){

   // Computes two closest points of two lines, vector and distance
   vector nearestOrigin1 = < LineOrigin1*LineDirection1, LineOrigin1*LineDirection2, 0>;
   vector nearestOrigin2 = < LineOrigin2*LineDirection1, LineOrigin2*LineDirection2, 0>;
   vector nearestDirection1 = < LineDirection1*LineDirection1, LineOrigin1*LineDirection2, 0>;
   vector nearestDirection2 = < LineOrigin2*LineDirection1, LineOrigin2*LineDirection2, 0>;
   
   float t = ( nearestDirection2.x*nearestDirection1.y - nearestDirection1.x*nearestDirection2.y );
   
   t = ( nearestDirection2.y*(nearestOrigin1.x-nearestOrigin2.x) - nearestDirection2.x*(nearestOrigin1.y-nearestOrigin2.y) ) / t;
   
   outPoint1 = LineOrigin1 + LineDirection1*t;
   outPoint2 = outPoint1 + CrossProduct(nearestDirection1,nearestDirection2);
   outVector1 = CrossProduct(nearestDirection1,nearestDirection2);
   outFloat1 = llVecMag(outVector1);}

// PLANE float gPlane2Point_Distance_Float(vector PlaneNormal,float PlaneDistance,vector A){

   // Finds distance of a point from a plane
   return A * PlaneNormal + PlaneDistance;}

vector gPlane2Point_Distance_Vector(vector PlaneNormal,float PlaneDistance,vector A){

   // Finds vector that points from point to nearest on plane
   return -(PlaneNormal * A + PlaneDistance)*PlaneNormal;}

vector gPlane2Point_Nearest_Point(vector PlaneNormal,float PlaneDistance,vector A){

   // Finds closest point on plane given point
   return A - (PlaneNormal * A + PlaneDistance) * PlaneNormal;}

float gPlane2Ray_Nearest_Float(vector PlaneNormal,float PlaneDistance,vector RayOrigin,vector RayDirection){

   // Finds distance to intersection of plane along ray
   return -( ( (PlaneNormal*RayDirection)+(PlaneNormal*RayOrigin) ) / (PlaneNormal*RayDirection) );}

vector gPlane2Ray_Distance_Vector(vector PlaneNormal,float PlaneDistance,vector RayOrigin,vector RayDirection){

   // Finds distance vector along a ray to a plane
   return RayDirection * gPlane2Ray_Nearest_Float(PlaneNormal,PlaneDistance,RayOrigin,RayDirection);}

vector gPlane2Ray_Intersection_Point(vector PlaneNormal,float PlaneDistance,vector RayOrigin,vector RayDirection){

   // Finds intersection point along a ray to a plane
   return RayOrigin + gPlane2Ray_Distance_Vector(PlaneNormal,PlaneDistance,RayOrigin,RayDirection);}

vector gPlane2Line_Intersection_Point(vector PlaneNormal,float PlaneDistance,vector LineOrigin,vector LineDirection){

   // Finds interesection point of a line and a plane
   return LineOrigin -( (PlaneNormal*LineDirection)/(PlaneNormal*LineOrigin+PlaneDistance) )*LineDirection;}

vector outLineOrigin;vector outLineDirection;

gPlane2Plane_Intersection_Line(vector PlaneA_Normal,float PlaneA_Distance,vector PlaneB_Normal,float PlaneB_Distance){

   // Finds line of intersection of two planes
   outLineDirection = CrossProduct(PlaneA_Normal,PlaneB_Normal)/llVecMag(CrossProduct(PlaneA_Normal,PlaneB_Normal));
   vector Cross = CrossProduct(CrossProduct(PlaneA_Normal,PlaneB_Normal),PlaneA_Normal);
   vector Bleh = (-PlaneA_Distance*PlaneA_Normal);
   outLineOrigin = Bleh - (PlaneB_Normal*Cross)/(PlaneB_Normal*Bleh+PlaneB_Distance)*Cross/llVecMag(Cross);}

float gRay2Point_Project_Float(vector RayOrigin,vector RayDirection,vector Projection){

   // Finds projected distance of a point along a ray
   return (Projection-RayOrigin)*RayDirection;}

gPlane2Ray_Project_Ray(vector PlaneNormal,float PlaneDistance,vector RayOrigin,vector RayDirection){

   // Projects a ray onto a plane
   outLineOrigin = RayOrigin - (PlaneNormal * RayOrigin + PlaneDistance) * PlaneNormal;
   vector t = llVecNorm( RayDirection - Project3D(RayDirection,PlaneNormal) );t = <1.0/t.x,1.0/t.y,1.0/t.z>;
   outLineDirection = CrossProduct(PlaneNormal,t);}

// SPHERE vector gSphere2Ray_Intersection_Point(vector SphereOrigin, float SphereRadius, vector RayOrigin, vector RayDirection){

   float t;RayOrigin = RayOrigin - SphereOrigin;
   if(RayDirection == ZERO_VECTOR) return ZERO_VECTOR;
   
   float a = RayDirection * RayDirection;
   float b = 2 * RayDirection * RayOrigin;
   float c = (RayOrigin * RayOrigin)  - (SphereRadius * SphereRadius);
   
   float disc = b * b - 4 * a * c;
   
   if(disc < 0) return ZERO_VECTOR;
   
   float distSqrt = llSqrt(disc);
   float q;
   
   if(b < 0)
       q = (-b - distSqrt)/2.0;
   else 
       q = (-b + distSqrt)/2.0;
   
   float t0 = q / a;
   float t1 = c / q;
   
   if(t0 > t1){
       float temp = t0;
       t0 = t1;
       t1 = temp;
   }
   
   if(t1 < 0) return ZERO_VECTOR;
   
   if(t0 < 0)
       t = t1;
   else
       t = t0;
   
   return RayOrigin + (t * RayDirection);

}

integer gSphere2Ray_Intersection(vector SphereOrigin, float SphereRadius, vector RayOrigin, vector RayDirection){

   // IS there a intersection?
   
   float t;RayOrigin = RayOrigin - SphereOrigin;
   if(RayDirection == ZERO_VECTOR) return FALSE;
   
   float a = RayDirection * RayDirection;
   float b = 2 * RayDirection * RayOrigin;
   float c = (RayOrigin * RayOrigin)  - (SphereRadius * SphereRadius);
   
   float disc = b * b - 4 * a * c;
   
   if(disc < 0) return FALSE;
   return TRUE;

}

// Other vector planeNormal;float planeDistance; gTriangle_into_Plane(vector p1,vector p2,vector p3){

   planeNormal = llVecNorm( CrossProduct((p2-p1),(p3-p1)) );
   planeDistance = -p1*planeNormal;}

integer gTriangle2Point_CheckCollision(vector p1,vector p2,vector p3,vector x){

   gTriangle_into_Plane(p1,p2,p3);
   vector Vn;vector En;
       Vn = p1 - x;
       En = CrossProduct((p2-p1),planeNormal);
   if( ((p1-x)*CrossProduct(p2-p1,planeNormal) >= 0)&&((p2-x)*CrossProduct(p3-p2,planeNormal) >= 0)&&((p3-x)*CrossProduct(p1-p3,planeNormal) >= 0) ) return TRUE;
   return FALSE;}

integer gTVXcC(vector p1,vector p2,vector p3,vector v,vector x){

   if( ((p1-x)*CrossProduct(p2-p1,v) >= 0)&&((p2-x)*CrossProduct(p3-p2,v) >= 0)&&((p3-x)*CrossProduct(p1-p3,v) >= 0) ) return TRUE;
   return FALSE;}

integer gTriangel2Ray_CheckCollision(vector p1,vector p2,vector p3,vector Origin,vector Direction){

   return gTVXcC(p1,p2,p3,Origin,Direction);}

vector gRay2Float_into_Point(vector Origin,vector Direction,float Float){

   return Origin+Float*Direction;}

default{state_entry(){}}

</lsl>

Optimized ESL

<lsl>//===================================================// // Geometric Library 1.0 Optimized ESL Build 1 // // "May 4 2008", "14:19:37" // // Copyright (C) 2008, Nexii Malthus (cc-by) // // Copyright (C) 2008, Strife Onizuka (cc-by) // // http://creativecommons.org/licenses/by/3.0/ // //===================================================//

  1. define CP(A, B) ((A) % (B))
  2. ifndef CP

vector CP(vector A,vector B){

   return A % B;}
  1. endif
  1. if 0

vector Project3D(vector A,vector B){

   vector proj;
   proj.x = ( (A*B) / (B.x*B.x + B.y*B.y + B.z*B.z) ) * B.x;
   proj.y = ( (A*B) / (B.x*B.x + B.y*B.y + B.z*B.z) ) * B.y;
   proj.z = ( (A*B) / (B.x*B.x + B.y*B.y + B.z*B.z) ) * B.z;
   return proj;}
  1. else

vector Project3D(vector A,vector B){

   return B * ((A*B) / (B*B));}
  1. endif

// POINT

  1. define gXXdZ llVecDist
  2. ifndef gXXdZ

float gXXdZ(vector A,vector B){

   // Distance P2P.
   return llVecDist(A,B);}
  1. endif
  1. define gXXdV(A,B) ((A) - (B))
  2. ifndef gXXdV

vector gXXdV(vector A,vector B){

   // Vector to move from P2P.
   return A-B;}
  1. endif

// LINE

  1. if 0

vector gLXdV(vector O,vector D,vector A){

   // Calculates the vector from a point to the closest point on a line
   return (O-A)-((O-A)*D)*D;}
  1. else

vector gLXdV(vector O,vector D,vector A){

   // Calculates the vector from a point to the closest point on a line
   vector t = (O-A);
   return t - (t*D)*D;}
  1. endif
  1. define gLXdZ(O, D, A) llVecMag(CP((A-O),D))
  2. ifndef gLXdZ

float gLXdZ(vector O,vector D,vector A){

   // Calculates distance of this vector, but faster on it's own
   return llVecMag(CP((A-O),D));}
  1. endif
  1. define gLLdV(O, D, A) Project3D( (O2-O1), CP(D1,D2) )
  2. ifndef gLLdV

vector gLLdV(vector O1,vector D1,vector O2,vector D2){

   // Shortest vector of two lines
   return Project3D( (O2-O1), CP(D1,D2) );}
  1. endif
  1. define gLLdZ(O1, D1, O2, D2) ((O2-O1) * llVecNorm(CP(D1,D2)))
  2. ifndef gLLdZ

float gLLdZ(vector O1,vector D1,vector O2,vector D2){

   // Returns the distance between two lines
   vector A = CP(D1,D2);float B = llVecMag(A);A = <A.x/B,A.y/B,A.z/B>;
   return (O2-O1) * A;}
  1. endif
  1. if 0

vector gLLnX(vector O1,vector D1,vector O2,vector D2){

   // Closest point of two lines
   vector nO1 = < O1*D1, O1*D2, 0>;
   vector nO2 = < O2*D1, O2*D2, 0>;
   vector nD1 = < D1*D1, O1*D2, 0>;
   vector nD2 = < O2*D1, O2*D2, 0>;

   float t = ( nD2.x*nD1.y - nD1.x*nD2.y );

   t = ( nD2.y*(nO1.x-nO2.x) - nD2.x*(nO1.y-nO2.y) ) / t;

   return O1 + D1*t;}
  1. else

vector gLLnX(vector O1,vector D1,vector O2,vector D2){

   // Closest point of two lines
   vector t = <O2*D1, O1*D2, O2*D2>;
   
   return O1 + D1 * (( t.z * ((O1*D1)-t.x) - t.x * (t.y-t.z) ) / ( t.x*t.y - (D1*D1)*t.z ));}
  1. endif

vector X1;vector X2;vector V1;float Z1;

  1. if 0

gLLnnXX(vector O1,vector D1,vector O2,vector D2){

   // Two closest points of two lines
   vector nO1 = < O1*D1, O1*D2, 0>;
   vector nO2 = < O2*D1, O2*D2, 0>;
   vector nD1 = < D1*D1, O1*D2, 0>;
   vector nD2 = < O2*D1, O2*D2, 0>;

   float t = ( nD2.x*nD1.y - nD1.x*nD2.y );

   t = ( nD2.y*(nO1.x-nO2.x) - nD2.x*(nO1.y-nO2.y) ) / t;

   X1 = O1 + D1*t;
   X2 = X1 + CP(nD1,nD2);}
  1. else

gLLnnXX(vector O1,vector D1,vector O2,vector D2){

   // Two closest points of two lines
   #define a (O1*D1)
   #define c (D1*D1)
   #define d (O2*D1)
   #define e (O1*D2)
   #define f (O2*D2)
   vector nD1 = < c, e, 0.0>;
   vector nD2 = < d, f, 0.0>;
   #undef c
   #undef d
   #undef e
   #undef f
   #define c nD1.x
   #define d nD2.x
   #define e nD1.y
   #define f nD2.y
   X2 = (X1 = (O1 + D1 * (( d*(a-d) - d*(e-f) ) / ( d*e - c*f )))) + CP(nD1,nD2);}
   #undef a
   #undef c
   #undef d
   #undef e
   #undef f
  1. endif
  1. if 0

gLLnnXXVZ(vector O1,vector D1,vector O2,vector D2){

   // Computes two closest points of two lines, vector and distance
   vector nO1 = < O1*D1, O1*D2, 0>;
   vector nO2 = < O2*D1, O2*D2, 0>;
   vector nD1 = < D1*D1, O1*D2, 0>;
   vector nD2 = < O2*D1, O2*D2, 0>;

   float t = ( nD2.x*nD1.y - nD1.x*nD2.y );

   t = ( nD2.y*(nO1.x-nO2.x) - nD2.x*(nO1.y-nO2.y) ) / t;

   X1 = O1 + D1*t;
   X2 = X1 + CP(nD1,nD2);
   V1 = CP(nD1,nD2);
   Z1 = llVecMag(V1);}
  1. else

gLLnnXXVZ(vector O1,vector D1,vector O2,vector D2){

   // Computes two closest points of two lines, vector and distance
   #define a (O1*D1)
   #define c (D1*D1)
   #define d (O2*D1)
   #define e (O1*D2)
   #define f (O2*D2)
   vector nD1 = < c, e, 0.0>;
   vector nD2 = < d, f, 0.0>;
   #undef c
   #undef d
   #undef e
   #undef f
   #define c nD1.x
   #define d nD2.x
   #define e nD1.y
   #define f nD2.y
   X2 = (X1 = (O1 + D1 * (( f * (a-d) - d * (e-f) ) / ( d*e - c*f )))) + (V1 = (CP(nD1,nD2)));
   Z1 = llVecMag(V1);}
   #undef a
   #undef c
   #undef d
   #undef e
   #undef f
  1. endif

// PLANE

  1. define gPXdZ(Pn, Pd, A) ((A) * (Pn) + (Pd))
  2. ifndef gPXdZ

float gPXdZ(vector Pn,float Pd,vector A){

   // Finds distance of a point from a plane
   return A * Pn + Pd;}
  1. endif

vector gPXdV(vector Pn,float Pd,vector A){

   // Finds vector that points from point to nearest on plane
   return -(Pn * A + Pd)*Pn;}

vector gPXnX(vector Pn,float Pd,vector A){

   // Finds closest point on plane given point
   return A - (Pn * A + Pd) * Pn;}
  1. if 0

float gPRxZ(vector Pn,float Pd,vector O,vector D){

   // Finds distance to intersection of plane along ray
   return -( ( (Pn*D)+(Pn*O) ) / (Pn*D) );}
   //return -( (Pn*D)/(Pn*O+Pd) );}
  1. else

float gPRxZ(vector Pn,float Pd,vector O,vector D){

   // Finds distance to intersection of plane along ray
   float a = (Pn*D);
   return -( ( a+(Pn*O) ) / a );}
   //return -( (Pn*D)/(Pn*O+Pd) );}
  1. endif

vector gPRdV(vector Pn,float Pd,vector O,vector D){

   // Finds distance vector along a ray to a plane
   return D * gPRxZ(Pn,Pd,O,D);}
   //return -( (Pn*D)/(Pn*O+Pd) )*D;}

vector gPRxX(vector Pn,float Pd,vector O,vector D){

   // Finds intersection point along a ray to a plane
   return O + gPRdV(Pn,Pd,O,D);}

vector gPLxX(vector Pn,float Pd,vector O,vector D){

   // Finds interesection point of a line and a plane
   return O -( (Pn*D)/(Pn*O+Pd) )*D;}

vector oO;vector oD;

  1. if 0

gPPxL(vector Pn,float Pd,vector Qn,float Qd){

   // Finds line of intersection of two planes
   oD = CP(Pn,Qn)/llVecMag(CP(Pn,Qn));
   vector Cross = CP(CP(Pn,Qn),Pn);
   vector Bleh = (-Pd*Pn);
   oO = Bleh - (Qn*Cross)/(Qn*Bleh+Qd)*Cross/llVecMag(Cross);}
  1. else

gPPxL(vector Pn,float Pd,vector Qn,float Qd){

   // Finds line of intersection of two planes
   vector a = CP(Pn,Qn);
   oD = llVecNorm(a);
   vector Cross = CP(a,Pn);
   vector Bleh = (-Pd*Pn);
   oO = Bleh - (Qn*Cross)/(Qn*Bleh+Qd)*llVecNorm(Cross);}
  1. endif
  1. define gRXpZ(O, D, A) (A-O)*D
  2. ifndef gRXpZ

float gRXpZ(vector O,vector D,vector A){

   // Finds projected distance of a point along a ray
   return (A-O)*D;}
  1. endif
  1. if 0

gPRpR(vector Pn,float Pd,vector O,vector D){

   // Projects a ray onto a plane
   oO = O - (Pn * O + Pd) * Pn;
   vector t = llVecNorm( D - Project3D(D,Pn) );t = <1.0/t.x,1.0/t.y,1.0/t.z>;
   oD = CP(Pn,t);}
  1. else

gPRpR(vector Pn,float Pd,vector O,vector D){

   // Projects a ray onto a plane
   oO = O - (Pn * O + Pd) * Pn;
   O = llVecNorm( D - Project3D(D,Pn) );
   oD = CP(Pn, (<1.0/O.x,1.0/O.y,1.0/O.z>));}
  1. endif

// SPHERE

  1. if 0

vector gSRxX(vector Sp, float Sr, vector Ro, vector Rd){

   float t;Ro = Ro - Sp;
   //vector RayOrg = llDetectedPos(x) - llGetPos();
   if(Rd == ZERO_VECTOR) return ZERO_VECTOR;

   float a = Rd * Rd;
   float b = 2 * Rd * Ro;
   float c = (Ro * Ro)  - (Sr * Sr);

   float disc = b * b - 4 * a * c;

   if(disc < 0) return ZERO_VECTOR;

   float distSqrt = llSqrt(disc);
   float q;

   if(b < 0)
       q = (-b - distSqrt)/2.0;
   else 
       q = (-b + distSqrt)/2.0;

   float t0 = q / a;
   float t1 = c / q;

   if(t0 > t1){
       float temp = t0;
       t0 = t1;
       t1 = temp;
   }

   if(t1 < 0) return ZERO_VECTOR;

   if(t0 < 0)
       t = t1;
   else
       t = t0;

   return Ro + (t * Rd);

}

  1. else

vector gSRxX(vector Sp, float Sr, vector Ro, vector Rd){

   if(Rd)
   {
       Ro -= Sp;
       //vector RayOrg = llDetectedPos(x) - llGetPos();
       float a = Rd * Rd;
       float b = 2 * Rd * Ro;
       float c = (Ro * Ro)  - (Sr * Sr);
    
       float disc = b * b - 4 * a * c;
    
       if(disc >= 0)
       {
           float q = ((llSqrt(disc) * ~((b > 0) * -2)) - b) / 2.0;
           if(q)//avoid a divide by zero!
           {
               float t0 = q / a;
               float t1 = c / q;
            
               if(((t0 < t1) || (t1 < 0)) && (t0 >= 0))
                   return Ro + (t0 * Rd);
               if(t1 >= 0)
                   return Ro + (t1 * Rd);
           }
       }
   }
   return ZERO_VECTOR;

}

  1. endif
  1. if 0

integer gSRx(vector Sp, float Sr, vector Ro, vector Rd){

   float t;Ro = Ro - Sp;
   //vector RayOrg = llDetectedPos(x) - llGetPos();
   if(Rd == ZERO_VECTOR) return FALSE;

   float a = Rd * Rd;
   float b = 2 * Rd * Ro;
   float c = (Ro * Ro)  - (Sr * Sr);

   float disc = b * b - 4 * a * c;

   if(disc < 0) return FALSE;
   return TRUE;

}

  1. else

integer gSRx(vector Sp, float Sr, vector Ro, vector Rd){

   if(Rd)
   {
       Ro -= Sp;
       //vector RayOrg = llDetectedPos(x) - llGetPos();
       float a = Rd * Rd;
       float b = 2 * Rd * Ro;
       float c = (Ro * Ro)  - (Sr * Sr);
       return (b * b - 4 * a * c) >= 0;
   }
   return FALSE;

}

  1. endif

// Other vector pN;float pD;

  1. if 0

gTiP(vector p1,vector p2,vector p3){

   // Turns three vector points in space into a plane
   pN = llVecNorm( CP((p2-p1),(p3-p1)) );
   pD = -p1*pN;}
  1. else

gTiP(vector p1,vector p2,vector p3){

   // Turns three vector points in space into a plane
   pD = -p1*(pN = llVecNorm( CP((p2-p1),(p3-p1)) ));}
  1. endif
  1. if 0

integer gTXcC(vector p1,vector p2,vector p3,vector x){

   gTiP(p1,p2,p3);
   vector Vn;vector En;
       Vn = p1 - x;
       En = CP((p2-p1),pN);
   if( ((p1-x)*CP(p2-p1,pN) >= 0)&&((p2-x)*CP(p3-p2,pN) >= 0)&&((p3-x)*CP(p1-p3,pN) >= 0) ) return TRUE;
   return FALSE;}
  1. else

integer gTXcC(vector p1,vector p2,vector p3,vector x){

   gTiP(p1,p2,p3);
   vector Vn = p1 - x;
   vector En = CP((p2-p1),pN);
   return( ((p1-x)*CP(p2-p1,pN) >= 0) && ((p2-x)*CP(p3-p2,pN) >= 0) && ((p3-x)*CP(p1-p3,pN) >= 0) );}
  1. endif
  1. if 0

integer gTVXcC(vector p1,vector p2,vector p3,vector v,vector x){

   if( ((p1-x)*CP(p2-p1,v) >= 0)&&((p2-x)*CP(p3-p2,v) >= 0)&&((p3-x)*CP(p1-p3,v) >= 0) ) return TRUE;
   return FALSE;}
  1. else

integer gTVXcC(vector p1,vector p2,vector p3,vector v,vector x){

   // Can be used to check weather a point is inside a triangle
   return ( ((p1-x)*CP(p2-p1,v) >= 0)&&((p2-x)*CP(p3-p2,v) >= 0)&&((p3-x)*CP(p1-p3,v) >= 0) );}
  1. endif
  1. define gTRcC gTVXcC
  2. ifndef gTRcC

integer gTRcC(vector p1,vector p2,vector p3,vector O,vector D){

   return gTVXcC(p1,p2,p3,O,D);}
  1. endif
  1. define gRZiX(O, D, z) ((O)+(D)*(z))
  2. ifndef gRZiX

vector gRZiX(vector O,vector D,float z){

   return O+z*D;}
  1. endif</lsl>