/* galerkinP.h: Galerkin Radisoity "private" declarations */

#ifndef _GALERKINP_H_
#define _GALERKINP_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>
#include "mymath.h"
#include "color.h"
#include "cubature.h"
#include "element.h"
#include "../SGL/sgl_context.h"

/* the Galerkin specifix data for a patch is its toplevel element. The
 * ELEMENT structure is defined in element.h. */

/* to save typing work: */
#define RADIANCE(patch) ((ELEMENT *)(patch->radiance_data))->radiance[0]
#define RECEIVED_RADIANCE(patch) ((ELEMENT *)(patch->radiance_data))->received_radiance[0]
#define UNSHOT_RADIANCE(patch) ((ELEMENT *)(patch->radiance_data))->unshot_radiance[0]
#define POTENTIAL(patch) ((ELEMENT *)(patch->radiance_data))->potential
#define UNSHOT_POTENTIAL(patch) ((ELEMENT *)(patch->radiance_data))->unshot_potential
#define RECEIVED_POTENTIAL(patch) ((ELEMENT *)(patch->radiance_data))->received_potential
#define FLUX(patch) ((ELEMENT *)(patch->radiance_data))->flux[0]
#define SELFEMITTED_RADIANCE(patch) ((ELEMENT *)(patch->radiance_data))->Ed
#define REFLECTIVITY(patch) ((ELEMENT *)(patch->radiance_data))->Rd
#define TOPLEVEL_ELEMENT(patch) ((ELEMENT *)(patch->radiance_data))
#define FLAGS(patch) ((ELEMENT *)(patch->radiance_data))->flags

/* Galerkin Radiosisty "state" information */
typedef enum {JACOBI, GAUSS_SEIDEL, SOUTHWELL} ITERATION_METHOD;

typedef enum {ALWAYS_DO_SHAFTCULLING, NEVER_DO_SHAFTCULLING, DO_SHAFTCULLING_FOR_REFINEMENT} SHAFTCULLMODE;

typedef enum {DEGREE_1, DEGREE_2, DEGREE_3, DEGREE_4, DEGREE_5, DEGREE_6, DEGREE_7,
	      DEGREE_8, DEGREE_9, DEGREE_3_PROD, DEGREE_5_PROD, DEGREE_7_PROD} CUBATURE_DEGREE;

typedef enum {RADIANCE_ERROR, POWER_ERROR} ERROR_NORM;

typedef enum {CONSTANT, LINEAR, QUADRATIC, CUBIC} BASIS_TYPE;

/* determines how source radiance of a source cluster is determined and
 * how irradiance is distributed over the patches in a receiver cluster */
typedef enum {ISOTROPIC, ORIENTED, Z_VISIBILITY} CLUSTERING_STRATEGY;

typedef struct GALERKIN_STATE {
  int iteration_nr, step_nr;	/* nr of iterations and nr of steps */

  int hierarchical;		/* set TRUE for hierarchical refinement */
  int importance_driven;	/* set TRUE for potential-driven comp. */
  int clustered;		/* set TRUE for clustering */
  ITERATION_METHOD iteration_method; /* how to solve the resulting linear set */
  int lazy_linking;		/* set TRUE for lazy linking */
  int exact_visibility;		/* for more exact treatment of visibility */
  int multires_visibility;	/* for multiresolution visibility determination */
  int use_constant_radiance;	/* set TRUE for constant radiance initialization */
  int use_ambient_radiance;	/* ambient radiance (for visualisation only) */
  COLOR constant_radiance, ambient_radiance;
  SHAFTCULLMODE shaftcullmode;	/* when to do shaftculling */

  /* cubature rules for computing form factors */
  CUBATURE_DEGREE rcv_degree, src_degree;
  CUBARULE *rcv3rule, *rcv4rule, *src3rule, *src4rule, *clusRule;

  /* global variables concerning clustering */
  ELEMENT *top_cluster;	/* toplevel cluster containing the whole scene */
  GEOM *top_geom;	/* a single COMPOUND GEOM containing the whole scene */

  /* parameters that control accuracy */
  ERROR_NORM error_norm;   /* control radiance or power error? */
  float rel_min_elem_area; /* subdivision of elements that are smaller
			    * than the total surface area of the scene
			    * times this number, will not be allowed. */
  float rel_link_error_threshold;  /* relative to max. selfemitted radiance 
			    * when controlling the radiance error and
			    * to the max. selfemitted power when controlling
			    * the power error. */
  float rel_total_error_threshold;	/* not used yet */

  BASIS_TYPE basis_type;	/* determines max. approximation order */

  /* clustering strategy */
  CLUSTERING_STRATEGY clustering_strategy;

  /* some global variables for formfactor computation */
  ELEMENT *fflastrcv, *fflastsrc;

  /* scratch offscreen renderer for various clustering operations. */
  SGL_CONTEXT *scratch;
  int scratch_fb_size;		/* scratch frame buffer size */
  int lastclusid;		/* used for caching cluster and eyepoint */
  POINT lasteye;		/* rendered into the scratch frame buffer */

  long lastclock;		/* for CPU timing */
  float cpu_secs;
  int wake_up;			/* for waking up now and then */
} GALERKIN_STATE;

extern GALERKIN_STATE gal;

/* default settings */
#define DEFAULT_GAL_HIERARCHICAL	TRUE
#define DEFAULT_GAL_IMPORTANCE_DRIVEN	FALSE
#define DEFAULT_GAL_CLUSTERED		TRUE
#define DEFAULT_GAL_ITERATION_METHOD	JACOBI
#define DEFAULT_GAL_LAZY_LINKING	TRUE
#define DEFAULT_GAL_CONSTANT_RADIANCE	FALSE
#define DEFAULT_GAL_AMBIENT_RADIANCE	FALSE
#define DEFAULT_GAL_SHAFTCULLMODE	DO_SHAFTCULLING_FOR_REFINEMENT
#define DEFAULT_GAL_RCV_CUBATURE_DEGREE	DEGREE_5
#define DEFAULT_GAL_SRC_CUBATURE_DEGREE	DEGREE_4
#define DEFAULT_GAL_REL_MIN_ELEM_AREA	1e-6
#define DEFAULT_GAL_REL_LINK_ERROR_THRESHOLD 1e-5
#define DEFAULT_GAL_REL_TOTAL_ERROR_THRESHOLD 0.05
#define DEFAULT_GAL_ERROR_NORM		POWER_ERROR
#define DEFAULT_GAL_BASIS_TYPE		LINEAR
#define DEFAULT_GAL_EXACT_VISIBILITY	TRUE
#define DEFAULT_GAL_MULTIRES_VISIBILITY	FALSE
#define DEFAULT_GAL_CLUSTERING_STRATEGY ISOTROPIC
#define DEFAULT_GAL_SCRATCH_FB_SIZE	200


extern void InitGalerkin(void);
extern void GalerkinRaycast(FILE *fp);

/* installs cubature rules for triangles and quadrilaterals of the specified degree */
extern void SetCubatureRules(CUBARULE **trirule, CUBARULE **quadrule, CUBATURE_DEGREE degree);

/* recomputes the color of a patch using ambient radiance term, ... if requested for */
extern void PatchRecomputeColor(PATCH *patch);

/* in ui_galerkin.c */
extern void CreateGalerkinControlPanel(void *parent_widget);
extern void ShowGalerkinControlPanel(void);
extern void HideGalerkinControlPanel(void);

/* in gathering.c. Returns TRUE when converged and FALSE if not. */
extern int DoGatheringIteration(void);
extern int DoClusteredGatheringIteration(void);
extern void GatheringUpdateDirectPotential(ELEMENT *top, float potential_increment);
extern void GatheringUpdateMaterial(MATERIAL *oldmaterial, MATERIAL *newmaterial);

/* in shooting.c. Returns TRUE when converged and FALSE if not. */
extern int DoShootingStep(void);
extern void ShootingUpdateDirectPotential(ELEMENT *top, float potential_increment);
extern void ShootingUpdateMaterial(MATERIAL *oldmaterial, MATERIAL *newmaterial);

/* in initiallinking.c */
typedef enum {SOURCE, RECEIVER} ROLE;
/* Creates the initial interactions for a toplevel element which is
 * considered to be a SOURCE or RECEIVER according to 'role'. Interactions
 * are stored at the receiver element when doing gathering and at the
 * source element when doing shooting. */
extern void CreateInitialLinks(ELEMENT *toplevelelement, ROLE role);

/* Creates an initial link between the given element and the top cluster. */
extern void CreateInitialLinkWithTopCluster(ELEMENT *elem, ROLE role);

/* in hierefine.c */
/* recursively refines the interactions of the given toplevel element */
extern void RefineInteractions(ELEMENT *toplevelelement);

/* in basis.c: converts the received radiance of a patch into exitant
 * radiance, making a consistent hierarchical representation. */
extern void PushPullRadiance(ELEMENT *top);

#ifdef __cplusplus
}
#endif

#endif /*_GALERKINP_H_*/
