/*
 GNU Maverik - a system for managing display and interaction in 
               Virtual Environment applications.
 Copyright (C) 1999-2001 Advanced Interfaces Group

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA


 The authors can be contacted via:
 www   - http://aig.cs.man.ac.uk
 email - maverik@aig.cs.man.ac.uk
 mail  - Advanced Interfaces Group, Room 2.94, Computer Science Building, 
         University of Manchester, Manchester, M13 9PL, UK
*/

#ifndef _MAV_CALLBACKS_INCLUDE
#define _MAV_CALLBACKS_INCLUDE

#ifdef __cplusplus
extern "C" {
#endif

/* Common process callbacks */

/* Draw  */

typedef struct {
  MAV_clipPlanes cp;
  MAV_viewParams vp;
  void *userdef;
} MAV_drawInfo;

extern MAV_callback *mav_callback_draw;
typedef int (*MAV_callbackDrawFn)(MAV_object *, MAV_drawInfo *);
void mav_callbackDrawSet(MAV_window *w, MAV_class *c, MAV_callbackDrawFn fn);
int  mav_callbackDrawExec(MAV_window *w, MAV_object *o, MAV_drawInfo *di);

/* Axis aligned bounding box */

typedef struct {
  MAV_vector min;
  MAV_vector max;
} MAV_BB;

extern MAV_callback *mav_callback_BB;
typedef int (*MAV_callbackBBFn)(MAV_object *, MAV_BB *);
void mav_callbackBBSet(MAV_window *w, MAV_class *c, MAV_callbackBBFn fn);
int  mav_callbackBBExec(MAV_window *w, MAV_object *o, MAV_BB *bb);

/* Intersect */

typedef struct {
  MAV_vector pt;
  MAV_vector dir;
} MAV_line;

typedef struct {
  float pt1;
  float pt2;
  MAV_vector intpt;
  MAV_vector surnorm;
} MAV_objectIntersection;

extern MAV_callback *mav_callback_intersect;
typedef int (*MAV_callbackIntersectFn)(MAV_object *, MAV_line *, MAV_objectIntersection *);
void mav_callbackIntersectSet(MAV_window *w, MAV_class *c, MAV_callbackIntersectFn fn);
int  mav_callbackIntersectExec(MAV_window *w, MAV_object *o, MAV_line ln, MAV_objectIntersection *oi);

/* ID */

extern MAV_callback *mav_callback_id;
typedef int (*MAV_callbackIDFn)(MAV_object *, char **);
void mav_callbackIDSet(MAV_window *w, MAV_class *c, MAV_callbackIDFn fn);
int  mav_callbackIDExec(MAV_window *w, MAV_object *o, char **id);

/* Dump */

extern MAV_callback *mav_callback_dump;
typedef int (*MAV_callbackDumpFn)(MAV_object *);
void mav_callbackDumpSet(MAV_window *w, MAV_class *c, MAV_callbackDumpFn fn);
int  mav_callbackDumpExec(MAV_window *w, MAV_object *o);

/* Get userdef */ 

extern MAV_callback *mav_callback_getUserdef;
typedef int (*MAV_callbackGetUserdefFn)(MAV_object *, void ***);
void mav_callbackGetUserdefSet(MAV_window *w, MAV_class *c, MAV_callbackGetUserdefFn fn);
int  mav_callbackGetUserdefExec(MAV_window *w, MAV_object *o, void ***ud);

/* Get matrix */

extern MAV_callback *mav_callback_getMatrix;
typedef int (*MAV_callbackGetMatrixFn)(MAV_object *, MAV_matrix **);
void mav_callbackGetMatrixSet(MAV_window *w, MAV_class *c, MAV_callbackGetMatrixFn fn);
int  mav_callbackGetMatrixExec(MAV_window *w, MAV_object *o, MAV_matrix **m);

/* Get surface colouring parameter */

extern MAV_callback *mav_callback_getSurfaceParams;
typedef int (*MAV_callbackGetSurfaceParamsFn)(MAV_object *, MAV_surfaceParams ***);
void mav_callbackGetSurfaceParamsSet(MAV_window *w, MAV_class *c, MAV_callbackGetSurfaceParamsFn fn);
int  mav_callbackGetSurfaceParamsExec(MAV_window *w, MAV_object *o, MAV_surfaceParams ***sp);



/* Supporting routines */

MAV_clipPlanes mav_clipPlanesGet(MAV_window *w, float xmin, float xmax, float ymin, float ymax, float zmin, float zmax);
MAV_clipPlanes mav_clipPlanesGetFromPixels(MAV_window *w, int xmin, int xmax, int ymin, int ymax, float zmin, float zmax);
MAV_clipPlanes mav_clipPlanesGetFromBB(MAV_BB bb);
void mav_clipPlanePrint(char *s, MAV_clipPlane cp);
void mav_clipPlanesPrint(char *s, MAV_clipPlanes cp);

int mav_BBCull(MAV_BB bb);
int mav_BBCullToClipPlanes(MAV_BB bb, MAV_clipPlanes cp);
int mav_BBGetCorner(MAV_vector v);
int mav_BBIntersectsLine(MAV_BB bb, MAV_line ln, MAV_objectIntersection *oi);
int mav_BBIntersectsBB(MAV_BB bb1, MAV_BB bb2);
int mav_BBInsideBB(MAV_BB bb1, MAV_BB bb2);
int mav_BBIntersectsClipPlanes(MAV_BB bb, int *clist, MAV_clipPlanes *cp);
void mav_BBAlign(MAV_BB in, MAV_matrix m, MAV_BB *out);
void mav_BBPrint(char *s, MAV_BB bb);
void mav_BBDisplay(MAV_window *w, MAV_BB bb);
void mav_BBDisplayWithColour(MAV_window *w, MAV_BB bb, int col);
void mav_BBDisplayWithSurfaceParams(MAV_window *w, MAV_BB bb, MAV_surfaceParams *sp);
void mav_BBCompInit(MAV_BB *bb);
void mav_BBCompBB(MAV_BB in, MAV_BB *out);
void mav_BBCompPt(MAV_vector v, MAV_BB *bb);

#define mav_BBDraw(A,B) mav_BBDisplay(A,B)
#define mav_BBDrawWithColour(A,B,C) mav_BBDisplayWithColour(A,B,C)
#define mav_BBDrawWithSurfaceParams(A,B,C) mav_BBDisplayWithSurfaceParams(A,B,C)
#define mav_BBIntersect(A,B,C) mav_BBIntersectsLine(A,B,C)

MAV_line mav_lineTransFrame(MAV_line in, MAV_matrix m);
MAV_drawInfo mav_drawInfoTransFrame(MAV_drawInfo in, MAV_matrix mat);
int  mav_lineInfPlaneIntersection(MAV_vector pt, MAV_vector norm, MAV_line ln, MAV_objectIntersection *oi);
int  mav_lineAxisPlaneIntersection(float xmin, float xmax, float ymin, float ymax, float zmin, float zmax, 
				   MAV_vector pt, MAV_vector norm, MAV_line ln, MAV_objectIntersection *oi);
int  mav_objectIntersectionsSort(int nhits, MAV_objectIntersection *hits, float scale, MAV_objectIntersection *res);
void mav_objectIntersectionPrint(char *s, MAV_objectIntersection oi);
void mav_linePrint(char *s, MAV_line ln);

typedef struct {
  MAV_window *win;
  MAV_object *obj;
  MAV_callbackDrawFn fn;
  MAV_drawInfo di;
  MAV_drawInfo *dip;
  MAV_matrix mat;
  float dist2;
} MAV_transObjData;

int  mav_objectIsTransparent(MAV_window *w, MAV_object *o);
void mav_transparentObjectsManage(MAV_window *w, MAV_object *o, MAV_drawInfo *di);
void mav_transparentObjectsRender(void *ignored);
extern MAV_list *mav_transObjList;

typedef struct {
  MAV_window *win;
  MAV_object *obj;
  MAV_callbackDrawFn fn;
  MAV_drawInfo di;
  MAV_drawInfo *dip;
  MAV_matrix mat;
} MAV_texturedObjData;

int  mav_objectIsTextured(MAV_window *w, MAV_object *o);
void mav_texturedObjectsManage(MAV_window *w, MAV_object *o, MAV_drawInfo *di);
void mav_texturedObjectsRender(void *ignored);
extern MAV_list **mav_textureObjList;



/* Options */

extern int mav_opt_trans;
extern int mav_opt_delayTexture;



/* Module initialise */

int mav_callbacksModuleInit(void);
char *mav_callbacksModuleID(void);

#ifdef __cplusplus
}
#endif
#endif
