You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

930 lines
34 KiB
C++

/**
* @file
* @brief Representation of an octree for show
* @author Jan Elseberg. Jacobs University Bremen gGmbH, Germany
* @author Andreas Nuechter. Jacobs University Bremen gGmbH, Germany
*/
#ifndef SHOWBOCTREE_H
#define SHOWBOCTREE_H
#include "slam6d/Boctree.h"
#include "show/colormanager.h"
#include "show/scancolormanager.h"
#include "show/viewcull.h"
#include "show/colordisplay.h"
#include "slam6d/scan.h"
using namespace show;
/**
* @brief Octree for show
*
* A cubic bounding box is calculated
* from the given 3D points. Then it
* is recusivly subdivided into smaller
* subboxes
*
* It contains software culling functionalities
*/
template <class T>
class Show_BOctTree : public colordisplay
{
protected:
BOctTree<T>* m_tree;
unsigned long maxtargetpoints;
unsigned int current_lod_mode;
//! A copy of pointdim of the tree initialized from
unsigned int POINTDIM;
DataOcttree* m_cache_access;
Scan* m_scan;
void init(ScanColorManager* scm) {
setColorManager(0);
if (scm) {
scm->registerTree(this);
scm->updateRanges(m_tree->getMins());
scm->updateRanges(m_tree->getMaxs());
}
POINTDIM = m_tree->getPointdim();
maxtargetpoints = maxTargetPoints(m_tree->getRoot());
current_lod_mode = 0;
m_cache_access = 0;
m_scan = 0;
}
public:
//! Create with tree held in cache, lock indefinitely
Show_BOctTree(Scan* scan, DataOcttree* cache_access, ScanColorManager* scm = 0)
{
m_tree = &cache_access->get();
init(scm);
// save cache access and hold it until an unlock
m_cache_access = cache_access;
m_scan = scan;
}
//! Retrieve a cache access object and update the tree pointer
void lockCachedTree() {
if(m_scan != 0 && m_cache_access == 0) {
m_cache_access = new DataOcttree(m_scan->get("octtree"));
m_tree = &(m_cache_access->get());
}
}
//! Remove the data access
void unlockCachedTree() {
if(m_scan != 0 && m_cache_access != 0) {
delete m_cache_access; m_cache_access = 0;
//m_tree = 0;
}
}
//! Create with already constructed tree and take ownership
Show_BOctTree(BOctTree<T>* tree, ScanColorManager* scm = 0) :
m_tree(tree)
{
init(scm);
}
//! Create tree by points
template <class P>
Show_BOctTree(P * const* pts, int n, T voxelSize, PointType pointtype = PointType(), ScanColorManager *scm = 0)
{
m_tree = new BOctTree<T>(pts, n, voxelSize, pointtype, true);
init(scm);
}
//! Create tree by deserializing from file
Show_BOctTree(std::string filename, ScanColorManager *scm = 0)
{
m_tree = new BOctTree<T>(filename);
init(scm);
}
virtual ~Show_BOctTree() {
// only delete cache access if created via this method
if(m_cache_access) {
delete m_cache_access;
}
// if not constructed by a cache-located tree, delete the owned tree
if(!m_scan)
delete m_tree;
}
BOctTree<T>* getTree() const { return m_tree; }
void serialize(const std::string& filename) const { m_tree->serialize(filename); }
unsigned int getMemorySize() const { return m_tree->getMemorySize(); }
// virtual functions from colordisplay
void selectRayBrushSize(set<T *> &points, int brushsize) {
selectRayBS(points, m_tree->getRoot(), m_tree->getCenter(), m_tree->getSize(), brushsize);
}
void selectRay(set<T *> &points, int depth = INT_MAX) {
selectRay(points, m_tree->getRoot(), m_tree->getCenter(), m_tree->getSize(), depth);
}
void selectRay(T * &point) {
selectRay(point, m_tree->getRoot(), m_tree->getCenter(), m_tree->getSize(), FLT_MAX);
}
void cycleLOD() {
current_lod_mode = (current_lod_mode+1)%3;
}
void drawLOD(float ratio) {
switch (current_lod_mode) {
case 0:
glBegin(GL_POINTS);
displayOctTreeCulledLOD(maxtargetpoints * ratio, m_tree->getRoot(), m_tree->getCenter(), m_tree->getSize());
glEnd();
break;
case 1:
glBegin(GL_POINTS);
displayOctTreeCulledLOD2(ratio, m_tree->getRoot(), m_tree->getCenter(), m_tree->getSize());
glEnd();
break;
case 2:
#ifdef WITH_GLEE
if (GLEE_ARB_point_parameters) {
glPointParameterfARB(GL_POINT_SIZE_MIN_ARB, 1.0);
glPointParameterfARB(GL_POINT_SIZE_MAX_ARB, 100000.0);
GLfloat p[3] = {0.0, 0.0000, 0.0000005};
glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, p);
displayOctTreeCPAllCulled(m_tree->getRoot(), m_tree->getCenter(), m_tree->getSize(),
m_tree->getSize() / pow(2, min( (int)(ratio * m_tree->getMaxDepth()), (int)(m_tree->getMaxDepth() - 3))));
p[0] = 1.0;
p[2] = 0.0;
glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, p);
}
#endif
break;
default:
break;
}
}
void draw() {
glBegin(GL_POINTS);
displayOctTreeAllCulled(m_tree->getRoot(), m_tree->getCenter(), m_tree->getSize());
glEnd();
}
// reroute center call (for recast from colordisplay to show_bocttree)
void getCenter(double _center[3]) const {
m_tree->getCenter(_center);
}
protected:
//! ?
unsigned long maxTargetPoints(const bitoct &node) {
bitunion<T> *children;
bitoct::getChildren(node, children);
unsigned long max = 0;
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
pointrep *points = children->getPointreps();
unsigned long length = points[0].length;
if (length > max) max = length;
} else { // recurse
unsigned long tp = maxTargetPoints(children->node);
if (tp > max) max = tp;
}
++children; // next child
}
}
return max*POPCOUNT(node.valid);
}
void displayOctTreeAll(const bitoct &node) {
// T ccenter[3];
bitunion<T> *children;
bitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
pointrep *points = children->getPointreps();
unsigned int length = points[0].length;
T *point = &(points[1].v); // first point
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
if(cm) cm->setColor(point);
glVertex3f( point[0], point[1], point[2]);
point+=POINTDIM;
}
} else { // recurse
displayOctTreeAll( children->node);
}
++children; // next child
}
}
}
void displayOctTreeAllCulled(const bitoct &node, const T* center, T size ) {
int res = CubeInFrustum2(center[0], center[1], center[2], size);
if (res==0) return; // culled do not continue with this branch of the tree
if (res == 2) { // if entirely within frustrum discontinue culling
displayOctTreeAll(node);
return;
}
T ccenter[3];
bitunion<T> *children;
bitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
BOctTree<T>::childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
// check if leaf is visible
// if ( CubeInFrustum(ccenter[0], ccenter[1], ccenter[2], size/2.0) ) {
pointrep *points = children->getPointreps();
unsigned int length = points[0].length;
T *point = &(points[1].v); // first point
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
if(cm) cm->setColor(point);
glVertex3f( point[0], point[1], point[2]);
point+=POINTDIM;
}
//}
} else { // recurse
displayOctTreeAllCulled( children->node, ccenter, size/2.0);
}
++children; // next child
}
}
}
void displayOctTreeLOD2(float ratio, const bitoct &node, const T* center, T size ) {
T ccenter[3];
bitunion<T> *children;
bitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
BOctTree<T>::childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
pointrep *points = children->getPointreps();
unsigned int length = points[0].length;
T *point = &(points[1].v); // first point
int l = LOD2(ccenter[0], ccenter[1], ccenter[2], size/2.0); // only a single pixel on screen only paint one point
l = max((int)(l*l*ratio), 0);
if (l > 1) {
if ((int)length > l ) {
T each = (T)POINTDIM * (T)((T)length/(T)l);
T *p;
int index;
for(int iterator = 0; iterator < l; iterator++ ) {
index = (T)iterator * each;
p = point + index - index%POINTDIM;
if(cm) cm->setColor(p);
glVertex3f( p[0], p[1], p[2]);
}
} else if ((int)length <= l) {
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
if(cm) cm->setColor(point);
glVertex3f( point[0], point[1], point[2]);
point+=POINTDIM;
}
} /* else if (l == 1) {
if(cm) cm->setColor(point);
glVertex3f( point[0], point[1], point[2]);
}*/
} else {
if(cm) cm->setColor(point);
glVertex3f( point[0], point[1], point[2]);
}
} else { // recurse
int l = LOD2(ccenter[0], ccenter[1], ccenter[2], size/2.0); // only a single pixel on screen only paint one point
l = max((int)(l*l*ratio), 0);
if (l > 0) {
displayOctTreeCulledLOD2(ratio, children->node, ccenter, size/2.0);
}
}
++children; // next child
}
}
}
void displayOctTreeCulledLOD2(float ratio, const bitoct &node, const T* center, T size ) {
int res = CubeInFrustum2(center[0], center[1], center[2], size);
if (res==0) return; // culled do not continue with this branch of the tree
if (res == 2) { // if entirely within frustrum discontinue culling
displayOctTreeLOD2(ratio, node, center, size);
return;
}
T ccenter[3];
bitunion<T> *children;
bitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
BOctTree<T>::childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
// check if leaf is visible
if ( CubeInFrustum(ccenter[0], ccenter[1], ccenter[2], size/2.0) ) {
pointrep *points = children->getPointreps();
unsigned int length = points[0].length;
T *point = &(points[1].v); // first point
int l = LOD2(ccenter[0], ccenter[1], ccenter[2], size/2.0); // only a single pixel on screen only paint one point
l = max((int)(l*l*ratio), 0);
if (l != 0) {
if ((int)length > l ) {
T each = (T)POINTDIM * (T)((T)length/(T)l);
T *p;
int index;
for(int iterator = 0; iterator < l; iterator++ ) {
index = (T)iterator * each;
p = point + index - index%POINTDIM;
if(cm) cm->setColor(p);
glVertex3f( p[0], p[1], p[2]);
}
} else if ((int)length <= l) {
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
if(cm) cm->setColor(point);
glVertex3f( point[0], point[1], point[2]);
point+=POINTDIM;
}
} else if (l == 1) {
if(cm) cm->setColor(point);
glVertex3f( point[0], point[1], point[2]);
}
}
}
} else { // recurse
//int l = LOD2(ccenter[0], ccenter[1], ccenter[2], size/2.0); // only a single pixel on screen only paint one point
//l = max((int)(l*l*ratio), 0);
//if (l > 0) {
displayOctTreeCulledLOD2(ratio, children->node, ccenter, size/2.0);
//}
}
++children; // next child
}
}
}
void displayOctTreeLOD3(long targetpts, const bitoct &node, const T* center, T size ) {
if (targetpts <= 0) return; // no need to display anything
T ccenter[3];
bitunion<T> *children;
bitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
BOctTree<T>::childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
pointrep *points = children->getPointreps();
unsigned int length = points[0].length;
T *point = &(points[1].v); // first point
int l = LOD2(ccenter[0], ccenter[1], ccenter[2], size/2.0); // only a single pixel on screen only paint one point
if ( l <= targetpts) { // only a single pixel on screen only paint one point
if(cm) cm->setColor(point);
glVertex3f( point[0], point[1], point[2]);
} else {
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
if(cm) cm->setColor(point);
glVertex3f( point[0], point[1], point[2]);
point+=POINTDIM;
}
}
} else { // recurse
displayOctTreeLOD3(targetpts, children->node, ccenter, size/2.0);
}
++children; // next child
}
}
}
void displayOctTreeCulledLOD3(long targetpts, const bitoct &node, const T* center, T size ) {
if (targetpts <= 0) return; // no need to display anything
int res = CubeInFrustum2(center[0], center[1], center[2], size);
if (res==0) return; // culled do not continue with this branch of the tree
if (res == 2) { // if entirely within frustrum discontinue culling
displayOctTreeLOD3(targetpts, node, center, size);
return;
}
T ccenter[3];
bitunion<T> *children;
bitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
BOctTree<T>::childcenter(center, ccenter, size, i); // childrens center
//l = std::min( max((int)(l*l*ratio), 1), targetpts);
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
// check if leaf is visible
if ( CubeInFrustum(ccenter[0], ccenter[1], ccenter[2], size/2.0) ) {
pointrep *points = children->getPointreps();
unsigned int length = points[0].length;
T *point = &(points[1].v); // first point
int l = LOD2(ccenter[0], ccenter[1], ccenter[2], size/2.0); // only a single pixel on screen only paint one point
if (targetpts <= 0 ) cout << l << " " << targetpts << endl;
if ( l <= targetpts) { // only a single pixel on screen only paint one point
if(cm) cm->setColor(point);
glVertex3f( point[0], point[1], point[2]);
} else {
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
if(cm) cm->setColor(point);
glVertex3f( point[0], point[1], point[2]);
point+=POINTDIM;
}
}
}
} else { // recurse
displayOctTreeCulledLOD3(targetpts, children->node, ccenter, size/2.0);
}
++children; // next child
}
}
}
void displayOctTreeCulledLOD(long targetpts, const bitoct &node, const T* center, T size ) {
if (targetpts <= 0) return; // no need to display anything
int res = CubeInFrustum2(center[0], center[1], center[2], size);
if (res==0) return; // culled do not continue with this branch of the tree
if (res == 2) { // if entirely within frustrum discontinue culling
displayOctTreeLOD(targetpts, node, center, size);
return;
}
T ccenter[3];
bitunion<T> *children;
bitoct::getChildren(node, children);
unsigned short nc = POPCOUNT(node.valid);
long newtargetpts = targetpts;
if (nc > 0) {
newtargetpts = newtargetpts/nc;
if (newtargetpts <= 0 ) return;
}
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
BOctTree<T>::childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
// check if leaf is visible
if ( CubeInFrustum(ccenter[0], ccenter[1], ccenter[2], size/2.0) ) {
pointrep *points = children->getPointreps();
unsigned int length = points[0].length;
T *point = &(points[1].v); // first point
if (length > 10 && !LOD(ccenter[0], ccenter[1], ccenter[2], size/2.0) ) { // only a single pixel on screen only paint one point
if(cm) cm->setColor(point);
glVertex3f( point[0], point[1], point[2]);
} else if (length <= newtargetpts) { // more points requested than possible, plot all
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
if(cm) cm->setColor(point);
glVertex3f( point[0], point[1], point[2]);
point+=POINTDIM;
}
} else { // select points to show
// TODO smarter subselection of points here
T each = (T)POINTDIM * (T)((T)length/(T)newtargetpts);
T *p;
int index;
for(unsigned int iterator = 0; iterator < newtargetpts; iterator++ ) {
index = (T)iterator * each;
p = point + index - index%POINTDIM;
if(cm) cm->setColor(p);
glVertex3f( p[0], p[1], p[2]);
//point += each;
}
}
}
} else { // recurse
displayOctTreeCulledLOD(newtargetpts, children->node, ccenter, size/2.0);
}
++children; // next child
}
}
}
void displayOctTreeLOD(long targetpts, const bitoct &node, const T* center, T size ) {
if (targetpts <= 0) return; // no need to display anything
T ccenter[3];
bitunion<T> *children;
bitoct::getChildren(node, children);
unsigned short nc = POPCOUNT(node.valid);
long newtargetpts = targetpts;
if (nc > 0) {
newtargetpts = newtargetpts/nc;
if (newtargetpts <= 0 ) return;
}
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
BOctTree<T>::childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
pointrep *points = children->getPointreps();
unsigned int length = points[0].length;
T *point = &(points[1].v); // first point
if (length > 10 && !LOD(ccenter[0], ccenter[1], ccenter[2], size/2.0) ) { // only a single pixel on screen only paint one point
if(cm) cm->setColor(point);
glVertex3f( point[0], point[1], point[2]);
} else if (length <= newtargetpts) { // more points requested than possible, plot all
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
if(cm) cm->setColor(point);
glVertex3f( point[0], point[1], point[2]);
point+=POINTDIM;
}
} else { // select points to show
// TODO smarter subselection of points here
T each = (T)POINTDIM * (T)((T)length/(T)newtargetpts);
T *p;
int index;
for(unsigned int iterator = 0; iterator < newtargetpts; iterator++ ) {
index = (T)iterator * each;
p = point + index - index%POINTDIM;
if(cm) cm->setColor(p);
glVertex3f( p[0], p[1], p[2]);
//point += each;
}
}
} else { // recurse
displayOctTreeLOD(newtargetpts, children->node, ccenter, size/2.0);
}
++children; // next child
}
}
}
void selectRay(set<T *> &selpoints, const bitoct &node, const T* center, T size, int max_depth, int depth = 0) {
if (depth < max_depth && !HitBoundingBox(center, size ))return;
T ccenter[3];
bitunion<T> *children;
bitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
BOctTree<T>::childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
// check if leaf is visible
if ( !(depth+1 < max_depth) || HitBoundingBox(ccenter, size) ) {
pointrep *points = children->getPointreps();
unsigned int length = points[0].length;
T *point = &(points[1].v); // first point
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
selpoints.insert(point);
point+=POINTDIM;
}
}
} else { // recurse
selectRay( selpoints, children->node, ccenter, size/2.0, max_depth, depth+1);
}
++children; // next child
}
}
}
void selectRayBS(set<T *> &selpoints, const bitoct &node, const T* center, T size, int brushsize) {
T ccenter[3];
bitunion<T> *children;
bitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
BOctTree<T>::childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
// check if leaf is visible
if ( HitBoundingBox(ccenter, size) ) {
pointrep *points = children->getPointreps();
unsigned int length = points[0].length;
T *point = &(points[1].v); // first point
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
if (ScreenDist(point) < brushsize && RayDist(point) > 100.0)
selpoints.insert(point);
point+=POINTDIM;
}
}
} else { // recurse
selectRayBS( selpoints, children->node, ccenter, size/2.0, brushsize);
}
++children; // next child
}
}
}
void selectRay(T * &selpoint, const bitoct &node, const T* center, T size, float min) {
if (!HitBoundingBox(center, size ))return;
T ccenter[3];
bitunion<T> *children;
bitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
BOctTree<T>::childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
// check if leaf is visible
if ( HitBoundingBox(ccenter, size) ) {
pointrep *points = children->getPointreps();
unsigned int length = points[0].length;
T *point = &(points[1].v); // first point
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
T dist = RayDist(point);
if (min > dist && ScreenDist(point) < 5 && dist > 100.0) {
selpoint = point;
min = dist;
}
point+=POINTDIM;
}
}
} else { // recurse
selectRay( selpoint, children->node, ccenter, size/2.0, min);
}
++children; // next child
}
}
}
void displayOctTreeCAllCulled(const bitoct &node, const T* center, T size, T minsize ) {
int res = CubeInFrustum2(center[0], center[1], center[2], size);
if (res==0) return; // culled do not continue with this branch of the tree
if (res == 2) { // if entirely within frustrum discontinue culling
displayOctTreeCAll(node, center, size, minsize);
return;
}
T ccenter[3];
bitunion<T> *children;
bitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
BOctTree<T>::childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf || minsize > size ) { // if ith node is leaf get center
// check if leaf is visible
if ( CubeInFrustum(ccenter[0], ccenter[1], ccenter[2], size/2.0) ) {
showCube(ccenter, size/2.0);
}
} else { // recurse
displayOctTreeCAllCulled( children->node, ccenter, size/2.0, minsize);
}
++children; // next child
}
}
}
void displayOctTreeCAll(const bitoct &node, const T* center, T size, T minsize ) {
T ccenter[3];
bitunion<T> *children;
bitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
BOctTree<T>::childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf || minsize > size ) { // if ith node is leaf get center
showCube(ccenter, size/2.0);
} else { // recurse
displayOctTreeCAll( children->node, ccenter, size/2.0, minsize);
}
++children; // next child
}
}
}
void displayOctTreeCPAllCulled(const bitoct &node, const T* center, T size, T minsize ) {
int res = CubeInFrustum2(center[0], center[1], center[2], size);
if (res==0) return; // culled do not continue with this branch of the tree
if (res == 2) { // if entirely within frustrum discontinue culling
displayOctTreeCPAll(node, center, size, minsize);
return;
}
T ccenter[3];
bitunion<T> *children;
bitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
BOctTree<T>::childcenter(center, ccenter, size, i); // childrens center
if ( minsize > size ) {
if ( CubeInFrustum(ccenter[0], ccenter[1], ccenter[2], size/2.0) ) {
if(cm) {
if (( 1 << i ) & node.leaf )
cm->setColor( &(children->getPoints()[1]) );
else
cm->setColor( m_tree->pickPoint(children->node) );
}
glPointSize(size/2.0);
glBegin(GL_POINTS);
glVertex3f( ccenter[0], ccenter[1], ccenter[2] );
glEnd();
}
}else if ( ( 1 << i ) & node.leaf ) {
if ( CubeInFrustum(ccenter[0], ccenter[1], ccenter[2], size/2.0) ) {
pointrep *points = children->getPointreps();
unsigned int length = points[0].length;
T *point = &(points[1].v); // first point
glPointSize(1.0);
glBegin(GL_POINTS);
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
if(cm) cm->setColor(point);
glVertex3f( point[0], point[1], point[2]);
point+=POINTDIM;
}
glEnd();
}
} else { // recurse
displayOctTreeCPAllCulled( children->node, ccenter, size/2.0, minsize);
}
++children; // next child
}
}
}
void displayOctTreeCPAll(const bitoct &node, const T* center, T size, T minsize ) {
T ccenter[3];
bitunion<T> *children;
bitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
BOctTree<T>::childcenter(center, ccenter, size, i); // childrens center
if ( minsize > size ) { // if ith node is leaf get center
// check if leaf is visible
if ( CubeInFrustum(ccenter[0], ccenter[1], ccenter[2], size/2.0) ) {
if(cm) {
if (( 1 << i ) & node.leaf )
cm->setColor( &(children->getPoints()[1]) );
else
cm->setColor( m_tree->pickPoint(children->node) );
}
glPointSize(size/2.0);
glBegin(GL_POINTS);
glVertex3f( ccenter[0], ccenter[1], ccenter[2] );
glEnd();
}
}else if ( ( 1 << i ) & node.leaf ) {
pointrep *points = children->getPointreps();
unsigned int length = points[0].length;
T *point = &(points[1].v); // first point
glPointSize(1.0);
glBegin(GL_POINTS);
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
if(cm) cm->setColor(point);
glVertex3f( point[0], point[1], point[2]);
point+=POINTDIM;
}
glEnd();
} else { // recurse
displayOctTreeCPAll( children->node, ccenter, size/2.0, minsize);
}
++children; // next child
}
}
}
void showCube(const T* center, T size) {
glLineWidth(1.0);
glBegin(GL_QUADS); // draw a cube with 6 quads
glColor3f(0.0f,1.0f,0.0f); // Set The Color To Green
glVertex3f(center[0] + size, center[1] + size, center[2] - size);
glVertex3f(center[0] - size, center[1] + size, center[2] - size);
glVertex3f(center[0] - size, center[1] + size, center[2] + size);
glVertex3f(center[0] + size, center[1] + size, center[2] + size);
glColor3f(1.0f,0.5f,0.0f); // Set The Color To Orange
glVertex3f(center[0] + size, center[1] - size, center[2] + size);
glVertex3f(center[0] - size, center[1] - size, center[2] + size);
glVertex3f(center[0] - size, center[1] - size, center[2] - size);
glVertex3f(center[0] + size, center[1] - size, center[2] - size);
glColor3f(1.0f,0.0f,0.0f); // Set The Color To Red
glVertex3f(center[0] + size, center[1] + size, center[2] + size);
glVertex3f(center[0] - size, center[1] + size, center[2] + size);
glVertex3f(center[0] - size, center[1] - size, center[2] + size);
glVertex3f(center[0] + size, center[1] - size, center[2] + size);
glColor3f(1.0f,1.0f,0.0f); // Set The Color To Yellow
glVertex3f(center[0] + size, center[1] - size, center[2] - size);
glVertex3f(center[0] - size, center[1] - size, center[2] - size);
glVertex3f(center[0] - size, center[1] + size, center[2] - size);
glVertex3f(center[0] + size, center[1] + size, center[2] - size);
glColor3f(0.0f,0.0f,1.0f); // Set The Color To Blue
glVertex3f(center[0] - size, center[1] + size, center[2] + size);
glVertex3f(center[0] - size, center[1] + size, center[2] - size);
glVertex3f(center[0] - size, center[1] - size, center[2] - size);
glVertex3f(center[0] - size, center[1] - size, center[2] + size);
glColor3f(1.0f,0.0f,1.0f); // Set The Color To Violet
glVertex3f(center[0] + size, center[1] + size, center[2] - size);
glVertex3f(center[0] + size, center[1] + size, center[2] + size);
glVertex3f(center[0] + size, center[1] - size, center[2] + size);
glVertex3f(center[0] + size, center[1] - size, center[2] - size);
glEnd();
}
void displayOctTreeAllCulled(const bitoct &node, const T* center, T size, float *frustum[6], unsigned char frustsize ) {
float *new_frustum[6]; unsigned char counter = 0;
for (unsigned char p = 0; p < frustsize; p++ ) {
char res = PlaneAABB(center[0], center[1], center[2], size, frustum[p]);
if (res == 0) { // cube is on the wrong side of the plane (not visible)
return;
} else if ( res == 1 ) { // plane intersects this volume continue culling with this plane
new_frustum[counter++] = frustum[p];
} // other case is simply not to continue culling with the respective plane
}
if (counter == 0) { // if entirely within frustrum discontinue culling
displayOctTreeAll(node);
return;
}
T ccenter[3];
bitunion<T> *children;
bitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
BOctTree<T>::childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
pointrep *points = children->getPointreps();
unsigned int length = points[0].length;
T *point = &(points[1].v); // first point
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
if(cm) cm->setColor(point);
glVertex3f( point[0], point[1], point[2]);
point+=POINTDIM;
}
} else { // recurse
displayOctTreeAllCulled( children->node, ccenter, size/2.0, new_frustum, counter);
}
++children; // next child
}
}
}
unsigned long int countVisiblePoints(const bitoct &node, const T* center, T size ) {
unsigned long int result = 0;
int res = CubeInFrustum2(center[0], center[1], center[2], size);
if (res==0) return 0; // culled do not continue with this branch of the tree
T ccenter[3];
bitunion<T> *children;
bitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
BOctTree<T>::childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
// check if leaf is visible
if ( CubeInFrustum(ccenter[0], ccenter[1], ccenter[2], size/2.0) ) {
pointrep *points = children->getPointreps();
unsigned int length = points[0].length;
result += length;
}
} else { // recurse
result += countVisiblePoints( children->node, ccenter, size/2.0);
}
++children; // next child
}
}
return result;
}
};
#endif