/*****************************************************************************
*   "Irit" - the 3d polygonal solid modeller.				     *
*									     *
* Written by:  Gershon Elber				Ver 0.1, Jan. 1992   *
******************************************************************************
* Main definition Header file  for Irit - the 3d polygonal solid modeller.   *
*****************************************************************************/

#ifndef	IRIT_SM_H
#define	IRIT_SM_H

/* Note program version should also be updated in *.c modules, in few        */
/* places, as some system can not chain strings in the pre-processor level.  */
#define  VERSION	"Version 4.0"			 /* Program version. */
#define  COPYRIGHT	"(C) Copyright 1989/90/91/92/93 Gershon Elber"

#include <string.h>

#ifndef	NULL
#define	NULL	0
#endif /* NULL */

#ifndef	TRUE
#define	TRUE	1
#define	FALSE	0
#endif /* TRUE */

#ifdef VoidPtr
#undef VoidPtr
#endif /* VoidPtr */

#ifdef NO_VOID_PTR
#define VoidPtr		char *
#else
#define VoidPtr		void *
#endif /* NO_VOID_PTR */

#if !defined(FLOAT) && !defined(DOUBLE)
#ifdef __MSDOS__
#define FLOAT
typedef	float		RealType;	    /* On IBMPC to reserve memory... */
#else
#define DOUBLE
typedef	double		RealType;
#endif /* __MSDOS__ */
#endif /* !FLOAT && !DOUBLE */

typedef	unsigned char	ByteType;

typedef	RealType	PointType[3];	/* For X, Y, Z coordinates of point. */
typedef RealType	VectorType[3]; /* For X, Y, Z coordinates of vector. */
typedef RealType	LineType[3];	      /* A, B, C in Ax + By + C = 0. */
typedef RealType	NormalType[3];	    /* Unit normalized normal coeff. */
typedef RealType	PlaneType[4];		    /* Plane equation coeff. */
typedef RealType	MatrixType[4][4];	   /* Homogeneous transform. */
typedef PointType	BBoxType[2];	      /* Axis parallel bounding box. */

#define EPSILON		1e-5
#define INFINITY	1e6

#ifndef M_PI
#define M_PI	3.14159265358979323846
#endif /* M_PI */

#define LINE_LEN_LONG	256		   /* Lines read from stdin/files... */
#define LINE_LEN	81		   /* Lines read from stdin/files... */
#define LINE_LEN_SHORT	31		   /* Lines read from stdin/files... */
#define OBJ_NAME_LEN	31				/* Names of objects. */
#define FILE_NAME_LEN	13		   /* Name (8) + Type (3) + Dot (1). */
#define PATH_NAME_LEN	80		              /* Name with full Path */

/* Follows by general purpose helpfull macros: */
#ifndef MIN
#define MIN(x, y)		((x) > (y) ? (y) : (x))
#endif /* MIN */
#ifndef MAX
#define MAX(x, y)		((x) > (y) ? (x) : (y))
#endif /* MAX */
#define BOUND(x, Min, Max)	(MAX(MIN(x, Max), Min))

#define ABS(x)			((x) > 0 ? (x) : (-(x)))
#define SQR(x)			((x) * (x))
#define SIGN(x)			((x) > 0 ? 1 : ((x) < 0 ? -1 : 0))

#define SWAP(type, x, y)	{ type temp = (x); (x) = (y); (y) = temp; }

#define REAL_TO_INT(R)		((int) (R + 0.5))
#define REAL_PTR_TO_INT(R)	((int) ((*R) + 0.5))

#define APX_EQ(x, y)		(ABS(x - y) < EPSILON)
#define PT_APX_EQ(Pt1, Pt2)	(APX_EQ(Pt1[0], Pt2[0]) && \
				 APX_EQ(Pt1[1], Pt2[1]) && \
				 APX_EQ(Pt1[2], Pt2[2]))
#define PLANE_APX_EQ(Pl1, Pl2)	(APX_EQ(Pl1[0], Pl2[0]) && \
				 APX_EQ(Pl1[1], Pl2[1]) && \
				 APX_EQ(Pl1[2], Pl2[2]) && \
				 APX_EQ(Pl1[3], Pl2[3]))


#define PT_CLEAR(Pt)		{ Pt[0] = Pt[1] = Pt[2] = 0.0; }

#define PT_SCALE(Pt, Scalar)	{ Pt[0] *= Scalar; \
				  Pt[1] *= Scalar; \
				  Pt[2] *= Scalar; \
			        }

/* The memcpy is sometimes defined to get (char *) pointers and sometimes    */
/* (void *) pointers. To be compatible with both it is coerced to (char *).  */
#define PT_COPY(PtDest, PtSrc)	  memcpy((char *) (PtDest), (char *) (PtSrc), \
							3 * sizeof(RealType))
#define PLANE_COPY(PlDest, PlSrc) memcpy((char *) (PlDest), (char *) (PlSrc), \
							4 * sizeof(RealType))
#define MAT_COPY(Dest, Src)	  memcpy((char *) (Dest), (char *) (Src), \
							16 * sizeof(RealType))
#define GEN_COPY(Dest, Src, Size) memcpy((char *) (Dest), (char *) (Src), Size)
#define ZAP_MEM(Dest, Size)	  memset((char *) (Dest), 0, Size);

#define PT_LENGTH(Pt)		sqrt(SQR(Pt[0]) + SQR(Pt[1]) + SQR(Pt[2]))

#define PT_NORMALIZE(Pt)	{ RealType Size = PT_LENGTH(Pt); \
				  Pt[0] /= Size; \
				  Pt[1] /= Size; \
				  Pt[2] /= Size; \
				}

#define PT_BLEND(Res, Pt1, Pt2, t) \
				{ Res[0] = Pt1[0] * t + Pt2[0] * (1 - t); \
				  Res[1] = Pt1[1] * t + Pt2[1] * (1 - t); \
				  Res[2] = Pt1[2] * t + Pt2[2] * (1 - t); \
			        }

#define PT_ADD(Res, Pt1, Pt2)	{ Res[0] = Pt1[0] + Pt2[0]; \
				  Res[1] = Pt1[1] + Pt2[1]; \
				  Res[2] = Pt1[2] + Pt2[2]; \
			        }

#define PT_SUB(Res, Pt1, Pt2)	{ Res[0] = Pt1[0] - Pt2[0]; \
				  Res[1] = Pt1[1] - Pt2[1]; \
				  Res[2] = Pt1[2] - Pt2[2]; \
				}

#define PT_SWAP(Pt1, Pt2)	{ SWAP(RealType, Pt1[0], Pt2[0]); \
				  SWAP(RealType, Pt1[1], Pt2[1]); \
				  SWAP(RealType, Pt1[2], Pt2[2]); \
				}

#define DOT_PROD(Pt1, Pt2)	(Pt1[0] * Pt2[0] + \
				 Pt1[1] * Pt2[1] + \
				 Pt1[2] * Pt2[2])

#define CROSS_PROD(PtRes, Pt1, Pt2) \
				{ PtRes[0] = Pt1[1] * Pt2[2] - Pt1[2] * Pt2[1]; \
				  PtRes[1] = Pt1[2] * Pt2[0] - Pt1[0] * Pt2[2]; \
				  PtRes[2] = Pt1[0] * Pt2[1] - Pt1[1] * Pt2[0]; }

#define DEG2RAD(Deg)		((Deg) * M_PI / 180.0)
#define RAD2DEG(Rad)		((Rad) * 180.0 / M_PI)

#if defined(_AIX) || defined(sgi) || defined(DJGCC) || defined(OS2GCC) || defined(__WINNT__) || defined(AMIGA)
#include <stdlib.h>
#ifdef sgi
#include <unistd.h>
#endif /* sgi */
#else
VoidPtr malloc(unsigned int Size);
void free(VoidPtr p);
char *getenv(char *Name);
int atoi(char *str);
#endif /* _AIX || sgi || DJGCC || OS2GCC || __WINNT__ || AMIGA */

char *IritStrdup(char *s);
void IritSleep(int MiliSeconds);
void IritRandomInit(long Seed);
RealType IritRandom(RealType Min, RealType Max);
RealType IritCPUTime(int Reset);
char *IritRealTimeDate(void);

#ifndef AMIGA
void movmem(VoidPtr Src, VoidPtr Dest, int Len);
#endif /* AMIGA */
char *searchpath(char *Name);

#ifdef STRICMP
int strnicmp(char *s1, char *s2, int n);
int stricmp(char *s1, char *s2);
#endif /* STRICMP */

#ifdef STRSTR
char *strstr(char *s, char *Pattern);
#endif /* STRSTR */

#ifdef STRDUP
char *strdup(char *s);
#endif /* STRDUP */

#ifdef GETCWD
char *getcwd(char *s, int Len);
#endif /* GETCWD */

void IritFatalError(char *Msg);

#endif	/* IRIT_SM_H */
