#pragma ident "@(#)types.h	1.2 98/08/25 SMI"

/*
 * types.h 
 *
 *	@(#)types.h 1.9 96/07/04 14:59:13
 *
 * Copyright (c) 1996, Sun Microsystems Computer Company, Mountain View, CA
 *
 *			All Rights Reserved
 *
 *	This is a program for manipulating 3D objects.  It is currently being
 *	developed by Mike M. Chow under the directions of Scott R. Nelson. 
 *
 *      This module contains the geometry types: Vertex, Facets, etc..
 */

#ifndef _modelviewer_types_
#define _modelviewer_types_
#include <stdio.h>
#include <sys/time.h>
#include "typedefs.h"
#include "attrib.h"
#include "meshify.h"
#include "utils.h"
#include "cgp.h"

/* 
 * Geometry Overview
 * =================
 * 
 * ModelViewer geometry primitives are divided into  vertices, edges,
 * facets, parts, and finally objects.  Vertices, edges, and facets are
 * related in a ring.  Like a winged-edge structure, each vertex knows
 * which facets sharing them.  Each edge knows the two facets that shares
 * the edge.  And each facet knows about the indices to the vertices.
 * 
 * This vertex-facet-edge ring structure is good for:
 * 
 * 1. Finding optimized triangle strips.  Sending long triangle strips
 * down to the hardware saves bandwidth and allow more vertices to be
 * sent per frame.  This reason along is important enough to motivate
 * this ring structure.
 *  
 * 2. Finding and removing redundant edges.  The algorithm in edge.c
 * shows how to do this with this ring structure.
 * 
 * 3. Finding hard edges and vertices with high curvature.  Currently,
 * they are not implemented.
 *            
 * 
 * Objects and Parts
 * =================
 * 
 * When an object is read from a file, we make a new object that contains
 * an initial vertex array which will be expanded as more vertices are
 * read in.  Each object has one vertex array that is referenced by all
 * of its facets and parts.  Thus, when an object is destroyed, so does
 * all of its geometry including vertex array and facet lists.
 * 
 * In wavefront files, a part is a subsection of an object (such as a
 * wheel of a car).  Thus, each ModelObject has an array of parts.  Each
 * part has a linked list of facets which is used for triangulation and
 * strips finding.  Each part also has a array of edge pointers.  See
 * edge.c for more info on edges.
 * 
 * After an object is loaded, we triangulate its facets and find the
 * triangle strips (stripifyer is in triStrips.c).  These strips are
 * stored in each part of the object.
 * 
 * Later, when we are ready to draw, we create a display list of the
 * triangles for each part of the object.  This way, during subsequent
 * drawings, we loop through each part and call their display lists.
 * 
 * 
 * Facet, Edge, and Vertex
 * =======================
 * 
 * Each facet has an array of vertex indices to the object's varray.
 * Each facet also has an array of edges (exactly numVert edges).  It
 * also has an prev and next pointer to facets.  This is used to link
 * together the facets that belongs to each part.  Note that a part is
 * the actual repository for the facets.
 * 
 * Edge is heavily used by the triangle stripifier (see triStrips.c) and
 * also by edge.c to find redundant edges.  Each edge has f1p1 and f1p2
 * to point to the indices to the facet1's vindex array.  This is mainly
 * for fast, constant time, access (trading processing time for memory
 * usage).  Same goes for f2p1 and f2p2.  See triStrips.c for usage info.
 * 
 * Each vertex lives in the vertex array of each object.  If the object
 * is deleted so will its vertices.  All references to vertices (vertex
 * indices) are made within each object (not across different objects).
 * Each vertex has a list of facets that share the vertex (FacetList).
 * This is part of the ring data structure for fast searches (used by
 * triStrips.c and edge.c).
 * 
 * Normals 
 * =======
 * 
 * A word on normals is due.  Currently, modelviewer supports only facet
 * normals. But it gives illusion of vertex normals by forcing each of
 * the vertices of a facet to have the same normal as the facet.  This
 * works well for smooth surfaces where surface normals change smoothly.
 * However, on hard edges, there will be lighting artifacts.
 * 
 */




/* Vertex */
 struct Vertex{
    Point       p;	      /* Actual x, y, z */
    Point       normal;	      /* Vertex normal */
    SurfaceProp *surf;        /* Vertex surface colors */
    int         flags;        /* flags: vtx_pos, vtx_pos_norm, 
			       * vtx_pos_norm_color, etc. */
    FacetList  *facets;       /* Facets sharing this vertex */ 
    LinkedList *elist;        /* List of edges sharing this vertex */
    Part       *owner;	      /* Part that owns this */
    
    int         tag;          /* General purpose tag (for time stamping) */
    float       radius;       /* Radius of curvature per vertex */
    int         boundaryVertex; /* Whether this vertex is at the boundary of
				* two regions */
 };

#define TYPES_VTX_POS   1
#define TYPES_VTX_NORM  2
#define TYPES_VTX_COLOR3f 4
#define TYPES_VTX_COLOR4f 8
#define TYPES_VTX_DATA  16

#define TYPES_VTX_FLAGS_HAS(vtx, flag) (vtx->flags & flag)


/* Edge */
struct Edge{
    int         f1p1,  	      /* facet1 index of point1 in facet's 
				 vindex array (see triStrips.c for usage)*/
		f1p2;	
    int         f2p1, f2p2;   /* facet2 index to its vindex array of
				 the two points of the edge. */
    VertIndex   vid1, vid2;   /* Indices to two vertices */
    Vertex      *v1, *v2;     /* Pointers to the two edge vertices */ 
    Facet       *f1, *f2;     /* Pointers to facets sharing the edge */
    Point       normal;       /* Average of two facet normals */
    Part        *owner;       /* Which part owns this */
    float       edgeAngle;    /* How sharp this edge is */
    int         hard;         /* Is edge a hard edge */
    Edge	*next;	      /* Next edge on Part's list of edges */
};

/* Facet */
struct Facet{
    Edge         **edges;     /* An array of pointers to edges */
    int          numEdges;    /* Total number of edges */
    VertIndex   *vindex;      /* Array of facet vertex indices*/
    int          vindexSize;  /* Size of vindex array */	
    int          numVerts;    /* Number of facet points */

    int         *tindex;      /* Array of texture indices */ 
    int          tindexSize;  /* Size of tindex array */
    int          numTexCoords;/* Num of tindex coords */
    Point        normal;      /* Normal for the facet */
    Part        *owner;       /* Which part owns this */
    long         timeStamp;   /* Time stamp used in triStrips.c */
    Facet       *prev;        /* Previous facet in list */
    Facet       *next;        /* Next facet in list*/
    int          selected;    /* For picking */
    float       *pickedColor; /* Picked color */
    int          adjacencyCnt; /* Number of adjacent facets (change at runtime
				  depending on meshify algorithm). */
    float       radius;       /* Average radius of curvature of verts */
    MeshRegion      *region;      /* Region that this facet belongs */
    int          boundaryFacet; /* Whether this facet is on the boundary of two 
				* regions. */
    int         hasHardEdge;    /* Whether this facet has an hard edge */
    int         minGridLoc[3];  /* Min and Max grid locations intersected */
    int         maxGridLoc[3];
    BBox        *bbox;          /* Bounding box around this facet */
};


/* FacetList
 *   A small linked list used for each vertex to find
 *   all facets sharing the point.
 */

struct FacetList {
	Facet *	current;       /* Actual pointer to the facet. */
	FacetList * next;      /* Next */
};

struct MeshRegion {
  Facet            *refFacet;  /* Reference facet for this region (center facet)*/
  LinkedList       *flist;     /* List of facets on this region */
  int               facetCnt;  /* Number of facets in this region */
  Part             *owner;     /* Part that owns this region */
  LinkedList       *adjRegions; /* List of neighboring regions */
  int               quantLevel; /* How much to quantize this region */
  float             maxNormalChange; /* Max change in normal between any two 
				      * facets in this region. */
  BBox             *bbox;       /* Region's bbox */
  float             bboxSize[3]; /* Region's bbox size */
  float             maxSizeRatio; /* Max size ratio of bbox length, width, height */
  float             boundaryRatio; /* Ratio of boundary verts to total verts */
  MeshInfo         *meshInfo;     /* GTmeshes for this region */
  CGubyte          *cmpBuff;      /* Compressed buffer */
  CGint             cmpSize;      /* Compressed buffer size */ 
  CGviewport        viewport;     /* Compressed geometry's local scale+offset*/
  float             aveTriBboxLen;/* Average triangle bbox length */
  float            *quantColor;  /* Color of the region */
};

struct EdgeList {
	Edge *current;       /* Actual pointer to the facet. */
	EdgeList *next;      /* Next */
};



/* Triangle strip */
struct TriStrip {
    VertIndex      *tri;       /* Array of vertex indices 
				* for the triangle strip.*/ 
    int            length;     /* The length of the strip. */
    int            arraySize;  /* tri array size */	
    int            triCnt;     /* Number of triangles */
    TriStrip       *next;      /* Pointer to next strip in a strip list */
};	
 	

/* Triangle strips */
struct TriStrips {
    TriStrip       *strips;    /* A list of triangle strips */
    int             numStrips; /* Number of triangle strips */
    int             triCnt;    /* Number of triangles */
};


/* Line strips */
/* Line strips is currently unimplemented. It'll be replaced by
   something similar to triStrips */

struct LineStrips {
    VertIndex      *lines;       /* Array of vertex indices 
				    for the line strips*/ 
    int            *lengths;     /* Array of lengths for the strips */
    int             numStrips;   /* Number of strips */
    int             lineCnt;     /* Number of lines */
};



/* Part */
struct Part {
    char           *name;       /* Part name */
    Facet          *facets;     /* List of facets */
    Edge           *edges;      /* Array of edges */
    ModelObject    *obj;	/* Object that part belongs to */
    TriStrips      *triStrips;  /* Stores the triangle strips
				 * for solid mode */
    LineStrips     *lineStrips; /* Stores the line strips for wire mode */
    MeshInfo       *meshInfo;   /* Set of GTMeshes */
    
/* display list mode */
    int         dlTri;		 /*display list id for triangles */
    int         dlEdges;	 /*dpy list id for edges */
    int         dlPt;		 /*dpy list id for points */

    int		triCnt;		/* Number of triangles in this part. */
    int		edgeCnt;	/* Number of edges. */
    int		pointCnt;	/* Number of points. */
		
    Attrib     *attrib;		/* Attributes */
    BBox       *bbox;            /* Bounding Box for this part */
    CGubyte    *cmpBuff;         /* Compressed buffer */
    CGint     cmpSize;         /* Compressed buffer size */
    FacetList  *cornerFacets;    /* List of boundary corner facets |__ */
    LinkedList *regions;         /* List of regions for this part*/
    int         aveStripLen;     /* Average triStrip length */
    int         maxQuant;        /* Maximum needed quantization */
    int         hardEdgeCount;   /* Total hard edges in this part */
};


/* ModelObject's Transforms */

struct ModelTrans {
  Point translate;		/* Translation */
  Point scale;			/* Scale       */
  Point center;			/* Object center in World Space */	
  double rotMat[16];		/* Rotation matrix */
  float xDeg, yDeg, rotDeg;	/* 2D rotation change when user moves the 
				  mouse. See modelViewer.c motion for more.*/
  float xAnimDeg, yAnimDeg, rotAnimDeg; /* Animation automatic motion */
};


/* BBox */
struct BBox {
	Point min;		/* minimums of the 6 coords */
	Point max;		/* max of the 6 coords */
};


/* ModelObject is a list of parts */
struct ModelObject {
    char           *name;	 /* Name of object */	
    char	   *filepath;	 /* File path to the object (for saving) */
    Part          **parts;       /* Parts array pointers */
    int             partCnt;     /* Part count */
    int             maxPartCnt;  /* Max Part count */    	
    Vertex         *varray;      /* Array of vertices */
    int             varraySize;  /* Vertex array size */	
    int             vertCnt;     /* total number of vertices */

    BBox	   *bbox;        /* Bbox for the object */			
    ModelTrans     *transform;   /* Model's dynamic state */
    Attrib         *attrib;	 /* Attributes */		
    int		    nodeCnt;	 /* How many nodes currently reference 
				    this obj. If nodeCnt is 0, this obj 
				    will be deleted. */ 
    int            dlistInitialized; /* This bit variable keeps track of 
					whether an object has its display
					lists initialized. */
    
};


/* a Surface has the material properties */
struct SurfaceProp{
    float *diffuse;
    float *specular;
    float *shininess;
    float *emission;
    float *ambient;
};


#define AVE_STRIP_SIZE 100	/*This is used by triStrips.c and types.c
				  for allocating the initial triStrip size */




/* Prototypes related to each of types */

/*types.c*/

/* Point and Vertex */
void printPoint(Point p);
void pointCopy(Point p1, Point p2);
int pointEqual(Point p1, Point p2);
void pointPrint(FILE *fp, int indent, float c[]);

int expandArray (void **ary, int elementSize,
		 int* currentSize, int expandSize);
Vertex *vertexNew();	
int findVertex(ModelObject *obj, Point pt);
int createVert(Vertex **varrayPtr, int *varraySize, 
	       int *vertCntPtr, Point newPt);
int findCreateVert(Vertex **varrayPtr, int *varraySize,
		   int *vertCntPtr, Point newPt, float equalThreshold);
int findCreateVertFast(Vertex **varrayPtr, int *varraySize, int *vertCntPtr, 
		       Point newPt, int timeOut, float equalThreshold);

/* Matrix */
void matrixCopy(Matrix m1, Matrix m2);
void matrixMakeIdentity(Matrix m);

/* Edge */
Edge *edgeNew(Part *owner, Vertex *v1, Vertex *v2);
void edgeDestrory(Edge *);
int applyToEdges (Edge *elist, int (*f)(Edge *));
void findPartEdges (Part *part);
void findObjEdges (ModelObject *obj);
void printEdges(Part *part);

/* Facet */ 
Facet *facetNew(Part *owner);
void facetAddVindex(Facet *fptr, ModelObject *obj, VertIndex index);
void facetNewEdges(Facet *fptr);
void facetAddEdge(Facet *fptr, int i, Edge *eptr);
int applyToFacets (Facet *flist, int (*f)(Facet *, int count, void *data),
		   void *data);
void facetPrint(Facet *fptr);

int facetForEachAdjFacet (Facet *currFptr, 
			  int (*f)(Facet *adjFacet, Edge *adjEdge, void *data),
			  void *data);
Edge *facetGetEdge(Facet *fptr, int p, int q);
void facetFindBbox(Facet *fptr);
void findFacetAdjacency(Part *part);

/* Facet List */
FacetList *flistNewNode ();
void flistAddFacet (FacetList **flist, Facet *fptr);
void flistDestroy(FacetList *flist);
/* Edge List (from LinkedList) */
void edgeListAddEdge(LinkedList **elist, Edge *eptr);

/* Parts */
Part *partCreate (ModelObject *ownerObj);
void partFindBbox(Part *p);
void partAddFacet(Part *part, Facet *fptr);

/* ModelTrans */
ModelTrans *transformCreate();
ModelTrans *transformReset(ModelTrans *mx, int class);
void transformCopy(ModelTrans *dest, ModelTrans *src);
void transformPrint(FILE *fp, int start, ModelTrans *trans);

/* ModelObject */
void objAddPart(ModelObject *obj, Part *newPart);
ModelObject *objCreate();
void objGotoCenter (ModelObject *obj);
Part *objLookupPart(ModelObject *obj, char *partName);
void addModelObj (ModelObject *obj);
void objDestroy(ModelObject *obj);
void objDestroyAll();
void objFindPartBbox (ModelObject *obj);

void gotNewPart(ModelObject *obj, Part **currPart, char *name);
void gotNewVertex(ModelObject *obj, Point p);


/* SurfaceProp */
SurfaceProp *surfCreate();
SurfaceProp *surfCreateEmpty();
SurfaceProp *surfCreateDefault();
void surfDestroy(SurfaceProp *surf);
void surfCopy(SurfaceProp *dest, SurfaceProp *src);
void surfSetAllColorMasks(Attrib *attrib);
void surfPrint(FILE *fp, int indent, SurfaceProp *surf);
float *rgbaCreate(float c[]);
float *rgbaCopy(float dest[], float src[]);

/* BBox */
BBox *bboxCreate();
void bboxDestroy(BBox *bbox);
void bboxExtendPoint (BBox *bbox, Point p);
BBox *bboxMerge(BBox *dest, BBox *src, ModelTrans *transform, Point scale);
BBox *bboxCopy(BBox *dest, BBox *src);
void bboxWrite(FILE *fp, int indent, BBox *bbox);
int  ptInBbox(Point p, BBox *bbox);

/* TriStrip */
TriStrip *triStripNew();
TriStrip *triStripCreate ();
void triStripExtendStrip (TriStrip *strip, int index);

/* TriStrips */
TriStrips *triStripsNew ();
void triStripsInit (TriStrips *tstrips);
void triStripsAddStrip (TriStrips *tstrips, TriStrip *ts);
void triStripPrint (TriStrip *strip, Vertex *varray);

/* triStrips.h */
void findTriStrips(Part *part);

/*cube.c*/
ModelObject *makeCube(int tess, char *name);

/* normals.h */
void pointFindNormal(Point p1, Point p2, Point p3, Point normal, int *flag);
void facetFindNormal(ModelObject *obj, Facet * facet_ptr);
void vertexGetNormal(Vertex *vert);
void objGetVertexNormals (ModelObject *obj);

#ifndef _MAXFLOAT
#define _MAXFLOAT
#define MAXFLOAT	((float)3.40282346638528860e+38)
#endif  /* _MAXFLOAT */

#endif    

 /* End of types.h*/
    

