// $Id: MC.h 1079 2010-11-10 23:03:23Z martin $
/*  This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
//
/////////////////////////////////////////////////////////////////////////////////////////////
//      FileName:       MarchingCubes.cpp
//      Author  :       Michael Y. Polyakov
//      email   :       myp@andrew.cmu.edu  or  mikepolyakov@hotmail.com
//      website :       www.angelfire.com/linux/myp
//      date    :       July 2002
//      
//      Description:    'Straight' and Recursive Marching Cubes Algorithms
//                              Normal vectors are defined for each vertex as a gradients
//                              For function definitions see MarchingCubes.h
//                              For a tutorial on Marching Cubes please visit www.angelfire.com/myp/linux
//
//      Please email me with any suggestion/bugs.
/////////////////////////////////////////////////////////////////////////////////////////////

#ifndef MARCHINGCUBES_H_
#define MARCHINGCUBES_H_

#include "mpVector.h"
//#include "MCTable.h"

//struct for storing triangle information - 3 vertices and 3 normal vectors for each vertex

typedef struct
{
    mpVector p[3];
    mpVector norm[3];
} TRIANGLE;


//does Linear Interpolation between points p1 and p2 (they already contain their computed values)
mpVector LinearInterp (mp4Vector p1, mp4Vector p2, float value);

////////////////////////////////////////////////////////////////////////////////////////
//POINTERS TO FUNCTIONS
//pointer to function which computes the value at point p
typedef float (*FORMULA) (mpVector);

////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////
///// MARCHING CUBES ALGORITHM /////
/////////////////////////////////////////////////////////////////////////////////////////

// 'STRAIGHT' Marching Cubes Algorithm //////////////////////////////////////////////////
//takes number of cells (ncellsX, ncellsY, ncellsZ) to subdivide on each axis
// minValue used to pass into LinearInterp
// gradFactor for each axis (multiplies each component of gradient vector by 1/(2*gradFactor) ).
//              Should be set to the length of a side (or close to it)
// array of length (ncellsX+1)(ncellsY+1)(ncellsZ+1) of mp4Vector points containing coordinates and values
//returns pointer to triangle array and the number of triangles in numTriangles
//note: array of points is first taken on z axis, then y and then x. So for example, if you iterate through it in a
//       for loop, have indexes i, j, k for x, y, z respectively, then to get the point you will have to make the
//               following index: i*(ncellsY+1)*(ncellsZ+1) + j*(ncellsZ+1) + k .
//              Also, the array starts at the minimum on all axes.
TRIANGLE *MC (int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY,
	      float gradFactorZ, float minValue, mp4Vector * points, int &numTriangles);

/////////////////////////////////////////////////////////////////////////////////////////
/*
extern "C" { // map the MC function to C
  TRIANGLE * MC_c (int ncellsX, int ncellsY, int ncellsZ, 
		   float gradFactorX, float gradFactorY, float gradFactorZ,
		   float minValue, mp4Vector * points, int &numTriangles) {
    return MC(ncellsX, ncellsY, ncellsZ, 
	      gradFactorX, gradFactorY, gradFactorZ,
	      minValue, points, &numTriangles);
  }
//  void MCfree_c (TRIANGLE * trianglePt) {delete [] trianglePt;}
}
*/
/////////////////////////////////////////////////////////////////////////////////////////


// RECURSIVE Marching Cubes     /////////////////////////////////////////////////////////////
//DrawBacks: must know how many objects are drawn

//This function starts the Recursive Marching Cubes
// numCubes: number of intersecting cubes passed as starting points
// ii, jj, kk: arrays of size numCubes. Contain respective indexes of cubes that are intersected
TRIANGLE *MarchingCubesRec (int ncellsX, int ncellsY, int ncellsZ,
			    float gradFactorX, float gradFactorY, float gradFactorZ,
			    int numCubes, int *ii, int *jj, int *kk,
			    float minValue, mp4Vector * points, int &numTriangles);

//Next 6 functions are called by the corresponding face of each cube (e.g. face 0 calls MCFace0 etc...)
// Each function accepts the following information as arguments:
//      First 3 arguments: number of cells to subdivide on each axis
//      gradFactor: factor to scale the gradient vectors (multiplies by 1/(2*gradFactor) )
//      ind: index of this cube in the points array (this is so it doesnt have to be computed again)
//      i,j,k: indexes of the this cube on x,y,z axis respectively
//      minValue: minimum used in LinearInterp
//      points: array of type mp4Vector and size (ncellsX+1)*(ncellsY+1)*(ncellsZ+1) that contains
//              coordinates and values at each point
//      triangle: array of triangles which is being built and returned at the end of recursion
//      numTriangles: number of triangles formed
//      prevVerts: adjacent 4 vertices of the previous cube, passed in the special order which the correspoding
//              MCFace function recognizes. For specificatino on which indexes passed from the last cube go to 
//              which vertexes of the current cube visit my website at www.angelfire.com/linux/myp
//      prevIntVerts: array of 4 linearly interpolated vertices on 4 adjacent edges
//      edgeIndex: integer, bits of which correspond to the edges of the current cube which have been computed
//              from the previous cube
//      prevGradVerts: array of 4 gradient vectors at 4 adjacent vertices
//      prevGrads: linearly interpolated gradient vectors on 4 adjacent edges
//      gradIndex: integer bits of which correspond to already computed vertices of the current cube
//      marchedCubes: bool array of size ncellsX*ncellsY*ncellsZ which stores which cubes already have been marched
//              through. Initialized to FALSE. This is not the most effective way in terms of memory management, but
//              faster than using STLs vector<bool> which stores booleans as bits.
// * NOTE *: Each of these 6 functions run marching cubes on the 'next'cube adjacent to the surface number
//              that is specified in their names (for numbering see my webpage). Each assigns the previous computed
//              values to the face 'opposite' of that specified. Then each one runs Marching Cubes for the current cube.
//              It returns doing nothing if the cube is not intersected, however, if it is then other recursive
//              functions are called using macros MC_FACE defined for each face. See MarchingCubes.cpp
//              For example MCFace0 will initialize surface 2 using the previous values that are passed to it. Then if
//              the current cube is intersected it will run MC_FACE0, MC_FACE1, MC_FACE3, MC_FACE4, and MC_FACE5. Each
//              returnes the pointer to the array of formed triangles.

//FACE 0 Marching Cubes
TRIANGLE *MCFace0 (int ncellsX, int ncellsY, int ncellsZ,
		   float gradFactorX, float gradFactorY, float gradFactorZ,
		   int ind, int i, int j, int k,
		   float minValue, mp4Vector * points, TRIANGLE * triangles,
		   int &numTriangles, mp4Vector prevVerts[4], mpVector prevIntVerts[4],
		   int edgeIndex, mp4Vector prevGradVerts[4], mpVector prevGrads[4],
		   int gradIndex, bool * marchedCubes);
//FACE 1 Marching Cubes
TRIANGLE *MCFace1 (int ncellsX, int ncellsY, int ncellsZ,
		   float gradFactorX, float gradFactorY, float gradFactorZ,
		   int ind, int i, int j, int k,
		   float minValue, mp4Vector * points, TRIANGLE * triangles,
		   int &numTriangles, mp4Vector prevVerts[4], mpVector prevIntVerts[4],
		   int edgeIndex, mp4Vector prevGradVerts[4], mpVector prevGrads[4],
		   int gradIndex, bool * marchedCubes);
//FACE 2 Marching Cubes
TRIANGLE *MCFace2 (int ncellsX, int ncellsY, int ncellsZ,
		   float gradFactorX, float gradFactorY, float gradFactorZ,
		   int ind, int i, int j, int k,
		   float minValue, mp4Vector * points, TRIANGLE * triangles,
		   int &numTriangles, mp4Vector prevVerts[4], mpVector prevIntVerts[4],
		   int edgeIndex, mp4Vector prevGradVerts[4], mpVector prevGrads[4],
		   int gradIndex, bool * marchedCubes);
//FACE 3 Marching Cubes
TRIANGLE *MCFace3 (int ncellsX, int ncellsY, int ncellsZ,
		   float gradFactorX, float gradFactorY, float gradFactorZ,
		   int ind, int i, int j, int k,
		   float minValue, mp4Vector * points, TRIANGLE * triangles,
		   int &numTriangles, mp4Vector prevVerts[4], mpVector prevIntVerts[4],
		   int edgeIndex, mp4Vector prevGradVerts[4], mpVector prevGrads[4],
		   int gradIndex, bool * marchedCubes);
//FACE 4 Marching Cubes
TRIANGLE *MCFace4 (int ncellsX, int ncellsY, int ncellsZ,
		   float gradFactorX, float gradFactorY, float gradFactorZ,
		   int ind, int i, int j, int k,
		   float minValue, mp4Vector * points, TRIANGLE * triangles,
		   int &numTriangles, mp4Vector prevVerts[4], mpVector prevIntVerts[4],
		   int edgeIndex, mp4Vector prevGradVerts[4], mpVector prevGrads[4],
		   int gradIndex, bool * marchedCubes);
//FACE 5 Marching Cubes
TRIANGLE *MCFace5 (int ncellsX, int ncellsY, int ncellsZ,
		   float gradFactorX, float gradFactorY, float gradFactorZ,
		   int ind, int i, int j, int k,
		   float minValue, mp4Vector * points, TRIANGLE * triangles,
		   int &numTriangles, mp4Vector prevVerts[4], mpVector prevIntVerts[4],
		   int edgeIndex, mp4Vector prevGradVerts[4], mpVector prevGrads[4],
		   int gradIndex, bool * marchedCubes);



//Does Marching Cubes on cube (i, j, k) in points
// Requirements: needs index ind which specifies which cube it is (its 0th point in points array)
//      If cube is intersected the triangles are added to triangles array passed to it, and numTriangles is
//      incremented appropriately. verts, array of vertices of this cube should be initialized.
//      intVerts, interpolated vertices on edges, gradVerts, gradients on vertices, and grads, interpolated
//      gradient vectors on edges dont have to be initialized, but if they are corresponding bits in edgeIndex
//      and indGrad index should show it. (for numbering see my web page)
//      Global variables YtimeZ should be initialized to (ncellsZ+1)*(ncellsY+1) and pointsZ should be ncellsZ+1
TRIANGLE *MarchOneCube (int ncellsZ,
			float gradFactorX, float gradFactorY, float gradFactorZ,
			int ind, float minValue, mp4Vector * points, TRIANGLE * triangles,
			int &numTriangles, mp4Vector verts[8], mpVector intVerts[12],
			int &edgeIndex, mp4Vector gradVerts[8], mpVector grads[12],
			int &indGrad);


//Find the first intersecting cube (if it exists).
//Starts at (i,j,k)=(0,0,0) at the minimum x,y,z and then goes linearly searching for an intersecting cube.
//Returns array of indices i,j,k of the first found cube or -1,-1,-1 if cube was not found
float *MCFind (int ncellsX, int ncellsY, int ncellsZ, float minValue, mp4Vector * points);

//Calls the MCFind and if found calls MarchingCubesRec with the returned indices
//If not found NULL is returned and numTriangles is set to ZERO.
TRIANGLE *MCRecFind (int ncellsX, int ncellsY, int ncellsZ,
		     float gradFactorX, float gradFactorY, float gradFactorZ,
		     float minValue, mp4Vector * points, int &numTriangles);

#endif
