User:Nexii Malthus/Geometric - Second Life Wiki

User:Nexii Malthus/Geometric

From Second Life Wiki

Nexii Malthus/Geometric
Jump to: navigation, search

Contents

Geometric Library

Line Functions

Line Nearest Point, Nearest Point

Returns nearest point on line to given point

 
vector gLXnX(vector O,vector D,vector A){
    return gLXdV(O,D,A) + A;}
 
Input Description
vector O Origin of Line
vector D Direction of Line
vector A Origin of Point
Output Description
return vector gLXnX Returns nearest point on line given point
Requirement
function vector gLXdV(vector O,vector D,vector A)
By Nexii Malthus

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.

//===================================================//
//               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(){}}
 
 

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.

 
//===================================================//
//               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(){}}
 
 

Optimized ESL

//===================================================//
//    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/    //
//===================================================//
 
#define CP(A, B) ((A) % (B))
#ifndef CP
vector CP(vector A,vector B){
    return A % B;}
#endif 
 
#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;}
#else
vector Project3D(vector A,vector B){
    return B * ((A*B) / (B*B));}
#endif
 
// POINT
#define gXXdZ llVecDist
#ifndef gXXdZ
float gXXdZ(vector A,vector B){
    // Distance P2P.
    return llVecDist(A,B);}
#endif 
 
#define gXXdV(A,B) ((A) - (B))
#ifndef gXXdV
vector gXXdV(vector A,vector B){
    // Vector to move from P2P.
    return A-B;}
#endif 
 
// LINE
#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;}
#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;}
#endif
 
#define gLXdZ(O, D, A) llVecMag(CP((A-O),D))
#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));}
#endif 
 
#define gLLdV(O, D, A) Project3D( (O2-O1), CP(D1,D2) )
#ifndef gLLdV
vector gLLdV(vector O1,vector D1,vector O2,vector D2){
    // Shortest vector of two lines
    return Project3D( (O2-O1), CP(D1,D2) );}
#endif 
 
#define gLLdZ(O1, D1, O2, D2) ((O2-O1) * llVecNorm(CP(D1,D2)))
#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;}
#endif 
 
#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;}
#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 ));}
#endif
 
vector X1;vector X2;vector V1;float Z1;
 
#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);}
#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
#endif
 
#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);}
#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
#endif
 
// PLANE
#define gPXdZ(Pn, Pd, A) ((A) * (Pn) + (Pd))
#ifndef gPXdZ
float gPXdZ(vector Pn,float Pd,vector A){
    // Finds distance of a point from a plane
    return A * Pn + Pd;}
#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;}
 
#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) );}
#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) );}
#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;
 
#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);}
#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);}
#endif
 
#define gRXpZ(O, D, A) (A-O)*D
#ifndef gRXpZ
float gRXpZ(vector O,vector D,vector A){
    // Finds projected distance of a point along a ray
    return (A-O)*D;}
#endif
 
#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);}
#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>));}
#endif
 
// SPHERE
#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);
}
#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;
}
#endif
 
#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;
}
#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;
}
#endif
 
// Other
vector pN;float pD;
#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;}
#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)) ));}
#endif
 
#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;}
#else
integer gTXcC(vector p1,vector p2,vector p3,vector x){
    gTiP(p1,p2,p3);
    vector Vn = p1 - x;
    vector En = CP((p2-p1)