Tas pour le LOD.

This commit is contained in:
Georges Dupéron 2011-12-18 22:36:45 +01:00
parent d171be9892
commit 46189836f5
6 changed files with 214 additions and 28 deletions

View File

@ -25,6 +25,7 @@ class Chose;
#include "hash.hh"
#include "view.hh"
// LOD must be included before chose.hh
#include "lod.hh"
#include "rules/chose.hh"

132
lod.cpp
View File

@ -33,9 +33,6 @@ Chose* Abr::popIfLessThan(int key) {
}
}
#define NegateEven(v, i) ((v)*(((i)&1) ? 1 : -1))
Lod::Lod(){};
@ -109,3 +106,132 @@ void Lod::addSplitCube(Chose* chose, int limits[6]) {
split[2*i+1].insert(NegateEven(limits[i],i+1), chose);
}
}
Heap::Heap(int id)
: id(id), buckets(new HeapNode*[1]), lastAllocatedBucket(-1),
bucketArraySize(1), lastNode(-1) {
}
void Heap::insert(int key, Chose* value) {
++lastNode;
if (getBucket(lastNode) > lastAllocatedBucket) {
allocateBucket();
}
buckets[getBucket(lastNode)][getIndex(lastNode)].key = key;
buckets[getBucket(lastNode)][getIndex(lastNode)].value = value;
siftUp(lastNode);
}
void Heap::remove(int node) {
--lastNode;
if (node > lastNode) { // On a supprimé le dernier noeud.
// + 1 pour garder au moins un bucket "en cache".
if (getBucket(lastNode) + 1 < lastAllocatedBucket)
freeBucket();
return;
}
buckets[getBucket(node)][getIndex(node)] = \
buckets[getBucket(lastNode)][getIndex(lastNode)];
// + 1 pour garder au moins un bucket "en cache".
if (getBucket(lastNode) + 1 < lastAllocatedBucket) {
freeBucket();
}
siftDown(node);
}
Chose* Heap::popIfLessThan(int key) {
if (lastNode >= 0 && buckets[0][0].key < key) {
Chose* ret = buckets[0][0].value;
remove(0);
return ret;
}
return NULL;
}
void Heap::siftUp(int node) {
HeapNode* n;
HeapNode* np;
while (true) {
n = &(buckets[getBucket(node)][getIndex(node)]);
if (node <= 0)
break;
int p = parent(node);
np = &(buckets[getBucket(p)][getIndex(p)]);
if (n->key >= np->key)
break;
HeapNode temp = *n;
*n = *np;
*np = temp;
// mettre à jour le champ lod.heaps[id] de l'ancien parent qu'on
// vient de descendre.
n->value->lod.heaps[id] = node;
node = p;
}
// après les break; qui sortent de la boucle, on a déjà actualisé
// le pointeur `n` vers buckets[getBucket(node)][getIndex(node)].
n->value->lod.heaps[id] = node;
}
void Heap::siftDown(int node) {
HeapNode* n;
HeapNode* nlc;
HeapNode* nrc;
while (true) {
n = &(buckets[getBucket(node)][getIndex(node)]);
int lc = leftchild(node);
int rc = rightchild(node);
nlc = &(buckets[getBucket(lc)][getIndex(lc)]);
nrc = &(buckets[getBucket(rc)][getIndex(rc)]);
// exchLeft et exchRight peuvent être tout deux true. Dans ce
// cas, c'est exchRight qui gagne.
bool exchLeft = (lc <= lastNode) && (n->key > nlc->key);
bool exchRight = (rc <= lastNode) && (n->key > nrc->key) && (nlc->key > nrc->key);
if ((!exchLeft) && (!exchRight))
break;
HeapNode temp = *n;
if (exchRight) {
*n = *nrc;
*nrc = temp;
} else {
*n = *nlc;
*nlc = temp;
}
// mettre à jour le champ lod.heaps[id] de l'ancien fils qu'on
// vient de remonter.
n->value->lod.heaps[id] = node;
node = (exchRight ? rc : lc);
}
// après les break; qui sortent de la boucle, on a déjà actualisé
// le pointeur `n` vers buckets[getBucket(node)][getIndex(node)].
n->value->lod.heaps[id] = node;
}
void Heap::allocateBucket() {
++lastAllocatedBucket;
if (lastAllocatedBucket >= bucketArraySize) {
HeapNode** old = buckets;
buckets = new HeapNode*[bucketArraySize*2];
for (int i = 0; i < lastAllocatedBucket; i++)
buckets[i] = old[i];
delete[] old;
bucketArraySize *= 2;
}
buckets[lastAllocatedBucket] = new HeapNode[bucketSize];
}
void Heap::freeBucket() {
delete[] buckets[lastAllocatedBucket];
--lastAllocatedBucket;
if (lastAllocatedBucket * 4 < bucketArraySize && bucketArraySize > 1) {
HeapNode** old = buckets;
buckets = new HeapNode*[bucketArraySize/2];
for (int i = 0; i <= lastAllocatedBucket; i++)
buckets[i] = old[i];
delete[] old;
bucketArraySize /= 2;
}
}

44
lod.hh
View File

@ -28,4 +28,48 @@ class Lod {
void setCamera(float camera[3]);
};
struct HeapNode {
int key;
Chose* value;
};
class Heap {
private:
int id;
static const int log2BucketSize = 9; // 2^9 = 512
static const int bucketSize = (1 << log2BucketSize);
HeapNode** buckets;
int lastAllocatedBucket;
int bucketArraySize;
int lastNode;
private:
inline int getBucket(int node) {
return (node >> log2BucketSize);
}
inline int getIndex(int node) {
return (node & (bucketSize - 1));
}
void allocateBucket(); // Allocate into last+1
void freeBucket(); // free last
void siftUp(int node);
void siftDown(int node);
inline int parent(int node) { return (node - 1)/2; }
inline int leftchild(int node) { return node * 2 + 1; }
inline int rightchild(int node) { return node * 2 + 2; }
public:
Heap(int id);
void insert(int key, Chose* value);
void remove(int node);
Chose* popIfLessThan(int key);
};
class LodNode {
public:
int heaps[18];
int aabb[6];
int inCounter;
HeapNode* splitCube[12];
HeapNode* mergeCube[6];
};
#endif

View File

@ -29,12 +29,20 @@ int main() {
Chose* c = QuartierQuad::factory(Chose::initialSeed, 0, ne, se, sw, nw);
// c->subdivide();
recursiveSubdivide(c);
Heap h(1);
(void)h;
h.insert(43,c);
h.insert(42,c->children[0]);
h.popIfLessThan(42); // NULL
h.popIfLessThan(43); // c->children[0]
h.popIfLessThan(44); // c
h.popIfLessThan(44); // NULL
View *v = new View(c);
Vertex cc = v->camera.cameraCenter;
float camera[3] = {cc.x, cc.y, cc.z};
camera[0] = camera[0];
Lod lod(camera);
// tile.subdivide tant qu'on n'a pas le niveau de détail désiré.
return 0;
}

View File

@ -2,23 +2,16 @@
Chose::Chose() : seed(initialSeed), children() {}
std::ostream& operator<<(std::ostream& os, const Chose* r) {
return os << *r;
}
std::ostream& operator<<(std::ostream& os, const Chose& r) {
(void)r; // unused
return os << "Chose";
}
void Chose::addChild(Chose* c) {
children.push_back(c);
// TODO : Ajouter c dans une file d'attente des éléments pouvant être split.
}
void Chose::addTriangle(Triangle* t) {
triangles.push_back(t);
// TODO : Ajouter t dans la liste des triangles à envoyer au GPU.
}
void Chose::merge() {
triangles.clear();
}
void Chose::display() {

View File

@ -10,6 +10,7 @@ class Chose {
unsigned int seed;
std::vector<Chose*> children;
std::vector<Triangle*> triangles;
LodNode lod;
int inCounter;
int splitCube[6];
int mergeCube[6];
@ -17,25 +18,38 @@ class Chose {
public :
void display();
virtual bool subdivide() = 0;
virtual void merge();
protected :
Chose();
inline void addEntropy(unsigned int x1) { seed = hash2(seed, x1); }
inline void addEntropy(unsigned int x1, unsigned int x2) { addEntropy(x1); addEntropy(x2); }
inline void addEntropy(unsigned int x1, unsigned int x2, unsigned int x3) { addEntropy(x1, x2); addEntropy(x3); }
inline void addEntropy(unsigned int x1, unsigned int x2, unsigned int x3, unsigned int x4) { addEntropy(x1, x2); addEntropy(x3, x4); }
inline void addEntropy(Vertex v1) { addEntropy(v1.x, v1.y); }
inline void addEntropy(Vertex v1, Vertex v2) { addEntropy(v1); addEntropy(v2); }
inline void addEntropy(Vertex v1, Vertex v2, Vertex v3) { addEntropy(v1, v2); addEntropy(v3); }
inline void addEntropy(Vertex v1, Vertex v2, Vertex v3, Vertex v4) { addEntropy(v1, v2); addEntropy(v3, v4); }
inline void addEntropy(unsigned int x1) {
seed = hash2(seed, x1);
}
inline void addEntropy(unsigned int x1, unsigned int x2) {
addEntropy(x1); addEntropy(x2);
}
inline void addEntropy(unsigned int x1, unsigned int x2, unsigned int x3) {
addEntropy(x1, x2); addEntropy(x3);
}
inline void addEntropy(unsigned int x1, unsigned int x2, unsigned int x3, unsigned int x4) {
addEntropy(x1, x2); addEntropy(x3, x4);
}
inline void addEntropy(Vertex v1) {
addEntropy(v1.x, v1.y);
}
inline void addEntropy(Vertex v1, Vertex v2) {
addEntropy(v1); addEntropy(v2);
}
inline void addEntropy(Vertex v1, Vertex v2, Vertex v3) {
addEntropy(v1, v2); addEntropy(v3);
}
inline void addEntropy(Vertex v1, Vertex v2, Vertex v3, Vertex v4) {
addEntropy(v1, v2); addEntropy(v3, v4);
}
void addChild(Chose* c);
void addTriangle(Triangle* t);
virtual void triangulation() = 0;
virtual std::vector<Vertex*> getBoundingBoxPoints() const = 0;
};
std::ostream& operator<<(std::ostream& os, const Chose& r);
std::ostream& operator<<(std::ostream& os, const Chose* r);
#endif