3103 lines
82 KiB
C++
3103 lines
82 KiB
C++
/*
|
|
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 2121 2007-09-15 03:36:21Z fayjf $
|
|
*/
|
|
|
|
|
|
#ifndef SG_H
|
|
#define SG_H 1
|
|
|
|
#include <stdio.h>
|
|
#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 (a<SG_ZERO) ? -a : a ; }
|
|
inline SGfloat sgHypot ( const SGfloat x, const SGfloat y ) { return sgSqrt( sgSquare(x) + sgSquare(y) ); }
|
|
|
|
|
|
/*
|
|
Type-casted sin/cos/tan/asin/acos/atan2 ANGLES IN DEGREES
|
|
*/
|
|
|
|
inline SGfloat sgASin ( SGfloat s )
|
|
{ return (SGfloat) asin ( s ) * SG_RADIANS_TO_DEGREES ; }
|
|
inline SGfloat sgACos ( SGfloat s )
|
|
{ return (SGfloat) acos ( s ) * SG_RADIANS_TO_DEGREES ; }
|
|
inline SGfloat sgATan ( SGfloat s )
|
|
{ return (SGfloat) atan ( s ) * SG_RADIANS_TO_DEGREES ; }
|
|
inline SGfloat sgATan2 ( SGfloat y, SGfloat x )
|
|
{ return (SGfloat) atan2 ( y,x ) * SG_RADIANS_TO_DEGREES ; }
|
|
inline SGfloat sgSin ( SGfloat s )
|
|
{ return (SGfloat) sin ( s * SG_DEGREES_TO_RADIANS ) ; }
|
|
inline SGfloat sgCos ( SGfloat s )
|
|
{ return (SGfloat) cos ( s * SG_DEGREES_TO_RADIANS ) ; }
|
|
inline SGfloat sgTan ( SGfloat s )
|
|
{ return (SGfloat) tan ( s * SG_DEGREES_TO_RADIANS ) ; }
|
|
|
|
|
|
inline int sgCompareFloat ( const SGfloat a, const SGfloat b, const SGfloat tol )
|
|
{
|
|
if ( ( a + tol ) < b ) return -1 ;
|
|
if ( ( b + tol ) < a ) return 1 ;
|
|
return 0 ;
|
|
}
|
|
|
|
|
|
/*
|
|
Types used in SG.
|
|
*/
|
|
|
|
typedef SGfloat sgVec2 [ 2 ] ;
|
|
typedef SGfloat sgVec3 [ 3 ] ;
|
|
typedef SGfloat sgVec4 [ 4 ] ;
|
|
|
|
typedef sgVec4 sgQuat ;
|
|
|
|
typedef SGfloat sgMat3 [3][3] ;
|
|
typedef SGfloat sgMat4 [4][4] ;
|
|
|
|
struct sgCoord
|
|
{
|
|
sgVec3 xyz ;
|
|
sgVec3 hpr ;
|
|
} ;
|
|
|
|
class sgSphere ;
|
|
class sgBox ;
|
|
class sgFrustum ;
|
|
|
|
/*
|
|
Some handy constants
|
|
*/
|
|
|
|
#define SG_OUTSIDE FALSE
|
|
#define SG_INSIDE TRUE
|
|
#define SG_STRADDLE 2
|
|
|
|
inline SGfloat sgHeightOfPlaneVec2 ( const sgVec4 plane, const sgVec2 pnt )
|
|
{
|
|
if ( plane[2] == SG_ZERO )
|
|
return SG_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)
|
|
The direction vector is X-coordinate = north, Y-coordinate = east, Z-coordinate = down
|
|
The heading ( = hpr[0] ) is in degrees south of east -- this is VERY nonstandard
|
|
The pitch ( = hpr[1] ) is in degrees positive up
|
|
The roll ( = hpr[2] ) is zero
|
|
*/
|
|
|
|
extern void sgHPRfromVec3 ( sgVec3 hpr, const sgVec3 src ) ;
|
|
|
|
extern void sgMakeCoordMat4 ( sgMat4 dst, const SGfloat x, const SGfloat y, const SGfloat z,
|
|
const SGfloat h, const SGfloat p, const SGfloat r ) ;
|
|
|
|
inline void sgMakeCoordMat4( sgMat4 dst, const sgVec3 xyz, const sgVec3 hpr )
|
|
{
|
|
sgMakeCoordMat4 ( dst, xyz[0], xyz[1], xyz[2],
|
|
hpr[0], hpr[1], hpr[2] ) ;
|
|
}
|
|
|
|
inline void sgMakeCoordMat4( sgMat4 dst, const sgCoord *src )
|
|
{
|
|
sgMakeCoordMat4 ( dst, src->xyz, 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. <sigh> */
|
|
#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 */
|
|
/* Note that to convert to parameters for gluPerspective you do the following:
|
|
* "fovy" is "vfov"
|
|
* "aspect" is the ratio "hfov" / "vfov"
|
|
* Note also that the "hfov" and "vfov" variables are NOT automatically set.
|
|
*/
|
|
|
|
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 <kevinbthompson@yahoo.com>
|
|
Modified by Sylvan W. Clebsch <sylvan@stanford.edu>
|
|
Largely rewritten by "Negative0" <negative0@earthlink.net>
|
|
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. <sigh> */
|
|
#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 <kevinbthompson@yahoo.com>
|
|
Modified by Sylvan W. Clebsch <sylvan@stanford.edu>
|
|
Largely rewritten by "Negative0" <negative0@earthlink.net>
|
|
*/
|
|
|
|
/*
|
|
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
|
|
|