/* t3dlib.h - definitions needed to interface to TTDDD library
 *          - written by Glenn M. Lewis - 7/19/91
 * $Id: t3dlib.h,v 1.26 1994/01/20 22:14:52 glewis Exp $
 */

#ifdef AMIGA

#ifdef _M68881
#include <m68881.h>
#endif

/* The following has been tested using SAS/C on an Amiga by Helge Rasmussen */
#ifdef __SASC
#include <string.h>
#include <stdlib.h>
#include <exec/types.h>
#else
#define  bcopy(s,d,n)	(void)memcpy((d),(s),(n))
#define  bzero(d,n)		(void)memset((d),0,(n))
#define  bcmp(b1,b2,n)	memcmp((b1),(b2),(n))
#define  index			strchr
#define  rindex			strrchr
#endif

#else

#include <strings.h>
#include <malloc.h>
char *calloc();

#endif

#ifdef SYSV
extern char *memcpy(), *memset();
#define bcopy(s,d,n)	(void)memcpy((d),(s),(n))
#define bzero(d,n)		(void)memset((d),0,(n))
#define bcmp(b1,b2,n)	memcmp((b1),(b2),(n))
#define index			strchr
#define rindex			strrchr
#endif

#ifndef AMIGA
#ifndef UBYTE
#define UBYTE unsigned char
#endif
#ifndef BYTE
#define BYTE char
#endif

#ifndef UWORD
#define UWORD unsigned short
#endif
#ifndef WORD
#define WORD short
#endif

#ifndef ULONG
#define ULONG unsigned long
#endif
#ifndef LONG
#define LONG long
#endif
#endif

#ifndef FRACT
#define FRACT double
#endif

typedef struct { double x,y,z; } XYZ_st;	/* Used to be val[3] */
typedef struct { UBYTE r,g,b;  } RGB_st;	/* Used to be val[3] */
typedef struct { XYZ_st came, rota; double foca; } OBSV;
typedef struct { double at, by; RGB_st to; } FADE;
typedef struct { RGB_st hori, zeni; } SKYC;
typedef char BRSH[81];
typedef struct { XYZ_st tran, scal, rota1, rota2, rota3; } MTRX;
typedef struct { XYZ_st xaxi, yaxi, zaxi; } AXIS;
typedef struct { char path[19]; XYZ_st tran, rota, scal; UWORD info; } STRY;
typedef struct {
	MTRX mtrx;
	char filename[81];
} EXTR;
typedef struct {
	UBYTE type;
	float indx;
} MTTR;
struct OBJECT {
	EXTR *extr;	/* Either EXTR or DESC */
	struct DESC *desc;
	struct OBJECT *parent;	/* whose child this OBJECT is */
	struct OBJECT *child;	/* children of this OBJECT - not for EXTR */
	struct OBJECT *next;	/* At this level in the hierarchy */
	void *user;		/* User-defined data for any purpose */
};
typedef struct OBJECT OBJECT;
typedef struct {
	UWORD num;
	UBYTE *eflg;
} EFLG;
struct FGRP {
	struct FGRP *next;	/* Linked list */
	UWORD num;
	char name[19];	/* 18 allowed in file */
	UWORD *face;
};
typedef struct FGRP FGRP;
typedef struct {
    UWORD  Flags;
	MTRX   TAxis;
	double Params[16];
	UBYTE  PFlags[16];
	UBYTE  SubName[81];
	UBYTE  Length;
	UBYTE  Name[81];
} TXT2;
typedef struct DESC {
	char name[19];
	WORD *shap;
	XYZ_st *posi;
	AXIS *axis;
	XYZ_st *size;
	XYZ_st *pnts;
	RGB_st *colr, *refl, *tran, *spc1;
	UWORD *edge, *face, pcount, ecount, fcount; 
	UBYTE *clst, *rlst, *tlst;
	double *tpar;
	UBYTE *surf;
	MTTR  *mttr;
	UBYTE *spec;
	UBYTE *prp0, *prp1;
	double *ints;
	XYZ_st *int1;
	STRY *stry;
	FGRP *fgrp;
	EFLG *eflg;
	TXT2 *txt2[4];
} DESC;

/* extern UBYTE defclst[3], defrlst[3], deftlst[3], defspc1[3]; */

/* Add staging file information for Imagine support */
/* It appears that the staging files use 3 FRACT's to represent colors
 * instead of 3 UBYTEs...  Hmmm...
 */

struct SAXIS { struct SAXIS *next, *prev; UWORD flags, start, stop; };
typedef struct SAXIS SAXIS;

struct GLB2 {
	struct GLB2 *next, *prev;
	UWORD flags, start, stop;
	ULONG sky_blending;
	double starfield;
	ULONG transition;
	/* The following are really colors */
	XYZ_st ambient, horizon, zenith1, zenith2, fog_color;
	double fog_bottom, fog_top, fog_length;
	ULONG brush_seq, backdrop_seq;
	char backdrop[256];			/* Fixed length */
	char globalbrush[256];		/* Variable length */
};
typedef struct GLB2 GLB2;

struct LITE {
	struct LITE *next, *prev;
	UWORD flags, start, stop;
	/* The following are really colors */
	XYZ_st color;
	ULONG transition;
};
typedef struct LITE LITE;

struct SFILE {
	struct SFILE *next, *prev;
	UWORD flags, start, stop;
	double cycles_to_perform;
	double initial_cycle_phase;
	ULONG transition;
	char object_description[256];	/* Variable length */
};
typedef struct SFILE SFILE;

struct OSIZ { struct OSIZ *next,*prev; UWORD flags, start, stop; XYZ_st size; };
typedef struct OSIZ OSIZ;	/* Size */

struct POSN { struct POSN *next,*prev; UWORD flags, start, stop; XYZ_st posn; };
typedef struct POSN POSN;	/* Position */

struct ALGN { struct ALGN *next,*prev; UWORD flags, start, stop; XYZ_st algn; };
typedef struct ALGN ALGN;	/* Alignment */

struct PALN { struct PALN *next,*prev; UWORD flags, start, stop; };
typedef struct PALN PALN;		/* Path Alignment */

struct PTH2 {
	struct PTH2 *next, *prev;
	UWORD flags, start, stop;
	ULONG acceleration_frames;
	double start_speed;
	ULONG deacceleration_frames;
	double end_speed;
	char path[256];				/* Variable length */
};
typedef struct PTH2 PTH2;		/* Follow Path */

struct TALN {
	struct TALN *next, *prev;
	UWORD flags, start, stop;
	double initial_y, final_y;
	char trackobj[256];			/* Variable length */
};
typedef struct TALN TALN;	/* Track alignment */

struct HING {
	struct HING *next, *prev;
	UWORD flags, start, stop;
	char hingeobj[256];			/* Variable length */
};
typedef struct HING HING;	/* Hinge */

struct SOBJ {
	struct SOBJ *next, *prev;
	/* Required subchunks in the SOBJ chunk... */
	char name[18];	/* CHUNK: Name, fixed=18 */
	UWORD stgf;		/* CHUNK: always zero? */
	/* Possible subchunks in the SOBJ chunk... */
	OSIZ *osiz;		/* Size */
	POSN *posn;		/* Position */
	ALGN *algn;		/* Alignment */
	PALN *paln;		/* Path Alignment */
	TALN *taln;		/* Track Alignment */
	PTH2 *pth2;		/* Follow Path */
	GLB2 *glb2;		/* Globals */
	SAXIS *axis;	/* Stagefile AXIS */
	LITE *lite;		/* Light */
	HING *hing;		/* Hinge */
	SFILE *file;	/* Stage file */
};
typedef struct SOBJ SOBJ;

typedef struct {
	UWORD maxf;
	/* Just so we don't have to search through the doubly-linked list */
	/* every time we wish to add to the tail, keep a pointer to head&tail */
	SOBJ *head, *tail;
} ISTG;

/* Back to old Turbo Silver stuff... */

#define STNC BRSH
#define TXTR BRSH
typedef struct {
	BRSH brsh[8];
	STNC stnc[8];
	TXTR txtr[8];
	OBSV *obsv;
	BYTE otrk[19];
	STRY *ostr;
	FADE *fade;
	SKYC *skyc;
	RGB_st *ambi;
	BYTE *glb0;
} INFO;

typedef struct {
	INFO *info;			/* The INFO description in the file */
	ISTG *istg;			/* Imagine staging file */
	OBJECT *object;		/* The first object in the world */
	void *user;		/* User-defined data for any purpose */
	/* Some private variables needed to parse input file - don't touch! */
	int num_OBJ, num_DESC, num_TOBJ, cur_line;
	FILE *inp;
	OBJECT *curobj;
} WORLD;

typedef struct {
	double minx, maxx, miny, maxy, minz, maxz;
} MBB;

#ifdef __STDC__
#define P0()			void
#define P1(a)			a
#define P2(a,b)			a,b
#define P3(a,b,c)		a,b,c
#define P4(a,b,c,d)		a,b,c,d
#define P5(a,b,c,d,e)	a,b,c,d,e
#else
#define P0()		
#define P1(a)		
#define P2(a,b)		
#define P3(a,b,c)	
#define P4(a,b,c,d)	
#define P5(a,b,c,d,e)	
#endif

WORLD *read_World(P1(FILE*));			/* world = read_World(FILE *); ..figures out format */
WORLD *free_World(P1(WORLD*));			/* world = free_World(world *);   ...frees a WORLD* */
void merge_World(P1(WORLD*));			/* merge_World(world *); ..optimizes points & edges */
WORLD *read_TTDDD(P1(FILE*));			/* world = read_TTDDD(FILE *);      ...0 on failure */
WORLD *read_TDDD(P1(FILE*));			/* world = read_TDDD(FILE *);       ...0 on failure */
WORLD *read_LWOB(P1(FILE*));			/* world = read_LWOB(FILE *);       ...0 on failure */
WORLD *read_ISTG(P1(FILE*));			/* world = read_ISTG(FILE *);       ...0 on failure */
int write_TTDDD(P2(WORLD*,FILE*));		/* write_TTDDD(world *, FILE *);    ...0 on failure */
int write_TDDD(P2(WORLD*,FILE*));		/* write_TDDD(world *, FILE *);     ...0 on failure */
int write_Rayshade(P2(WORLD*,FILE*));	/* write_Rayshade(world *, FILE *); ...0 on failure */
int write_PostScript(P3(WORLD*,FILE*,int));	/* write_PostScript(world *, FILE *, view); ..ditto */
int write_MIF(P3(WORLD*,FILE*,int));	/* write_MIF(world *, FILE *, view); ..0 on failure */
void calculate_MBB_world(P1(WORLD*));	/* calculate_MBB_world(WORLD *); */
void calculate_MBB(P1(OBJECT*));		/* calculate_MBB(OBJECT *); */
OBJECT *linear_morph(P3(OBJECT*,OBJECT*,double));	/* linear_morph(obj1, obj2, time); /* 0.0<=time<=1.0 */
OBJECT *create_object(P0());			/* p = create_object(); */
OBJECT *free_object(P1(OBJECT*));		/* from freeworld.c */
int count_objects(P2(OBJECT*,OBJECT**));	/* Used by "morph()" */
int morph(P5(WORLD*,WORLD*,int,char*,OBJECT*(*func)()));	/* morph(world1, world2, num, name, morph_function); */
void free_desc(P1(DESC*));				/* free_desc(DESC *); */
void match_points(P3(int,OBJECT*,OBJECT*));	/* match_points(numpoints, obj1, obj2); */
void sort_points(P2(DESC*,int(*cmp)()));
int cmpXYZ(P2(XYZ_st*,XYZ_st*));		/* comparison for sort_points */
void move_extr(P2(OBJECT*,MTRX*));
void OUT_MEM(P1(char*));
void load_staging_frame_objects(P2(WORLD*,int));	/* (world, frame); load a frame's objects */
int write_OFF(P4(WORLD*,char*,int,int));
int write_NFF(P2(WORLD*,FILE*));
int write_DXF(P2(WORLD*,FILE*));
int write_POVRay(P2(WORLD*,FILE*));
int write_Vort(P2(WORLD*,FILE*));
int write_LWOB(P2(WORLD*,FILE*));

/* Some stuff for PostScript and MIF output */
extern double XSIZE, YSIZE;	/* (in inches) Default: 8.5x11.0 */

#define VIEW_TOP	0	/* eye at (0,0,+inf) */
#define VIEW_FRONT	1	/* eye at (0,-inf,0) */
#define VIEW_ISO	2	/* eye at (+inf,-inf,+inf) */
#define VIEW_RIGHT	3	/* eye at (+inf,0,0) */
#define VIEW_ALL_FOUR 4	/* Place all on the same page */
