#ifndef dpltyp_h
#define dpltyp_h
#ifdef __cplusplus
extern "C" {
#endif

/* **************************************************

   Copyright DIVISION Limited (c) 1994
   All rights reserved


   File    : dpltypes.h
   Project : dpl interface
   Author  : PJA
   Date    : 18/6/94

   Function: Flesh out all the datatypes

   History : Rev 1.0, 18 / 06 / 1994
                 1.1, 22 / 06 / 1994  fixed unimplementable lists by
                                      introducing dpl_superlist
                 1.2, 27 / 06 / 1994  dislocated heirarchy from instances
                                      and dropped back to matrix-only DCS
                 2.0  16 / 11 / 1994  angusification started

  **************************** */

#include <dsys/divtypes.h>
#include <dpl/dpltypes.h>

#define OFF_SITE 1

#ifdef i860
#define REMOTE 1
#endif

#define dpl_arg_sep '~'

#define dcs_node_enable       0x1
#define dcs_subtree_enable    0x2
#define dcs_no_view_concat    0x4

#define dcs_billboard_x       0x8
#define dcs_billboard_y       0x10
#define dcs_billboard_z       0x20
#define dcs_explode_geo       0x40
#define dcs_ignore_geo        0x80

#define dcs_inherit_lmodel    0x100
#define dcs_force_eval_lmodel 0x200
#define dcs_near_field        0x400
#define dcs_bounded           0x800
#define dcs_backwards         0x1000
#define dcs_uniform_scale     0x2000

#define dpl_draw_faceted      0x0000
#define dpl_draw_smooth       0x0001
#define dpl_draw_colored      0x0002
#define dpl_draw_luminance    0x0004
#define dpl_draw_textured     0x0008
#define dpl_draw_3dtextured   0x0010
#define dpl_draw_front        0x0200
#define dpl_draw_back         0x0400
#define dpl_draw_edges        0x0800
#define dpl_draw_wireframe    0x1000
#define dpl_draw_last         0x2000
#define dpl_draw_envmapped    0x4000
#define dpl_draw_flipped      0x8000
#define dpl_draw_f_emissive   0x0020
#define dpl_draw_b_emissive   0x0040

#define dpl_X 0
#define dpl_Y 1
#define dpl_Z 2
#define dpl_W 3

#ifdef _DOS
#define dpl_path_separator '\\'
#else
#define dpl_path_separator '/'
#endif

/*
   NOTE in rpc implementations, the rather large overhead
   of the dpl_node dplnode is never passed over to the
   remote renderer, its just in the host space for management
*/

typedef struct s_dplnode* (*node_create_function)( void );

typedef struct s_dplnode {
  int32    clean;
  void    *app_specific;
  void    *remote;         /* this MUST be 1st word of REMOTE data */
  dpl_TYPE type_check;
} dpl_node;

typedef struct s_dplremote_node {
  void    *remote;
  dpl_TYPE type_check;
} dpl_remote_node;

#ifdef REMOTE
#define dpl_node dpl_remote_node
#endif

typedef struct s_dpl_chain_node {
  dpl_node node;
  struct s_dpl_chain_node *next_node;
  struct s_dpldcs *dcs;
} dpl_chain_node;

typedef int32 (*load_function)( dpl_node *, char * );

typedef struct s_dpllist {
  dpl_node *item;
  dpl_TYPE type_check;
  struct s_dpllist *next;
  struct s_dpllist *prev;
} dpl_list;

/*
   the dpl_superlist is used as the head node for
   dpl_lists
*/

typedef struct s_dplsuperlist {
  dpl_node *dplnode;

  dpl_list *last_accessed;
  dpl_list *head;
  dpl_list *tail;
} dpl_superlist;

typedef float32 dpl_POINT [4];
typedef float32 dpl_MATRIX[4][4];

typedef union {
  double dbl_MATRIX[8];
  dpl_MATRIX matrix;
} dpl_dblMATRIX;

/* introduce local datatypes */


/*

The renderer is currently blowing off way too much storage on the card,
which stands to sense when each polygon is around 144 bytes, 80 bytes for the
vertex and 64 for the connection structure. The currently unused datatypes
below will eventually attempt to buy back a lot of storage by moving away
from linked lists and towards packed structures

*/


typedef struct s_rvert {
  dpl_POINT position;          /* 0 */
  dpl_POINT normcol;           /* 16 */
  float32 texcoords [3];       /* 32 */
  struct s_rvert *next;        /* 44 */
  dpl_POINT xform_posn;        /* 48 */
  float32 rendered_color[3];   /* 64 */
  int32   touched;             /* 76 */
} dpl_VERTEX;

typedef struct s_conn {
  struct s_conn *next;             /* 0 */
  int32  n_verts;                  /* 4 */
  dpl_VERTEX*         indices[6];  /* 8 */
  dpl_POINT planeEqn;              /* 32 */
  float32 rendered_color[3];       /* 48 */
  int32 touched;                   /* 60 */
} dpl_CONNECTION;


/* we will only use this structure for polys, not spheres,
   so the W-coordinate (radius) holds the touched word
 */

typedef struct s_ivert {
  float32   position[3];       /* 3 */
  int32     touched;           /* 4 */
  dpl_POINT normcol;           /* 8 */
  float32   texcoords [2];     /* 10 total = 40 bytes */
} dpl_idealVERTEX;

typedef struct s_iconn {
  dpl_POINT        planeEqn;         /* 4  */
  dpl_idealVERTEX* indices[6];       /* 10 */
} dpl_idealCONNECTION;               /* total 40 bytes */

typedef struct s_oconn {
  float planeEqn[3];
  int touched;
  int indices[6];
} dpl_outputCONNECTION;          /* total 40 bytes */


/*
   it looks like we can drop polygon storage down to 80 bytes
   per poly, rather than 144, so we can achieve around 80% more
   database storage

   the assumption is that we use connection[3] == NULL as the triangle
   spotter. is this iffy? it lets us keep hexes for performance.

   planeEqn[3] = touched for output conns, so we have 32 bytes, giving
   a 72 byte triangle and _doubling_ storage.

   in order to make this work, we will need a single PMESH of worst-case
   size hanging round in memory. So xforming and lighting will no longer
   happen in-place, but the destination for the work will always be the
   same area of memory. So we'll get better cache and page coherence.

   It is recommended that we drop PMESH size from 6 to 4.

   The VERTEX pointers in the connection structure must now become
   byte indices, so we just add on the base address of the VERTEX
   structure.

   The only problem is special effects - the sphere effects are just dealt
   with by keeping spherelists in the old vertex format; triangle effects
   may be more difficult to deal with.

 */



/* flesh out the datatypes in dpltypes.h */

#if 0
struct s_dpl_statistics {
  float32 polys_in_last_frame;
  float32 last_edit_time;
  float32 last_cull_time;
  float32 last_frame_time;
  float32 last_frame_time_sb;
  float32 polys_per_second;
  float32 polys_per_second_sb;
} dpl_STATISTICS;

#endif

struct s_dpldcs {
  dpl_node   dplnode;
  dpl_chain_node  *nodes;
  struct s_dplzone *zone;
  dpl_MATRIX matrix;
  int32      traversal;  /* overload billboards in here for compactness */
  struct     s_dpldcs *parent;
  struct     s_dpldcs *sibling;
  struct     s_dpldcs *child;
  int32      lighting_mask;
  dpl_POINT  bounds[2];
#ifdef REMOTE
  dpl_dblMATRIX invModel;
  float sphere_scale, sphere_big_scale;
#endif
} ;
struct s_dplzone {
  dpl_node dplnode;

  int32      view_enable;
} ;
struct s_dplview {
  dpl_chain_node dplnode;

  int32   view_id;
  int32   pipe;
  float32 x0, y0, x1, y1, zeye;
  float32 x_size, y_size;
  float32 hither_clip;
  float32 yon_clip;
  float32 back_color[3];
  int32   fog_enable;
  float32 fog[5];       /* near, phar, r, g, b */
  struct s_dplview *share_view;
  void *display_2d;
} ;
struct s_dpllight {
  dpl_chain_node dplnode;

  dpl_LIGHT_TYPE    light_type;
  float32  color   [3];
  float32  radius  [2];  /* for radial lights  */
  float32  umbra   [2];  /* for conical lights */
  int32    lighting_mask;
#ifdef REMOTE
  float32  position[3];
#endif
};
struct s_dpltexture {
  dpl_node dplnode;

  struct s_dpltexmap *texmap;

  int32   minify;
  int32   magnify;
  int32   alpha;
  int32   wrap_u;
  int32   wrap_v;
  int32   detail;
  float32 u0;
  float32 v0;
  float32 du;
  float32 dv;
  float32 animate_time;
  int32   bitslice;
  int32   delta_size;
  int32   delta_offs;
};
struct s_dpltexmap {
  dpl_node dplnode;

  int32 *texels;
  int32  u_size;
  int32  v_size;
  int32  bits_per_texel;
  int32  alpha;
#ifdef REMOTE
  int32 hwareSize;
  int32 hwareOffs;
  int32 bilinear;
  void *cell;
#endif
};
struct s_dplmtl {
  dpl_node dplnode;

  struct s_dpltexture   *texture;
  struct s_dpltexture   *environment;
  int32  immunity;
  struct s_dplramp *ramp;
  float32 emissive [3];
  float32 ambient  [3];
  float32 diffuse  [3];
  float32 opacity  [3];
  float32 specular [4];
  float32 dither;
#ifdef REMOTE
  float surf_opacity;
  float *specular_table;
  int32   pxpl5_cntl_word;
  float du, dv;
  float alpha_c, alpha_r;
  int32   alpha_texture;
  int32 cull_frame;
#endif
};
struct s_dplramp {
  dpl_node dplnode;

  float32 color0 [3];
  float32 color1 [3];
  int32   cntl_word;
};
struct s_dplinstance {
  dpl_chain_node dplnode;

  dpl_ISECT_MODE   intersectmode;
  int32 visibility;
  struct s_dplobject    *object;
  struct s_dpllod       *forcelod;
  struct s_dplmtl       *f_material;
  struct s_dplmtl       *b_material;
  int32  intersect_mask;
  int32  wireframe;
#ifdef REMOTE
  int32  frame_count;
  int32  last_LOD_index;
#endif
};
#define MAX_LODS_PER_OBJECT 16

struct s_dplobject {
  dpl_node dplnode;

  dpl_superlist lod_list;
  dpl_POINT lod_hot_spot;
  float32   lod_ranges[MAX_LODS_PER_OBJECT];
  float32   lod_fade_range;
  int32     invalid_lods;
  int32     clone;
#ifdef REMOTE
  int32     lod_count;
  float32   bounds[2][4];
  dpl_POINT sphere_bounds;
#endif
};
struct s_dpllod {
  dpl_node dplnode;

  float32     bounds[2][4];
  struct s_dplobject *parent;
  dpl_superlist geogroup_list;
  float32 hot_spot[3];
#ifdef REMOTE
  dpl_POINT sphere_bounds;
#endif
};
struct s_dplgeogroup {
  dpl_node dplnode;

  float32  bounds[2][4];
  struct s_dpllod *parent;
  int32    draw_mode;
  dpl_superlist geometry_list;
  struct s_dplmtl *f_material;
  struct s_dplmtl *b_material;
  float32 decal_offs;
  int32   lock;
#ifdef REMOTE
  dpl_POINT sphere_bounds;
  int32 clean;
#endif
};
struct s_dplgeometry {
  dpl_node dplnode;

  dpl_GEO_TYPE geometry_type;
  dpl_VERTEX_TYPE vertex_type;
  int32 num_vertices;
  struct s_dplgeogroup *parent;
  dpl_CONNECTION  *connections;
  dpl_VERTEX      *vertices;
  float lineWidth, pointSize;

#ifdef REMOTE
  int32 variable_alpha;
  int32 n_connections;
  int32 n_vertices;
  dpl_CONNECTION  *connection_tail;
  dpl_VERTEX      *vertex_tail;
  int32 packed;
#endif

};
#if 0
struct s_dpl_status {
  int32 ok;
} dpl_STATUS;
#endif


/* ******************************************

  BEWARE ! ! ! ! !

  FOR REASONS OF STORAGE AND APPLICATIONS EFFICIENCY, THE FOLLOWING
  DATA TYPES ARE   N O T   SUPERSETS OF DPL_NODE

  BE CAREFUL DEALING WITH VERTICES

*/

/* typedefs for tracing performance */

typedef struct s_dpl_version {
  int32 host;
  int32 major_version;
  int32 minor_version;
  int32 firmware_major_version;
  int32 firmware_minor_version;
  char detailed[256];
} dpl_VERSION;

/* **********************************************************
   a scene contains a list of root-node dcs's, a list of zones
   and a list of views
 */

typedef struct s_dplscene {
  dpl_node dplnode;

  dpl_superlist zone_list;
  dpl_superlist view_list;
  dpl_superlist dcs_list;
  dpl_superlist light_list;
} dpl_SCENE;

typedef enum {
  dpl_artic_matrix,
  dpl_artic_singleX,
  dpl_artic_singleY,
  dpl_artic_singleZ,
  dpl_artic_quaternion
} dpl_ARTICULATION;

/* additional geometry types - keep small for switch optim */

#define vpx_geo_type_f_t_dam    16
#define vpx_geo_type_sca        17
#define vpx_geo_type_undamage   18
#define vpx_geo_type_f_t_undam  19
#define vpx_geo_type_damage_set 20

#define dpl_morph_vertices   0x1
#define dpl_morph_normals    0x2
#define dpl_morph_texcoords  0x4
#define dpl_morph_colors     0x8



typedef void (*vfptr)();

extern void *
dpl_svtRead(char8 *, int32 bilinear );

extern void *
dpl_bilRead(char8 *);

extern void *
dpl_glmRead(char8 *);

extern void
dpl_explodeTexels ( dpl_TEXMAP *tm,
                    int32 *dest_texels,
                    uint8 *src_texels,
                    int32 n_texels,
                    int32 start, int32 bilinear );


#define POLY_FBITS   12
#define SPHERE_FBITS 24

#ifdef __cplusplus
}
#endif
#endif
