/*
======================================================================
def.h

Ernie Wright  01 Jun 05

Definitions for the SPD geometry library.  This is a modified subset
of the original, for use with a LightWave Modeler plug-in.
====================================================================== */

#ifndef DEF_H
#define DEF_H

#if __cplusplus
extern "C" {
#endif


#define SPD_MIN                1
#define SPD_BALLS              1
#define SPD_GEARS              2
#define SPD_MOUNT              3
#define SPD_RINGS              4
#define SPD_TEAPOT             5
#define SPD_TETRA              6
#define SPD_TREE               7
#define SPD_READDXF            8
#define SPD_LATTICE            9
#define SPD_SHELLS            10
#define SPD_READNFF           11
#define SPD_READOBJ           12
#define SPD_JACKS             13
#define SPD_SOMBRERO          14
#define SPD_NURBTST           15
#define SPD_GENERIC           16
#define SPD_MAX      SPD_GENERIC


#ifndef EPSILON
#define EPSILON 1.0e-8
#endif

#ifndef EPSILON2
#define EPSILON2 1.0e-6
#endif

#ifndef FALSE
#define FALSE 0
#endif

#ifndef TRUE
#define TRUE 1
#endif

#ifndef PI
#define PI 3.1415926535897932384626433832795
#endif

typedef double MATRIX[4][4];  /* row major form */
typedef double COORD3[3];
typedef double COORD4[4];

/* COORD3/COORD4 indices */
#define X 0
#define Y 1
#define Z 2
#define W 3

/* COORD3 (color) indices */
#define R_COLOR 0
#define G_COLOR 1
#define B_COLOR 2

#ifndef ABS
#define ABS(A)       ( (A) < 0 ? -(A) : (A) )
#endif

#define POW(A,B)     ( (A) == 0.0 ? 0.0 : ( (B) == 0.0 ? 1.0 : pow(A, B) ) )
#define SGN(A)       ( (A) < 0.0 ? -1.0 : ( (A) > 0.0 ? 1.0 : 0.0) )
#define FRACTION(A)  ( (A) - (int)(A) )
#define MAX(A,B)     ( (A) > (B) ? (A) : (B) )
#define MIN(A,B)     ( (A) < (B) ? (A) : (B) )
#define SQR(A)       ( (A) * (A) )
#define IS_VAL_ALMOST_ZERO(A,E) ( ABS(A) <= (E) )

#define ADD2_COORD3(r,a)   { (r)[X] += (a)[X]; (r)[Y] += (a)[Y];\
                             (r)[Z] += (a)[Z]; }

#define ADD3_COORD3(r,a,b) { (r)[X] = (a)[X] + (b)[X];\
                             (r)[Y] = (a)[Y] + (b)[Y];\
                             (r)[Z] = (a)[Z] + (b)[Z]; }

#define COPY_COORD3(r,a) { (r)[X] = (a)[X];\
                           (r)[Y] = (a)[Y];\
                           (r)[Z] = (a)[Z];}

#define COPY_COORD4(r,a) { (r)[X] = (a)[X];\
                           (r)[Y] = (a)[Y];\
                           (r)[Z] = (a)[Z];\
                           (r)[W] = (a)[W]; }

#define CROSS(r,a,b) { (r)[X] = (a)[Y] * (b)[Z] - (a)[Z] * (b)[Y];\
                       (r)[Y] = (a)[Z] * (b)[X] - (a)[X] * (b)[Z];\
                       (r)[Z] = (a)[X] * (b)[Y] - (a)[Y] * (b)[X]; }

#define DOT_PRODUCT(a,b) ( (a)[X] * (b)[X] +\
                           (a)[Y] * (b)[Y] +\
                           (a)[Z] * (b)[Z] )

#define DOT4(a,b) ( (a)[X] * (b)[X] +\
                    (a)[Y] * (b)[Y] +\
                    (a)[Z] * (b)[Z] +\
                    (a)[W] * (b)[W] )

#define IS_COORD3_ALMOST_ZERO(a,E)   (\
                                     IS_VAL_ALMOST_ZERO( (a)[X], (E) )\
                                  && IS_VAL_ALMOST_ZERO( (a)[Y], (E) )\
                                  && IS_VAL_ALMOST_ZERO( (a)[Z], (E) ) )

#define SET_COORD3(r,A,B,C)    { (r)[X] = (A); (r)[Y] = (B); (r)[Z] = (C); }

#define SET_COORD4(r,A,B,C,D)  { (r)[X] = (A); (r)[Y] = (B); (r)[Z] = (C);\
                                 (r)[W] = (D); }

#define SUB2_COORD3(r,a)   { (r)[X] -= (a)[X]; (r)[Y] -= (a)[Y];\
                             (r)[Z] -= (a)[Z]; }

#define SUB3_COORD3(r,a,b) { (r)[X] = (a)[X] - (b)[X];\
                             (r)[Y] = (a)[Y] - (b)[Y];\
                             (r)[Z] = (a)[Z] - (b)[Z]; }

#define LERP_COORD(r, a, b, u) { (r)[X] = (a)[X] + (u) * ((b)[X] - (a)[X]);\
                                 (r)[Y] = (a)[Y] + (u) * ((b)[Y] - (a)[Y]);\
                                 (r)[Z] = (a)[Z] + (u) * ((b)[Z] - (a)[Z]); }

#define COMB_COORD(r, a, b, u, v) { (r)[X] = (a)[X] * (u) + (b)[X] * (v);\
                                    (r)[Y] = (a)[Y] * (u) + (b)[X] * (v);\
                                    (r)[Z] = (a)[Z] * (u) + (b)[X] * (v); }

#define RAD2DEG(x) ((x) * 57.295779513082320876798154814105)
#define DEG2RAD(x) ((x) * 1.74532925199432957692369076848e-2)
#define log2(x)    (log(x) * 1.4426950408889634073599246810019)

#if __cplusplus
}
#endif


#endif /* DEF_H */
