/*
Copyright (C) 1997, 1998, 1999 by Alex Pfaffe
(Digital Dawn Graphics Inc)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _ddgMesh_Class_
#define _ddgMesh_Class_
#include "math/ddgvec.h"
#include "math/ddgbbox.h"
#include "struct/ddghemap.h"
#include "struct/ddgcache.h"
class ddgTBinTree;
class ddgTBinMesh;
class ddgContext;
// Block size of bintrees within a binmesh.
#define ddgTBinMesh_size 32
#define ddgPriorityResolution 1024
typedef unsigned int ddgTriIndex;
typedef unsigned int ddgTreeIndex;
typedef unsigned short ddgPriority;
typedef enum { eINNER = 0, eTOP = 1, eLEFT = 2, eDIAG = 3} Edge;
class WEXP ddgMSTri
{
public:
unsigned int row, col; // Maybe possible to calculate.
ddgTriIndex v0, v1;
ddgTriIndex neighbour;
inline Edge edge(void)
{
if (row == 0)
return eTOP;
if (col == 0)
return eLEFT;
if (row + col == ddgTBinMesh_size)
return eDIAG;
return eINNER;
}
};
class WEXP ddgTNode : public ddgLNode {
friend class ddgTCache;
private:
ddgTriIndex _tindex;
ddgPriority _priority;
ddgVisState _vis;
ddgCacheIndex _qscacheIndex;
ddgCacheIndex _qmcacheIndex;
float _priorityFactor;
public:
void qscacheIndex( ddgCacheIndex ci ) { _qscacheIndex = ci; }
ddgCacheIndex qscacheIndex( void ) { return _qscacheIndex; }
void qmcacheIndex( ddgCacheIndex ci ) { _qmcacheIndex = ci; }
ddgCacheIndex qmcacheIndex( void ) { return _qmcacheIndex; }
inline ddgTriIndex tindex(void) { return _tindex; }
inline void tindex(ddgTriIndex ti) { _tindex = ti; }
inline void priority(int p ) { _priority = p; }
inline int priority(void) { return _priority; }
inline void vis(float v ) { _vis = ddgVisState(v); }
inline ddgVisState vis(void) { return _vis; }
inline void priorityFactor(float pf) { _priorityFactor = pf; }
inline float priorityFactor(void) { return _priorityFactor; }
};
class WEXP ddgTCache : public ddgLCache {
typedef ddgLCache super;
public:
inline void init (unsigned int size ) { super::init(size,sizeof(ddgTNode)); }
inline ddgTNode* get(ddgCacheIndex n)
{
return (ddgTNode*) ddgLCache::get(n);
}
};
class WEXP ddgQNode : public ddgSNode {
friend class ddgQTCache;
private:
ddgTriIndex _tindex;
ddgTreeIndex _tree;
public:
inline ddgTriIndex tindex(void) { return _tindex; }
inline void tindex(ddgTriIndex ti) { _tindex = ti; }
inline ddgTreeIndex tree(void) { return _tree; }
inline void tree(ddgTreeIndex t) { _tree = t; }
};
class WEXP ddgQCache : public ddgSCache {
typedef ddgSCache super;
public:
void init (unsigned int size, unsigned int bn, bool r = false ) {
super::init(size,sizeof(ddgQNode),bn,r);
}
inline ddgQNode* get(unsigned short index)
{
return (ddgQNode*) ddgCache::get(index);
}
inline ddgCacheIndex insert(ddgTreeIndex t, ddgTriIndex ti, short b)
{
ddgCacheIndex ci = super::insert(b);
// Initialize the new node.
ddgQNode *qn = get(ci);
qn->tree(t);
qn->tindex(ti);
return ci;
}
inline void move(ddgCacheIndex ci, short b)
{
super::remove(ci);
super::insert(b);
}
};
class WEXP ddgTBinMesh
{
unsigned int _maxLevel;
unsigned int _triNo;
unsigned int _leafTriNo;
unsigned int _bintreeMax;
ddgTBinTree ** _bintree;
ddgTCache _tcache;
bool _merge;
bool _splitRun;
ddgQCache _qscache;
ddgQCache _qmcache;
unsigned int _nr;
unsigned int _nc;
unsigned int _minDetail;
unsigned int _maxDetail;
unsigned int _absMaxDetail;
float _farClip;
float _farClipSQ;
float _nearClip;
ddgHeightMap *_heightMap;
float _scale;
float _base;
int _absMinHeight;
int _absMaxHeight;
int _absDiffHeight;
unsigned int _triVis;
unsigned int _triCount;
unsigned int _priCount;
unsigned int _insCount;
unsigned int _remCount;
unsigned int _movCount;
unsigned int _visCount;
unsigned int _balCount;
ddgTriIndex *_indexLUT;
ddgBBox3 _bbox;
public:
ddgTBinMesh( ddgHeightMap *i);
~ddgTBinMesh(void);
ddgMSTri* stri;
bool init( ddgContext *ctx );
void initNeighbours( void );
void initVertex( unsigned int level,
ddgTriIndex va,
ddgTriIndex v1,
ddgTriIndex v0,
ddgTriIndex vc);
inline void incrTriVis(void) { _triVis++; }
inline void decrTriVis(void) { _triVis--; }
unsigned int countTriVis(void) { return _triVis; }
inline unsigned int edge(ddgTriIndex i)
{
return stri[i].edge();
}
ddgTriIndex *indexLUT(void) { return _indexLUT; }
inline ddgTriIndex v0(ddgTriIndex i)
{ ddgAssert(i < triNo()); return stri[i].v0; }
inline ddgTriIndex v1(ddgTriIndex i)
{ ddgAssert(i < triNo()); return stri[i].v1; }
ddgTCache *tcache(void) { return &_tcache; }
bool merge(void) { return _merge; }
void merge(bool m) { _merge = m; }
bool splitRun(void) { return _splitRun; }
ddgQCache *qscache(void) { return &_qscache; }
ddgQCache *qmcache(void) { return &_qmcache; }
inline ddgTriIndex lookupIndex( unsigned short row, unsigned short col )
{
ddgAsserts(row >= 0 && row <= ddgTBinMesh_size
&&col >= 0 && col <= ddgTBinMesh_size,"Invalid coord");
ddgAssert(_indexLUT[row * (ddgTBinMesh_size+1) + col] < _triNo+2);
return _indexLUT[row * (ddgTBinMesh_size+1) + col];
}
ddgHeightMap *heightMap(void) { return _heightMap; }
inline float wheight(short rh)
{
return ddgHeightMap::sconvert(rh,_base,_scale);
}
unsigned int minDetail( void ) { return _minDetail; }
void minDetail( unsigned int d ) { _minDetail = d; }
unsigned int maxDetail( void ) { return _maxDetail; }
void maxDetail( unsigned int d ) { _maxDetail = d; }
unsigned int absMaxDetail( void ) { return _absMaxDetail; }
void absMaxDetail( unsigned int d ) { _absMaxDetail = d; }
unsigned int triNo(void) { return _triNo; }
unsigned int leafTriNo(void) { return _leafTriNo; }
unsigned int maxLevel( void ) { return _maxLevel; }
bool calculate(ddgContext *ctx);
void addBinTree( ddgTBinTree *bt );
void removeBinTree( ddgTBinTree *bt );
ddgTBinTree *getBinTree( ddgTreeIndex i)
{ ddgAssert(i < _bintreeMax && i >= 0); return _bintree[i]; }
unsigned int getBinTreeNo(void) { return _bintreeMax; }
float farClip(void) { return _farClip; }
float farClipSQ(void) { return _farClipSQ; }
float nearClip(void) { return _nearClip; }
inline void farClip(float f) { _farClip = f; _farClipSQ = f * f; }
inline void nearClip(float n) { _nearClip = n; }
bool mapPosToTree(float *x, float *z, ddgTBinTree **bt, unsigned int *r, unsigned int *c);
float height(float x, float z);
int absDiffHeight(void) { return _absDiffHeight; }
int absMinHeight(void) { return _absMinHeight; }
int absMaxHeight(void) { return _absMaxHeight; }
ddgBBox3* bbox(void) { return &_bbox; }
void triCountIncr(void) { _triCount++; }
#ifdef _DEBUG
void priCountIncr(void) { _priCount++; }
void insCountIncr(void) { _insCount++; }
void remCountIncr(void) { _remCount++; }
void movCountIncr(void) { _movCount++; }
void visCountIncr(void) { _visCount++; }
#endif
unsigned int triCount(void) { return _triCount; }
unsigned int priCount(void) { return _priCount; }
unsigned int insCount(void) { return _insCount; }
unsigned int remCount(void) { return _remCount; }
unsigned int movCount(void) { return _movCount; }
unsigned int visCount(void) { return _visCount; }
unsigned int balCount(void) { return _balCount; }
};
#endif