/*                            D B 4 . H
 * BRL-CAD
 *
 * Copyright (c) 1985-2021 United States Government as represented by
 * the U.S. Army Research Laboratory.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this file; see the file named COPYING for more
 * information.
 */
/** @addtogroup db4 */
/** @{ */
/** @file rt/db4.h
 * @brief
 *		GED Database Format v4
 *
 * All records are rounded up to have a fixed length;  each such
 * database record is also known as a "granule", and is the smallest
 * unit of database storage.
 *
 * Every granule can be identified by the first byte, which can
 * be accessed by the u_id name.  Note that the u_id field is not
 * valid when writing the actual data for splines.
 *
 * Each granule is read into a "union record", and is then processed
 * based on the value of u_id.  Each granule will have one of these formats:
 *	A Free record
 *	An ID record
 *	A SOLID record
 *	A COMBINATION record, followed by multiple
 *		MEMBER records
 *	An ARS `A' (header) record, followed by multiple
 *		ARS `B' (data) records
 *	A Polygon header record, followed by multiple
 *		Polygon data records
 *      A B-spline solid header record, followed by multiple
 *		B-spline surface records, followed by
 *			d_kv_size[0] floats,
 *			d_kv_size[1] floats,
 *			padded to d_nknots granules, followed by
 *			ctl_size[0]*ctl_size[1]*geom_type floats,
 *			padded to d_nctls granules.
 *
 * The records are stored as binary records corresponding to PDP-11 and
 * VAX C structs, so padding must be supplied explicitly for alignment.
 *
 * For the time being, the representation of the floating point numbers
 * in the database is machine-specific, requiring conversion to ASCII
 * (via g2asc) and back to binary (via asc2g) when exchanging between
 * machines of dissimilar types.  In time, an external representation
 * for floats might be implemented.
 *
 */

#ifndef RT_DB4_H
#define RT_DB4_H

#include "common.h"

#include "vmath.h"  /* Needed only for the deprecated functions below using fastf_t */

__BEGIN_DECLS

#define NAMESIZE		16

/* don't use bu_strlcpy for NAMEMOVE */
#define NAMEMOVE(from,to)	(void)strncpy(to, from, NAMESIZE)

/*
 *  Define the database format for storing binary floating point values.
 *  The ultimate intention is to store everything in 8 bytes, using
 *  IEEE double precision in network order.
 */
typedef float dbfloat_t;

#define DB_MINREC	128


struct ident {
    char	i_id;		/* ID_IDENT */
    char	i_units;	/* units */
/* Values of 0..5 are fixed for file compat with Release 2.3 through 4.5 */
#define ID_NO_UNIT	0		/* unspecified */
#define ID_MM_UNIT	1		/* millimeters (preferred) */
#define ID_CM_UNIT	2		/* centimeters */
#define ID_M_UNIT	3		/* meters */
#define ID_IN_UNIT	4		/* inches */
#define ID_FT_UNIT	5		/* feet */
/* These new values 6..9 added in Release 5.0 */
#define ID_UM_UNIT	6		/* micrometers */
#define ID_KM_UNIT	7		/* kilometers */
#define ID_YD_UNIT	8		/* yards */
#define ID_MI_UNIT	9		/* miles */
    char	i_version[6];	/* Version code of Database format */
#define ID_VERSION	"v4"		/* Current Version */
    char	i_title[72];	/* Title or description */
    /* For the future */
    char	i_byteorder;	/* Byte ordering */
#define ID_BY_UNKNOWN	0		/* unknown */
#define ID_BY_VAX	1		/* VAX (Little Endian) */
#define ED_BY_IBM	2		/* IBM (Big Endian) */
    char	i_floattype;	/* Floating point type */
#define ID_FT_UNKNOWN	0		/* unknown */
#define ID_FT_VAX	1		/* VAX */
#define ID_FT_IBM	2		/* IBM */
#define ID_FT_IEEE	3		/* IEEE */
#define ID_FT_CRAY	4		/* Cray */
}; /* struct ident */

struct solidrec {
    char	s_id;		/* ID_SOLID */
    char	s_type;		/* GED primitive type */
#define RPP	1	/* axis-aligned rectangular parallelepiped */
#define BOX	2	/* arbitrary rectangular parallelepiped */
#define RAW	3	/* right-angle wedge */
#define ARB4	4	/* tetrahedron */
#define ARB5	5	/* pyramid */
#define ARB6	6	/* extruded triangle */
#define ARB7	7	/* weird 7-vertex shape */
#define ARB8	8	/* hexahedron */
#define ELL	9	/* ellipsoid */
#define ELL1	10	/* another ellipsoid definition */
#define SPH	11	/* sphere */
#define RCC	12	/* right circular cylinder */
#define REC	13	/* right elliptic cylinder */
#define TRC	14	/* truncated regular cone */
#define TEC	15	/* truncated elliptic cone */
#define TOR	16	/* toroid */
#define TGC	17	/* truncated general cone */
#define GENTGC	18	/* supergeneralized TGC; internal form */
#define GENELL	19	/* ready for drawing ELL:  V, A, B, C */
#define GENARB8	20	/* generalized ARB8:  V, and 7 other vectors */
#define	ARS	21	/* HACK arbitrary triangular-surfaced polyhedron */
#define ARSCONT 22	/* HACK extension record type for ARS solid */
#define ELLG	23	/* comgeom version of GENELL ellipsoid */
#define HALFSPACE 24	/* half-space */
#define SPLINE  25	/* HACK and trouble */
#define RPC	26	/* Right Parabolic Cylinder */
#define RHC	27	/* Right Parabolic Cylinder */
#define EPA	28	/* Elliptical Paraboloid */
#define EHY	29	/* Elliptical Hyperboloid */
#define ETO	30	/* Elliptical Torus */
#define GRP	31	/* Grip pseudo solid */
#define SUPERELL 32     /* Superquadratic Ellipsoid */
#define HYP	33	/* Hyperboloid of one sheet */
    char	s_name[NAMESIZE];	/* unique name */
    short	s_cgtype;		/* COMGEOM solid type */
    dbfloat_t	s_values[24];		/* parameters */
#define s_tgc_V	s_values[0]
#define s_tgc_H	s_values[3]
#define s_tgc_A s_values[6]
#define s_tgc_B s_values[9]
#define s_tgc_C s_values[12]
#define s_tgc_D s_values[15]

#define s_tor_V	s_values[0]
#define s_tor_H	s_values[3]
#define s_tor_A	s_values[6]
#define s_tor_B	s_values[9]
#define s_tor_C	s_values[12]
#define s_tor_D	s_values[15]
#define s_tor_E	s_values[18]
#define s_tor_F	s_values[21]

#define s_ell_V s_values[0]
#define s_ell_A s_values[3]
#define s_ell_B s_values[6]
#define s_ell_C s_values[9]

#define s_superell_V s_values[0]
#define s_superell_A s_values[3]
#define s_superell_B s_values[6]
#define s_superell_C s_values[9]
#define s_superell_n s_values[12]
#define s_superell_e s_values[13]

#define s_half_N s_values[0]
#define s_half_d s_values[3]

#define s_grip_C s_values[0]
#define s_grip_N s_values[3]
#define s_grip_m s_values[6]
}; /* struct solidrec */

struct combination {
    char	c_id;			/* ID_COMB */
    char	c_flags;		/* `R' if region, else ` ' */
#define DBV4_NON_REGION			' '
#define DBV4_NON_REGION_NULL		'\0'
#define DBV4_REGION			'R'
#define DBV4_REGION_FASTGEN_PLATE	'P'
#define DBV4_REGION_FASTGEN_VOLUME	'V'
    char	c_name[NAMESIZE];	/* unique name */
    short	c_regionid;		/* region ID code */
    short	c_aircode;		/* air space code */
    short	c_pad1;		/* was c_length, DEPRECATED: # of members */
    short	c_pad2;		/* was c_num, DEPRECATED */
    short	c_material;		/* (GIFT) material code */
    short	c_los;			/* equivalent LOS estimate */
    char	c_override;		/* non-0 ==> c_rgb is color */
    unsigned char c_rgb[3];		/* 0..255 color override */
    char	c_matname[32];		/* Reference: Material name */
    char	c_matparm[60];		/* String Material parms */
    char	c_inherit;		/* Inheritance property */
#define DB_INH_LOWER	0			/* Lower nodes override */
#define DB_INH_HIGHER	1			/* Higher nodes override */
}; /* struct combination */

struct member {
    char	m_id;			/* ID_MEMB */
    char	m_relation;		/* boolean operation as u,-,+ char */
    char	m_brname[NAMESIZE];	/* DEPRECATED: name of this branch */
    char	m_instname[NAMESIZE];	/* name of referred-to obj. */
    short	m_pad1;
    dbfloat_t m_mat[16];		/* homogeneous trans matrix */
    short	m_pad2;	/* was m_num, DEPRECATED: COMGEOM solid # ref */
}; /* struct member */

struct material_rec {		/* whole record is DEPRECATED */
    char	md_id;		/* = ID_MATERIAL color override */
    char	md_flags;	/* UNUSED */
    short	md_low;		/* lower end of region IDs affected */
    short	md_hi;		/* upper end of region IDs affected */
    unsigned char md_r;
    unsigned char md_g;	/* color of these regions:  0..255 */
    unsigned char md_b;
    char	md_material[100]; /* UNUSED now */
}; /* struct material_rec */

struct B_solid {
    char	B_id;		/* = ID_BSOLID */
    char	B_pad;
    char	B_name[NAMESIZE];
    short	B_nsurf;	/* #  of surfaces in this solid */
    dbfloat_t B_unused;	/* UNUSED (was resolution of flatness) */
}; /* struct B_solid */

struct b_surf {
    char    d_id;		/* = ID_BSURF */
    short   d_order[2];	/* order of u and v directions */
    short   d_kv_size[2];	/* knot vector size  (u and v) */
    short   d_ctl_size[2];  /* control mesh size ( u and v) */
    short   d_geom_type;	/* geom type 3 or 4 */
    short	d_nknots;	/* # granules of knots */
    short	d_nctls;	/* # granules of ctls */
}; /* struct b_surf */

struct polyhead {
    char	p_id;		/* = POLY_HEAD */
    char	p_pad1;
    char	p_name[NAMESIZE];
}; /* struct polyhead */

struct polydata {
    char	q_id;		/* = POLY_DATA */
    char	q_count;	/* # of vertices <= 5 */
    dbfloat_t q_verts[5][3]; /* Actual vertices for this polygon */
    dbfloat_t q_norms[5][3]; /* Normals at each vertex */
}; /* struct polydata */

struct ars_rec {
    char	a_id;			/* ID_ARS_A */
    char	a_type;			/* primitive type */
    char	a_name[NAMESIZE];	/* unique name */
    /* these cannot be size_t due to v4 compatibility */
    short	a_m;			/* # of curves */
    short	a_n;			/* # of points per curve */
    short	a_curlen;		/* # of granules per curve */
    short	a_totlen;		/* # of granules for ARS */
    /* Remainder are unused, and exist for ?compatibility */
    short	a_pad;
    dbfloat_t a_xmax;		/* max x coordinate */
    dbfloat_t a_xmin;		/* min x coordinate */
    dbfloat_t a_ymax;		/* max y coordinate */
    dbfloat_t a_ymin;		/* min y coordinate */
    dbfloat_t a_zmax;		/* max z coordinate */
    dbfloat_t a_zmin;		/* min z coordinate */
}; /* struct ars_rec */

struct ars_ext {
    char	b_id;			/* ID_ARS_B */
    char	b_type;			/* primitive type */
    short	b_n;			/* current curve # */
    short	b_ngranule;		/* curr. granule for curve */
    short	b_pad;
    dbfloat_t	b_values[8*3];		/* vectors */
}; /* struct ars_ext */

struct strsol {
    char	ss_id;			/* ID_STRSOL */
    char	ss_pad;
    char	ss_name[NAMESIZE];	/* solid name */
#define DB_SS_NGRAN	8			/* All STRSOL's have this many granules */
#define DB_SS_LEN	(DB_SS_NGRAN*DB_MINREC-2*NAMESIZE-2)
    char	ss_keyword[NAMESIZE];	/* solid keyword */
    char	ss_args[4];		/* DB_SS_LEN bytes of str args */
}; /* struct strsol */

struct arbn_rec {
    char	n_id;			/* DBID_ARBN */
    char	n_pad;
    char	n_name[NAMESIZE];
    unsigned char	n_neqn[4];	/* # equations which follow */
    unsigned char	n_grans[4];	/* # eqn granules to follow */
    /* Note that eqn granules are in "network" byte order */
}; /* struct arbn_rec */

struct exported_pipe_pnt  {
    unsigned char	epp_coord[8*3];
    unsigned char	epp_bendradius[8];
    unsigned char	epp_id[8];
    unsigned char	epp_od[8];
}; /* exported_pipe_pnt */

struct pipewire_rec {
    char	pwr_id;			/* DBID_PIPE */
    char	pwr_pad;
    char	pwr_name[NAMESIZE];
    unsigned char	pwr_pt_count[4]; /* number of points in this pipe solid */
    unsigned char	pwr_count[4];	/* # additional granules */
    struct exported_pipe_pnt pwr_data[1];			/* mach indep segments */
}; /* struct pipewire_rec */

struct particle_rec {
    char	p_id;			/* DBID_PARTICLE */
    char	p_pad;
    char	p_name[NAMESIZE];
    unsigned char	p_v[8*3];	/* vertex (mach indep fmt) */
    unsigned char	p_h[8*3];	/* height vector */
    unsigned char	p_vrad[8];	/* radius at vertex */
    unsigned char	p_hrad[8];	/* radius at end of height */
}; /* struct particle_rec */

struct nmg_rec {
    char	N_id;			/* DBID_NMG */
    char	N_version;		/* Version indicator */
    char	N_name[NAMESIZE];
    char	N_pad2[2];		/* neatness */
    unsigned char	N_count[4];	/* # additional granules */
    unsigned char	N_structs[26*4];/* # of structs needed */
}; /* struct nmg_rec */

struct extr_rec	{
    char	ex_id;			/* DBID_EXTR */
    char	ex_pad;
    char	ex_name[NAMESIZE];
    unsigned char	ex_V[8*3];	/* Vertex */
    unsigned char	ex_h[8*3];	/* extrusion vector */
    unsigned char	ex_uvec[8*3];	/* vector in U parameter direction */
    unsigned char	ex_vvec[8*3];	/* vector in V parameter direction */
    unsigned char	ex_key[4];	/* keypoint index */
    unsigned char	ex_count[4];	/* number of additional granules
					 * (for now, this will always be 1 ) */
}; /* struct extr_rec */

struct sketch_rec {
    char	skt_id;			/* DBID_SKETCH */
    char	skt_pad;
    char	skt_name[NAMESIZE];
    unsigned char	skt_V[8*3];	/* vertex */
    unsigned char	skt_uvec[8*3];	/* vector in U parameter direction */
    unsigned char	skt_vvec[8*3];	/* vector in V parameter direction */
    unsigned char	skt_vert_count[4];	/* number of vertices in sketch */
    unsigned char	skt_seg_count[4];	/* number of segments in sketch */
    unsigned char	skt_count[4];		/* number of additional granules */
}; /* struct sketch_rec */

struct annot_rec {
    char	ant_id;			/*DBID_ANNOT */
    char	ant_pad;
    char	ant_name[NAMESIZE];
    unsigned char	ant_V[8*3];		/* orgin map */
    unsigned char       ant_vert_count[4];      /* number of vertices in annotation */
    unsigned char       ant_seg_count[4];       /* number of segments in annotation */
    unsigned char       ant_count[4];           /* number of additional granules */
}; /* struct annot_rec */

struct script_rec {
    char    script_id;         /*DBID_SCRIPT */
    char    script_pad;
    char    script_name[NAMESIZE];
}; /* struct script_rec */

struct cline_rec {
    char	cli_id;			/* DBID_CLINE */
    char	cli_pad;
    char	cli_name[NAMESIZE];
    unsigned char	cli_V[8*3];	/* vertex */
    unsigned char	cli_h[8*3];	/* height vector */
    unsigned char	cli_radius[8];	/* radius */
    unsigned char	cli_thick[8];	/* plate thickness (0 means volume mode) */
}; /* struct cline_rec */

struct bot_rec {
    char		bot_id;
    char		bot_pad;
    char		bot_name[NAMESIZE];
    unsigned char	bot_nrec[4];		/* number of additional records required */
    unsigned char	bot_orientation;	/* unoriented, ccw, or cw */
    unsigned char	bot_mode;		/* surface or volume */
    unsigned char	bot_err_mode;
    unsigned char	bot_num_verts[4];	/* number of vertices */
    unsigned char	bot_num_triangles[4];	/* number of triangles */
    unsigned char	bot_data[1];		/* the start of the data:
						 * num_verts*3*8 for the vertex floats
						 * num_triangles*3*4 for the triangle ints
						 * if mode is RT_BOT_PLATE, then additional data is:
						 * num_triangles*8 for the face thicknesses
						 * followed by a null terminated hex digit string "face_mode" (bit vector) */
}; /* struct bot_rec */

union record {

    char	u_id;		/* To differentiate record types */
#define ID_IDENT	'I'
#define ID_SOLID	'S'
#define ID_COMB		'C'
#define ID_MEMB		'M'
#define ID_ARS_A	'A'
#define ID_ARS_B	'B'
#define ID_FREE		'F'	/* Free record -- ignore */
#define ID_P_HEAD	'P'	/* Polygon header */
#define ID_P_DATA	'Q'	/* Polygon data record */
#define ID_BSOLID	'b'	/* B-spline solid.  multiple surfs */
#define ID_BSURF	'D'     /* d_spline surface header */
#define ID_MATERIAL	'm'	/* Material description record */
#define DBID_STRSOL	's'	/* String solid description */
#define DBID_ARBN	'n'	/* Convex polyhedron with N faces */
#define DBID_PIPE	'w'	/* pipe (wire) solid */
#define DBID_PARTICLE	'p'	/* a particle (lozenge) */
#define DBID_NMG	'N'	/* NMG solid */
#define	DBID_SKETCH	'd'	/* 2D sketch */
#define DBID_ANNOT	'a'	/* 2D annotations */
#define	DBID_EXTR	'e'	/* solid of extrusion */
#define DBID_CLINE	'c'	/* FASTGEN4 CLINE solid */
#define	DBID_BOT	't'	/* Bag o' triangles */
#define DBID_SCRIPT 'T' /* script */

    char	u_size[DB_MINREC];	/* Minimum record size */

    struct ident i;
    struct solidrec s;
    struct combination c;
    struct member M;
    struct material_rec md;
    struct B_solid B;
    struct b_surf d;
    /*
     * The b_surf record is followed by
     * d_nknots granules of knot vectors (first u, then v),
     * and then by d_nctls granules of control mesh information.
     * Note that neither of these have an ID field!
     */
    struct polyhead p;
    struct polydata q;
    struct ars_rec a;
    struct ars_ext b;
    /*
     *  All records below here are in machine-independent format.
     */
    struct strsol ss;
    struct arbn_rec n;
    /* new pipe solid */
    struct pipewire_rec pwr;
    struct particle_rec part;

    /* Version 0 is Release 4.0 to 4.2, Version 1 is Release 4.4 */
    struct nmg_rec nmg;

    /* Solid of extrusion */
    struct extr_rec extr;

    /* sketch */
    struct sketch_rec skt;

    /* annotation */
    struct annot_rec ant;

    /* script */
    struct script_rec scr;

    /* FASTGEN4 CLINE element */
    struct cline_rec cli;

    /* Bag o' triangles
     *  The vertices are stored in an array
     *  The faces are arrays of three ints each indexing into the array of vertices
     */
    struct bot_rec bot;

}; /* union record */
#define DB_RECORD_NULL	((union record *)0)


/* DEPRECATED: do not use. */
DEPRECATED void rt_fastf_float(fastf_t *ff, const dbfloat_t *fp, int n, int flip);

/* DEPRECATED: do not use. */
DEPRECATED void rt_mat_dbmat(fastf_t *ff, const dbfloat_t *dbp, int flip);

/* DEPRECATED: do not use. */
DEPRECATED void rt_dbmat_mat(dbfloat_t *dbp, const fastf_t *ff);

__END_DECLS

#endif	/* RT_DB4_H */

/** @} */
/*
 * Local Variables:
 * mode: C
 * tab-width: 8
 * indent-tabs-mode: t
 * c-file-style: "stroustrup"
 * End:
 * ex: shiftwidth=4 tabstop=8
 */
