/* 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 _ddgBinTree_Class_ #define _ddgBinTree_Class_ #include "struct/ddgtmesh.h" #include "struct/ddgcntxt.h" typedef unsigned short ddgPriority; #define ddgMAXPRI 0xFFFF #define ddgMINPRI 0 const unsigned int ddgBintreeOffset[32] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000,0x20000000,0x40000000,0x80000000 }; class WEXP ddgTBinTree { static ddgTBinMesh *_mesh; int _dc; int _dr; bool _mirror:1; unsigned int _index; ddgCacheIndex *_cacheIndex; short *_rawHeight; short *_rawMinVal; short *_rawMaxVal; ddgVisState _vis; ddgTBinTree *_pNeighbourDiag; ddgTBinTree *_pNeighbourTop; ddgTBinTree *_pNeighbourLeft; static ddgContext *_ctx; static ddgVector2 _pos; static ddgVector2 _forward; static float _farClip; static float _nearClip; static float _farClipSQ; static int _clipPlanes; static float _cosHalfFOV; static float _varianceScale; static ddgMSTri *_stri; static ddgTCache *_tcache; ddgCacheIndex _chain; unsigned int _visTriangle; ddgPriority forceSplit2( ddgTriIndex tindex); public: ddgTBinTree(ddgTreeIndex i, int dr = 0, int dc = 0, bool mirror = false); ~ddgTBinTree(void); void freeChain(void) { _chain = 0; } ddgCacheIndex chain(void) { return _chain; } unsigned int visTriangle(void) { return _visTriangle; } void visTriangle(unsigned int v) { _visTriangle = v; } ddgTBinTree* pNeighbourDiag(void) { return _pNeighbourDiag; } ddgTBinTree* pNeighbourTop(void) { return _pNeighbourTop; } ddgTBinTree* pNeighbourLeft(void) { return _pNeighbourLeft; } void pNeighbourDiag(ddgTBinTree* t) { _pNeighbourDiag = t; } void pNeighbourTop(ddgTBinTree* t) { _pNeighbourTop = t; } void pNeighbourLeft(ddgTBinTree* t) { _pNeighbourLeft = t; } int dc(void) { return _dc; } int dr(void) { return _dr; } bool mirror(void) { return _mirror; } bool init(void); private: unsigned int row(unsigned int i); unsigned int col(unsigned int i); unsigned int mrow(unsigned int i); unsigned int mcol(unsigned int i); static unsigned int offset(unsigned int l) { return ddgBintreeOffset[l]; } public: static unsigned int level(ddgTriIndex i) { unsigned int l = 0; if (i > 0) while ((i=i/2) > 1) l++; return l; } static bool isRight(ddgTriIndex i) { return ((i%2) == 1); } static bool isLeft(ddgTriIndex i) { return ((i%2) == 0); } static ddgTriIndex parent(ddgTriIndex i) { // asserts (i < _triNo,"Invalid element number."); if (i == 0) return 0; // Was _triNo if (i == 1) return 0; return i/2; } static ddgTriIndex right(ddgTriIndex i) { return i*2; } static ddgTriIndex left(ddgTriIndex i) { return right(i)+1; } private: ddgTriIndex neighbour( ddgTriIndex i); ddgTBinTree *neighbourTree( ddgTriIndex i); public: void tcacheId( ddgTriIndex tindex, ddgCacheIndex ci ) { _cacheIndex[tindex] = ci; } ddgCacheIndex tcacheId( ddgTriIndex tindex ) { return _cacheIndex[tindex]; } short rawHeight( ddgTriIndex tindex ) { return _rawHeight[tindex]; } short rawMinVal( ddgTriIndex tindex ) { return _rawMinVal[tindex]; } short rawMaxVal( ddgTriIndex tindex ) { return _rawMaxVal[tindex]; } private: ddgTNode *gnode(ddgTriIndex tindex); ddgTNode *snode(ddgTriIndex tindex); public: ddgVisState vis(void) { return _vis; } ddgVisState vis(ddgTriIndex tindex) { return gnode(tindex)->vis(); } void vis(ddgTriIndex tindex, ddgVisState v) { snode(tindex)->vis(v); } int priority(ddgTriIndex tindex) { return gnode(tindex)->priority(); } void priority(ddgTriIndex tindex, int p) { snode(tindex)->priority( p ); } float priorityFactor(ddgTriIndex tindex) { return gnode(tindex)->priorityFactor(); } void priorityFactor(ddgTriIndex tindex, float pf) { snode(tindex)->priorityFactor( pf ); } ddgCacheIndex qscacheIndex(ddgTriIndex tindex){ return gnode( tindex)->qscacheIndex(); } void qscacheIndex(ddgTriIndex tindex, ddgCacheIndex i) { snode( tindex)->qscacheIndex(i); } ddgCacheIndex qmcacheIndex(ddgTriIndex tindex){ return gnode( tindex)->qmcacheIndex(); } void qmcacheIndex(ddgTriIndex tindex, ddgCacheIndex i) { snode( tindex)->qmcacheIndex(i); } float heightByPos(unsigned int r, unsigned int c); float treeHeight(unsigned int r, unsigned int c, float dx, float dz); void vertex(ddgTriIndex tindex, ddgVector3 *vout); void textureC(unsigned int tindex, ddgVector2 *vout) { if (_mirror) vout->set(ddgTBinMesh_size-row(tindex),ddgTBinMesh_size-col(tindex)); else vout->set(row(tindex),col(tindex)); vout->multiply( 1.0 / (float)ddgTBinMesh_size); } ddgVisState visibilityTriangle(ddgTriIndex tvc); bool visible(ddgTriIndex i) { return (vis(i) != ddgOUT) ? true : false; } bool fullyvisible(ddgTriIndex i) { return (vis(i) == ddgIN) ? true : false; } void initTriangle( unsigned int level, ddgTriIndex va, ddgTriIndex v1, ddgTriIndex v0, ddgTriIndex vc); void insertSQ(ddgTriIndex tindex, ddgPriority p, ddgCacheIndex ci, ddgVisState parentVis ); ddgCacheIndex removeSQ(ddgTriIndex tindex); void insertMQ(ddgTriIndex tindex, ddgPriority p); void removeMQ(ddgTriIndex tindex); void forceSplit( ddgTriIndex tindex); void forceMerge( ddgTriIndex tindex); void updateSplit(ddgTriIndex tindex, ddgVisState newVis ); void updateMerge(ddgTriIndex tindex, ddgPriority pr); ddgPriority priorityCalc(ddgTriIndex tindex, float priorityFactor); unsigned int index(void) { return _index; } static void initContext( ddgContext *context, ddgTBinMesh *mesh ); static void updateContext( ddgContext *context, ddgTBinMesh *mesh ); bool rayTest( ddgVector3 p1, ddgVector3 p2, ddgTriIndex tindex, int depth = -1 ); }; #ifdef DDGSTREAM WEXP ostream& WFEXP operator << ( ostream&s, ddgTBinTree v ); WEXP ostream& WFEXP operator << ( ostream&s, ddgTBinTree* v ); #endif // DDGSTREAM #endif