/*
 * fractalobject.h
 *
 * Peter Janssen - janssen@cs.kuleuven.ac.be
 *
 */

#ifndef FRACTALOBJECT_H
#define FRACTALOBJECT_H

#define GeomFractalObjCreate(m, n, d, s, e) \
           GeomCreate((GeomRef)FractalObjCreate(m, n, d, s, e), FractalObjMethods())

#define MAXVALUE              2147483647
#define PointsToAllocate      70
#define TrianglesToAllocate   150
#define EntitiesToAllocate    6

#define max3(a, b, c) (((a) > (b)) && ((a) > (c)) ? (a) :  \
                      (((b) > (c)) ? (b) : (c)))
#define min3(a, b, c) (((a) < (b)) && ((a) < (c)) ? (a) :  \
                      (((b) < (c)) ? (b) : (c)))


#define CheckPoints(p, n, a)                               \
           if (n == a) {                                   \
               a += PointsToAllocate;                      \
               p = (FractalPoint *)realloc((char *)p, a * sizeof(FractalPoint));   \
           }

#define CheckTriangles(t, n, a)                              \
           if (n == a) {                                     \
               a += TrianglesToAllocate;                     \
               t = (FractalTriangle *)realloc((char *)t, a  * sizeof(FractalTriangle)); \
           }

#define CheckEntities(e, n, a)                               \
           if (n == a) {                                     \
               a += EntitiesToAllocate;                      \
               e = (FractalEntity *)realloc((char *)e, a * sizeof(FractalEntity));    \
           }

/*
 * Convert from voxel number along X/Y/Z to corresponding coordinate.
 */
#define Fvoxel2x(g,x)            ((x) * g->VoxelSize[0] + g->Bounds[0][0])
#define Fvoxel2y(g,y)            ((y) * g->VoxelSize[1] + g->Bounds[0][1])
#define Fvoxel2z(g,z)            ((z) * g->VoxelSize[2] + g->Bounds[0][2])
/*
 * And vice-versa.
 */
#define Fx2voxel(g,x)            (equal(g->VoxelSize[0], 0.) ? 0 :             \
                                   (((x) - g->Bounds[0][0]) / g->VoxelSize[0]))
#define Fy2voxel(g,y)            (equal(g->VoxelSize[1], 0.) ? 0 :             \
                                   (((y) - g->Bounds[0][1]) / g->VoxelSize[1]))
#define Fz2voxel(g,z)            (equal(g->VoxelSize[2], 0.) ? 0 :             \
                                   (((z) - g->Bounds[0][2]) / g->VoxelSize[2]))

typedef struct DeltaInfo {
    Float   x, y, z, distance;
} DeltaInfo;

typedef struct FractalPoint {
    Float  x, y, z;
} FractalPoint;

typedef struct PointPool {
    int            NumberOfPoints;
    int            PointsAllocated;
    FractalPoint  *Points;
} PointPool;

typedef struct FractalTriangle {
   int    Point[3];
} FractalTriangle;

typedef struct TrianglePool {
   int               NumberOfTriangles;
   int               TrianglesAllocated;
   int               PoolChanged;
   FractalTriangle  *Triangles;
} TrianglePool;

typedef struct TriangleList {
   int                   TriangleNumber;
   struct TriangleList  *Next;
} TriangleList;

typedef struct FractalEntity {
   int            XSize, YSize, ZSize;
   TriangleList  *Triangles;
} FractalEntity;

typedef struct EntityPool {
    int             XSize, YSize, ZSize;
    int             NumberOfEntities;
    int             EntitiesAllocated;
    FractalEntity  *Entities;
} EntityPool;

typedef struct LastPoint {
    int                  Point;
    int                  NewPoint;
    struct LastPoint    *Next;
} LastPoint;

typedef struct FirstPoint {
    int                  Point;
    LastPoint           *Info;
    struct FirstPoint   *Next;
} FirstPoint;



typedef struct FractalClosure {
    PointPool      *Pointpool;
    TrianglePool   *Trianglepool;
    EntityPool     *Entitypool;
} FractalClosure;

typedef struct TriangleInfo {
    int                       Point[3];
    unsigned long             Counter;
} TriangleInfo;

typedef struct TriangleClosure {
    TriangleInfo             *Triangle;
    struct TriangleClosure   *Next;
} TriangleClosure;


typedef struct SubObject {
    Float                 Bounds[2][3];
    short                 XSize, YSize, ZSize;
    Float                 VoxelSize[3];
    TriangleClosure   ****Cells;
    TrianglePool         *Trianglepool;
    struct SubObject     *Next;
} SubObject;



typedef struct FractalObj {
   Float            MaximumSize;
   Float            Dimension;
   Float            Excentricity;
   Float            Bounds[2][3];
   SubObject       *SubObjects;
   FractalClosure  *Closure;

   Vector           IntersectPos;
   Vector           Normal;

} FractalObj;



extern FractalObj *FractalObjCreate();
extern int         FractalObjIntersect(), FractalObjNormal();
extern void        FractalObjStats();
extern char       *FractalObjName();
extern Methods    *FractalObjMethods();

extern FractalClosure *Fractalclosure;

#endif /* FRACTALOBJECT_H */





