#ifndef _mviewer_voxel
#define _mviewer_voxel

typedef struct VGrid VGrid;
typedef struct VGridPoint VGridPoint;
typedef struct VertList VertList;
typedef struct VertSet VertSet;


  
/* VertList is a linked list to keep track of children. */
extern int CurrVertTag; /* Tag used for a vertex in vertex list */ 
struct VertList {
  Vertex	*current;	/* Vert pointer */ 
  VertList	*next;		/* Next node */
};

struct VGridPoint {
  VertList *vertList;
  int       occupied;
  int       numVerts;
  int       selfx, selfy, selfz;
  Point     objLoc;      /* Location in object space */
  Point     projPt;      /* Projected point on the object */
  FacetList *flist;             /* List of original facets bordering 
				 * this pt */
  int       xsectFacet;  /* The number of intersected facets */
  float     distance;    /* Distance from nearest facet */
  float     value;       /* Plugin-dependent value */
  void     *data1;       /* Plugin-dependent pointer */
  void     *data2;       /* Another plugin-dependent pointer */
};

struct VGrid {
  VGridPoint ***vgridpt;
  int        dim[3];
  ModelObject *obj;
  BBox       *bbox;
  Point      bboxSize;
  float      gridScale;         /* Ave. distance bet two verts */
  Vertex     *varray;
  int         varraySize;
  int         vertCnt;
  void       *data1;            /* Plugin dependent data1 */
  void       *data2;            /* Plugin dependent data1 */
};


/* Init distance from surface in voxel grid */
#define VGRIDPT_INIT_DIST 99.0


struct VertSet {
  VertList *vertList;
  int       numVerts;
};

VertList *vertListNewNode ();


void vertListAddVert (VertList **vlist, Vertex *vert);
void vertListRemoveVert (VertList **vlist, Vertex *vert);

void vgridAddVert(VGrid *vgrid, Vertex *vert, int gridLoc[3]);
void vgridRemoveVert(VGrid *vg, Vertex *vert);

VGrid *vgridCreate();

/* vgridFindGridDim takes the arg, gridScaleFactor, 
 * 
 * The ave triangle size is scaled by this factor to make the actual grid
 * size bigger or smaller than actually represented by the triangle
 * size. This is used to make the voxel grid fit tightly or loosely on
 * the object.
 */

void vgridFindGridDim(VGrid *vgrid, BBox *bbox, float gridScaleFactor,
		      float aveTriLength);

void vgridFillGridPoints(VGrid *vg);
void vgridInit(VGrid *vgrid, Point minLoc);

void vgridFindGridLoc(VGrid *vg, Point pt, int gridLoc[3]);

void vgridInsertObj(ModelObject *obj, float gridScaleFactor);
void vgridBinFacet(VGrid *vg, Facet *fptr);
void vgridBinVerts(VGrid *vgrid, ModelObject *obj);
void vgridReBinVert(Vertex *vert, VGrid *vg);
void vgridForEachGridPt(VGrid *vgrid, 
			int (*act)(VGrid *vg, VGridPoint *vgpt, void *data),
			void *data);

void vgridForEachNeighbor2(VGrid *vg, Vertex *vert,
		int (*act)(Vertex *vert, void *data),
		void *data);

void vgridForEachNeighbor(VGrid *vg, Vertex *vstart,
		int (*act)(Vertex *vert, VGridPoint *vgpt, void *data),
		void *data);

Vertex *vgridFindNearestNeighbor(VGrid *vg, Vertex *vert, float axisline, int dir );
#endif

