/*  gstypes.h
   Bill Brown, USACERL
   January 1993
 */

#ifndef _GSTYPES_H
#define _GSTYPES_H

#include <grass/config.h>
#include <grass/gsurf.h>
#include <grass/bitmap.h>
#if defined(OPENGL_X11) || defined(OPENGL_WINDOWS)
#include <GL/gl.h>
#endif
#ifdef OPENGL_AQUA
#include <OpenGL/gl.h>
#endif

/*#define TRACE_FUNCS */
/*#define DEBUG */

#define X 0
#define Y 1
#define Z 2
#define W 3
#define FROM 0
#define TO 1

/* colormodes */
#define CM_COLOR               0
#define CM_EMISSION            1
#define CM_AMBIENT             2
#define CM_DIFFUSE             3
#define CM_SPECULAR            4
#define CM_AD                  5
#define CM_NULL                6

#define CM_WIRE CM_COLOR

#define NULL_COLOR 0xFFFFFF

/* attribute sizes - NOT YET USED */
#define GS_CHAR8      char
#define GS_SHORT16   short
#define GS_INT32       int

/* attribute ***types*** */
#define ATTY_NULL       32	/* internal use only */
#define ATTY_MASK       16	/* can't use this one for numbytes */
#define ATTY_FLOAT       8	/* can't use this one for numbytes */
#define ATTY_INT         4
#define ATTY_SHORT       2
#define ATTY_CHAR        1
#define ATTY_ANY        63	/* internal use only */
#define LEGAL_TYPE(t)    \
(t==ATTY_MASK || t==ATTY_FLOAT || t==ATTY_INT || t==ATTY_SHORT || t==ATTY_CHAR)

#define MAXDIMS 4

#define FUDGE(gs) ((gs->zmax_nz - gs->zmin_nz)/500.)
#define DOT3( a, b )    ( (a)[X]*(b)[X] + (a)[Y]*(b)[Y] + (a)[Z]*(b)[Z] )

/* changed flags for datasets */
#define CF_NOT_CHANGED 0x000000
#define CF_COLOR_PACKED 0x000001
#define CF_USR_CHANGED 0x000010
#define CF_CHARSCALED  0x000100

#define MAX_TF 6

#define MASK_TL 0x10000000
#define MASK_TR 0x01000000
#define MASK_BR 0x00100000
#define MASK_BL 0x00010000
#define MASK_NPTS 0x00000007

#define OGSF_POINT 1
#define OGSF_LINE  2
#define OGSF_POLYGON 3

typedef float Point4[4];
typedef float Point3[3];
typedef float Point2[2];

typedef struct
{
    float *fb;
    int *ib;
    short *sb;
    unsigned char *cb;
    struct BM *bm;
    struct BM *nm;		/* null mask: set = null */
    float (*tfunc) (float, int);
    float k;
} typbuff;

typedef struct
{				/* use hash table? */
    int n_elem;			/* if n_elem == 256, index == NULL */
    char *index;
    int *value;
} table256;

typedef struct
{				/* applied thusly: offset, mult, if(use_lookup) lookup */
    float offset;
    float mult;
    int use_lookup;
    table256 lookup;
} transform;

/* move this to dataset file? */
typedef struct
{
    int data_id;
    int dims[MAXDIMS];
    int ndims;
    int numbytes;
    char *unique_name;
    typbuff databuff;
    IFLAG changed;
    int need_reload;
} dataset;

/* maybe add transformation matrix? */
typedef struct
{
    IFLAG att_src;		/* NOTSET_ATT, MAP_ATT, CONST_ATT, FUNC_ATT */
    IFLAG att_type;		/* ATTY_INT, ATTY_SHORT, ATTY_CHAR, or ATTY_FLOAT */
    int hdata;			/* handle to dataset */
    int (*user_func) ();
    float constant;
    int *lookup;		/* TODO: use transform instead */
    float min_nz, max_nz, range_nz;
    float default_null;
} gsurf_att;

typedef struct g_surf
{
    int gsurf_id;
    int cols, rows;
    gsurf_att att[MAX_ATTS];	/* mask, topo, color, etc. */
    IFLAG draw_mode;		/*DM_GOURAUD | DM_FRINGE | DM_POLY, DM_WIRE, DM_WIRE_POLY */
    long wire_color;		/* 0xBBGGRR or WC_COLOR_ATT */
    double ox, oy;		/* real world origin (i.e., SW corner) */
    double xres, yres;
    float z_exag;
    float x_trans, y_trans, z_trans;
    float xmin, xmax, ymin, ymax, zmin, zmax, zminmasked;
    float xrange, yrange, zrange;
    float zmin_nz, zmax_nz, zrange_nz;
    int x_mod, y_mod, x_modw, y_modw;	/*cells per viewcell, per wire viewcell */
    int nz_topo, nz_color;	/* no zero flags */
    int mask_needupdate, norm_needupdate;
    unsigned long *norms;
    struct BM *curmask;
    struct g_surf *next;
    void *clientdata;
} geosurf;

/* maybe put attribute info here instead of in geovect - allow a single
   vector file to have multiple attributes ?   Cached lines should
   usually be stored as 2d, since they may be draped on multiple
   surfaces & Z will vary depending upon surface. */
typedef struct g_line
{
    int type;
    float norm[3];
    int dims, npts;
    Point3 *p3;
    Point2 *p2;
    struct g_line *next;
} geoline;

typedef struct g_vect
{
    int gvect_id;
    int use_mem, n_lines;
    int drape_surf_id[MAX_SURFS];	/* if you want 'em flat, define the surface */
    int flat_val;
    int n_surfs;
    int color, width;
    char *filename;
    float x_trans, y_trans, z_trans;
    /* also maybe center & rotate? */
    geoline *lines;
    geoline *fastlines;
    int (*bgn_read) (), (*end_read) (), (*nxt_line) ();
    struct g_vect *next;
    void *clientdata;
} geovect;

/* ACS_MODIFY one line site_attr ********************************************** */
#define GPT_MAX_ATTR 8

typedef struct g_point
{
    int dims;
    Point3 p3;
    float fattr;		/* may want to make these pointers or arrays for mult atts */
    int iattr;
    char *cattr;

    /* ACS_MODIFY_BEGIN site_attr ************************************************* */
    int cat;
    int color[GPT_MAX_ATTR];
    float size[GPT_MAX_ATTR];
    int marker[GPT_MAX_ATTR];
    /* ACS_MODIFY_END site_attr *************************************************** */

    /* ACS_MODIFY_BEGIN highlight ************************************************* */
    int highlight_color;
    int highlight_size;
    int highlight_marker;

    int highlight_color_value;
    float highlight_size_value;
    int highlight_marker_value;
    /* ACS_MODIFY_END highlight *************************************************** */

    struct g_point *next;
} geopoint;

typedef struct g_site
{
    int gsite_id;
    int drape_surf_id[MAX_SURFS];	/* ditto */
    int n_surfs, n_sites;
    int color, width, marker, use_z, use_mem;
    int has_z, has_att;		/* set when file loaded */
    int attr_mode;		/* ST_ATT_COLOR, ST_ATT_MARKER, ST_ATT_SIZE, ST_ATT_NONE */

    /* ACS_MODIFY OneLine site_attr *********************************************** */
    int use_attr[GPT_MAX_ATTR];	/* ST_ATT_COLOR, ST_ATT_MARKER, ST_ATT_SIZE, ST_ATT_NONE, for multiple attr's */

    char *filename;
    transform attr_trans;
    float size;
    float x_trans, y_trans, z_trans;
    geopoint *points;
    int (*bgn_read) (), (*end_read) (), (*nxt_site) ();
    struct g_site *next;
    void *clientdata;
} geosite;

typedef struct
{
    int data_id;		/* id */
    IFLAG file_type;		/* file type */
    unsigned int count;		/* number of referencies to this file */
    char *file_name;		/* file name */

    IFLAG data_type;
    void *map;			/* pointer to volume file descriptor */
    double min, max;		/* minimum, maximum value in file */

    IFLAG status;		/* current status */
    IFLAG mode;			/* current read mode */

    void *buff;			/* data buffer */
} geovol_file;

typedef struct
{
    IFLAG att_src;

    int hfile;
    int (*user_func) ();
    float constant;

    void *att_data;
    int changed;
} geovol_isosurf_att;

typedef struct
{
    int inout_mode;
    geovol_isosurf_att att[MAX_ATTS];

    int data_desc;
    unsigned char *data;
} geovol_isosurf;

typedef struct
{
    int dir;
    float x1, x2, y1, y2, z1, z2;
    unsigned char *data;
    int changed;

    int mode, transp;
} geovol_slice;

typedef struct g_vol
{
    int gvol_id;
    struct g_vol *next;

    int hfile;
    int cols, rows, depths;
    double ox, oy, oz;
    double xres, yres, zres;
    double xmin, xmax, ymin, ymax, zmin, zmax;
    double xrange, yrange, zrange;
    float x_trans, y_trans, z_trans;

    int n_isosurfs;
    geovol_isosurf *isosurf[MAX_ISOSURFS];
    int isosurf_x_mod, isosurf_y_mod, isosurf_z_mod;
    IFLAG isosurf_draw_mode;

    int n_slices;
    geovol_slice *slice[MAX_SLICES];
    int slice_x_mod, slice_y_mod, slice_z_mod;
    IFLAG slice_draw_mode;

    void *clientdata;
} geovol;

struct lightdefs
{
    float position[4];		/* X, Y, Z, (1=local/0=inf) */
    float color[3];		/* R, G, B */
    float ambient[3];		/* R, G, B */
    float emission[3];		/* R, G, B */
    float shine;		/* 0. to 128. */
};

struct georot 
{ 
    int do_rot;                 /* do rotation */ 
    double rot_angle;           /* rotation angle */ 
    double rot_axes[3];         /* rotation axis */ 
    GLdouble rotMatrix[16];     /* rotation matrix */ 
};
    
typedef struct
{
    int coord_sys;		/* latlon, equal area, etc */
    int view_proj;		/* perspective, ortho */
    int infocus;		/* fixed center of view - true or false */
    float from_to[2][4];
    struct georot rotate;
    int twist, fov, incl, look;	/* 10ths of degrees */
    float real_to[4], vert_exag;	/* a global Z exag */
    float scale;
    struct lightdefs lights[MAX_LIGHTS];
} geoview;

typedef struct
{				/* need to add elements here for off_screen drawing */
    float nearclip, farclip, aspect;
    short left, right, bottom, top;	/* Screen coordinates */
    int bgcol;
} geodisplay;

extern void (*Cxl_func) ();
extern void (*Swap_func) ();

/* Bring all the function prototypes */
#include "ogsf_proto.h"

#endif /* _GSTYPES_H */
