/* PLIB - A Suite of Portable Game Libraries Copyright (C) 1998,2002 Steve Baker This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA For further information visit http://plib.sourceforge.net $Id: sg.h,v 1.3 2005/02/01 15:36:04 berniw Exp $ */ #ifndef SG_H #define SG_H 1 #include #include "ul.h" #define sgFloat float #define SGfloat float #define SG_ZERO 0.0f #define SG_HALF 0.5f #define SG_ONE 1.0f #define SG_TWO 2.0f #define SG_THREE 3.0f #define SG_FOUR 4.0f #define SG_45 45.0f #define SG_60 60.0f #define SG_90 90.0f #define SG_180 180.0f #define SG_MAX FLT_MAX #define SG_X 0 #define SG_Y 1 #define SG_Z 2 #define SG_W 3 #ifndef M_PI #define SG_PI 3.1415926535f #else #define SG_PI ((SGfloat) M_PI) #endif #define SG_DEGREES_TO_RADIANS (SG_PI/SG_180) #define SG_RADIANS_TO_DEGREES (SG_180/SG_PI) /* These are just convenient redefinitions of standard math library functions to stop float/double warnings. */ inline SGfloat sgSqrt ( const SGfloat x ) { return (SGfloat) sqrt ( x ) ; } inline SGfloat sgSquare ( const SGfloat x ) { return x * x ; } inline SGfloat sgAbs ( const SGfloat a ) { return (axyz, src->hpr ) ; } extern void sgMakeLookAtMat4 ( sgMat4 dst, const sgVec3 eye, const sgVec3 center, const sgVec3 up ) ; extern void sgMakeRotMat4 ( sgMat4 dst, const SGfloat angle, const sgVec3 axis ) ; inline void sgMakeRotMat4 ( sgMat4 dst, const sgVec3 hpr ) { sgMakeCoordMat4 ( dst, SG_ZERO, SG_ZERO, SG_ZERO, hpr[0], hpr[1], hpr[2] ) ; } inline void sgMakeRotMat4 ( sgMat4 dst,const SGfloat h, const SGfloat p, const SGfloat r ) { sgMakeCoordMat4 ( dst, SG_ZERO, SG_ZERO, SG_ZERO, h, p, r ) ; } extern void sgMakeTransMat4 ( sgMat4 dst, const sgVec3 xyz ) ; extern void sgMakeTransMat4 ( sgMat4 dst, const SGfloat x, const SGfloat y, const SGfloat z ) ; extern void sgSetCoord ( sgCoord *coord, const sgMat4 src ) ; extern void sgMultMat4 ( sgMat4 dst, const sgMat4 a, const sgMat4 b ) ; extern void sgPostMultMat4 ( sgMat4 dst, const sgMat4 a ) ; extern void sgPreMultMat4 ( sgMat4 dst, const sgMat4 a ) ; extern void sgTransposeNegateMat4 ( sgMat4 dst ) ; extern void sgTransposeNegateMat4 ( sgMat4 dst, const sgMat4 src ) ; extern void sgInvertMat4 ( sgMat4 dst, const sgMat4 src ) ; inline void sgInvertMat4 ( sgMat4 dst ) { sgInvertMat4 ( dst, dst ) ; } extern void sgXformVec3 ( sgVec3 dst, const sgVec3 src, const sgMat4 mat ) ; extern void sgXformPnt3 ( sgVec3 dst, const sgVec3 src, const sgMat4 mat ) ; extern void sgXformVec4 ( sgVec4 dst, const sgVec4 src, const sgMat4 mat ) ; extern void sgXformPnt4 ( sgVec4 dst, const sgVec4 src, const sgMat4 mat ) ; extern void sgFullXformPnt3 ( sgVec3 dst, const sgVec3 src, const sgMat4 mat ) ; extern void sgFullXformPnt4 ( sgVec4 dst, const sgVec4 src, const sgMat4 mat ) ; inline void sgXformVec3 ( sgVec3 dst, const sgMat4 mat ) { sgXformVec3 ( dst, dst, mat ) ; } inline void sgXformPnt3 ( sgVec3 dst, const sgMat4 mat ) { sgXformPnt3 ( dst, dst, mat ) ; } inline void sgXformVec4 ( sgVec4 dst, const sgMat4 mat ) { sgXformVec4 ( dst, dst, mat ) ; } inline void sgXformPnt4 ( sgVec4 dst, const sgMat4 mat ) { sgXformPnt4 ( dst, dst, mat ) ; } inline void sgFullXformPnt3 ( sgVec3 dst, const sgMat4 mat ) { sgFullXformPnt3 ( dst, dst, mat ) ; } inline void sgFullXformPnt4 ( sgVec4 dst, const sgMat4 mat ) { sgFullXformPnt4 ( dst, dst, mat ) ; } /* Bits returned by sgClassifyMat4 */ #define SG_IDENTITY 0x00 // for clarity #define SG_ROTATION 0x01 // includes a rotational component #define SG_MIRROR 0x02 // changes handedness (det < 0) #define SG_SCALE 0x04 // uniform scaling #define SG_NONORTHO 0x10 // 3x3 not orthogonal #define SG_TRANSLATION 0x20 // translates #define SG_PROJECTION 0x40 // forth column not 0,0,0,1 /* Are these needed? sgClassifyMat4() does set the general scale bit for some matrices, * but it is not easily defined. Use SG_NONORTHO instead (which is also set). */ #define SG_UNIFORM_SCALE SG_SCALE #define SG_GENERAL_SCALE 0x08 // x, y and z scaled differently extern int sgClassifyMat4 ( const sgMat4 mat ) ; /* Basic low-level vector functions. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For each of Vec2, Vec3 and Vec4, we provide inlines for Zero - set all elements to zero. Set - set each element individually. Add - add vectors element by element. Sub - subtract vectors element by element. Scale - multiply each element of a vector by a variable. AddScaled - multiply second vector by a constant and add the result to the first vector. Negate - negate each element of a vector. Compare - compare vectors element by element with optional tolerance. (return TRUE if vectors are equal - within tolerances) Equal - return TRUE if vectors are exactly equal. Length - compute length of a vector. Distance - compute distance between two points. ScalarProduct - scalar (dot) product. VectorProduct - vector (cross) product (3-element vectors ONLY!). Normalise/Normalize - make vector be one unit long. */ inline void sgZeroVec2 ( sgVec2 dst ) { dst[0]=dst[1]=SG_ZERO ; } inline void sgZeroVec3 ( sgVec3 dst ) { dst[0]=dst[1]=dst[2]=SG_ZERO ; } inline void sgZeroVec4 ( sgVec4 dst ) { dst[0]=dst[1]=dst[2]=dst[3]=SG_ZERO ; } inline void sgSetVec2 ( sgVec2 dst, const SGfloat x, const SGfloat y ) { dst [ 0 ] = x ; dst [ 1 ] = y ; } inline void sgSetVec3 ( sgVec3 dst, const SGfloat x, const SGfloat y, const SGfloat z ) { dst [ 0 ] = x ; dst [ 1 ] = y ; dst [ 2 ] = z ; } inline void sgSetVec4 ( sgVec4 dst, const SGfloat x, const SGfloat y, const SGfloat z, const SGfloat w ) { dst [ 0 ] = x ; dst [ 1 ] = y ; dst [ 2 ] = z ; dst [ 3 ] = w ; } inline void sgCopyVec2 ( sgVec2 dst, const sgVec2 src ) { dst [ 0 ] = src [ 0 ] ; dst [ 1 ] = src [ 1 ] ; } inline void sgCopyVec3 ( sgVec3 dst, const sgVec3 src ) { dst [ 0 ] = src [ 0 ] ; dst [ 1 ] = src [ 1 ] ; dst [ 2 ] = src [ 2 ] ; } inline void sgCopyVec4 ( sgVec4 dst, const sgVec4 src ) { dst [ 0 ] = src [ 0 ] ; dst [ 1 ] = src [ 1 ] ; dst [ 2 ] = src [ 2 ] ; dst [ 3 ] = src [ 3 ] ; } inline void sgAddVec2 ( sgVec2 dst, const sgVec2 src ) { dst [ 0 ] += src [ 0 ] ; dst [ 1 ] += src [ 1 ] ; } inline void sgAddVec3 ( sgVec3 dst, const sgVec3 src ) { dst [ 0 ] += src [ 0 ] ; dst [ 1 ] += src [ 1 ] ; dst [ 2 ] += src [ 2 ] ; } inline void sgAddVec4 ( sgVec4 dst, const sgVec4 src ) { dst [ 0 ] += src [ 0 ] ; dst [ 1 ] += src [ 1 ] ; dst [ 2 ] += src [ 2 ] ; dst [ 3 ] += src [ 3 ] ; } inline void sgAddVec2 ( sgVec2 dst, const sgVec2 src1, const sgVec2 src2 ) { dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] ; dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] ; } inline void sgAddVec3 ( sgVec3 dst, const sgVec3 src1, const sgVec3 src2 ) { dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] ; dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] ; dst [ 2 ] = src1 [ 2 ] + src2 [ 2 ] ; } inline void sgAddVec4 ( sgVec4 dst, const sgVec4 src1, const sgVec4 src2 ) { dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] ; dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] ; dst [ 2 ] = src1 [ 2 ] + src2 [ 2 ] ; dst [ 3 ] = src1 [ 3 ] + src2 [ 3 ] ; } inline void sgSubVec2 ( sgVec2 dst, const sgVec2 src ) { dst [ 0 ] -= src [ 0 ] ; dst [ 1 ] -= src [ 1 ] ; } inline void sgSubVec3 ( sgVec3 dst, const sgVec3 src ) { dst [ 0 ] -= src [ 0 ] ; dst [ 1 ] -= src [ 1 ] ; dst [ 2 ] -= src [ 2 ] ; } inline void sgSubVec4 ( sgVec4 dst, const sgVec4 src ) { dst [ 0 ] -= src [ 0 ] ; dst [ 1 ] -= src [ 1 ] ; dst [ 2 ] -= src [ 2 ] ; dst [ 3 ] -= src [ 3 ] ; } inline void sgSubVec2 ( sgVec2 dst, const sgVec2 src1, const sgVec2 src2 ) { dst [ 0 ] = src1 [ 0 ] - src2 [ 0 ] ; dst [ 1 ] = src1 [ 1 ] - src2 [ 1 ] ; } inline void sgSubVec3 ( sgVec3 dst, const sgVec3 src1, const sgVec3 src2 ) { dst [ 0 ] = src1 [ 0 ] - src2 [ 0 ] ; dst [ 1 ] = src1 [ 1 ] - src2 [ 1 ] ; dst [ 2 ] = src1 [ 2 ] - src2 [ 2 ] ; } inline void sgSubVec4 ( sgVec4 dst, const sgVec4 src1, const sgVec4 src2 ) { dst [ 0 ] = src1 [ 0 ] - src2 [ 0 ] ; dst [ 1 ] = src1 [ 1 ] - src2 [ 1 ] ; dst [ 2 ] = src1 [ 2 ] - src2 [ 2 ] ; dst [ 3 ] = src1 [ 3 ] - src2 [ 3 ] ; } inline void sgNegateVec2 ( sgVec2 dst ) { dst [ 0 ] = -dst [ 0 ] ; dst [ 1 ] = -dst [ 1 ] ; } inline void sgNegateVec3 ( sgVec3 dst ) { dst [ 0 ] = -dst [ 0 ] ; dst [ 1 ] = -dst [ 1 ] ; dst [ 2 ] = -dst [ 2 ] ; } inline void sgNegateVec4 ( sgVec4 dst ) { dst [ 0 ] = -dst [ 0 ] ; dst [ 1 ] = -dst [ 1 ] ; dst [ 2 ] = -dst [ 2 ] ; dst [ 3 ] = -dst [ 3 ] ; } inline void sgNegateVec2 ( sgVec2 dst, const sgVec2 src ) { dst [ 0 ] = -src [ 0 ] ; dst [ 1 ] = -src [ 1 ] ; } inline void sgNegateVec3 ( sgVec3 dst, const sgVec3 src ) { dst [ 0 ] = -src [ 0 ] ; dst [ 1 ] = -src [ 1 ] ; dst [ 2 ] = -src [ 2 ] ; } inline void sgNegateVec4 ( sgVec4 dst, const sgVec4 src ) { dst [ 0 ] = -src [ 0 ] ; dst [ 1 ] = -src [ 1 ] ; dst [ 2 ] = -src [ 2 ] ; dst [ 3 ] = -src [ 3 ] ; } inline void sgScaleVec2 ( sgVec2 dst, const SGfloat s ) { dst [ 0 ] *= s ; dst [ 1 ] *= s ; } inline void sgScaleVec3 ( sgVec3 dst, const SGfloat s ) { dst [ 0 ] *= s ; dst [ 1 ] *= s ; dst [ 2 ] *= s ; } inline void sgScaleVec4 ( sgVec4 dst, const SGfloat s ) { dst [ 0 ] *= s ; dst [ 1 ] *= s ; dst [ 2 ] *= s ; dst [ 3 ] *= s ; } inline void sgScaleVec2 ( sgVec2 dst, const sgVec2 src, const SGfloat s ) { dst [ 0 ] = src [ 0 ] * s ; dst [ 1 ] = src [ 1 ] * s ; } inline void sgScaleVec3 ( sgVec3 dst, const sgVec3 src, const SGfloat s ) { dst [ 0 ] = src [ 0 ] * s ; dst [ 1 ] = src [ 1 ] * s ; dst [ 2 ] = src [ 2 ] * s ; } inline void sgScaleVec4 ( sgVec4 dst, const sgVec4 src, const SGfloat s ) { dst [ 0 ] = src [ 0 ] * s ; dst [ 1 ] = src [ 1 ] * s ; dst [ 2 ] = src [ 2 ] * s ; dst [ 3 ] = src [ 3 ] * s ; } inline void sgAddScaledVec2 ( sgVec2 dst, const sgVec2 src, const SGfloat s ) { dst [ 0 ] += src [ 0 ] * s ; dst [ 1 ] += src [ 1 ] * s ; } inline void sgAddScaledVec3 ( sgVec3 dst, const sgVec3 src, const SGfloat s ) { dst [ 0 ] += src [ 0 ] * s ; dst [ 1 ] += src [ 1 ] * s ; dst [ 2 ] += src [ 2 ] * s ; } inline void sgAddScaledVec4 ( sgVec4 dst, const sgVec4 src, const SGfloat s ) { dst [ 0 ] += src [ 0 ] * s ; dst [ 1 ] += src [ 1 ] * s ; dst [ 2 ] += src [ 2 ] * s ; dst [ 3 ] += src [ 3 ] * s ; } inline void sgAddScaledVec2 ( sgVec2 dst, const sgVec2 src1, const sgVec2 src2, const SGfloat s ) { dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] * s ; dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] * s ; } inline void sgAddScaledVec3 ( sgVec3 dst, const sgVec3 src1, const sgVec3 src2, const SGfloat s ) { dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] * s ; dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] * s ; dst [ 2 ] = src1 [ 2 ] + src2 [ 2 ] * s ; } inline void sgAddScaledVec4 ( sgVec4 dst, const sgVec4 src1, const sgVec4 src2, const SGfloat s ) { dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] * s ; dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] * s ; dst [ 2 ] = src1 [ 2 ] + src2 [ 2 ] * s ; dst [ 3 ] = src1 [ 3 ] + src2 [ 3 ] * s ; } inline int sgCompareVec2 ( const sgVec2 a, const sgVec2 b, const SGfloat tol ) { if ( sgCompareFloat( a[0], b[0], tol ) != 0 ) return FALSE ; if ( sgCompareFloat( a[1], b[1], tol ) != 0 ) return FALSE ; return TRUE ; } inline int sgCompareVec3 ( const sgVec3 a, const sgVec3 b, const SGfloat tol ) { if ( sgCompareFloat( a[0], b[0], tol ) != 0 ) return FALSE ; if ( sgCompareFloat( a[1], b[1], tol ) != 0 ) return FALSE ; if ( sgCompareFloat( a[2], b[2], tol ) != 0 ) return FALSE ; return TRUE ; } inline int sgCompareVec4 ( const sgVec4 a, const sgVec4 b, const SGfloat tol ) { if ( sgCompareFloat( a[0], b[0], tol ) != 0 ) return FALSE ; if ( sgCompareFloat( a[1], b[1], tol ) != 0 ) return FALSE ; if ( sgCompareFloat( a[2], b[2], tol ) != 0 ) return FALSE ; if ( sgCompareFloat( a[3], b[3], tol ) != 0 ) return FALSE ; return TRUE ; } inline int sgEqualVec2 ( const sgVec2 a, const sgVec2 b ) { return a[0] == b[0] && a[1] == b[1] ; } inline int sgEqualVec3 ( const sgVec3 a, const sgVec3 b ) { return a[0] == b[0] && a[1] == b[1] && a[2] == b[2] ; } inline int sgEqualVec4 ( const sgVec4 a, const sgVec4 b ) { return a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3] ; } inline SGfloat sgScalarProductVec2 ( const sgVec2 a, const sgVec2 b ) { return a[0]*b[0] + a[1]*b[1] ; } inline SGfloat sgScalarProductVec3 ( const sgVec3 a, const sgVec3 b ) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] ; } inline SGfloat sgScalarProductVec4 ( const sgVec4 a, const sgVec4 b ) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3] ; } extern void sgVectorProductVec3 ( sgVec3 dst, const sgVec3 a, const sgVec3 b ) ; inline SGfloat sgLerp ( const SGfloat a, const SGfloat b, const SGfloat f ) { return a + f * ( b - a ) ; } inline void sgLerpVec4 ( sgVec4 dst, const sgVec4 a, const sgVec4 b, const SGfloat f ) { dst[0] = a[0] + f * ( b[0] - a[0] ) ; dst[1] = a[1] + f * ( b[1] - a[1] ) ; dst[2] = a[2] + f * ( b[2] - a[2] ) ; dst[3] = a[3] + f * ( b[3] - a[3] ) ; } inline void sgLerpVec3 ( sgVec3 dst, const sgVec3 a, const sgVec3 b, const SGfloat f ) { dst[0] = a[0] + f * ( b[0] - a[0] ) ; dst[1] = a[1] + f * ( b[1] - a[1] ) ; dst[2] = a[2] + f * ( b[2] - a[2] ) ; } inline void sgLerpVec2 ( sgVec2 dst, const sgVec2 a, const sgVec2 b, const SGfloat f ) { dst[0] = a[0] + f * ( b[0] - a[0] ) ; dst[1] = a[1] + f * ( b[1] - a[1] ) ; } inline void sgLerpAnglesVec3 ( sgVec3 dst, const sgVec3 a, const sgVec3 b, const SGfloat f ) { sgVec3 tmp ; if ( b[0] - a[0] > 180.0f ) tmp[0] = a[0] + 360.0f ; else if ( b[0] - a[0] < -180.0f ) tmp[0] = a[0] - 360.0f ; else tmp[0] = a[0] ; if ( b[1] - a[1] > 180.0f ) tmp[1] = a[1] + 360.0f ; else if ( b[1] - a[1] < -180.0f ) tmp[1] = a[1] - 360.0f ; else tmp[1] = a[1] ; if ( b[2] - a[2] > 180.0f ) tmp[2] = a[2] + 360.0f ; else if ( b[2] - a[2] < -180.0f ) tmp[2] = a[2] - 360.0f ; else tmp[2] = a[2] ; dst[0] = tmp[0] + f * ( b[0] - tmp[0] ) ; dst[1] = tmp[1] + f * ( b[1] - tmp[1] ) ; dst[2] = tmp[2] + f * ( b[2] - tmp[2] ) ; } inline SGfloat sgDistanceSquaredVec2 ( const sgVec2 a, const sgVec2 b ) { return sgSquare ( a[0]-b[0] ) + sgSquare ( a[1]-b[1] ) ; } inline SGfloat sgDistanceSquaredVec3 ( const sgVec3 a, const sgVec3 b ) { return sgSquare ( a[0]-b[0] ) + sgSquare ( a[1]-b[1] ) + sgSquare ( a[2]-b[2] ) ; } inline SGfloat sgDistanceSquaredVec4 ( const sgVec4 a, const sgVec4 b ) { return sgSquare ( a[0]-b[0] ) + sgSquare ( a[1]-b[1] ) + sgSquare ( a[2]-b[2] ) + sgSquare ( a[3]-b[3] ) ; } inline SGfloat sgDistanceVec2 ( const sgVec2 a, const sgVec2 b ) { return sgSqrt ( sgSquare ( a[0]-b[0] ) + sgSquare ( a[1]-b[1] ) ) ; } inline SGfloat sgDistanceVec3 ( const sgVec3 a, const sgVec3 b ) { return sgSqrt ( sgSquare ( a[0]-b[0] ) + sgSquare ( a[1]-b[1] ) + sgSquare ( a[2]-b[2] ) ) ; } inline SGfloat sgDistanceVec4 ( const sgVec4 a, const sgVec4 b ) { return sgSqrt ( sgSquare ( a[0]-b[0] ) + sgSquare ( a[1]-b[1] ) + sgSquare ( a[2]-b[2] ) + sgSquare ( a[3]-b[3] ) ) ; } inline SGfloat sgLengthVec2 ( const sgVec2 src ) { return sgSqrt ( sgScalarProductVec2 ( src, src ) ) ; } inline SGfloat sgLengthVec3 ( const sgVec3 src ) { return sgSqrt ( sgScalarProductVec3 ( src, src ) ) ; } inline SGfloat sgLengthVec4 ( const sgVec4 src ) { return sgSqrt ( sgScalarProductVec4 ( src, src ) ) ; } inline SGfloat sgLengthSquaredVec2 ( sgVec2 const src ) { return sgScalarProductVec2 ( src, src ) ; } inline SGfloat sgLengthSquaredVec3 ( sgVec3 const src ) { return sgScalarProductVec3 ( src, src ) ; } inline SGfloat sgLengthSquaredVec4 ( sgVec4 const src ) { return sgScalarProductVec4 ( src, src ) ; } /* Anglo-US spelling issues. */ #define sgNormalizeVec2 sgNormaliseVec2 #define sgNormalizeVec3 sgNormaliseVec3 #define sgNormalizeVec4 sgNormaliseVec4 #define sgNormalizeQuat sgNormaliseQuat inline void sgNormaliseVec2 ( sgVec2 dst ) { sgScaleVec2 ( dst, SG_ONE / sgLengthVec2 ( dst ) ) ; } inline void sgNormaliseVec3 ( sgVec3 dst ) { sgScaleVec3 ( dst, SG_ONE / sgLengthVec3 ( dst ) ) ; } inline void sgNormaliseVec4 ( sgVec4 dst ) { sgScaleVec4 ( dst, SG_ONE / sgLengthVec4 ( dst ) ) ; } inline void sgNormaliseVec2 ( sgVec2 dst, const sgVec2 src ) { sgScaleVec2 ( dst, src, SG_ONE / sgLengthVec2 ( src ) ) ; } inline void sgNormaliseVec3 ( sgVec3 dst, const sgVec3 src ) { sgScaleVec3 ( dst, src, SG_ONE / sgLengthVec3 ( src ) ) ; } inline void sgNormaliseVec4 ( sgVec4 dst, const sgVec4 src ) { sgScaleVec4 ( dst, src, SG_ONE / sgLengthVec4 ( src ) ) ; } inline void sgZeroCoord ( sgCoord *dst ) { sgSetVec3 ( dst->xyz, SG_ZERO, SG_ZERO, SG_ZERO ) ; sgSetVec3 ( dst->hpr, SG_ZERO, SG_ZERO, SG_ZERO ) ; } inline void sgSetCoord ( sgCoord *dst, const SGfloat x, const SGfloat y, const SGfloat z, const SGfloat h, const SGfloat p, const SGfloat r ) { sgSetVec3 ( dst->xyz, x, y, z ) ; sgSetVec3 ( dst->hpr, h, p, r ) ; } inline void sgSetCoord ( sgCoord *dst, const sgVec3 xyz, const sgVec3 hpr ) { sgCopyVec3 ( dst->xyz, xyz ) ; sgCopyVec3 ( dst->hpr, hpr ) ; } inline void sgCopyCoord ( sgCoord *dst, const sgCoord *src ) { sgCopyVec3 ( dst->xyz, src->xyz ) ; sgCopyVec3 ( dst->hpr, src->hpr ) ; } inline void sgCopyMat4 ( sgMat4 dst, const sgMat4 src ) { sgCopyVec4 ( dst[ 0 ], src[ 0 ] ) ; sgCopyVec4 ( dst[ 1 ], src[ 1 ] ) ; sgCopyVec4 ( dst[ 2 ], src[ 2 ] ) ; sgCopyVec4 ( dst[ 3 ], src[ 3 ] ) ; } inline void sgScaleMat4 ( sgMat4 dst, const sgMat4 src, const SGfloat scale ) { sgScaleVec4 ( dst[0], src[0], scale ) ; sgScaleVec4 ( dst[1], src[1], scale ) ; sgScaleVec4 ( dst[2], src[2], scale ) ; sgScaleVec4 ( dst[3], src[3], scale ) ; } inline void sgMakeIdentMat4 ( sgMat4 dst ) { sgSetVec4 ( dst[0], SG_ONE , SG_ZERO, SG_ZERO, SG_ZERO ) ; sgSetVec4 ( dst[1], SG_ZERO, SG_ONE , SG_ZERO, SG_ZERO ) ; sgSetVec4 ( dst[2], SG_ZERO, SG_ZERO, SG_ONE , SG_ZERO ) ; sgSetVec4 ( dst[3], SG_ZERO, SG_ZERO, SG_ZERO, SG_ONE ) ; } extern void sgMakePickMatrix( sgMat4 mat, sgFloat x, sgFloat y, sgFloat width, sgFloat height, sgVec4 viewport ) ; extern int sgCompare3DSqdDist ( const sgVec3 a, const sgVec3 b, const SGfloat sqd_dist ) ; inline SGfloat sgDistToLineVec2 ( const sgVec3 line, const sgVec2 pnt ) { return sgScalarProductVec2 ( line, pnt ) + line[2] ; } struct sgLineSegment3 /* Bounded line segment */ { sgVec3 a ; sgVec3 b ; } ; struct sgLine3 /* Infinite line */ { sgVec3 point_on_line ; sgVec3 direction_vector ; /* Should be a unit vector */ } ; inline void sgLineSegment3ToLine3 ( sgLine3 *line, const sgLineSegment3 lineseg ) { sgCopyVec3 ( line->point_on_line , lineseg.a ) ; sgSubVec3 ( line->direction_vector, lineseg.b, lineseg.a ) ; sgNormaliseVec3 ( line->direction_vector ) ; } SGfloat sgDistSquaredToLineVec3 ( const sgLine3 line, const sgVec3 pnt ) ; SGfloat sgDistSquaredToLineSegmentVec3 ( const sgLineSegment3 line, const sgVec3 pnt ) ; inline SGfloat sgDistToLineVec3 ( const sgLine3 line, const sgVec3 pnt ) { return sgSqrt ( sgDistSquaredToLineVec3 ( line, pnt ) ); } inline SGfloat sgDistToLineSegmentVec3 ( const sgLineSegment3 line, const sgVec3 pnt ) { return sgSqrt ( sgDistSquaredToLineSegmentVec3(line,pnt) ) ; } inline SGfloat sgDistToPlaneVec3 ( const sgVec4 plane, const sgVec3 pnt ) { return sgScalarProductVec3 ( plane, pnt ) + plane[3] ; } inline SGfloat sgHeightAbovePlaneVec3 ( const sgVec4 plane, const sgVec3 pnt ) { return pnt[2] - sgHeightOfPlaneVec2 ( plane, pnt ) ; } extern void sgReflectInPlaneVec3 ( sgVec3 dst, const sgVec3 src, const sgVec4 plane ) ; inline void sgReflectInPlaneVec3 ( sgVec3 dst, const sgVec4 plane ) { sgReflectInPlaneVec3 ( dst, dst, plane ) ; } extern void sgMakeNormal ( sgVec2 dst, const sgVec3 a, const sgVec3 b ) ; extern void sgMakeNormal ( sgVec3 dst, const sgVec3 a, const sgVec3 b, const sgVec3 c ) ; inline void sgMake2DLine ( sgVec3 dst, const sgVec2 a, const sgVec2 b ) { dst[0] = b[1]-a[1] ; dst[1] = -(b[0]-a[0]) ; sgNormalizeVec2 ( dst ) ; dst[2] = - ( dst[0]*a[0] + dst[1]*a[1] ) ; } inline void sgMakePlane ( sgVec4 dst, const sgVec3 normal, const sgVec3 pnt ) { sgCopyVec3 ( dst, normal ) ; dst [ 3 ] = - sgScalarProductVec3 ( normal, pnt ) ; } inline void sgMakePlane ( sgVec4 dst, const sgVec3 a, const sgVec3 b, const sgVec3 c ) { /* Ax + By + Cz + D == 0 ; D = - ( Ax + By + Cz ) = - ( A*a[0] + B*a[1] + C*a[2] ) = - sgScalarProductVec3 ( normal, a ) ; */ sgMakeNormal ( dst, a, b, c ) ; dst [ 3 ] = - sgScalarProductVec3 ( dst, a ) ; } float sgTriArea( sgVec3 p0, sgVec3 p1, sgVec3 p2 ); // Fast code. Result is in the range 0..180: inline SGfloat sgAngleBetweenNormalizedVec3 ( sgVec3 v1, sgVec3 v2 ) { float f = sgScalarProductVec3 ( v1, v2 ) ; return (float) acos ( ( f >= 1.0f ) ? 1.0f : ( f <= -1.0f ) ? -1.0f : f ) * SG_RADIANS_TO_DEGREES ; } // Fast code. Result is in the range 0..180: SGfloat sgAngleBetweenVec3 ( sgVec3 v1, sgVec3 v2 ); // All three have to be normalized. Slow code. Result is in the range 0..360: SGfloat sgAngleBetweenNormalizedVec3 (sgVec3 first, sgVec3 second, sgVec3 normal); // Normal has to be normalized. Slow code. Result is in the range 0..360: SGfloat sgAngleBetweenVec3 ( sgVec3 v1, sgVec3 v2, sgVec3 normal ); class sgSphere { public: sgVec3 center ; SGfloat radius ; sgSphere () { empty () ; } const SGfloat *getCenter (void) const { return center ; } void setCenter ( const sgVec3 c ) { sgCopyVec3 ( center, c ) ; } void setCenter ( const SGfloat x, const SGfloat y, const SGfloat z ) { sgSetVec3 ( center, x, y, z ) ; } SGfloat getRadius (void) const { return radius ; } void setRadius ( const SGfloat r ) { radius = r ; } int isEmpty (void) const { return radius < SG_ZERO ; } void empty (void) { radius = - SG_ONE ; } void orthoXform ( const sgMat4 m ) { sgXformPnt3 ( center, center, m ) ; // radius *= sgLengthVec3 ( m[0] ) ; -- degrades performance for non-scaled matrices ... } void extend ( const sgSphere *s ) ; void extend ( const sgBox *b ) ; void extend ( const sgVec3 v ) ; int intersects ( const sgSphere *s ) const { return sgCompare3DSqdDist ( center, s->getCenter(), sgSquare ( radius + s->getRadius() ) ) <= 0 ; } int intersects ( const sgVec4 plane ) const { return sgAbs ( sgDistToPlaneVec3 ( plane, center ) ) <= radius ; } int intersects ( const sgBox *b ) const ; } ; class sgBox { public: sgVec3 min ; sgVec3 max ; sgBox () { empty () ; } const SGfloat *getMin (void) const { return min ; } const SGfloat *getMax (void) const { return max ; } void setMin ( const SGfloat x, const SGfloat y, const SGfloat z ) { sgSetVec3 ( min, x, y, z ) ; } void setMin ( const sgVec3 src ) { sgCopyVec3 ( min, src ) ; } void setMax ( const SGfloat x, const SGfloat y, const SGfloat z ) { sgSetVec3 ( max, x, y, z ) ; } void setMax ( const sgVec3 src ) { sgCopyVec3 ( max, src ) ; } int isEmpty(void) const { return ( min[0] > max[0] || min[1] > max[1] || min[2] > max[2] ) ; } void empty (void) { sgSetVec3 ( min, SG_MAX, SG_MAX, SG_MAX ) ; sgSetVec3 ( max, -SG_MAX, -SG_MAX, -SG_MAX ) ; } void extend ( const sgSphere *s ) ; void extend ( const sgBox *b ) ; void extend ( const sgVec3 v ) ; int intersects ( const sgSphere *s ) const { return s -> intersects ( this ) ; } int intersects ( const sgBox *b ) const { return min[0] <= b->getMax()[0] && max[0] >= b->getMin()[0] && min[1] <= b->getMax()[1] && max[1] >= b->getMin()[1] && min[2] <= b->getMax()[2] && max[2] >= b->getMin()[2] ; } int intersects ( const sgVec4 plane ) const ; } ; #define SG_LEFT_PLANE 0 #define SG_RIGHT_PLANE 1 #define SG_BOT_PLANE 2 #define SG_TOP_PLANE 3 #define SG_NEAR_PLANE 4 #define SG_FAR_PLANE 5 class sgFrustum { /* Is the projection orthographic (or perspective)? */ int ortho ; /* The parameters for glFrustum/glOrtho */ SGfloat left, right, bot, top, nnear, ffar ; /* The computed projection matrix for this frustum */ sgMat4 mat ; /* The A,B,C,D terms of the plane equations of the clip planes */ /* A point (x,y,z) is inside the frustum iff Ax + By + Cz + D >= 0 for all planes */ sgVec4 plane [ 6 ] ; /* These two are only valid for simple frusta */ SGfloat hfov ; /* Horizontal Field of View -or- Orthographic Width */ SGfloat vfov ; /* Vertical Field of View -or- Orthographic Height */ void update (void) ; int getOutcode ( const sgVec4 src ) const ; public: sgFrustum (void) { ortho = FALSE ; nnear = SG_ONE ; ffar = 1000000.0f ; hfov = SG_45 ; vfov = SG_45 ; update () ; } void setFrustum ( const SGfloat l, const SGfloat r, const SGfloat b, const SGfloat t, const SGfloat n, const SGfloat f ) { ortho = FALSE ; left = l ; right = r ; bot = b ; top = t ; nnear = n ; ffar = f ; hfov = vfov = SG_ZERO ; update () ; } void setOrtho ( const SGfloat l, const SGfloat r, const SGfloat b, const SGfloat t, const SGfloat n, const SGfloat f ) { ortho = TRUE ; left = l ; right = r ; bot = b ; top = t ; nnear = n ; ffar = f ; hfov = vfov = SG_ZERO ; update () ; } void getMat4 ( sgMat4 dst ) { sgCopyMat4 ( dst, mat ) ; } SGfloat getLeft (void) const { return left ; } SGfloat getRight(void) const { return right ; } SGfloat getBot (void) const { return bot ; } SGfloat getTop (void) const { return top ; } SGfloat getNear (void) const { return nnear ; } SGfloat getFar (void) const { return ffar ; } const SGfloat *getPlane ( int i ) const { return plane [ i ] ; } SGfloat getHFOV (void) const { return hfov ; } SGfloat getVFOV (void) const { return vfov ; } void getFOV ( SGfloat *h, SGfloat *v ) const { if ( h != (SGfloat *) 0 ) *h = hfov ; if ( v != (SGfloat *) 0 ) *v = vfov ; } void setFOV ( const SGfloat h, const SGfloat v ) { ortho = FALSE ; hfov = ( h <= 0 ) ? ( v * SG_FOUR / SG_THREE ) : h ; vfov = ( v <= 0 ) ? ( h * SG_THREE / SG_FOUR ) : v ; update () ; } void getOrtho ( SGfloat *w, SGfloat *h ) const { if ( w != (SGfloat *) 0 ) *w = right - left ; if ( h != (SGfloat *) 0 ) *h = top - bot ; } void setOrtho ( const SGfloat w, const SGfloat h ) { ortho = TRUE ; hfov = ( w <= 0 ) ? ( h * SG_FOUR / SG_THREE ) : w ; vfov = ( h <= 0 ) ? ( w * SG_FOUR / SG_THREE ) : h ; update () ; } void getNearFar ( SGfloat *n, SGfloat *f ) const { if ( n != (SGfloat *) 0 ) *n = nnear ; if ( f != (SGfloat *) 0 ) *f = ffar ; } void setNearFar ( const SGfloat n, const SGfloat f ) { nnear = n ; ffar = f ; update () ; } int isOrtho (void) const { return ortho ; } int contains ( const sgVec3 p ) const ; int contains ( const sgSphere *s ) const ; int contains ( const sgBox *b ) const ; } ; /* Quaternion routines are Copyright (C) 1999 Kevin B. Thompson Modified by Sylvan W. Clebsch Largely rewritten by "Negative0" Added to by John Fay */ /* Quaternion structure w = real, (x, y, z) = vector CHANGED sqQuat to float array so that syntax matches vector and matrix routines */ inline void sgMakeIdentQuat ( sgQuat dst ) { sgSetVec4 ( dst, SG_ZERO, SG_ZERO, SG_ZERO, SG_ONE ) ; } inline void sgSetQuat ( sgQuat dst, const SGfloat w, const SGfloat x, const SGfloat y, const SGfloat z ) { sgSetVec4 ( dst, x, y, z, w ) ; } inline void sgCopyQuat ( sgQuat dst, const sgQuat src ) { sgCopyVec4 ( dst, src ) ; } /* Construct a unit quaternion (length==1) */ inline void sgNormaliseQuat ( sgQuat dst, const sgQuat src ) { SGfloat d = sgScalarProductVec4 ( src, src ) ; d = (d > SG_ZERO) ? (SG_ONE / sgSqrt ( d )) : SG_ONE ; sgScaleVec4 ( dst, src, d ) ; } inline void sgNormaliseQuat ( sgQuat dst ) { sgNormaliseQuat ( dst, dst ) ; } inline void sgInvertQuat ( sgQuat dst, const sgQuat src ) { SGfloat d = sgScalarProductVec4 ( src, src ) ; d = ( d == SG_ZERO ) ? SG_ONE : ( SG_ONE / d ) ; dst[SG_W] = src[SG_W] * d ; dst[SG_X] = -src[SG_X] * d ; dst[SG_Y] = -src[SG_Y] * d ; dst[SG_Z] = -src[SG_Z] * d ; } inline void sgInvertQuat ( sgQuat dst ) { sgInvertQuat ( dst, dst ) ; } /* Make an angle and axis of rotation from a Quaternion. */ void sgQuatToAngleAxis ( SGfloat *angle, sgVec3 axis, const sgQuat src ) ; void sgQuatToAngleAxis ( SGfloat *angle, SGfloat *x, SGfloat *y, SGfloat *z, const sgQuat src ) ; /* Make a quaternion from a given angle and axis of rotation */ void sgAngleAxisToQuat ( sgQuat dst, const SGfloat angle, const sgVec3 axis ) ; void sgAngleAxisToQuat ( sgQuat dst, const SGfloat angle, const SGfloat x, const SGfloat y, const SGfloat z ) ; /* Convert a matrix to/from a quat */ void sgMatrixToQuat ( sgQuat quat, const sgMat4 m ) ; void sgQuatToMatrix ( sgMat4 m, const sgQuat quat ) ; /* Convert a set of eulers to/from a quat */ void sgQuatToEuler( sgVec3 hpr, const sgQuat quat ) ; void sgEulerToQuat( sgQuat quat, const sgVec3 hpr ) ; inline void sgEulerToQuat( sgQuat dst, SGfloat h, SGfloat p, SGfloat r ) { sgVec3 hpr ; sgSetVec3 ( hpr, h, p, r ) ; sgEulerToQuat( dst, hpr ) ; } inline void sgHPRToQuat ( sgQuat dst, SGfloat h, SGfloat p, SGfloat r ) { sgVec3 hpr; hpr[0] = h * SG_DEGREES_TO_RADIANS ; hpr[1] = p * SG_DEGREES_TO_RADIANS ; hpr[2] = r * SG_DEGREES_TO_RADIANS ; sgEulerToQuat( dst, hpr ) ; } inline void sgHPRToQuat ( sgQuat dst, const sgVec3 hpr ) { sgVec3 tmp ; sgScaleVec3 ( tmp, hpr, SG_DEGREES_TO_RADIANS ) ; sgEulerToQuat ( dst, tmp ) ; } /* Multiply quaternions together (concatenate rotations) */ void sgMultQuat ( sgQuat dst, const sgQuat a, const sgQuat b ) ; inline void sgPostMultQuat ( sgQuat dst, const sgQuat q ) { sgQuat r ; sgCopyQuat ( r, dst ) ; sgMultQuat ( dst, r, q ) ; } inline void sgPreMultQuat ( sgQuat dst, const sgQuat q ) { sgQuat r ; sgCopyQuat ( r, dst ) ; sgMultQuat ( dst, q, r ) ; } /* Rotate a quaternion by a given angle and axis (convenience function) */ inline void sgPreRotQuat ( sgQuat dst, const SGfloat angle, const sgVec3 axis ) { sgQuat q ; sgAngleAxisToQuat ( q, angle, axis ) ; sgPreMultQuat ( dst, q ) ; sgNormaliseQuat ( dst ) ; } inline void sgPostRotQuat ( sgQuat dst, const SGfloat angle, const sgVec3 axis ) { sgQuat q ; sgAngleAxisToQuat ( q, angle, axis ) ; sgPostMultQuat ( dst, q ) ; sgNormaliseQuat ( dst ) ; } inline void sgPreRotQuat ( sgQuat dst, const SGfloat angle, const SGfloat x, const SGfloat y, const SGfloat z ) { sgVec3 axis ; sgSetVec3 ( axis, x, y, z ) ; sgPreRotQuat ( dst, angle, axis ) ; } inline void sgPostRotQuat ( sgQuat dst, const SGfloat angle, const SGfloat x, const SGfloat y, const SGfloat z ) { sgVec3 axis ; sgSetVec3 ( axis, x, y, z ) ; sgPostRotQuat ( dst, angle, axis ) ; } /* more meaningful names */ #define sgWorldRotQuat sgPostRotQuat #define sgLocalRotQuat sgPreRotQuat /* for backwards compatibility */ #define sgRotQuat sgPostRotQuat /* SWC - Interpolate between to quaternions */ extern void sgSlerpQuat ( sgQuat dst, const sgQuat from, const sgQuat to, const SGfloat t ) ; /* Intersection testing. */ int sgIsectPlanePlane ( sgVec3 point, sgVec3 dir, sgVec4 plane1, sgVec4 plane2 ) ; int sgIsectInfLinePlane ( sgVec3 dst, sgVec3 l_org, sgVec3 l_vec, sgVec4 plane ) ; int sgIsectInfLineInfLine ( sgVec3 dst, sgVec3 l1_org, sgVec3 l1_vec, sgVec3 l2_org, sgVec3 l2_vec ) ; SGfloat sgIsectLinesegPlane ( sgVec3 dst, sgVec3 v1, sgVec3 v2, sgVec4 plane ) ; bool sgPointInTriangle3 ( sgVec3 point, sgVec3 tri[3] ) ; bool sgPointInTriangle2 ( sgVec2 point, sgVec2 tri[3] ) ; inline bool sgPointInTriangle ( sgVec3 point, sgVec3 tri[3] ) { return sgPointInTriangle3 ( point, tri ) ; } /**********************************************************************/ #define sgdFloat double #define SGDfloat double #define SGD_ZERO 0.0 #define SGD_HALF 0.5 #define SGD_ONE 1.0 #define SGD_TWO 2.0 #define SGD_THREE 3.0 #define SGD_FOUR 4.0 #define SGD_45 45.0 #define SGD_60 60.0 #define SGD_90 90.0 #define SGD_180 180.0 #define SGD_MAX DBL_MAX #define SGD_X 0 #define SGD_Y 1 #define SGD_Z 2 #define SGD_W 3 #ifndef M_PI #define SGD_PI 3.14159265358979323846 /* From M_PI under Linux/X86 */ #else #define SGD_PI M_PI #endif #define SGD_DEGREES_TO_RADIANS (SGD_PI/SGD_180) #define SGD_RADIANS_TO_DEGREES (SGD_180/SGD_PI) /* These are just convenient redefinitions of standard math library functions to stop float/double warnings. */ inline SGDfloat sgdSqrt ( const SGDfloat x ) { return sqrt ( x ) ; } inline SGDfloat sgdSquare ( const SGDfloat x ) { return x * x ; } inline SGDfloat sgdAbs ( const SGDfloat a ) { return ( a < SGD_ZERO ) ? -a : a ; } inline SGDfloat sgdASin ( SGDfloat s ) { return (SGDfloat) asin ( s ) * SGD_RADIANS_TO_DEGREES ; } inline SGDfloat sgdACos ( SGDfloat s ) { return (SGDfloat) acos ( s ) * SGD_RADIANS_TO_DEGREES ; } inline SGDfloat sgdATan ( SGDfloat s ) { return (SGDfloat) atan ( s ) * SGD_RADIANS_TO_DEGREES ; } inline SGDfloat sgdATan2 ( SGDfloat y, SGDfloat x ) { return (SGDfloat) atan2 ( y,x ) * SGD_RADIANS_TO_DEGREES ; } inline SGDfloat sgdSin ( SGDfloat s ) { return (SGDfloat) sin ( s * SGD_DEGREES_TO_RADIANS ) ; } inline SGDfloat sgdCos ( SGDfloat s ) { return (SGDfloat) cos ( s * SGD_DEGREES_TO_RADIANS ) ; } inline SGDfloat sgdTan ( SGDfloat s ) { return (SGDfloat) tan ( s * SGD_DEGREES_TO_RADIANS ) ; } inline int sgdCompareFloat ( const SGDfloat a, const SGDfloat b, const SGDfloat tol ) { if ( ( a + tol ) < b ) return -1 ; if ( ( b + tol ) < a ) return 1 ; return 0 ; } /* Types used in SGD. */ typedef SGDfloat sgdVec2 [ 2 ] ; typedef SGDfloat sgdVec3 [ 3 ] ; typedef SGDfloat sgdVec4 [ 4 ] ; typedef sgdVec4 sgdQuat ; typedef SGDfloat sgdMat3 [3][3] ; typedef SGDfloat sgdMat4 [4][4] ; struct sgdCoord { sgdVec3 xyz ; sgdVec3 hpr ; } ; class sgdSphere ; class sgdBox ; class sgdFrustum ; /* Some handy constants */ #define SGD_OUTSIDE FALSE #define SGD_INSIDE TRUE #define SGD_STRADDLE 2 inline SGDfloat sgdHeightOfPlaneVec2 ( const sgdVec4 plane, const sgdVec2 pnt ) { if ( plane[2] == SGD_ZERO ) return SGD_ZERO ; else return -( plane[0] * pnt[0] + plane[1] * pnt[1] + plane[3] ) / plane[2] ; } /* Convert a direction vector into a set of euler angles, (with zero roll) */ extern void sgdHPRfromVec3 ( sgdVec3 hpr, const sgdVec3 src ) ; extern void sgdMakeCoordMat4 ( sgdMat4 dst, const SGDfloat x, const SGDfloat y, const SGDfloat z, const SGDfloat h, const SGDfloat p, const SGDfloat r ) ; inline void sgdMakeCoordMat4( sgdMat4 dst, const sgdVec3 xyz, const sgdVec3 hpr ) { sgdMakeCoordMat4 ( dst, xyz[0], xyz[1], xyz[2], hpr[0], hpr[1], hpr[2] ) ; } inline void sgdMakeCoordMat4( sgdMat4 dst, const sgdCoord *src ) { sgdMakeCoordMat4 ( dst, src->xyz, src->hpr ) ; } extern void sgdMakeRotMat4 ( sgdMat4 dst, const SGDfloat angle, const sgdVec3 axis ) ; inline void sgdMakeRotMat4 ( sgdMat4 dst, const sgdVec3 hpr ) { sgdMakeCoordMat4 ( dst, SGD_ZERO, SGD_ZERO, SGD_ZERO, hpr[0], hpr[1], hpr[2] ) ; } inline void sgdMakeRotMat4 ( sgdMat4 dst, const SGDfloat h, const SGDfloat p, const SGDfloat r ) { sgdMakeCoordMat4 ( dst, SGD_ZERO, SGD_ZERO, SGD_ZERO, h, p, r ) ; } extern void sgdMakeTransMat4 ( sgdMat4 dst, const sgdVec3 xyz ) ; extern void sgdMakeTransMat4 ( sgdMat4 dst, const SGDfloat x, const SGDfloat y, const SGDfloat z ) ; extern void sgdSetCoord ( sgdCoord *coord, const sgdMat4 src ) ; extern void sgdMultMat4 ( sgdMat4 dst, const sgdMat4 a, const sgdMat4 b ) ; extern void sgdPostMultMat4 ( sgdMat4 dst, const sgdMat4 a ) ; extern void sgdPreMultMat4 ( sgdMat4 dst, const sgdMat4 a ) ; extern void sgdTransposeNegateMat4 ( sgdMat4 dst ) ; extern void sgdTransposeNegateMat4 ( sgdMat4 dst, const sgdMat4 src ) ; extern void sgdInvertMat4 ( sgdMat4 dst, const sgdMat4 src ) ; inline void sgdInvertMat4 ( sgdMat4 dst ) { sgdInvertMat4 ( dst, dst ) ; } extern void sgdXformVec3 ( sgdVec3 dst, const sgdVec3 src, const sgdMat4 mat ) ; extern void sgdXformPnt3 ( sgdVec3 dst, const sgdVec3 src, const sgdMat4 mat ) ; extern void sgdXformVec4 ( sgdVec4 dst, const sgdVec4 src, const sgdMat4 mat ) ; extern void sgdXformPnt4 ( sgdVec4 dst, const sgdVec4 src, const sgdMat4 mat ) ; extern void sgdFullXformPnt3 ( sgdVec3 dst, const sgdVec3 src, const sgdMat4 mat ) ; extern void sgdFullXformPnt4 ( sgdVec4 dst, const sgdVec4 src, const sgdMat4 mat ) ; inline void sgdXformVec3 ( sgdVec3 dst, const sgdMat4 mat ) { sgdXformVec3 ( dst, dst, mat ) ; } inline void sgdXformPnt3 ( sgdVec3 dst, const sgdMat4 mat ) { sgdXformPnt3 ( dst, dst, mat ) ; } inline void sgdXformVec4 ( sgdVec4 dst, const sgdMat4 mat ) { sgdXformVec4 ( dst, dst, mat ) ; } inline void sgdXformPnt4 ( sgdVec4 dst, const sgdMat4 mat ) { sgdXformPnt4 ( dst, dst, mat ) ; } inline void sgdFullXformPnt3 ( sgdVec3 dst, const sgdMat4 mat ) { sgdFullXformPnt3 ( dst, dst, mat ) ; } inline void sgdFullXformPnt4 ( sgdVec4 dst, const sgdMat4 mat ) { sgdFullXformPnt4 ( dst, dst, mat ) ; } /* Basic low-level vector functions. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For each of Vec2, Vec3 and Vec4, we provide inlines for Zero - set all elements to zero. Set - set each element individually. Add - add vectors element by element. Sub - subtract vectors element by element. Scale - multiply each element of a vector by a variable. Negate - negate each element of a vector. Compare - compare vectors element by element with optional tolerance. (return TRUE if vectors are equal - within tolerances) Equal - return TRUE if vectors are exactly equal. Length - compute length of a vector. Distance - compute distance between two points. LengthSquared - compute the square of the length of a vector. DistanceSquared - compute the square of the distance between two points. ScalarProduct - scalar (dot) product. VectorProduct - vector (cross) product (3-element vectors ONLY!). Normalise/Normalize - make vector be one unit long. Lerp - linear interpolation by a fraction 'f'. */ inline void sgdZeroVec2 ( sgdVec2 dst ) { dst[0]=dst[1]=SGD_ZERO ; } inline void sgdZeroVec3 ( sgdVec3 dst ) { dst[0]=dst[1]=dst[2]=SGD_ZERO ; } inline void sgdZeroVec4 ( sgdVec4 dst ) { dst[0]=dst[1]=dst[2]=dst[3]=SGD_ZERO ; } inline void sgdSetVec2 ( sgdVec2 dst, const SGDfloat x, const SGDfloat y ) { dst [ 0 ] = x ; dst [ 1 ] = y ; } inline void sgdSetVec3 ( sgdVec3 dst, const SGDfloat x, const SGDfloat y, const SGDfloat z ) { dst [ 0 ] = x ; dst [ 1 ] = y ; dst [ 2 ] = z ; } inline void sgdSetVec4 ( sgdVec4 dst, const SGDfloat x, const SGDfloat y, const SGDfloat z, const SGDfloat w ) { dst [ 0 ] = x ; dst [ 1 ] = y ; dst [ 2 ] = z ; dst [ 3 ] = w ; } inline void sgdCopyVec2 ( sgdVec2 dst, const sgdVec2 src ) { dst [ 0 ] = src [ 0 ] ; dst [ 1 ] = src [ 1 ] ; } inline void sgdCopyVec3 ( sgdVec3 dst, const sgdVec3 src ) { dst [ 0 ] = src [ 0 ] ; dst [ 1 ] = src [ 1 ] ; dst [ 2 ] = src [ 2 ] ; } inline void sgdCopyVec4 ( sgdVec4 dst, const sgdVec4 src ) { dst [ 0 ] = src [ 0 ] ; dst [ 1 ] = src [ 1 ] ; dst [ 2 ] = src [ 2 ] ; dst [ 3 ] = src [ 3 ] ; } inline void sgdAddVec2 ( sgdVec2 dst, const sgdVec2 src ) { dst [ 0 ] += src [ 0 ] ; dst [ 1 ] += src [ 1 ] ; } inline void sgdAddVec3 ( sgdVec3 dst, const sgdVec3 src ) { dst [ 0 ] += src [ 0 ] ; dst [ 1 ] += src [ 1 ] ; dst [ 2 ] += src [ 2 ] ; } inline void sgdAddVec4 ( sgdVec4 dst, const sgdVec4 src ) { dst [ 0 ] += src [ 0 ] ; dst [ 1 ] += src [ 1 ] ; dst [ 2 ] += src [ 2 ] ; dst [ 3 ] += src [ 3 ] ; } inline void sgdAddVec2 ( sgdVec2 dst, const sgdVec2 src1, const sgdVec2 src2 ) { dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] ; dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] ; } inline void sgdAddVec3 ( sgdVec3 dst, const sgdVec3 src1, const sgdVec3 src2 ) { dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] ; dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] ; dst [ 2 ] = src1 [ 2 ] + src2 [ 2 ] ; } inline void sgdAddVec4 ( sgdVec4 dst, const sgdVec4 src1, const sgdVec4 src2 ) { dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] ; dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] ; dst [ 2 ] = src1 [ 2 ] + src2 [ 2 ] ; dst [ 3 ] = src1 [ 3 ] + src2 [ 3 ] ; } inline void sgdSubVec2 ( sgdVec2 dst, const sgdVec2 src ) { dst [ 0 ] -= src [ 0 ] ; dst [ 1 ] -= src [ 1 ] ; } inline void sgdSubVec3 ( sgdVec3 dst, const sgdVec3 src ) { dst [ 0 ] -= src [ 0 ] ; dst [ 1 ] -= src [ 1 ] ; dst [ 2 ] -= src [ 2 ] ; } inline void sgdSubVec4 ( sgdVec4 dst, const sgdVec4 src ) { dst [ 0 ] -= src [ 0 ] ; dst [ 1 ] -= src [ 1 ] ; dst [ 2 ] -= src [ 2 ] ; dst [ 3 ] -= src [ 3 ] ; } inline void sgdSubVec2 ( sgdVec2 dst, const sgdVec2 src1, const sgdVec2 src2 ) { dst [ 0 ] = src1 [ 0 ] - src2 [ 0 ] ; dst [ 1 ] = src1 [ 1 ] - src2 [ 1 ] ; } inline void sgdSubVec3 ( sgdVec3 dst, const sgdVec3 src1, const sgdVec3 src2 ) { dst [ 0 ] = src1 [ 0 ] - src2 [ 0 ] ; dst [ 1 ] = src1 [ 1 ] - src2 [ 1 ] ; dst [ 2 ] = src1 [ 2 ] - src2 [ 2 ] ; } inline void sgdSubVec4 ( sgdVec4 dst, const sgdVec4 src1, const sgdVec4 src2 ) { dst [ 0 ] = src1 [ 0 ] - src2 [ 0 ] ; dst [ 1 ] = src1 [ 1 ] - src2 [ 1 ] ; dst [ 2 ] = src1 [ 2 ] - src2 [ 2 ] ; dst [ 3 ] = src1 [ 3 ] - src2 [ 3 ] ; } inline void sgdNegateVec2 ( sgdVec2 dst ) { dst [ 0 ] = -dst [ 0 ] ; dst [ 1 ] = -dst [ 1 ] ; } inline void sgdNegateVec3 ( sgdVec3 dst ) { dst [ 0 ] = -dst [ 0 ] ; dst [ 1 ] = -dst [ 1 ] ; dst [ 2 ] = -dst [ 2 ] ; } inline void sgdNegateVec4 ( sgdVec4 dst ) { dst [ 0 ] = -dst [ 0 ] ; dst [ 1 ] = -dst [ 1 ] ; dst [ 2 ] = -dst [ 2 ] ; dst [ 3 ] = -dst [ 3 ] ; } inline void sgdNegateVec2 ( sgdVec2 dst, const sgdVec2 src ) { dst [ 0 ] = -src [ 0 ] ; dst [ 1 ] = -src [ 1 ] ; } inline void sgdNegateVec3 ( sgdVec3 dst, const sgdVec3 src ) { dst [ 0 ] = -src [ 0 ] ; dst [ 1 ] = -src [ 1 ] ; dst [ 2 ] = -src [ 2 ] ; } inline void sgdNegateVec4 ( sgdVec4 dst, const sgdVec4 src ) { dst [ 0 ] = -src [ 0 ] ; dst [ 1 ] = -src [ 1 ] ; dst [ 2 ] = -src [ 2 ] ; dst [ 3 ] = -src [ 3 ] ; } inline void sgdScaleVec2 ( sgdVec2 dst, const SGDfloat s ) { dst [ 0 ] *= s ; dst [ 1 ] *= s ; } inline void sgdScaleVec3 ( sgdVec3 dst, const SGDfloat s ) { dst [ 0 ] *= s ; dst [ 1 ] *= s ; dst [ 2 ] *= s ; } inline void sgdScaleVec4 ( sgdVec4 dst, const SGDfloat s ) { dst [ 0 ] *= s ; dst [ 1 ] *= s ; dst [ 2 ] *= s ; dst [ 3 ] *= s ; } inline void sgdScaleVec2 ( sgdVec2 dst, const sgdVec2 src, const SGDfloat s ) { dst [ 0 ] = src [ 0 ] * s ; dst [ 1 ] = src [ 1 ] * s ; } inline void sgdScaleVec3 ( sgdVec3 dst, const sgdVec3 src, const SGDfloat s ) { dst [ 0 ] = src [ 0 ] * s ; dst [ 1 ] = src [ 1 ] * s ; dst [ 2 ] = src [ 2 ] * s ; } inline void sgdScaleVec4 ( sgdVec4 dst, const sgdVec4 src, const SGDfloat s ) { dst [ 0 ] = src [ 0 ] * s ; dst [ 1 ] = src [ 1 ] * s ; dst [ 2 ] = src [ 2 ] * s ; dst [ 3 ] = src [ 3 ] * s ; } inline void sgdAddScaledVec2 ( sgdVec2 dst, const sgdVec2 src, const SGDfloat s ) { dst [ 0 ] += src [ 0 ] * s ; dst [ 1 ] += src [ 1 ] * s ; } inline void sgdAddScaledVec3 ( sgdVec3 dst, const sgdVec3 src, const SGDfloat s ) { dst [ 0 ] += src [ 0 ] * s ; dst [ 1 ] += src [ 1 ] * s ; dst [ 2 ] += src [ 2 ] * s ; } inline void sgdAddScaledVec4 ( sgdVec4 dst, const sgdVec4 src, const SGDfloat s ) { dst [ 0 ] += src [ 0 ] * s ; dst [ 1 ] += src [ 1 ] * s ; dst [ 2 ] += src [ 2 ] * s ; dst [ 3 ] += src [ 3 ] * s ; } inline void sgdAddScaledVec2 ( sgdVec2 dst, const sgdVec2 src1, const sgdVec2 src2, const SGDfloat s ) { dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] * s ; dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] * s ; } inline void sgdAddScaledVec3 ( sgdVec3 dst, const sgdVec3 src1, const sgdVec3 src2, const SGDfloat s ) { dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] * s ; dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] * s ; dst [ 2 ] = src1 [ 2 ] + src2 [ 2 ] * s ; } inline void sgdAddScaledVec4 ( sgdVec4 dst, const sgdVec4 src1, const sgdVec4 src2, const SGDfloat s ) { dst [ 0 ] = src1 [ 0 ] + src2 [ 0 ] * s ; dst [ 1 ] = src1 [ 1 ] + src2 [ 1 ] * s ; dst [ 2 ] = src1 [ 2 ] + src2 [ 2 ] * s ; dst [ 3 ] = src1 [ 3 ] + src2 [ 3 ] * s ; } inline int sgdCompareVec2 ( const sgdVec2 a, const sgdVec2 b, const SGDfloat tol ) { int val = 0 ; if ( ( val = sgdCompareFloat( a[0], b[0], tol ) ) != 0 ) return val ; if ( ( val = sgdCompareFloat( a[1], b[1], tol ) ) != 0 ) return val ; return 0 ; } inline int sgdCompareVec3 ( const sgdVec3 a, const sgdVec3 b, const SGDfloat tol ) { int val = 0 ; if ( ( val = sgdCompareFloat( a[0], b[0], tol ) ) != 0 ) return val ; if ( ( val = sgdCompareFloat( a[1], b[1], tol ) ) != 0 ) return val ; if ( ( val = sgdCompareFloat( a[2], b[2], tol ) ) != 0 ) return val ; return 0 ; } inline int sgdCompareVec4 ( const sgdVec4 a, const sgdVec4 b, const SGDfloat tol ) { int val = 0 ; if ( ( val = sgdCompareFloat( a[0], b[0], tol ) ) != 0 ) return val ; if ( ( val = sgdCompareFloat( a[1], b[1], tol ) ) != 0 ) return val ; if ( ( val = sgdCompareFloat( a[2], b[2], tol ) ) != 0 ) return val ; if ( ( val = sgdCompareFloat( a[3], b[3], tol ) ) != 0 ) return val ; return 0 ; } inline int sgdEqualVec2 ( const sgdVec2 a, const sgdVec2 b ) { return a[0] == b[0] && a[1] == b[1] ; } inline int sgdEqualVec3 ( const sgdVec3 a, const sgdVec3 b ) { return a[0] == b[0] && a[1] == b[1] && a[2] == b[2] ; } inline int sgdEqualVec4 ( const sgdVec4 a, const sgdVec4 b ) { return a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3] ; } inline SGDfloat sgdScalarProductVec2 ( const sgdVec2 a, const sgdVec2 b ) { return a[0]*b[0] + a[1]*b[1] ; } inline SGDfloat sgdScalarProductVec3 ( const sgdVec3 a, const sgdVec3 b ) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] ; } inline SGDfloat sgdScalarProductVec4 ( const sgdVec4 a, const sgdVec4 b ) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3] ; } extern void sgdVectorProductVec3 ( sgdVec3 dst, const sgdVec3 a, const sgdVec3 b ) ; inline void sgdLerpVec4 ( sgdVec4 dst, const sgdVec4 a, const sgdVec4 b, const SGDfloat f ) { dst[0] = a[0] + f * ( b[0] - a[0] ) ; dst[1] = a[1] + f * ( b[1] - a[1] ) ; dst[2] = a[2] + f * ( b[2] - a[2] ) ; dst[3] = a[3] + f * ( b[3] - a[3] ) ; } inline void sgdLerpVec3 ( sgdVec3 dst, const sgdVec3 a, const sgdVec3 b, const SGDfloat f ) { dst[0] = a[0] + f * ( b[0] - a[0] ) ; dst[1] = a[1] + f * ( b[1] - a[1] ) ; dst[2] = a[2] + f * ( b[2] - a[2] ) ; } inline void sgdLerpVec2 ( sgdVec2 dst, const sgdVec2 a, const sgdVec2 b, const SGDfloat f ) { dst[0] = a[0] + f * ( b[0] - a[0] ) ; dst[1] = a[1] + f * ( b[1] - a[1] ) ; } inline void sgdLerpAnglesVec3 ( sgdVec3 dst, const sgdVec3 a, const sgdVec3 b, const SGDfloat f ) { sgdVec3 tmp ; if ( b[0] - a[0] > 180.0 ) tmp[0] = a[0] + 360.0 ; else if ( b[0] - a[0] < -180.0 ) tmp[0] = a[0] - 360.0 ; else tmp[0] = a[0] ; if ( b[1] - a[1] > 180.0 ) tmp[1] = a[1] + 360.0 ; else if ( b[1] - a[1] < -180.0 ) tmp[1] = a[1] - 360.0 ; else tmp[1] = a[1] ; if ( b[2] - a[2] > 180.0 ) tmp[2] = a[2] + 360.0 ; else if ( b[2] - a[2] < -180.0 ) tmp[2] = a[2] - 360.0 ; else tmp[2] = a[2] ; dst[0] = tmp[0] + f * ( b[0] - tmp[0] ) ; dst[1] = tmp[1] + f * ( b[1] - tmp[1] ) ; dst[2] = tmp[2] + f * ( b[2] - tmp[2] ) ; } inline SGDfloat sgdDistanceSquaredVec2 ( const sgdVec2 a, const sgdVec2 b ) { return sgdSquare ( a[0]-b[0] ) + sgdSquare ( a[1]-b[1] ) ; } inline SGDfloat sgdDistanceSquaredVec3 ( const sgdVec3 a, const sgdVec3 b ) { return sgdSquare ( a[0]-b[0] ) + sgdSquare ( a[1]-b[1] ) + sgdSquare ( a[2]-b[2] ) ; } inline SGDfloat sgdDistanceSquaredVec4 ( const sgdVec4 a, const sgdVec4 b ) { return sgdSquare ( a[0]-b[0] ) + sgdSquare ( a[1]-b[1] ) + sgdSquare ( a[2]-b[2] ) + sgdSquare ( a[3]-b[3] ) ; } inline SGDfloat sgdDistanceVec2 ( const sgdVec2 a, const sgdVec2 b ) { return sgdSqrt ( sgdSquare ( a[0]-b[0] ) + sgdSquare ( a[1]-b[1] ) ) ; } inline SGDfloat sgdDistanceVec3 ( const sgdVec3 a, const sgdVec3 b ) { return sgdSqrt ( sgdSquare ( a[0]-b[0] ) + sgdSquare ( a[1]-b[1] ) + sgdSquare ( a[2]-b[2] ) ) ; } inline SGDfloat sgdDistanceVec4 ( const sgdVec4 a, const sgdVec4 b ) { return sgdSqrt ( sgdSquare ( a[0]-b[0] ) + sgdSquare ( a[1]-b[1] ) + sgdSquare ( a[2]-b[2] ) + sgdSquare ( a[3]-b[3] ) ) ; } inline SGDfloat sgdLengthVec2 ( sgdVec2 const src ) { return sgdSqrt ( sgdScalarProductVec2 ( src, src ) ) ; } inline SGDfloat sgdLengthVec3 ( sgdVec3 const src ) { return sgdSqrt ( sgdScalarProductVec3 ( src, src ) ) ; } inline SGDfloat sgdLengthVec4 ( sgdVec4 const src ) { return sgdSqrt ( sgdScalarProductVec4 ( src, src ) ) ; } inline SGDfloat sgdLengthSquaredVec2 ( sgdVec2 const src ) { return sgdScalarProductVec2 ( src, src ) ; } inline SGDfloat sgdLengthSquaredVec3 ( sgdVec3 const src ) { return sgdScalarProductVec3 ( src, src ) ; } inline SGDfloat sgdLengthSquaredVec4 ( sgdVec4 const src ) { return sgdScalarProductVec4 ( src, src ) ; } /* Anglo-US spelling issues. */ #define sgdNormalizeVec2 sgdNormaliseVec2 #define sgdNormalizeVec3 sgdNormaliseVec3 #define sgdNormalizeVec4 sgdNormaliseVec4 #define sgdNormalizeQuat sgdNormaliseQuat inline void sgdNormaliseVec2 ( sgdVec2 dst ) { sgdScaleVec2 ( dst, SGD_ONE / sgdLengthVec2 ( dst ) ) ; } inline void sgdNormaliseVec3 ( sgdVec3 dst ) { sgdScaleVec3 ( dst, SGD_ONE / sgdLengthVec3 ( dst ) ) ; } inline void sgdNormaliseVec4 ( sgdVec4 dst ) { sgdScaleVec4 ( dst, SGD_ONE / sgdLengthVec4 ( dst ) ) ; } inline void sgdNormaliseVec2 ( sgdVec2 dst, const sgdVec2 src ) { sgdScaleVec2 ( dst, src, SGD_ONE / sgdLengthVec2 ( src ) ) ; } inline void sgdNormaliseVec3 ( sgdVec3 dst, const sgdVec3 src ) { sgdScaleVec3 ( dst, src, SGD_ONE / sgdLengthVec3 ( src ) ) ; } inline void sgdNormaliseVec4 ( sgdVec4 dst, const sgdVec4 src ) { sgdScaleVec4 ( dst, src, SGD_ONE / sgdLengthVec4 ( src ) ) ; } inline void sgdZeroCoord ( sgdCoord *dst ) { sgdSetVec3 ( dst->xyz, SGD_ZERO, SGD_ZERO, SGD_ZERO ) ; sgdSetVec3 ( dst->hpr, SGD_ZERO, SGD_ZERO, SGD_ZERO ) ; } inline void sgdSetCoord ( sgdCoord *dst, const SGDfloat x, const SGDfloat y, const SGDfloat z, const SGDfloat h, const SGDfloat p, const SGDfloat r ) { sgdSetVec3 ( dst->xyz, x, y, z ) ; sgdSetVec3 ( dst->hpr, h, p, r ) ; } inline void sgdSetCoord ( sgdCoord *dst, const sgdVec3 xyz, const sgdVec3 hpr ) { sgdCopyVec3 ( dst->xyz, xyz ) ; sgdCopyVec3 ( dst->hpr, hpr ) ; } inline void sgdCopyCoord ( sgdCoord *dst, const sgdCoord *src ) { sgdCopyVec3 ( dst->xyz, src->xyz ) ; sgdCopyVec3 ( dst->hpr, src->hpr ) ; } inline void sgdCopyMat4 ( sgdMat4 dst, const sgdMat4 src ) { sgdCopyVec4 ( dst[ 0 ], src[ 0 ] ) ; sgdCopyVec4 ( dst[ 1 ], src[ 1 ] ) ; sgdCopyVec4 ( dst[ 2 ], src[ 2 ] ) ; sgdCopyVec4 ( dst[ 3 ], src[ 3 ] ) ; } inline void sgdScaleMat4 ( sgdMat4 dst, const sgdMat4 src, const SGDfloat scale ) { sgdScaleVec4 ( dst[0], src[0], scale ) ; sgdScaleVec4 ( dst[1], src[1], scale ) ; sgdScaleVec4 ( dst[2], src[2], scale ) ; sgdScaleVec4 ( dst[3], src[3], scale ) ; } inline void sgdMakeIdentMat4 ( sgdMat4 dst ) { sgdSetVec4 ( dst[0], SGD_ONE , SGD_ZERO, SGD_ZERO, SGD_ZERO ) ; sgdSetVec4 ( dst[1], SGD_ZERO, SGD_ONE , SGD_ZERO, SGD_ZERO ) ; sgdSetVec4 ( dst[2], SGD_ZERO, SGD_ZERO, SGD_ONE , SGD_ZERO ) ; sgdSetVec4 ( dst[3], SGD_ZERO, SGD_ZERO, SGD_ZERO, SGD_ONE ) ; } extern void sgdMakeTransMat4 ( sgdMat4 m, const SGDfloat x, const SGDfloat y, const SGDfloat z ) ; extern void sgdMakeTransMat4 ( sgdMat4 m, const sgdVec3 xyz ) ; extern void sgdMakeCoordMat4 ( sgdMat4 m, const SGDfloat x, const SGDfloat y, const SGDfloat z, const SGDfloat h, const SGDfloat p, const SGDfloat r ) ; extern void sgdMakeCoordMat4 ( sgdMat4 m, const sgdCoord *c ) ; extern int sgdCompare3DSqdDist ( const sgdVec3 a, const sgdVec3 b, const SGDfloat sqd_dist ) ; inline SGDfloat sgdDistToLineVec2 ( const sgdVec3 line, const sgdVec2 pnt ) { return sgdScalarProductVec2 ( line, pnt ) + line[2] ; } struct sgdLineSegment3 /* Bounded line segment */ { sgdVec3 a ; sgdVec3 b ; } ; struct sgdLine3 /* Infinite line */ { sgdVec3 point_on_line ; sgdVec3 direction_vector ; /* Should be a unit vector */ } ; inline void sgdLineSegment3ToLine3 ( sgdLine3 *line, const sgdLineSegment3 lineseg ) { sgdCopyVec3 ( line->point_on_line , lineseg.a ) ; sgdSubVec3 ( line->direction_vector, lineseg.b, lineseg.a ) ; sgdNormaliseVec3 ( line->direction_vector ) ; } SGDfloat sgdDistSquaredToLineVec3 ( const sgdLine3 line, const sgdVec3 pnt ) ; SGDfloat sgdDistSquaredToLineSegmentVec3 ( const sgdLineSegment3 line, const sgdVec3 pnt ) ; inline SGDfloat sgdDistToLineVec3 ( const sgdLine3 line, const sgdVec3 pnt ) { return sgdSqrt ( sgdDistSquaredToLineVec3 ( line, pnt ) ); } inline SGDfloat sgdDistToLineSegmentVec3 ( const sgdLineSegment3 line, const sgdVec3 pnt ) { return sgdSqrt ( sgdDistSquaredToLineSegmentVec3(line,pnt) ) ; } inline SGDfloat sgdDistToPlaneVec3 ( const sgdVec4 plane, const sgdVec3 pnt ) { return sgdScalarProductVec3 ( plane, pnt ) + plane[3] ; } inline SGDfloat sgdHeightAbovePlaneVec3 ( const sgdVec4 plane, const sgdVec3 pnt ) { return pnt[2] - sgdHeightOfPlaneVec2 ( plane, pnt ) ; } extern void sgdReflectInPlaneVec3 ( sgdVec3 dst, const sgdVec3 src, const sgdVec4 plane ) ; inline void sgdReflectInPlaneVec3 ( sgdVec3 dst, const sgdVec4 plane ) { sgdReflectInPlaneVec3 ( dst, dst, plane ) ; } extern void sgdMakeNormal ( sgdVec3 dst, const sgdVec3 a, const sgdVec3 b, const sgdVec3 c ) ; inline void sgdMake2DLine ( sgdVec3 dst, const sgdVec2 a, const sgdVec2 b ) { dst[0] = b[1]-a[1] ; dst[1] = -b[0]-a[0] ; sgdNormalizeVec2 ( dst ) ; dst[2] = - ( dst[0]*a[0] + dst[1]*a[1] ) ; } inline void sgdMakePlane ( sgdVec4 dst, const sgdVec3 normal, const sgdVec3 pnt ) { sgdCopyVec3 ( dst, normal ) ; dst [ 3 ] = - sgdScalarProductVec3 ( normal, pnt ) ; } inline void sgdMakePlane ( sgdVec4 dst, const sgdVec3 a, const sgdVec3 b, const sgdVec3 c ) { /* Ax + By + Cz + D == 0 ; D = - ( Ax + By + Cz ) = - ( A*a[0] + B*a[1] + C*a[2] ) = - sgdScalarProductVec3 ( normal, a ) ; */ sgdMakeNormal ( dst, a, b, c ) ; dst [ 3 ] = - sgdScalarProductVec3 ( dst, a ) ; } SGDfloat sgdTriArea( sgdVec3 p0, sgdVec3 p1, sgdVec3 p2 ); // Fast code. Result is in the range 0..180: inline SGDfloat sgdAngleBetweenNormalizedVec3 ( sgdVec3 v1, sgdVec3 v2 ) { SGDfloat f = sgdScalarProductVec3 ( v1, v2 ) ; return (float) acos ( ( f >= 1.0f ) ? 1.0f : ( f <= -1.0f ) ? -1.0f : f ) * SGD_RADIANS_TO_DEGREES ; } // Fast code. Result is in the range 0..180: SGDfloat sgdAngleBetweenVec3 ( sgdVec3 v1, sgdVec3 v2 ); // All three have to be normalized. Slow code. Result is in the range 0..360: SGDfloat sgdAngleBetweenNormalizedVec3 (sgdVec3 first, sgdVec3 second, sgdVec3 normal); // Normal has to be normalized. Slow code. Result is in the range 0..360: SGDfloat sgdAngleBetweenVec3 ( sgdVec3 v1, sgdVec3 v2, sgdVec3 normal ); class sgdSphere { public: sgdVec3 center ; SGDfloat radius ; const SGDfloat *getCenter (void) const { return center ; } void setCenter ( const sgdVec3 c ) { sgdCopyVec3 ( center, c ) ; } void setCenter ( const SGDfloat x, const SGDfloat y, const SGDfloat z ) { sgdSetVec3 ( center, x, y, z ) ; } SGDfloat getRadius (void) const { return radius ; } void setRadius ( const SGDfloat r ) { radius = r ; } int isEmpty (void) const { return radius < SGD_ZERO ; } void empty (void) { radius = - SGD_ONE ; } void orthoXform ( const sgdMat4 m ) { sgdXformPnt3 ( center, center, m ) ; // radius *= sgdLengthVec3 ( m[0] ) ; } void extend ( const sgdSphere *s ) ; void extend ( const sgdBox *b ) ; void extend ( const sgdVec3 v ) ; int intersects ( const sgdSphere *s ) const { return sgdCompare3DSqdDist ( center, s->getCenter(), sgdSquare ( radius + s->getRadius() ) ) <= 0 ; } int intersects ( const sgdVec4 plane ) const { return sgdAbs ( sgdDistToPlaneVec3 ( plane, center ) ) <= radius ; } int intersects ( const sgdBox *b ) const ; } ; class sgdBox { public: sgdVec3 min ; sgdVec3 max ; const SGDfloat *getMin (void) const { return min ; } const SGDfloat *getMax (void) const { return max ; } void setMin ( const SGDfloat x, const SGDfloat y, const SGDfloat z ) { sgdSetVec3 ( min, x, y, z ) ; } void setMin ( const sgdVec3 src ) { sgdCopyVec3 ( min, src ) ; } void setMax ( const SGDfloat x, const SGDfloat y, const SGDfloat z ) { sgdSetVec3 ( max, x, y, z ) ; } void setMax ( const sgdVec3 src ) { sgdCopyVec3 ( max, src ) ; } int isEmpty(void) const { return ( min[0] > max[0] || min[1] > max[1] || min[2] > max[2] ) ; } void empty (void) { sgdSetVec3 ( min, SGD_MAX, SGD_MAX, SGD_MAX ) ; sgdSetVec3 ( max, -SGD_MAX, -SGD_MAX, -SGD_MAX ) ; } void extend ( const sgdSphere *s ) ; void extend ( const sgdBox *b ) ; void extend ( const sgdVec3 v ) ; int intersects ( const sgdSphere *s ) const { return s -> intersects ( this ) ; } int intersects ( const sgdBox *b ) const { return min[0] <= b->getMax()[0] && max[0] >= b->getMin()[0] && min[1] <= b->getMax()[1] && max[1] >= b->getMin()[1] && min[2] <= b->getMax()[2] && max[2] >= b->getMin()[2] ; } int intersects ( const sgdVec4 plane ) const ; } ; class sgdFrustum { /* Is the projection orthographic (or perspective)? */ int ortho ; /* The parameters for glFrustum/glOrtho */ SGDfloat left, right, bot, top, nnear, ffar ; /* The computed projection matrix for this frustum */ sgdMat4 mat ; /* The A,B,C,D terms of the plane equations of the clip planes */ /* A point (x,y,z) is inside the frustum iff Ax + By + Cz + D >= 0 for all planes */ sgdVec4 plane [ 6 ] ; /* These two are only valid for simple frusta */ SGDfloat hfov ; /* Horizontal Field of View -or- Orthographic Width */ SGDfloat vfov ; /* Vertical Field of View -or- Orthographic Height */ void update (void) ; int getOutcode ( const sgdVec4 src ) const ; public: sgdFrustum (void) { ortho = FALSE ; nnear = SGD_ONE ; ffar = 1000000.0f ; hfov = SGD_45 ; vfov = SGD_45 ; update () ; } void setFrustum ( const SGDfloat l, const SGDfloat r, const SGDfloat b, const SGDfloat t, const SGDfloat n, const SGDfloat f ) { ortho = FALSE ; left = l ; right = r ; bot = b ; top = t ; nnear = n ; ffar = f ; hfov = vfov = SGD_ZERO ; update () ; } void setOrtho ( const SGDfloat l, const SGDfloat r, const SGDfloat b, const SGDfloat t, const SGDfloat n, const SGDfloat f ) { ortho = TRUE ; left = l ; right = r ; bot = b ; top = t ; nnear = n ; ffar = f ; hfov = vfov = SGD_ZERO ; update () ; } void getMat4 ( sgdMat4 dst ) { sgdCopyMat4 ( dst, mat ) ; } SGDfloat getLeft (void) const { return left ; } SGDfloat getRight(void) const { return right ; } SGDfloat getBot (void) const { return bot ; } SGDfloat getTop (void) const { return top ; } SGDfloat getNear (void) const { return nnear ; } SGDfloat getFar (void) const { return ffar ; } const SGDfloat *getPlane ( int i ) const { return plane [ i ] ; } SGDfloat getHFOV (void) const { return hfov ; } SGDfloat getVFOV (void) const { return vfov ; } void getFOV ( SGDfloat *h, SGDfloat *v ) const { if ( h != (SGDfloat *) 0 ) *h = hfov ; if ( v != (SGDfloat *) 0 ) *v = vfov ; } void setFOV ( const SGDfloat h, const SGDfloat v ) { ortho = FALSE ; hfov = ( h <= 0 ) ? ( v * SGD_FOUR / SGD_THREE ) : h ; vfov = ( v <= 0 ) ? ( h * SGD_THREE / SGD_FOUR ) : v ; update () ; } void getOrtho ( SGDfloat *w, SGDfloat *h ) const { if ( w != (SGDfloat *) 0 ) *w = right - left ; if ( h != (SGDfloat *) 0 ) *h = top - bot ; } void setOrtho ( const SGDfloat w, const SGDfloat h ) { ortho = TRUE ; hfov = ( w <= 0 ) ? ( h * SGD_FOUR / SGD_THREE ) : w ; vfov = ( h <= 0 ) ? ( w * SGD_FOUR / SGD_THREE ) : h ; update () ; } void getNearFar ( SGDfloat *n, SGDfloat *f ) const { if ( n != (SGDfloat *) 0 ) *n = nnear ; if ( f != (SGDfloat *) 0 ) *f = ffar ; } void setNearFar ( const SGDfloat n, const SGDfloat f ) { nnear = n ; ffar = f ; update () ; } int isOrtho (void) const { return ortho ; } int contains ( const sgdVec3 p ) const ; int contains ( const sgdSphere *s ) const ; int contains ( const sgdBox *b ) const ; } ; /* Quaternion routines are Copyright (C) 1999 Kevin B. Thompson Modified by Sylvan W. Clebsch Largely rewritten by "Negative0" */ /* Quaternion structure w = real, (x, y, z) = vector CHANGED sqQuat to float array so that syntax matches vector and matrix routines */ inline void sgdMakeIdentQuat ( sgdQuat dst ) { sgdSetVec4 ( dst, SGD_ZERO, SGD_ZERO, SGD_ZERO, SGD_ONE ) ; } inline void sgdSetQuat ( sgdQuat dst, const SGDfloat w, const SGDfloat x, const SGDfloat y, const SGDfloat z ) { sgdSetVec4 ( dst, x, y, z, w ) ; } inline void sgdCopyQuat ( sgdQuat dst, const sgdQuat src ) { sgdCopyVec4 ( dst, src ) ; } /* Construct a unit quaternion (length==1) */ inline void sgdNormaliseQuat ( sgdQuat dst, const sgdQuat src ) { SGDfloat d = sgdScalarProductVec4 ( src, src ) ; d = (d > SGD_ZERO) ? (SGD_ONE / sgdSqrt ( d )) : SGD_ONE ; sgdScaleVec4 ( dst, src, d ) ; } inline void sgdNormaliseQuat ( sgdQuat dst ) { sgdNormaliseQuat ( dst, dst ) ; } inline void sgdInvertQuat ( sgdQuat dst, const sgdQuat src ) { SGDfloat d = sgdScalarProductVec4 ( src, src ) ; d = ( d == SGD_ZERO ) ? SGD_ONE : ( SGD_ONE / d ) ; dst[SG_W] = src[SG_W] * d ; dst[SG_X] = -src[SG_X] * d ; dst[SG_Y] = -src[SG_Y] * d ; dst[SG_Z] = -src[SG_Z] * d ; } inline void sgdInvertQuat ( sgdQuat dst ) { sgdInvertQuat ( dst, dst ) ; } /* Make an angle and axis of rotation from a Quaternion. */ void sgdQuatToAngleAxis ( SGDfloat *angle, sgdVec3 axis, const sgdQuat src ) ; void sgdQuatToAngleAxis ( SGDfloat *angle, SGDfloat *x, SGDfloat *y, SGDfloat *z, const sgdQuat src ) ; /* Make a quaternion from a given angle and axis of rotation */ void sgdAngleAxisToQuat ( sgdQuat dst, const SGDfloat angle, const sgdVec3 axis ) ; void sgdAngleAxisToQuat ( sgdQuat dst, const SGDfloat angle, const SGDfloat x, const SGDfloat y, const SGDfloat z ); /* Convert a matrix to/from a quat */ void sgdMatrixToQuat ( sgdQuat quat, const sgdMat4 m ) ; void sgdQuatToMatrix ( sgdMat4 m, const sgdQuat quat ) ; /* Convert a set of eulers to/from a quat */ void sgdQuatToEuler( sgdVec3 hpr, const sgdQuat quat ) ; void sgdEulerToQuat( sgdQuat quat, const sgdVec3 hpr ) ; inline void sgdEulerToQuat( sgdQuat dst, SGDfloat h, SGDfloat p, SGDfloat r ) { sgdVec3 hpr ; sgdSetVec3 ( hpr, h, p, r ) ; sgdEulerToQuat( dst, hpr ) ; } inline void sgdHPRToQuat ( sgdQuat dst, SGDfloat h, SGDfloat p, SGDfloat r ) { sgdVec3 hpr; hpr[0] = h * SGD_DEGREES_TO_RADIANS ; hpr[1] = p * SGD_DEGREES_TO_RADIANS ; hpr[2] = r * SGD_DEGREES_TO_RADIANS ; sgdEulerToQuat( dst, hpr ) ; } inline void sgdHPRToQuat ( sgdQuat dst, const sgdVec3 hpr ) { sgdVec3 tmp ; sgdScaleVec3 ( tmp, hpr, SGD_DEGREES_TO_RADIANS ) ; sgdEulerToQuat ( dst, tmp ) ; } /* Multiply quaternions together (concatenate rotations) */ void sgdMultQuat ( sgdQuat dst, const sgdQuat a, const sgdQuat b ) ; inline void sgdPostMultQuat ( sgdQuat dst, const sgdQuat q ) { sgdQuat r ; sgdCopyQuat ( r, dst ) ; sgdMultQuat ( dst, r, q ) ; } inline void sgdPreMultQuat ( sgdQuat dst, const sgdQuat q ) { sgdQuat r ; sgdCopyQuat ( r, dst ) ; sgdMultQuat ( dst, q, r ) ; } /* Rotate a quaternion by a given angle and axis (convenience function) */ inline void sgdRotQuat ( sgdQuat dst, const SGDfloat angle, const sgdVec3 axis ) { sgdQuat q ; sgdAngleAxisToQuat ( q, angle, axis ) ; sgdPostMultQuat ( dst, q ) ; sgdNormaliseQuat ( dst ) ; } inline void sgdRotQuat ( sgdQuat dst, const SGDfloat angle, const SGDfloat x, const SGDfloat y, const SGDfloat z ) { sgdVec3 axis ; sgdSetVec3 ( axis, x, y, z ) ; sgdRotQuat ( dst, angle, axis ) ; } /* SWC - Interpolate between to quaternions */ extern void sgdSlerpQuat ( sgdQuat dst, const sgdQuat from, const sgdQuat to, const SGDfloat t ) ; /* Conversions between sg and sgd types. */ inline void sgSetVec2 ( sgVec2 dst, sgdVec2 src ) { dst [ 0 ] = (SGfloat) src [ 0 ] ; dst [ 1 ] = (SGfloat) src [ 1 ] ; } inline void sgSetVec3 ( sgVec3 dst, sgdVec3 src ) { dst [ 0 ] = (SGfloat) src [ 0 ] ; dst [ 1 ] = (SGfloat) src [ 1 ] ; dst [ 2 ] = (SGfloat) src [ 2 ] ; } inline void sgSetVec4 ( sgVec4 dst, sgdVec4 src ) { dst [ 0 ] = (SGfloat) src [ 0 ] ; dst [ 1 ] = (SGfloat) src [ 1 ] ; dst [ 2 ] = (SGfloat) src [ 2 ] ; dst [ 3 ] = (SGfloat) src [ 3 ] ; } inline void sgdSetVec2 ( sgdVec2 dst, sgVec2 src ) { dst [ 0 ] = (SGDfloat) src [ 0 ] ; dst [ 1 ] = (SGDfloat) src [ 1 ] ; } inline void sgdSetVec3 ( sgdVec3 dst, sgVec3 src ) { dst [ 0 ] = (SGDfloat) src [ 0 ] ; dst [ 1 ] = (SGDfloat) src [ 1 ] ; dst [ 2 ] = (SGDfloat) src [ 2 ] ; } inline void sgdSetVec4 ( sgdVec4 dst, sgVec4 src ) { dst [ 0 ] = (SGDfloat) src [ 0 ] ; dst [ 1 ] = (SGDfloat) src [ 1 ] ; dst [ 2 ] = (SGDfloat) src [ 2 ] ; dst [ 3 ] = (SGDfloat) src [ 3 ] ; } inline void sgSetMat4 ( sgMat4 dst, sgdMat4 src ) { sgSetVec4 ( dst [ 0 ], src [ 0 ] ) ; sgSetVec4 ( dst [ 1 ], src [ 1 ] ) ; sgSetVec4 ( dst [ 2 ], src [ 2 ] ) ; sgSetVec4 ( dst [ 3 ], src [ 3 ] ) ; } inline void sgdSetMat4 ( sgdMat4 dst, sgMat4 src ) { sgdSetVec4 ( dst [ 0 ], src [ 0 ] ) ; sgdSetVec4 ( dst [ 1 ], src [ 1 ] ) ; sgdSetVec4 ( dst [ 2 ], src [ 2 ] ) ; sgdSetVec4 ( dst [ 3 ], src [ 3 ] ) ; } inline void sgSetCoord ( sgCoord *dst, sgdCoord *src ) { sgSetVec3 ( dst->xyz, src->xyz ) ; sgSetVec3 ( dst->hpr, src->hpr ) ; } inline void sgdSetCoord ( sgdCoord *dst, sgCoord *src ) { sgdSetVec3 ( dst->xyz, src->xyz ) ; sgdSetVec3 ( dst->hpr, src->hpr ) ; } inline void sgSetQuat ( sgQuat dst, sgdQuat src ) { sgSetVec4 ( dst, src ) ; } inline void sgdSetQuat ( sgdQuat dst, sgQuat src ) { sgdSetVec4 ( dst, src ) ; } /* Function to rotate a vector through a given quaternion using the formula * R = Q r Q-1 -- this gives the components of a ROTATED vector in a STATIONARY * coordinate system. We assume that Q is a unit quaternion. */ void sgRotateVecQuat ( sgVec3 vec, sgQuat q ) ; void sgdRotateVecQuat ( sgdVec3 vec, sgdQuat q ) ; /* Function to rotate a vector through a given quaternion using the formula * R = Q-1 r Q -- this gives the components of a STATIONARY vector in a ROTATED * coordinate system. We assume that Q is a unit quaternion. */ void sgRotateCoordQuat ( sgVec3 vec, sgQuat q ) ; void sgdRotateCoordQuat ( sgdVec3 vec, sgdQuat q ) ; sgFloat sgDistSquaredToLineLineSegment ( const sgLineSegment3 seg, const sgLine3 line ) ; sgdFloat sgdDistSquaredToLineLineSegment ( const sgdLineSegment3 seg, const sgdLine3 line ) ; /* Intersection testing. */ int sgdIsectPlanePlane ( sgdVec3 point, sgdVec3 dir, sgdVec4 plane1, sgdVec4 plane2 ) ; int sgdIsectInfLinePlane ( sgdVec3 dst, sgdVec3 l_org, sgdVec3 l_vec, sgdVec4 plane ) ; int sgdIsectInfLineInfLine ( sgdVec3 dst, sgdVec3 l1_org, sgdVec3 l1_vec, sgdVec3 l2_org, sgdVec3 l2_vec ) ; SGDfloat sgdIsectLinesegPlane ( sgdVec3 dst, sgdVec3 v1, sgdVec3 v2, sgdVec4 plane ) ; bool sgdPointInTriangle ( sgdVec3 point, sgdVec3 tri[3] ); /* TRIANGLE SOLVERS - These work for any triangle. SSS == Side-lengths for all three sides. SAS == Side-lengths for two sides - plus the angle between them. ASA == Two angles plus the length of the Side between them. Area == The area of the triangle. */ SGfloat sgTriangleSolver_ASAtoArea ( SGfloat angA, SGfloat lenB, SGfloat angC ); SGfloat sgTriangleSolver_SAStoArea ( SGfloat lenA, SGfloat angB, SGfloat lenC ); SGfloat sgTriangleSolver_SSStoArea ( SGfloat lenA, SGfloat lenB, SGfloat lenC ); SGfloat sgTriangleSolver_SAAtoArea ( SGfloat lenA, SGfloat angB, SGfloat angA ); SGfloat sgTriangleSolver_ASStoArea ( SGfloat angB, SGfloat lenA, SGfloat lenB, int angA_is_obtuse ); void sgTriangleSolver_SSStoAAA ( SGfloat lenA, SGfloat lenB, SGfloat lenC, SGfloat *angA, SGfloat *angB, SGfloat *angC ) ; void sgTriangleSolver_SAStoASA ( SGfloat lenA, SGfloat angB, SGfloat lenC, SGfloat *angA, SGfloat *lenB, SGfloat *angC ) ; void sgTriangleSolver_ASAtoSAS ( SGfloat angA, SGfloat lenB, SGfloat angC, SGfloat *lenA, SGfloat *angB, SGfloat *lenC ) ; void sgTriangleSolver_SAAtoASS ( SGfloat lenA, SGfloat angB, SGfloat angA, SGfloat *angC, SGfloat *lenB, SGfloat *lenC ) ; void sgTriangleSolver_ASStoSAA ( SGfloat angB, SGfloat lenA, SGfloat lenB, int angA_is_obtuse, SGfloat *lenC, SGfloat *angA, SGfloat *angC ) ; SGDfloat sgdTriangleSolver_ASAtoArea ( SGDfloat angA, SGDfloat lenB, SGDfloat angC ); SGDfloat sgdTriangleSolver_SAStoArea ( SGDfloat lenA, SGDfloat angB, SGDfloat lenC ); SGDfloat sgdTriangleSolver_SSStoArea ( SGDfloat lenA, SGDfloat lenB, SGDfloat lenC ); SGDfloat sgdTriangleSolver_SAAtoArea ( SGDfloat lenA, SGDfloat angB, SGDfloat angA ); SGDfloat sgdTriangleSolver_ASStoArea ( SGDfloat angB, SGDfloat lenA, SGDfloat lenB, int angA_is_obtuse ); void sgdTriangleSolver_SSStoAAA ( SGDfloat lenA, SGDfloat lenB, SGDfloat lenC, SGDfloat *angA, SGDfloat *angB, SGDfloat *angC ) ; void sgdTriangleSolver_SAStoASA ( SGDfloat lenA, SGDfloat angB, SGDfloat lenC, SGDfloat *angA, SGDfloat *lenB, SGDfloat *angC ) ; void sgdTriangleSolver_ASAtoSAS ( SGDfloat angA, SGDfloat lenB, SGDfloat angC, SGDfloat *lenA, SGDfloat *angB, SGDfloat *lenC ) ; void sgdTriangleSolver_SAAtoASS ( SGDfloat lenA, SGDfloat angB, SGDfloat angA, SGDfloat *angC, SGDfloat *lenB, SGDfloat *lenC ) ; void sgdTriangleSolver_ASStoSAA ( SGDfloat angB, SGDfloat lenA, SGDfloat lenB, int angA_is_obtuse, SGDfloat *lenC, SGDfloat *angA, SGDfloat *angC ) ; /* SPRING-MASS-DAMPER (with simple Euler integrator) */ extern sgVec3 _sgGravity ; inline void sgSetGravity ( float g ) { sgSetVec3 ( _sgGravity, 0.0f, 0.0f, -g ) ; } inline void sgSetGravityVec3 ( sgVec3 g ) { sgCopyVec3 ( _sgGravity, g ) ; } inline float *sgGetGravityVec3 () { return _sgGravity ; } inline float sgGetGravity () { return - _sgGravity[2] ; } class sgParticle { float ooMass ; /* One-over-mass */ sgVec3 pos ; sgVec3 vel ; sgVec3 force ; public: sgParticle ( float mass, sgVec3 _pos ) { setMass ( mass ) ; sgCopyVec3 ( pos, _pos ) ; sgZeroVec3 ( vel ) ; sgZeroVec3 ( force ) ; } sgParticle ( float mass, float x = 0.0f, float y = 0.0f, float z = 0.0f ) { setMass ( mass ) ; sgSetVec3 ( pos, x, y, z ) ; sgZeroVec3 ( vel ) ; sgZeroVec3 ( force ) ; } SGfloat *getPos () { return pos ; } SGfloat *getVel () { return vel ; } SGfloat *getForce () { return force ; } const SGfloat *getPos () const { return pos ; } const SGfloat *getVel () const { return vel ; } const SGfloat *getForce () const { return force ; } float getOneOverMass () { return ooMass ; } float getMass () { return 1.0f / ooMass ; } void setPos ( sgVec3 p ) { sgCopyVec3 ( pos , p ) ; } void setVel ( sgVec3 v ) { sgCopyVec3 ( vel , v ) ; } void setForce ( sgVec3 f ) { sgCopyVec3 ( force, f ) ; } void setPos ( float x, float y, float z ) { sgSetVec3 ( pos ,x,y,z ) ; } void setVel ( float x, float y, float z ) { sgSetVec3 ( vel ,x,y,z ) ; } void setForce ( float x, float y, float z ) { sgSetVec3 ( force,x,y,z ) ; } void setOneOverMass ( float oom ) { ooMass = oom ; } void setMass ( float m ) { assert ( m > 0.0f ) ; ooMass = 1.0f / m ; } void zeroForce () { sgZeroVec3 ( force ) ; } void addForce ( sgVec3 f ) { sgAddVec3 ( force, f ) ; } void subForce ( sgVec3 f ) { sgSubVec3 ( force, f ) ; } void gravityOnly () { sgScaleVec3 ( force, sgGetGravityVec3 (), ooMass ) ; } void bounce ( sgVec3 normal, float coefRestitution ) { sgVec3 vn, vt ; sgScaleVec3 ( vn, normal, sgScalarProductVec3 ( normal, vel ) ) ; sgSubVec3 ( vt, vel, vn ) ; sgAddScaledVec3 ( vel, vt, vn, -coefRestitution ) ; } void update ( float dt ) { sgAddScaledVec3 ( vel, force, dt * ooMass ) ; sgAddScaledVec3 ( pos, vel, dt ) ; } } ; class sgSpringDamper { sgParticle *p0 ; sgParticle *p1 ; float restLength ; float stiffness ; float damping ; public: sgSpringDamper () { p0 = p1 = NULL ; stiffness = 1.0f ; damping = 1.0f ; restLength = 1.0f ; } sgSpringDamper ( sgParticle *_p0, sgParticle *_p1, float _stiffness, float _damping, float _restLength = -1.0f ) { p0 = _p0 ; p1 = _p1 ; stiffness = _stiffness ; damping = _damping ; if ( _restLength < 0.0f ) { if ( p0 != NULL && p1 != NULL ) restLength = sgDistanceVec3 ( p0->getPos(), p1->getPos() ) ; else restLength = _restLength ; } else restLength = 1.0f ; } float getRestLength () { return restLength ; } float getStiffness () { return stiffness ; } float getDamping () { return damping ; } sgParticle *getParticle ( int which ) { return ( which == 0 ) ? p0 : p1 ; } void setParticles ( sgParticle *_p0, sgParticle *_p1 ) { p0 = _p0 ; p1 = _p1 ; } void setParticle ( int which, sgParticle *p ) { if ( which == 0 ) p0 = p ; else p1 = p ; } void setRestLength () { restLength = sgDistanceVec3 ( p0->getPos(), p1->getPos() ) ; } void setRestLength ( float l ) { restLength = l ; } void setStiffness ( float s ) { stiffness = s ; } void setDamping ( float d ) { damping = d ; } void update () { sgVec3 dP ; sgSubVec3 ( dP, p0->getPos(), p1->getPos() ) ; sgVec3 dV ; sgSubVec3 ( dV, p0->getVel(), p1->getVel() ) ; float L = sgLengthVec3 ( dP ) ; if ( L == 0.0f ) L = 0.0000001f ; float H = ( L - restLength ) * stiffness ; float D = sgScalarProductVec3 ( dV, dP ) * damping / L ; sgVec3 F ; sgScaleVec3 ( F, dP, - ( H + D ) / L ) ; p0 -> addForce ( F ) ; p1 -> subForce ( F ) ; } } ; /* It must be true that (x % NOISE_WRAP_INDEX) == (x & NOISE_MOD_MASK) so NOISE_WRAP_INDEX must be a power of two, and NOISE_MOD_MASK must be that power of 2 - 1. as indices are implemented, as unsigned chars, NOISE_WRAP_INDEX shoud be less than or equal to 256. There's no good reason to change it from 256, really. NOISE_LARGE_PWR2 is a large power of 2, we'll go for 4096, to add to negative numbers in order to make them positive */ #define SG_PERLIN_NOISE_WRAP_INDEX 256 #define SG_PERLIN_NOISE_MOD_MASK 255 #define SG_PERLIN_NOISE_LARGE_PWR2 4096 class sgPerlinNoise_1D { private: SGfloat gradTable [ SG_PERLIN_NOISE_WRAP_INDEX * 2 + 2 ] ; public: sgPerlinNoise_1D () ; void regenerate () ; SGfloat getNoise ( SGfloat x ) ; } ; class sgPerlinNoise_2D { private: sgVec2 gradTable [ SG_PERLIN_NOISE_WRAP_INDEX * 2 + 2 ] ; public: sgPerlinNoise_2D () ; void regenerate () ; SGfloat getNoise ( sgVec2 pos ) ; SGfloat getNoise ( SGfloat x, SGfloat y ) { sgVec2 p ; sgSetVec2 ( p, x, y ) ; return getNoise ( p ) ; } } ; class sgPerlinNoise_3D { private: sgVec3 gradTable [ SG_PERLIN_NOISE_WRAP_INDEX * 2 + 2 ] ; public: sgPerlinNoise_3D () ; void regenerate () ; SGfloat getNoise ( sgVec3 pos ) ; SGfloat getNoise ( SGfloat x, SGfloat y, SGfloat z ) { sgVec3 p ; sgSetVec3 ( p, x, y, z ) ; return getNoise ( p ) ; } } ; #endif