/* patch.h: PATCH structure and some routines to operate on patches. */

#ifndef _PATCH_H_
#define _PATCH_H_ 

#include "color.h"
#include "point.h"
#include "vector.h"
#include "vertex.h"
#include "surface.h"
#include "interactionlist.h"
#include "bounds.h"
#include "tvertelim.h"
#include "jacobian.h"
#include "basis.h"

#define PATCHMAXVERTICES 4	/* max. 4 vertices per patch */

typedef struct PATCH {
	int 	id;		/* identification number for debugging ... */
	struct  VERTEX	*vertex[PATCHMAXVERTICES];	/* pointers to the vertices */
	struct 	SURFACE	*surface;	/* pointer to surface data (contains vertexlist, material properties ... */
	struct  COLOR	*radiance, *unshot_radiance, *received_radiance,
	                *importance, *unshot_importance, *received_importance;
	                                /* the number of coefficients depends on the basis being used on the patch */
	float	direct_importance;	/* needed for incremental update of directly received importance after a change of viewing parameters */
	struct 	INTERACTIONLIST	*interactions;	/* links and formfactors */
	int	nrinteractions;     	/* the number of interactions */
	struct	PATCHLIST *subpatches;	/* subpatches after refinement */
	struct	PATCH	*parent;	/* pointer to parent patch */
	struct  TPATCHLIST *Tpatches;	/* for T-vertex elimination */
	struct  VECTOR 	norm;		/* Normal to polygon */
	struct 	POINT	midpoint;	/* midpoint of patch */
	float 	d;			/* patch plane constant */
	float  	area;			/* surface area */
	struct 	JACOBIAN *jacobian;	/* jacobian */
	struct 	BASIS	*basis;		/* basisfunctions to be used on the patch */
	Float	*inverse_overlap;	/* inverse of the basis overlap
					 * matrix on the patch, needed
					 * for renormalisation of
					 * received radiance on irregular
					 * patches. */
	float	*bounds;		/* bounding box for raycasting acceleration */
	char	nrvertices;		/* nr of verticles: 3 or 4 */
	char	twosided;		/* TRUE if the patch is twosided */
	char 	index;			/* Which normal coord is "dominant"? */
	char	interactionscreated;	/* TRUE if the interactions with the other toplevel patches have been created */
	char	updated;		/* flag indicating whether or not the vertex colors need to be recomputed */
	char	reserved[3];
} PATCH; 

#include <stdio.h>
#include "ray.h"
#include "patchlist.h"

/* allocates memory, computes area, jacobian, links the vertices ... */
extern PATCH *PatchCreate(int nrvertices, struct VERTEX *v1, struct VERTEX *v2, struct VERTEX *v3, struct VERTEX *v4, int twosided);

/* disposes the memory allocated for the patch, unlinks vertices ... */
extern void PatchDestroy(PATCH *patch);

/* for debugging */
extern void PatchPrint(FILE *out, PATCH *patch);
extern void PatchPrintID(FILE *out, PATCH *patch);

/* ray-patch intersection test, for computing formfactors, creating raycast 
 * images ... */
extern PATCH *PatchIntersect(PATCH *patch, RAY *ray, float mindist, float *maxdist);

/* returns a bounding box for the patch */
extern float *PatchBounds(PATCH *patch, float *bounds);

/* given the parameters (u,v) for a point on the patch, computes the 
 * coordinates of the point in 3D space */
extern POINT *PatchPoint(PATCH *patch, float u, float v, POINT *point);

/* computes (u,v) parameters of the point on the patch */
extern void PatchUV(PATCH *poly, POINT *point, float *u, float *v);

/* subdivides the patch for hierarchical refinement - we do regular
 * subdivision */
extern struct PATCHLIST *PatchRefine(PATCH *patch);

/* returns a pointer to the patch on top of the hierarchy */
extern PATCH *ToplevelPatch(PATCH *patch);

/* returns a pointer to the lowest level subpatch of the patch at the 
 * point with given parameters. u and v are replaced with the parameters
 * of the same point on the lowest level patch. */
extern PATCH *LowestLevelPatch(PATCH *patch, float *u, float *v);

/* returns the index of the vertex in the patches vertex list */
extern int PatchWhichVertex(PATCH *patch, struct VERTEX *vertex);

/* for statistics, loading a new scene ... */
extern int GetNumberOfElements(void);
extern void PatchSetNextID(int id);
extern int PatchGetNextID(void);

#endif /*_PATCH_H_*/
