Logo Search packages:      
Sourcecode: earth3d version File versions  Download package

heightfieldTreeNode.cpp

#include "heightfieldTreeNode.h"
#include "heightfieldTree.h"
#include <iostream>
#include <assert.h>
#include "globaltimer.h"
#include "stopableDownload.h"

using namespace std;

HeightfieldTreeNode::HeightfieldTreeNode(HeightfieldTree *htree, HeightfieldTreeNode *parent) : HeightfieldTreeNodeCore(), StopableDownload() {
  this->htree = htree;
  this->parent = parent;

  for(int i=0; i<4; i++) child[i]=NULL;

  /* get endianess */
  littleendian = false;
  short int order = 1;
  char *corder = (char *) &order;
  if (corder[0]==1) { // little endian, we need to convert the data
    littleendian = true;
  }

  /* set usage timers */
  lastused = globaltime;
  lastchildused = globaltime;
}

HeightfieldTreeNode::~HeightfieldTreeNode() {
  stopDownloads();

  for(int i=0; i<4; i++) {
    delete(child[i]);
  }
}

HeightfieldTreeNode *HeightfieldTreeNode::getChild(int nr) {
  assert(nr>=0 && nr<4);
  return(child[nr]);
}

void HeightfieldTreeNode::setChild(int nr, HeightfieldTreeNode *hnode) {
  assert(nr>=0 && nr<4);
  child[nr]=hnode;
}

void HeightfieldTreeNode::enqueueRequest(HeightfieldTreeNodeCore *hcore) {
  /* add to queue */
  hcorelistmutex.lock();
  assert(hcore!=NULL);
  assert(hcore->getRequestID()!=NULL);
  
  assert(hcore->magicdebug==123456);
  hcorelist.push_back(hcore);
  hcorelistmutex.unlock();

  /* register with downloadable */
  hcore->addDownloader(this);
}

void HeightfieldTreeNode::dequeueRequest(HeightfieldTreeNodeCore *hcore) {
  /* remove from queue */
  hcorelistmutex.lock();
  assert(hcore!=NULL);
  assert(hcore->getRequestID()!=NULL);
  
  assert(hcore->magicdebug==123456);
  vector<HeightfieldTreeNodeCore *>::iterator i;
  do {
    for(i=hcorelist.begin(); i!=hcorelist.end(); i++) {
      if (*i==hcore) {
      hcorelist.erase(i);
      i=hcorelist.begin();
      break;
      }
    }
  } while(i!=hcorelist.end());

  hcorelistmutex.unlock();

  /* deregister with downloadable */
//   hcore->removeDownloader(this);
}

void HeightfieldTreeNode::setImage(int width, int height, const char *image, int size, const char *type) {
  heightfieldTreeMutex.lock();

  MapTileTreeNodeCore::setImage(width, height, (char *) image, size, type);

#ifdef EARTH3DDEBUG
  cout << "RECEIVED HEIGHTFIELD IMAGE" << endl;
#endif

  heightfieldTreeMutex.unlock();

  RerequestObjects();
}

void HeightfieldTreeNode::RerequestObjects() {
  // must run while hcorelist.size()>0 ?
  // NO: There are some textures that can not be requested because they are not available
  // because they are too deep in the tree, with a highter resolution than available
  int count = hcorelist.size();
  while(count>0) {
    hcorelistmutex.lock();
    count = hcorelist.size();
    if (count<=0) {
      hcorelistmutex.unlock();
      break;
    }
    HeightfieldTreeNodeCore *core = hcorelist[0];
    hcorelist.erase(hcorelist.begin());
    hcorelistmutex.unlock();

    assert(core->magicdebug==123456);
#ifdef DEBUG
    printf("DEQUEUE HEIGHTTILE\n");
#endif
    core->removeDownloader(this);
    htree->request(core);
    count--;
  }
}

void HeightfieldTreeNode::getArea(int ax, int ay, int width, int height, float *target) {
  float *image = (float *) getScaledUncompressedImage();
#ifdef DEBUG
  cout << "getArea: image " << (image==NULL ? "NULL":"not null") << endl;
#endif

  /* this node was used now */
  setLastUsed(globaltime);

  /* and its a child of its parent node */
  if (parent) parent->setLastChildUsed(globaltime);

  assert(ax>=0 && ay>=0 && ((ay+height)*width<=getScaledWidth()*getScaledHeight() || image==NULL) && width<=256 && height<=256);

  int thiswidth = getScaledWidth();
  for(int y=ay; y<ay+height; y++) {
    for(int x=ax; x<ax+width; x++) {
      if (image) {
      target[(y-ay)*width+(x-ax)] = image[y*thiswidth+x];
      }
      else {
      target[(y-ay)*width+(x-ax)] = 0;
      }
    }
  }
}

void HeightfieldTreeNode::garbageCollect() {
  /* do not call superclass as it relies on getSelectedForDrawing, that
   * is not used in this subclass
   */
  
  /* delete children if they were not used for at least 30 timesteps */
  if (globaltime-lastchildused>30) {
    for(int i=0; i<4; i++) {
      HeightfieldTreeNode *child = getChild(i);
      if (child && child->canBeDeleted()) {
      setChild(i, NULL);
      delete(child);
      }
    }
  }

  /* delete data from this node if the data was not needed for at least 30 timesteps */
  if (globaltime-lastused>30) {
    tile->discardScaledImage();
    tile->discardUncompressedImage();

    assert(vertexarray==NULL);
  }
}

void HeightfieldTreeNode::setLastUsed(unsigned long timenow) {
  lastused = timenow;
}
  
/** Sets the last child usage time of this node and all parents */
void HeightfieldTreeNode::setLastChildUsed(unsigned long timenow) {
  lastchildused = timenow;

  /* set last child usage of parents recursively */
  if (parent) parent->setLastChildUsed(timenow);
}

bool HeightfieldTreeNode::canBeDeleted() {
  QMutexLocker qml(&hcorelistmutex);
  if (hcorelist.size()>0) return(false);

  for(int i=0; i<4; i++) {
    if (getChild(i)) {
      if (!getChild(i)->canBeDeleted()) {
      return(false);
      }
    }
  }

  return(true);
}

void HeightfieldTreeNode::stopDownload(Downloadable *downloadable) {
  StopableDownload::stopDownload(downloadable);

  /* remove downloadable from hcorelist */
  dequeueRequest((HeightfieldTreeNodeCore *) downloadable);
}

void HeightfieldTreeNode::setDownloadFailed() {
  HeightfieldTreeNodeCore::setDownloadFailed();

  QMutexLocker qml(&heightfieldTreeMutex);

  RerequestObjects();
}

Generated by  Doxygen 1.6.0   Back to index