2012-09-16 12:33:11 +00:00
|
|
|
/**
|
|
|
|
* @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"
|
|
|
|
|
2012-10-24 09:22:27 +00:00
|
|
|
using namespace show;
|
2012-09-16 12:33:11 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @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
|