/*------------------------------------------------------------------
			Geometry Include
			----------------

	This is the main Geometry include file. Any Geometry
	implementation should include this as it provides
	prototypes for all functions that must be implemented,
	important macros, usefull helper function prototypes
	and includes for any other relevent include files. Tools
	should also include this file in order to get at the
	Geometry code, although the helper functions are not
	relevent to them

	(C) Silicon Dream Ltd 1994

  ------------------------------------------------------------------

Changes:						Date:
* Created file						05/10/94
*/

#ifndef GEOMETRY
#define GEOMETRY

#include <windows.h>
#include <atomic.h>
#include <cppmaths.h>

/* Handle types. All types are compatible with type Handle */

typedef ulong Handle;			// han
typedef Handle HanCoorSys;		// hcsys
typedef Handle HanObject;		// hobj
typedef Handle HanPatch;		// hpat
typedef Handle HanVertex;		// hver
typedef Handle HanNormal;		// hnor
typedef Handle HanEdge;			// hedg
typedef Handle HanLight;		// hli
typedef Handle HanSurf;			// hsur

typedef enum HandleType{COORSYS_HANDLE,	// htype
			OBJECT_HANDLE,
			PATCH_HANDLE,
			VERTEX_HANDLE,
			NORMAL_HANDLE,
			SURFACE_HANDLE,
			LIGHT_HANDLE};

/* All Geometry and helper functions return the following */

typedef ulong GeomErr;			// gerr

/* Define the NULL handle. If an implementation uses handles as indexes then
   the indexes must be based at one */

#define NULL_HANDLE		((Handle) 0)

/* Top level coordinate system handle */

#define HCSYS_TOP		NULL_HANDLE

/* Define coordinate system types */

#define CT_LEFTHAND		16384
#define CT_RIGHTHAND		32768

/* usTransType values for ModCoorSys */

#define MCS_TRANS_LAST		0
#define MCS_TRANS_FIRST		1
#define MCS_REPLACE		2

/* Any implementation should not allow patches with greater number of edges
   than the following, as this will prevent tools and helper functions using
   static or local buffers on calls such as QryPatch, meaning that either the
   calling code or the geometry engine is forced to dynamically allocate the
   buffers all the time */

#define MAX_PATCH_EDGES		20

/* usFlags values for DefPatch and AddPatch */

#define DP_AUTOSMOOTH		1
#define DP_SMOOTH_BY_SURF	2
#define DP_SMOOTH_BY_ANGLE	4
#define DP_DONT_VALIDATE	8
#define DP_CONVEX		16
#define DP_ATTEMPT_TO_FIX_PLANE	32

#pragma pack(2)		// ushorts should be word NOT dword aligned

typedef struct Colourtag		// col
	{
	byte			byRed;		// Red component
	byte			byGrn;		// Green component
	byte			byBlu;		// Blue component
	} Colour;

typedef struct ViewParamstag		// vp
	{
	float			fAngX;		// Horizontal view angle
	float			fAngY;		// Vertical view angle
	float			fClipFront;	// Z depth of the front clipping plane
	float			fClipBack;	// Z depth of the back clipping plane
	ushort			usResX;		// X resolution of the bitmap
	ushort			usResY;		// Y resolution of the bitmap
	} ViewParams;

typedef struct VertInfotag		// vi
	{
	Vec			vec;		// Vertex position
	ulong			ulNumPatches;	// Number of patches using vertex
	ulong			ulRef;		// Reference to first patch (used for QryVertPatch)
	float			fScrnX;		// Last screen X coor rendered
	float			fScrnY;		// Last screen Y coor rendered
	ulong			ulUser;		// User data
	HanVertex		hverNext;	// Handle to next vertex in object
	} VertInfo;

typedef struct NormInfotag		// ni
	{
	Vec			vec;		// Normal direction
	ulong			ulUser;		// User data
	HanNormal		hnorNext;	// Handle to next normal in object
	} NormInfo;

#define PI_FLAT			1
#define PI_VISIBLE		2

typedef struct PatchInfotag		// pi
	{
	ushort			usNumEdges;	// Number of edges (verts and norms)
	ushort			usFlags;	// Patch flag values (PI_ values)
	HanSurf			hsur;		// Surface handle
	HanVertex		*ahver;		// Ptr to an array of vertex handles
	HanNormal		*ahnor;		// Ptr to an array of normal handles
	Vec			vecNorm;	// Normal of plane of patch
	ulong			ulUser;		// User data
	HanPatch		hpatNext;	// Handle to next patch in object
	} PatchInfo;

typedef struct EdgeInfotag		// ei
	{
	HanVertex		hverA;		// Handle to vertex at one endpoint
	HanVertex		hverB;		// Handle to vertex at other endpoint
	HanPatch		hpatAB;		// Handle to patch using endpoints A to B
	HanPatch		hpatBA;		// Handle to patch using endpoints B to A
	HanEdge			hedgNext;	// Handle to next edge in object
	} EdgeInfo;

typedef struct ObjectInfotag		// oi
	{
	ulong			ulNumVerts;	// Number of verticies used by object
	ulong			ulNumNorms;	// Number of normals used by object
	ulong			ulNumPatches;	// Number of patches used by object
	ulong			ulNumEdges;	// Number of edges used by object
	float			fNewVertTol;	// Indication of how close verticies can be
	ulong			ulMemUsed;	// Total memory used by object (in bytes)
	ushort			usCoorType;	// Coor type of object (CT_* value)
	HanCoorSys		hcsys;		// Coor system object belongs to
	HanVertex		hverFirst;	// Handle to first vertex
	HanNormal		hnorFirst;	// Handle to first normal
	HanPatch		hpatFirst;	// Handle to first patch
	HanEdge			hedgFirst;	// Handle to first edge
	ulong			ulUser;		// User data
	HanObject		hobjNext;	// Handle to next object in coor system
	} ObjectInfo;

typedef struct CoorSysInfotag		// csi
	{
	ushort			usType;		// Coordinate system type (CT_* value)
	Mat			matToParent;	// Our position relative to parent
	Mat			matFromParent;	// Parents position relative to us
	HanCoorSys		hcsysParent;	// Handle to parent coordinate system
	HanCoorSys		hcsysNext;	// Handle to next sibling coordinate system
	HanCoorSys		hcsysFirstChild;// Handle to first child coordinate system
	HanLight		hliFirst;	// Handle to first light in coordinate system
	HanObject		hobjFirst;	// Handle to first object in coordinate system
	ulong			ulUser;		// User data
	} CoorSysInfo;

#define LI_DIRECTIONAL		1
#define LI_DIMINISHING		2

typedef struct LightDeftag		// ld
	{
	Vec			vecPos;		// Light position
	Vec			vecDir;		// Direction of light
	ushort			usFlags;	// Flags (LI_* values)
	float			fInt;		// Intensity (0.0 - 1.0)
	float			fAng;		// Angle of spread of light
	Colour			col;		// Colour of light
	float			fHalfIntDist;	// Distance over which light int halves
	HanCoorSys		hcsys;		// Coor system light belongs to
	ulong			ulUser;		// User data
	HanLight		hliNext;	// Handle to next light in coor system
	} LightDef;

/* Surface type flags */

#define DS_TEXTURE		1
#define DS_RECURSIVE_TEXTURE	2
#define DS_TILE_TEXTURE		4
#define DS_BUMPED		8
#define DS_ALL			(DS_TEXTURE | DS_RECURSIVE_TEXTURE | DS_TILE_TEXTURE | DS_BUMPED)

/* Specular reflection characteristic type */

#define SRC_DULL		0
#define SRC_ROCK		SRC_DULL	// All these do not have
#define SRC_RUBBER		SRC_DULL	// specular reflections
#define SRC_WOOD		SRC_DULL	// and are therefore the
#define SRC_FABRIC		SRC_DULL	// same as SRC_DULL
#define SRC_CONSTANT		1
#define SRC_LINEAR		2
#define SRC_SILVER		3
#define SRC_GOLD		4
#define SRC_GLASS		5
#define SRC_BRASS		6
#define SRC_COPPER		7
#define SRC_ALUMINIUM		8
#define SRC_IRON		9
#define SRC_PLASTIC		10
#define SRC_WATER		11
#define SRC_CHINA		12
#define SRC_LEATHER		13
#define SRC_SILK		14
#define SRC_100PCT_GLOSS	15
#define SRC_75PCT_GLOSS		16
#define SRC_50PCT_GLOSS		17
#define SRC_25PCT_GLOSS		18

/* Handle used to represent see through indexes in recursive textures */

#define HSUR_SEE_THROUGH	((Handle) ULONG_MAX)

typedef struct SurfTypetag		// st
	{
	Colour			col;		// Basic RGB colour
	ushort			usFlags;	// Flags (DS_* values)
	ushort			usSpecRefChar;	// Specifies specular reflection characteristics
	float			fShineCoef;	// Degree of 'polishedness' (0.0 - 1.0)
	float			fTransCoef;	// Degree of 'see throughness' (0.0 - 1.0)
	HanCoorSys		hcsysTex;	// Coor system texture is placed in
	Mat			matTex;		// Orientation within coor sys of texture bitmap
	HanSurf			hsurSurf0;	// Surface showing for pixel value 0
	HanSurf			hsurSurf1;	// Surface showing for pixel value 1
	HanSurf			hsurSurf2;	// Surface showing for pixel value 2
	HanSurf			hsurSurf3;	// Surface showing for pixel value 3
	float			fBumpHeight;	// Maximum height of bump mapping
	ulong			ulUser;		// User data
	HanSurf			hsurNext;	// Handle to next surface
	char			szFNTex[128];	// Texture filename
	} SurfType;

#pragma pack()

/* Geometry function prototypes */

#define LSREPORT_LOADING		0
#define LSREPORT_SAVING			1
#define LSREPORT_POLYGONS		2
extern "C"
	{
	typedef void fnLoadSaveCallback (ulong ulNumBytes, ushort usReportType);
	typedef void fnDelCallback (Handle han, HandleType htype, ulong ulUser);
	}

GeomErr _dyn GetErrorText (GeomErr gerr, char *szBuff, ushort usBuffSize);
GeomErr _dyn Initialise (void);
GeomErr _dyn Terminate (void);
GeomErr _dyn AddCoorSys (HanCoorSys hcsysParent, Mat const &matToParent, Mat const &matFromParent,
			 ushort usType, HanCoorSys *phcsys);
GeomErr _dyn DelCoorSys (HanCoorSys hcsys);
GeomErr _dyn QryCoorSys (HanCoorSys hcsys, CoorSysInfo *pcsi);
GeomErr _dyn ModCoorSys (HanCoorSys hcsys, Mat const &matToParent, Mat const &matFromParent,
			 ushort usTransType, ushort usNewType);
GeomErr _dyn SetCamera (HanCoorSys hcsys, Vec const &vecPos, Vec const &vecDir, Vec const &vecUp,
			ViewParams *pvp);
GeomErr _dyn AddObject (HanCoorSys hcsys, float fNewVertTol, HanObject *phobj);
GeomErr _dyn DelObject (HanObject hobj);
GeomErr _dyn QryObject (HanObject hobj, ObjectInfo *poi);
GeomErr _dyn MoveObject (HanObject hobj, Vec const &vec);
GeomErr _dyn ScaleObject (HanObject hobj, float fScale);
GeomErr _dyn PrtObject (HanObject hobj);
GeomErr _dyn AddVertex (HanObject hobj, Vec const &vec, HanVertex *phver);
GeomErr _dyn DelVertex (HanObject hobj, HanVertex hver);
GeomErr _dyn QryVertex (HanObject hobj, HanVertex hver, VertInfo *pvi);
GeomErr _dyn ModVertex (HanObject hobj, HanVertex hver, Vec const &vec);
GeomErr _dyn AddNormal (HanObject hobj, Vec const &vec, HanNormal *phnor);
GeomErr _dyn DelNormal (HanObject hobj, HanNormal hnor);
GeomErr _dyn QryNormal (HanObject hobj, HanNormal hnor, NormInfo *pni);
GeomErr _dyn ModNormal (HanObject hobj, HanNormal hnor, Vec const &vec);
GeomErr _dyn QryEdge (HanObject hobj, HanEdge hedg, EdgeInfo *pei);
GeomErr _dyn AddLight (HanCoorSys hcsys, LightDef *pld, HanLight *phli);
GeomErr _dyn DelLight (HanLight hli);
GeomErr _dyn QryLight (HanLight hli, LightDef *pld);
GeomErr _dyn ModLight (HanLight hli, LightDef *pld);
GeomErr _dyn SetAmbient (float fInt);
GeomErr _dyn DefPatch (HanObject hobj, ushort usNumEdges, ushort usFlags, float fSmoothAng,
		       HanVertex *ahver, HanNormal *ahnor, HanSurf hsur, ushort *pusNumPats,
		       HanPatch *ahpat);
GeomErr _dyn DelPatch (HanObject hobj, HanPatch hpat);
GeomErr _dyn QryPatch (HanObject hobj, HanPatch hpat, PatchInfo *ppi);
GeomErr _dyn ModPatchSurf (HanObject hobj, HanPatch hpat, HanSurf hsur);
GeomErr _dyn QryVertPatch (ulong *pulRef, HanPatch *phpat);
GeomErr _dyn DeleteRenBitmap (BITMAPINFO *pbmi);
GeomErr _dyn Render (BITMAPINFO **ppbmi);
GeomErr _dyn UpdateImage (ulong ulHDC, BITMAPINFO *pbmi, ushort usX, ushort usY);
GeomErr _dyn DefSurfType (SurfType *pst, bool bReuse, HanSurf *phsur);
GeomErr _dyn DelSurfType (HanSurf hsur);
GeomErr _dyn QrySurfType (HanSurf hsur, SurfType *pst, BITMAPINFOHEADER *pbmih,
			  ulong *pulNumPats);
GeomErr _dyn GetFirstSurfType (HanSurf *phsur);
GeomErr _dyn SetUserData (Handle han, HandleType htype, ulong ulUser);
GeomErr _dyn SetDelCallback (fnDelCallback *DelCallback);
GeomErr _dyn ModSurfType (HanSurf hsur, SurfType *pst);
GeomErr _dyn Get3DLine (HanCoorSys hcsys, Vec const &vecA, Vec const &vecB,
			float *pfStartX, float *pfStartY, float *pfEndX, float *pfEndY);
GeomErr _dyn Get3DPoint (HanCoorSys hcsys, Vec const &vec, float *pfX, float *pfY);
GeomErr _dyn SaveScene (HFILE hfile, HanCoorSys hcsys,
			ulong *pulNumCSys, HanCoorSys *ahcsys,
			ulong *pulNumObjs, HanObject *ahobj,
			fnLoadSaveCallback *Report);
GeomErr _dyn LoadScene (HFILE hfile, HanCoorSys hcsysParent, char *szTexPath,
			ulong *pulNumCSys, HanCoorSys *ahcsys,
			ulong *pulNumObjs, HanObject *ahobj,
			fnLoadSaveCallback *Report);
GeomErr _dyn LoadLWObject (HFILE hfile, HanCoorSys hcsys,
			   char *szTexPath, HanObject *phobj,
			   fnLoadSaveCallback *Report);

/* Standard error values */

#define GERR_OK				0L
#define GERR_BASE			0x1000000
#define GERR_COINCIDENT_POINTS		(GERR_BASE+0)
#define GERR_THIN_SEGMENT		(GERR_BASE+1)
#define GERR_NOT_ON_PLANE		(GERR_BASE+2)
#define GERR_OUT_OF_MEMORY		(GERR_BASE+3)
#define GERR_BUFFER_TOO_SMALL		(GERR_BASE+4)
#define GERR_NOT_ENOUGH_POINTS		(GERR_BASE+5)
#define GERR_IN_USE			(GERR_BASE+6)
#define GERR_CANT_SET_CAM_IN_TOP	(GERR_BASE+7)
#define GERR_INVALID_LIGHT_INT		(GERR_BASE+8)
#define GERR_TOO_MANY_SURFACE_TYPES	(GERR_BASE+9)
#define GERR_BITMAP_FILE_NOT_FOUND	(GERR_BASE+10)
#define GERR_NOT_A_BMP_FILE		(GERR_BASE+11)
#define GERR_IMAGE_SIZE_NOT_MULT_4	(GERR_BASE+12)
#define GERR_NOT_VISIBLE		(GERR_BASE+13)
#define GERR_TOO_MANY_BITMAPS		(GERR_BASE+14)
#define GERR_BITMAP_TOO_SMALL		(GERR_BASE+15)
#define GERR_INVALID_HANDLE		(GERR_BASE+16)
#define GERR_GEOMETRY_DIDNT_CREATE_BMP	(GERR_BASE+17)
#define GERR_INT_PROCESSING_ERROR	(GERR_BASE+18)
#define GERR_INVALID_GEN_FILE		(GERR_BASE+19)
#define GERR_INVALID_OPP_IN_TOP		(GERR_BASE+20)
#define GERR_INVALID_LIGHT_ANG		(GERR_BASE+21)
#define GERR_INVALID_IFF_FILE		(GERR_BASE+22)
#define GERR_NO_FORM_CHUNK		(GERR_BASE+23)
#define GERR_NO_LWOB_FORM		(GERR_BASE+24)
#define GERR_INVALID_PNTS_CHUNK		(GERR_BASE+25)
#define GERR_INVALID_SRFS_CHUNK		(GERR_BASE+26)
#define GERR_INVALID_POLS_CHUNK		(GERR_BASE+27)
#define GERR_INVALID_SURF_CHUNK		(GERR_BASE+28)
#define GERR_INVALID_COLR_CHUNK		(GERR_BASE+29)
#define GERR_INVALID_FLAG_CHUNK		(GERR_BASE+30)
#define GERR_INVALID_SPEC_CHUNK		(GERR_BASE+31)
#define GERR_INVALID_TRAN_CHUNK		(GERR_BASE+32)
#define GERR_INVALID_GLOS_CHUNK		(GERR_BASE+33)
#define GERR_INVALID_XTEX_CHUNK		(GERR_BASE+34)
#define GERR_INVALID_TFLG_CHUNK		(GERR_BASE+35)
#define GERR_INVALID_TSIZ_CHUNK		(GERR_BASE+36)
#define GERR_INVALID_TCTR_CHUNK		(GERR_BASE+37)
#define GERR_INVALID_TAMP_CHUNK		(GERR_BASE+38)
#define GERR_COMPLEX_OUTLINE		(GERR_BASE+39)
#define GERR_TEXTURE_FILE_NOT_FOUND	(GERR_BASE+40)
#define GERR_CANT_CHANGE_TYPE		(GERR_BASE+41)
#define GERR_VISIBLE_FRONT_CLIP		(GERR_BASE+42)
#define GERR_UNKNOWN_ERROR		(GERR_BASE+500)

/*********************************** Helper section ***********************************/

/* usType values for ExtractVecs */

#define EV_NORMS		0
#define EV_VERTS		1

/* usFlags values for ValidPatch */

#define VP_CHECK_THIN_SEGMENT	1
#define VP_CHECK_ON_PLANE	2

/* usFlag values for CompNormal (CT_* values can also be used) */

#define CN_DIRECTION_IMPORTANT	1
#define CN_CONVEX		2

/* usFlags values for Split */

#define SP_SUPPORT_CONCAVE	1
#define SP_RETURN_INDEX		2

/* usFlags for Autosmooth are the DP_SMOOTH_* flags */

typedef struct ASUndoBufftag		// asub
	{
	HanObject		hobj;
	ushort			usNew;
	ushort			usMod;
	HanNormal		*ahnorNew;
	HanNormal		*ahnorMod;
	Vec			*avecMod;
	} ASUndoBuff;

/* Helper functions */

#define Gerr(x) RegisterError((GeomErr) x, __FILE__, __LINE__)
GeomErr RegisterError (GeomErr gerrIn, char *szFNIn, ushort usLineIn);

GeomErr GetHlpErrorText (GeomErr gerr, char *szBuff, ushort usBuffSize);
GeomErr ValidPatch (Vec *avec, ushort usNumVecs, ushort usFlags);
GeomErr ExtractVecs (HanObject hobj, ushort usType, Handle *ahan, ushort usNum, Vec **pavec);
GeomErr CompNormal (Vec *avec, ushort usNumVecs, ushort usFlags, Vec *pvecNorm);
GeomErr Split (Vec *avecMain, ushort usNumMainVecs,
	       ushort usMaxPerPatch, ushort usFlags,
	       ushort *pusNumSets, void **apvSets, ushort *ausNumInSets);
GeomErr Autosmooth (HanObject hobj, HanVertex *ahver, ushort usNumVerts, Vec &vecNorm,
		    ushort usFlags, HanSurf hsur, float fSmoothAng, HanNormal *ahnor,
		    ASUndoBuff *pasub);
GeomErr CommitAS (ASUndoBuff *pasub);
GeomErr UndoAS (ASUndoBuff *pasub);
GeomErr LoadBmp (char *szFN, BITMAPINFO **ppbmi);
GeomErr SaveSceneHlp (HFILE hfile, HanCoorSys hcsys,
		      ulong *pulNumCSys, HanCoorSys *ahcsys,
		      ulong *pulNumObjs, HanObject *ahobj,
		      fnLoadSaveCallback *Report);
GeomErr LoadSceneHlp (HFILE hfile, HanCoorSys hcsysParent, char *szTexPath,
		      ulong *pulNumCSys, HanCoorSys *ahcsys,
		      ulong *pulNumObjs, HanObject *ahobj,
		      fnLoadSaveCallback *Report);
GeomErr LoadLWObjectHlp (HFILE hfile, HanCoorSys hcsys,
			 char *szTexPath, HanObject *phobj,
			 fnLoadSaveCallback *Report);
#endif
