home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
RISC DISC 3
/
RISC_DISC_3.iso
/
resources
/
etexts
/
gems
/
gemsv
/
ch7_7
/
mactbox
/
tool.h
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-28
|
12KB
|
306 lines
/* ------------------------------------------------------------------------- *\
TOOL.H :
Basic definitions (based on A. Glassner in Graphics Gems I)
by Christophe Schlick (1 June 1992)
"A Toolbox of Macro Functions for Computer Graphics"
in Graphics Gems V (edited by A. Paeth), Academic Press
\* ------------------------------------------------------------------------- */
#ifndef _TOOL_
#define _TOOL_
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/* ------------------------------------------------------------------------- *\
TYPES AND CONSTANTS
\* ------------------------------------------------------------------------- */
/*
** Type definitions (boolean, byte and file)
*/
typedef unsigned int bool;
typedef unsigned char byte;
typedef FILE *file;
/*
** Boolean constants
*/
#define TRUE (1)
#define FALSE (0)
#define ON (1)
#define OFF (0)
/*
** Mathematical constants
*/
#ifdef SINGLE_REAL
#define LO_TOL ((float) 0.000010)
#define TOL ((float) 0.000100)
#define HI_TOL ((float) 0.001000)
#define E ((float) 2.718282)
#define PI ((float) 3.141593)
#define HALF_PI ((float) 1.570796)
#define DBLE_PI ((float) 6.283185)
#define SQRT2 ((float) 1.414214)
#define HALF_SQRT2 ((float) 0.707107)
#define DBLE_SQRT2 ((float) 2.828427)
#define SQRT3 ((float) 1.732051)
#define HALF_SQRT3 ((float) 0.860254)
#define DBLE_SQRT3 ((float) 3.464102)
#define GOLD_RATIO ((float) 1.618340)
#define DEG_TO_RAD ((float) 0.017453)
#define RAD_TO_DEG ((float) 57.29578)
#else
#define LO_TOL ((double) 0.0000000000000010)
#define TOL ((double) 0.0000000000000100)
#define HI_TOL ((double) 0.0000000000001000)
#define E ((double) 2.7182818284590498)
#define PI ((double) 3.1415926535897929)
#define HALF_PI ((double) 1.5707963267948965)
#define DBLE_PI ((double) 6.2831853071795858)
#define SQRT2 ((double) 1.4142135623730951)
#define HALF_SQRT2 ((double) 0.7071067811865476)
#define DBLE_SQRT2 ((double) 2.8284271248461902)
#define SQRT3 ((double) 1.7320508075688772)
#define HALF_SQRT3 ((double) 0.8602540378443859)
#define DBLE_SQRT3 ((double) 3.4641016151377544)
#define GOLD_RATIO ((double) 1.6183398874989489)
#define DEG_TO_RAD ((double) 0.0174532925199433)
#define RAD_TO_DEG ((double) 57.295779513082322)
#endif
/* ------------------------------------------------------------------------- *\
MATHEMATICAL MACROS
\* ------------------------------------------------------------------------- */
/*
** ABS(t) = Absolute value of 't'
** SGN(t) = Sign value of 't'
** FLOOR(t) = Map 't' to the default integer
** ROUND(t) = Map 't' to the nearest integer
*/
#define ABS(t) ((t) < 0 ? -(t) : (t))
#define SGN(t) ((t) < 0 ? -1 : (t) > 0 ? 1 : 0)
#define FLOOR(t) ((t) < 0 ? (int) ((t)-1.0) : (int) (t))
#define ROUND(t) ((t) < 0 ? (int) ((t)-0.5) : (int) ((t)+0.5))
/*
** ZERO(a) = Test if a = 0 with a given tolerance
** SAME(a,b) = Test if a = b with a given tolerance
** LESS(a,b) = Test if a < b with a given tolerance
** MORE(a,b) = Test if a > b with a given tolerance
** !LESS(a,b) = Test if a >= b with a given tolerance
** !MORE(a,b) = Test if a <= b with a given tolerance
** XXXX_TOL(a,b,t) = Same thing but with a user-provided tolerance
*/
#define ZERO(a) ((a) > -TOL && (a) < TOL)
#define ZERO_TOL(a,t) ((a) > -(t) && (a) < (t))
#define SAME(a,b) ((a) > (b)-TOL && (a) < (b)+TOL)
#define SAME_TOL(a,b,t) ((a) > (b)-(t) && (a) < (b)+(t))
#define LESS(a,b) ((a) < (b)-TOL)
#define LESS_TOL(a,b,t) ((a) < (b)-(t))
#define MORE(a,b) ((a) > (b)+TOL)
#define MORE_TOL(a,b,t) ((a) > (b)+(t))
/*
** IN(t,lo,hi) = Test if t > lo and t < hi
** !IN(t,lo,hi) = Test if t <= lo or t >= hi
** OUT(t,lo,hi) = Test if t < lo or t > hi
** !OUT(t,lo,hi) = Test if t >= lo and t <= hi
** CLAMP(t,lo,hi) = Clamp a value 't' to the range [lo,hi]
*/
#define IN(t,lo,hi) ((t) > (lo) && (t) < (hi))
#define OUT(t,lo,hi) ((t) < (lo) || (t) > (hi))
#define CLAMP(t,lo,hi) ((t) < (lo) ? (lo) : (t) > (hi) ? (hi) : (t))
/*
** MIN(a,b) = Minimum of values 'a' and 'b'
** MAX(a,b) = Maximum of values 'a' and 'b'
** MINMIN(a,b,c) = Minimum of values 'a', 'b' and 'c'
** MAXMAX(a,b,c) = Maximum of values 'a', 'b' and 'c'
*/
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MINMIN(a,b,c) ((a) < (b) ? MIN (a,c) : MIN (b,c))
#define MAXMAX(a,b,c) ((a) > (b) ? MAX (a,c) : MAX (b,c))
/*
** LERP(t,a,b) = Linear interpolation between 'a' and 'b' using 't' (0<=t<=1)
** ==> LERP(0) = a, LERP(1) = b
**
** HERP(t,a,b) = Hermite interpolation between 'a' and 'b' using 't' (0<=t<=1)
** ==> HERP(0) = a, HERP'(0) = 0, HERP(1) = b, HERP'(1) = 0
**
** CERP(t,a,b) = Cardinal interpolation between 'a' and 'b' using 't' (0<=t<=1)
** ==> CERP(0) = a, CERP'(0) = 0.5*(b-aa), HERP(1) = b, HERP'(1) = 0.5*(bb-a)
*/
#define LERP(t,a,b) ((a) + ((b)-(a))*(t))
#define HERP(t,a,b) ((a) + ((b)-(a))*(t)*(t)*(3.0-(t)-(t)))
#define CERP(t,aa,a,b,bb) ((a) + 0.5*(t)*((b)-(aa)+(t)*(2.0*(aa)-5.0*(a)\
+4.0*(b)-(bb)+(t)*((bb)-3.0*(b)+3.0*(a)-(aa)))))
/*
** BIAS(t,p) = Rational bias operator (0 <= t <= 1 and 0 < p < 1)
** GAIN(t,p) = Rational gain operator (0 <= t <= 1 and 0 < p < 1)
**
** Note : For details, see the Gem given by C. Schlick in "Graphics Gems IV"
*/
#define BIAS(t,p) ((p)*(t)/((p)+((p)+(p)-1.0)*((t)-1.0)))
#define GAIN(t,p) ((t)<0.5 ? (p)*(t)/((p)+((p)+(p)-1.0)*((t)+(t)-1.0)):\
(p)*((t)-1.0)/((p)-((p)+(p)-1.0)*((t)+(t)-1.0))+1.0)
/*
** SWAP(a,b,t) = Swap 'a' and 'b' using 't' as temporary variable
**
** Warning : The Gem given by B. Wyvill in "Graphics Gems I" should not be used
** because it is compiler-dependent when using non-integer variables!
*/
#define SWAP(a,b,t) ((t) = (a), (a) = (b), (b) = (t))
/*
** Resolution (real solutions only) of a quadratic equation: a*x^2+b*x+c = 0
**
** Warning : This is a hacker-like implementation of a quadratic solver. It
** is intended to be optimal in terms of floating point operations
** but warn that values of parameters a, b and c are destroyed!
**
** Return : a = Smallest solution (if it exists)
** b = Greatest solution (if it exists)
** Return value = Number of solutions (0, 1, or 2)
*/
#define QUADRATIC(a,b,c)\
(ZERO (a) ? ZERO (b) ? 0 : (a = -c / b, b = a, 1) :\
(a = -0.5 / a, b *= a, c *= a + a, c += b * b,\
(c > TOL) ? (c = sqrt (c), a = b - c, b = b + c, 2) :\
(c < -TOL) ? 0 : (a = b, 1)))
/* ------------------------------------------------------------------------- *\
MEMORY MANAGEMENT MACROS
\* ------------------------------------------------------------------------- */
/*
** USR_INIT_MEM = User-provided memory allocation routine (default = malloc)
** USR_EXIT_MEM = User-provided memory deallocation routine (default = free)
**
** Note: If you do not like standard (de)allocation routines, simply redefine
** USR_INIT_MEM and USR_EXIT_MEM with your favorite functions
*/
#ifndef USR_INIT_MEM
#define USR_INIT_MEM malloc
#endif
#ifndef USR_EXIT_MEM
#define USR_EXIT_MEM free
#endif
/*
** INIT_MEM(Var,Type,Nbr) = Allocation for 'Nbr' elements of type 'Type'
** EXIT_MEM(Var) = Deallocation of variable 'Var'
** ZERO_MEM(Var,Type,Nbr) = Fill 'Nbr' elements of type 'Type' with zero
** COPY_MEM(Var,Mem,Type,Nbr) = Copy 'Nbr' elements from 'Mem' to 'Var'
** SAME_MEM(Var,Mem,Type,Nbr) = Test if 'Var=Mem' (only 'Nbr' first elements)
** LESS_MEM(Var,Mem,Type,Nbr) = Test if 'Var<Mem' (only 'Nbr' first elements)
** MORE_MEM(Var,Mem,Type,Nbr) = Test if 'Var>Mem' (only 'Nbr' first elements)
*/
#define INIT_MEM(Var,Type,Nbr) (Var = (Type*) (malloc(sizeof(Type)*(Nbr))))
#define EXIT_MEM(Var) (free (Var))
#define ZERO_MEM(Var,Type,Nbr) (bzero (Var,sizeof(Type)*(Nbr)))
#define COPY_MEM(Var,Mem,Type,Nbr) (bcopy (Mem,Var,sizeof(Type)*(Nbr))))
#define SAME_MEM(Var,Mem,Type,Nbr) (bcmp (Var,Mem,sizeof(Type)*(Nbr)) == 0)
#define LESS_MEM(Var,Mem,Type,Nbr) (bcmp (Var,Mem,sizeof(Type)*(Nbr)) < 0)
#define MORE_MEM(Var,Mem,Type,Nbr) (bcmp (Var,Mem,sizeof(Type)*(Nbr)) > 0)
/* ------------------------------------------------------------------------- *\
FILE MANAGEMENT MACROS
\* ------------------------------------------------------------------------- */
/*
** Symbolic constants for standard streams and file modes
*/
#define SOF stdout /* Standard output file */
#define SIF stdin /* Standard input file */
#define SEF stderr /* Standard error file */
#define RFILE "r" /* Open an existing file in read mode */
#define WFILE "a" /* Open an existing file in write mode */
#define NFILE "w" /* Create a new file (or recreate an existing one) */
/*
** INIT_FILE(File,Name,Mode) = Open or create file 'Name' in a given 'Mode'
** EXIT_FILE(File) = Close file 'File'
** TEST_FILE(File) = Test if the file pointer is within 'File'
** HEAD_FILE(File) = Set the file pointer at the head of 'File'
** TAIL_FILE(File) = Set the file pointer at the tail of 'File'
*/
#define INIT_FILE(File,Name,Mode) ((File) = fopen (Name, Mode))
#define EXIT_FILE(File) (fclose (File))
#define TEST_FILE(File) (!feof (File))
#define HEAD_FILE(File) (fseek (File, (long)0, 0))
#define TAIL_FILE(File) (fseek (File, (long)0, 2))
/*
** GET_BYTE(File,Var) = Get a byte in 'File' and put it in 'Var'
** PUT_BYTE(File,Var) = Put a byte 'Var' at the current position in 'File'
** GET_STR(File,Var) = Get a string (until the next blank caracter) from 'File'
** PUT_STR(File,Var) = Put a null-terminated string 'Var' in 'File'
** GET_LINE(File,Var,Max) = Get a line of at most 'Max' characters from 'File'
** PUT_LINE(File,Var) = Put a string 'Var' ended with a newline char in 'File'
*/
#define GET_BYTE(File,Var) ((Var) = getc (File))
#define PUT_BYTE(File,Var) (putc (Var, File))
#define GET_STR(File,Var) (fscanf (File, "%s\n", Var))
#define PUT_STR(File,Var) (fprintf (File, "%s", Var))
#define GET_LINE(File,Var,Max) (fgets (Var, Max, File))
#define PUT_LINE(File,Var) (fprintf (File, "%s\n", Var))
/* ------------------------------------------------------------------------- *\
ERROR MANAGEMENT MACROS
\* ------------------------------------------------------------------------- */
/*
** ASSERT(Test) = If 'Test' is false, display a standard error message
** WARN_ERROR(Test,Mesg,Name) = If 'Test' is false, display an error 'Mesg'
** including an eventual identifier 'Name'
** STOP_ERROR(Test,Mesg,Name) = If 'Test' is false, display an error 'Mesg'
** including an identifier 'Name' and stop
** CURE_ERROR(Test,Cure,Var) = If 'Test' is false, try to 'Cure' the error
*/
#define ASSERT(Test)\
((Test) ? TRUE :\
(fprintf (SEF, "Assertion \"%s\" failed in file %s at line %d\n",\
#Test, __FILE__, __LINE__), exit (0)))
#define WARN_ERROR(Test,Mesg,Name) (Test ?: fprintf (SEF,Mesg,Name))
#define STOP_ERROR(Test,Mesg,Name) (Test ?: (fprintf (SEF,Mesg,Name),exit(0)))
#define CURE_ERROR(Test,Cure,Var) (Test ?: (Cure) ((void *) Var))
#endif
/* ------------------------------------------------------------------------- */