/*****************************************************************************
*   "Irit" - the 3d polygonal solid modeller.				     *
*									     *
* Written by:  Gershon Elber				Ver 0.2, Mar. 1990   *
******************************************************************************
* Main definition Header file  for Irit - the 3d polygonal solid modeller.   *
*****************************************************************************/

#ifndef	IRIT_H
#define	IRIT_H

/* Note program version should also be updated in irit.c module, in few      */
/* places, as some system can not chain strings in the pre-processor level.  */
#define  VERSION	"Version 2.1"			 /* Program version. */

#ifdef NO_VOID_PTR
#define VoidPtr		char *
#else
#define VoidPtr		void *
#endif /* NO_VOID_PTR */

#ifdef __MSDOS__
#include <mem.h>			            /* Used for memcpy rtns. */
#else
#include "xgeneral.h"
#endif /* __MSDOS__ */

#include <setjmp.h>	/* Used for the long jumps - to main iteration loop. */

#ifndef	NULL
#define	NULL	0
#endif /* NULL */

#ifndef	TRUE
#define	TRUE	1
#define	FALSE	0
#endif /* TRUE */

#define BSPACE	8
#define TAB	9
#define LF	10
#define CR	13
#define	ESC     27

#ifdef __MSDOS__
typedef	float		RealType;	    /* On IBMPC to reserve memory... */
#else
#define DOUBLE
typedef	double		RealType;
#endif /* __MSDOS__ */

typedef	unsigned char	ByteType;

typedef	RealType	PointType[3];	/* For X, Y, Z coordinates of point. */
typedef RealType	VectorType[3];
typedef RealType	PlaneType[4];		    /* Plane equation coeff. */
typedef RealType	MatrixType[4][4];	   /* Homogeneous transform. */

#define EPSILON		1e-5
#define INFINITY	1e6

#define NO_TYPE		0			   /* Basic structure types. */
#define VERTEX_TYPE	1
#define POLYGON_TYPE	2
#define OBJECT_TYPE	3
#define OTHER_TYPE	10  /* Anything which is not one of the basic types. */

#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	11				/* Names of objects. */
#define FILE_NAME_LEN	13		   /* Name (8) + Type (3) + Dot (1). */

#define MAX_OBJ_LIST	20	   /* Maximum size of geometric object list. */

#define DEFAULT_LOAD_COLOR 1  /* Default colors for object loaded using LOAD */
#define DEFAULT_BOOL_COLOR 2  /* command, for boolean result objects, for    */
#define DEFAULT_ICRV_COLOR 14 /* boolean intersection curves and for basic   */
#define DEFAULT_PRIM_COLOR 4  /* primitives colors, respectively.	     */

#define UNDEF_OBJ	0       /* Objects (ObjectStruct - OBJECT_TYPE) types*/
#define GEOMETRIC_OBJ	1	/* Dont change the order of these objects as */
#define NUMERIC_OBJ	2	/* the over loading table (see OverLoad.c)   */
#define VECTOR_OBJ	3	/* is hardwired to it. If you add objects    */
#define MATRIX_OBJ	4	/* update that module properly.		     */
#define STRING_OBJ	5
#define OBJ_LIST_OBJ	6

#define NUM_OF_OBJECT_TYPES	6

#define DELAY_CONST_DEFAULT	500		    /* Used in cursor delay. */

#define DEFAULT_RESOLUTION	20	/* Used in Primitiv/Boolean modules. */
#define DEFAULT_INTERNAL	FALSE		  /* View of Internal edges? */
#define DEFAULT_INTERCRV	FALSE	      /* Return intersection curves? */

/*****************************************************************************
* Global data structures:						     *
* Objects in the system might be (real) scalars, (R3) vectors, matrices      *
* (4 by 4 - transformation matrix), strings of chars, lists of objects, or   *
* geometric objects. All but the last are simple and all their data is saved *
* in the object space itself. The last (geometric) object points on a	     *
* polygonal list of the form:						     *
*									     *
* Polygon -> Polygon -> Polygon -> Polygon -> .... -> NULL		     *
*    |		|	   |	      |					     *
*    V          V          V          V					     *
*  VList      VList      VList      VList	(VList = Vertex List)	     *
*									     *
* Each VList is a CIRCULAR vertex list. Each VList element (VertexStruct)    *
* implicitly defines an edge from this vertex, to the next. As each edge     *
* is used by exactly two polygons, a pointer to the other polygon using this *
* edge exists in the VertexStruct. Each polygon has also its Plane	     *
* definition for fast processing, with its normal pointing INTO the object.  *
*   Few other tags & flags are included in the data structures for different *
* modules.								     *
*   Note, vertices are not shared by few VLists/Polygons although it may     *
* decrease memory usage (suprisingly, not much). The main reason to that is  *
* the basic assumption of this solid modeller, which is simplicity...	     *
*****************************************************************************/

/*****************************************************************************
* Vertex Type - holds single 3D point, including some attributes on it as    *
* Tags & Count. The 3D coordinates are saved in Pt. Pointer to next in chain *
* is Pnext, and the pointer to the adjacent polygon (to the edge defined by  *
* this Vertex and Vertex->Pnext) is PAdj.				     *
*****************************************************************************/
typedef struct VertexStruct {
    ByteType Count, Tags;				/* Same attributes. */
    PointType Pt;			      /* Holds X, Y, Z coordinates. */
    struct PolygonStruct *PAdj;			    /* To adjacent polygon. */
    struct VertexStruct *Pnext;			       /* To next in chain. */
} VertexStruct;

/* Internal edge, or edge generated by the polygon decomposition stage when */
/* only convex polygons are allowed. This edge was not in the input	    */
/* non-convex polygon, and therefore one may not want to see/display it.    */
/* Note bits 4-7 (high nibble of Tags) are reserved for the different	    */
/* modules to perform their local tasks and so should not be used here.	    */
#define INTERNAL_TAG	0x01	       /* Edge Tag - This edge is internal. */

#define	IS_INTERNAL_EDGE(Vrtx)	((Vrtx)->Tags & INTERNAL_TAG)
#define	SET_INTERNAL_EDGE(Vrtx)	((Vrtx)->Tags |= INTERNAL_TAG)
#define	RST_INTERNAL_EDGE(Vrtx)	((Vrtx)->Tags &= ~INTERNAL_TAG)

/*****************************************************************************
* Polygon Type - holds single polygon - Its Plane definition, and a pointer  *
* to its vertices contour list V. As for VertexStruct, different attributes  *
* can be saved in Count & Tags. PAux can be used locally by different	     *
* modules, for local usage only, and nothing sould be assumed on entry.	     *
*****************************************************************************/
typedef struct PolygonStruct {
    ByteType Count, Tags;				/* Same attributes. */
    PlaneType Plane;			/* Holds Plane as Ax + By + Cz + D. */
    VoidPtr PAux;	 /* May be used locally (temporary!) by any module. */
    struct VertexStruct *V;		      /* To vertices circular list. */
    struct PolygonStruct *Pnext;		       /* To next in chain. */
} PolygonStruct;

/* Note bits 4-7 (high nibble of Tags) are reserved for the different	    */
/* modules to perform their local tasks and so should not be used here.	    */
#define CONVEX_TAG	0x01	  /* Convex Tag - Set if polygon is convex. */

#define	IS_CONVEX_POLY(Poly)	((Poly)->Tags & CONVEX_TAG)
#define	SET_CONVEX_POLY(Poly)	((Poly)->Tags |= CONVEX_TAG)
#define	RST_CONVEX_POLY(Poly)	((Poly)->Tags &= ~CONVEX_TAG)

/*****************************************************************************
* Object Type - main system structure, which holds all the objects defined   *
* in the system like Numeric, Geometric etc.				     *
*   Note that as the number of objects will be usually extermely low (100 is *
* high estimate!) we can waste some memory here...			     *
*****************************************************************************/
typedef struct ObjectStruct {
    char Name[OBJ_NAME_LEN];				 /* Name of object. */
    ByteType ObjType;		   /* Object Type: Numeric, Geometric, etc. */
    ByteType Count;	      /* Count Number of references to this object. */
    union {
	struct PolygonStruct *Pl;		       /* To polygons list. */
	RealType R;				      /* Numeric real data. */
	VectorType Vec;			       /* Numeric real vector data. */
	MatrixType Mat;		   /* Numeric 4 by 4 transformation matrix. */
	struct ObjectStruct *PObjList[MAX_OBJ_LIST];	/* List of objects. */
	char Str[LINE_LEN];		 /* General string for text object. */
	ByteType Attr[LINE_LEN];   /* Used to hold attributes of objects... */
    } U;
    struct ObjectStruct *Pnext;			       /* To next in chain. */
} ObjectStruct;

#define IS_UNDEF_OBJ(Obj)	((Obj)->ObjType == UNDEF_OBJ)
#define IS_GEOM_OBJ(Obj)	((Obj)->ObjType == GEOMETRIC_OBJ)
#define IS_NUM_OBJ(Obj)		((Obj)->ObjType == NUMERIC_OBJ)
#define IS_VEC_OBJ(Obj)		((Obj)->ObjType == VECTOR_OBJ)
#define IS_MAT_OBJ(Obj)		((Obj)->ObjType == MATRIX_OBJ)
#define IS_STR_OBJ(Obj)		((Obj)->ObjType == STRING_OBJ)
#define IS_OLST_OBJ(Obj)	((Obj)->ObjType == OBJ_LIST_OBJ)

/* Note the following is should be used only if the object is geometric! */
#define GET_OBJECT_COLOR(Obj)   ((int) ((Obj)->U.Attr[4]))
#define SET_OBJECT_COLOR(Obj, Value)   (((Obj)->U.Attr[4]) = Value)
#define	IS_POLYLINE_GEOM_OBJ(Obj)	((int) (Obj)->U.Attr[5])
#define	SET_POLYLINE_GEOM_OBJ(Obj)	((Obj)->U.Attr[5] = TRUE)
#define	RST_POLYLINE_GEOM_OBJ(Obj)	((Obj)->U.Attr[5] = FALSE)
#define COPY_GEOM_ATTRIB(Dest, Src)	memcpy(&(Dest)->U.Attr[4], \
					       &(Src)->U.Attr[4], 2);
/* Follows by general purpose helpfull macros: */

#define MIN(x, y)		((x) > (y) ? (y) : (x))
#define MAX(x, y)		((x) > (y) ? (x) : (y))
#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(x, y, type)	{ type temp = (x); (x) = (y); (y) = temp; }

#define APX_EQ(x, y)		(ABS(x - y) < EPSILON)
#define PT_EQ(Pt1, Pt2)		(APX_EQ(Pt1[0], Pt2[0]) && \
				 APX_EQ(Pt1[1], Pt2[1]) && \
				 APX_EQ(Pt1[2], Pt2[2]))

#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

#define PT_COPY(PtDest, PtSrc)	memcpy(PtDest, PtSrc, 3 * sizeof(RealType))
#define PLANE_COPY(PlDest, PlSrc) memcpy(PlDest, PlSrc, 4 * sizeof(RealType))
#define MAT_COPY(Dest, Src)	memcpy(Dest, Src, 16 * sizeof(RealType))
#define GEN_COPY(Dest, Src, Size) memcpy(Dest, Src, 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_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 DOT_PROD(Pt1, Pt2)	(Pt1[0] * Pt2[0] + \
				 Pt1[1] * Pt2[1] + \
				 Pt1[2] * Pt2[2])

#define DEG2RAD(Deg)		((Deg) * M_PI / 180.0)
#define RAD2DEG(Rad)		((Rad) * 180.0 / M_PI)


extern struct ObjectStruct *GlblObjList;	   /* All objects on system. */

extern jmp_buf LongJumpBuffer;		          /* Used in error recovery. */

extern FILE *LogFile;		   /* If do log everything, it goes to here. */

extern char CurrentWorkingDir[],       /* Save start CWD to recover on exit. */
	    *PrgmHeader, *CopyRight, *AuthorName,
	    *HelpFileName,
	    *StartFileName,		/* Name of startup file to executed. */
	    *LogFileName,				/* Name of log file. */
	    *EditPrgm;		/* Name of editor to execute (edit command). */

extern int MouseExists, GraphDriver, /* Graph driver kind & mouse existance. */
	   DelayConstant,		    /* Delay used in cursor display. */
	   GlblFatalError,	  /* True if disaster in system - must quit! */
	   PrintLogFile,	     /* If TRUE everything goes to log file. */
	   LoadColor,	      /* Default colors for object loaded using LOAD */
	   BoolColor,	      /* command, for boolean result objects or      */
	   ICrvColor,	      /* boolean intersection curves and for basic   */
	   PrimColor;	      /* primitives colors, respectively.	     */

void MyExit(int ExitCode);
void FatalError(char * ErrorMsg);
void DefaultFPEHandler(int Sig, int Type, int *RegList);

#endif	/* IRIT_H */
