Simplification de Lod.

This commit is contained in:
Georges Dupéron 2011-12-22 15:41:56 +01:00
parent f5cf397376
commit c8f30f064e
6 changed files with 52 additions and 44 deletions

View File

@ -1,8 +1,9 @@
CXX=g++ CXX=g++
# -ansi -pedantic -Wconversion # -ansi -pedantic -Wconversion
CCWARN=-Wall -Wextra -Werror CCWARN=-Wall -Wextra -Werror
# -flto (nécessite GCC 4.5) -m32 ou -m64 # TODO : -O3 -m32 ou -m64
CFLAGS=-O0 -I. $(CCWARN) # -g -rdynamic uniquement pour le debug.
CFLAGS=-O0 -I. $(CCWARN) -g -rdynamic
SOURCES = $(shell echo *.cpp rules/*.cpp rules/*/*.cpp) SOURCES = $(shell echo *.cpp rules/*.cpp rules/*/*.cpp)
HEADERS = $(shell echo *.hh rules/*.hh rules/*/*.hh) HEADERS = $(shell echo *.hh rules/*.hh rules/*/*.hh)

View File

@ -5,6 +5,9 @@ typedef long long int64;
class Chose; class Chose;
// DEBUG
#include <typeinfo>
#include <iostream> #include <iostream>
#include <cstdlib> #include <cstdlib>
#include <cmath> #include <cmath>

View File

@ -3,9 +3,9 @@ Heap::Heap()
bucketArraySize(1), lastNode(-1) { bucketArraySize(1), lastNode(-1) {
} }
void Heap::setId(int id) { this->id = id; } void Heap::init(int id, int factor) { this->id = id; this->factor = factor; }
void Heap::insert(int key, Chose* value) { void Heap::insert(float key, Chose* value) {
{ // DEBUG { // DEBUG
int _d_node = value->lod.heaps[id]; int _d_node = value->lod.heaps[id];
if (_d_node <= lastNode && _d_node >= 0 && if (_d_node <= lastNode && _d_node >= 0 &&
@ -23,8 +23,6 @@ void Heap::insert(int key, Chose* value) {
siftUp(lastNode); siftUp(lastNode);
} }
void handler();
int global = 0;
void Heap::remove(Chose* value) { void Heap::remove(Chose* value) {
int node = value->lod.heaps[id]; int node = value->lod.heaps[id];
@ -57,8 +55,12 @@ void Heap::remove(Chose* value) {
siftDown(node); siftDown(node);
} }
Chose* Heap::popIfLessThan(int key) { bool Heap::lessThan(float a, float b) {
if (lastNode >= 0 && buckets[0][0].key < key) { return (a * factor < b * factor);
}
Chose* Heap::popIfLessThan(float key) {
if (lastNode >= 0 && buckets[0][0].key * factor < key * factor) {
Chose* ret = buckets[0][0].value; Chose* ret = buckets[0][0].value;
remove(ret); remove(ret);
return ret; return ret;
@ -75,7 +77,7 @@ void Heap::siftUp(int node) {
break; break;
int p = parent(node); int p = parent(node);
np = &(buckets[getBucket(p)][getIndex(p)]); np = &(buckets[getBucket(p)][getIndex(p)]);
if (n->key >= np->key) if (n->key * factor <= np->key * factor)
break; break;
HeapNode temp = *n; HeapNode temp = *n;
*n = *np; *n = *np;
@ -102,8 +104,9 @@ void Heap::siftDown(int node) {
nrc = &(buckets[getBucket(rc)][getIndex(rc)]); nrc = &(buckets[getBucket(rc)][getIndex(rc)]);
// exchLeft et exchRight peuvent être tout deux true. Dans ce // exchLeft et exchRight peuvent être tout deux true. Dans ce
// cas, c'est exchRight qui gagne. // cas, c'est exchRight qui gagne.
bool exchLeft = (lc <= lastNode) && (n->key > nlc->key); bool exchLeft = (lc <= lastNode) && (n->key * factor < nlc->key * factor);
bool exchRight = (rc <= lastNode) && (n->key > nrc->key) && (nlc->key > nrc->key); bool exchRight = (rc <= lastNode) && (n->key * factor < nrc->key * factor);
exchRight = exchRight && (nlc->key * factor < nrc->key * factor);
if ((!exchLeft) && (!exchRight)) if ((!exchLeft) && (!exchRight))
break; break;
HeapNode temp = *n; HeapNode temp = *n;

14
heap.hh
View File

@ -1,5 +1,5 @@
struct HeapNode { struct HeapNode {
int key; float key;
Chose* value; Chose* value;
}; };
@ -19,17 +19,19 @@ private:
inline int getIndex(int node) { inline int getIndex(int node) {
return (node & (bucketSize - 1)); return (node & (bucketSize - 1));
} }
void allocateBucket(); // Allocate into last+1 void allocateBucket(); // Allocate into lastAllocatedBucket+1
void freeBucket(); // free last void freeBucket(); // free lastAllocatedBucket
void siftUp(int node); void siftUp(int node);
void siftDown(int node); void siftDown(int node);
inline int parent(int node) { return (node - 1)/2; } inline int parent(int node) { return (node - 1)/2; }
inline int leftchild(int node) { return node * 2 + 1; } inline int leftchild(int node) { return node * 2 + 1; }
inline int rightchild(int node) { return node * 2 + 2; } inline int rightchild(int node) { return node * 2 + 2; }
public: public:
int factor;
Heap(); Heap();
void insert(int key, Chose* value); void insert(float key, Chose* value);
void remove(Chose* value); void remove(Chose* value);
Chose* popIfLessThan(int key); Chose* popIfLessThan(float key);
void setId(int id); bool lessThan(float a, float b); // Renvoie true ssi a < b dans l'ordre du tas.
void init(int id, int factor); // factor = -1 pour tas Min, 1 pour tas max
}; };

42
lod.cpp
View File

@ -1,8 +1,11 @@
#include "all_includes.hh" #include "all_includes.hh"
Lod::Lod(Vertex camera, Chose* root) { Lod::Lod(Vertex camera, Chose* root) {
for (int i = 0; i < 6; i++) merge[i].setId(i); for (int i = 0; i < 6; i++) {
for (int i = 0; i < 12; i++) split[i].setId(6+i); merge[i].init(i, (i & 1) ? -1 : 1);
splitIn[i].init(6+i, (i & 1) ? 1 : -1);
splitOut[i].init(6+i, (i & 1) ? -1 : 1);
}
this->camera[0] = camera.x; this->camera[0] = camera.x;
this->camera[1] = camera.y; this->camera[1] = camera.y;
this->camera[2] = camera.z; this->camera[2] = camera.z;
@ -18,8 +21,7 @@ void Lod::setCamera(Vertex newCamera) {
// Merge. // Merge.
for(int i = 0; i < 6; i++) { for(int i = 0; i < 6; i++) {
Chose* c; Chose* c;
int pos = NegateEven(camera[i>>1], i); while((c = merge[i].popIfLessThan(camera[i>>1]))) {
while((c = merge[i].popIfLessThan(pos))) {
for(int j = 0; j < 6; j++) { for(int j = 0; j < 6; j++) {
if(i == j) continue; if(i == j) continue;
merge[j].remove(c); merge[j].remove(c);
@ -30,18 +32,19 @@ void Lod::setCamera(Vertex newCamera) {
// Split out vers split in. // Split out vers split in.
for(int i = 0; i < 6; i++) { for(int i = 0; i < 6; i++) {
Chose* c; Chose* c;
int pos = NegateOdd(camera[i>>1], i); while((c = splitOut[i].popIfLessThan(camera[i>>1]))) {
while((c = split[2*i+1].popIfLessThan(pos))) { // std::cout << "soi " << c->lod.inCounter + 1 << " ";
// std::cout << typeid(*c).name() << " " << c << std::endl;
if(c->lod.inCounter == 5) { if(c->lod.inCounter == 5) {
for(int j = 0; j < 6; j++) { for(int j = 0; j < 6; j++) {
if(i == j) continue; if(i == j) continue;
split[2*j].remove(c); splitIn[j].remove(c);
} }
doSplit(c); doSplit(c);
} }
else { else {
c->lod.inCounter++; c->lod.inCounter++;
split[2*i].insert(c->lod.splitBox[i], c); splitIn[i].insert(c->lod.splitBox[i], c);
} }
} }
} }
@ -49,10 +52,9 @@ void Lod::setCamera(Vertex newCamera) {
// Split in vers split out. // Split in vers split out.
for(int i = 0; i < 6; i++) { for(int i = 0; i < 6; i++) {
Chose* c; Chose* c;
int pos = NegateEven(camera[i>>1], i); while((c = splitIn[i].popIfLessThan(camera[i>>1]))) {
while((c = split[2*i].popIfLessThan(pos))) {
c->lod.inCounter--; c->lod.inCounter--;
split[2*i+1].insert(c->lod.splitBox[i], c); splitOut[i].insert(c->lod.splitBox[i], c);
} }
} }
} }
@ -77,24 +79,26 @@ void Lod::doSplit(Chose* c) {
void Lod::addMergeCube(Chose* chose) { void Lod::addMergeCube(Chose* chose) {
for(int i = 0; i < 5; i++) for(int i = 0; i < 5; i++)
merge[i].insert(NegateEven(chose->lod.mergeBox[i], i), chose); merge[i].insert(chose->lod.mergeBox[i], chose);
} }
void Lod::addSplitCube(Chose* chose) { void Lod::addSplitCube(Chose* chose) {
chose->lod.inCounter = 0; chose->lod.inCounter = 0;
for(int i = 0; i < 6; i++) { for(int i = 0; i < 6; i++) {
if(NegateEven(chose->lod.splitBox[i] - camera[i>>1], i) >= 0) { // std::cout << chose->lod.splitBox[i] << " " << camera[i>>1] << " " << splitOut[i].factor;
// std::cout << " " << (splitOut[i].lessThan(chose->lod.splitBox[i], camera[i>>1]) ? "t" : "f");
// std::cout << std::endl;
if(splitOut[i].lessThan(chose->lod.splitBox[i], camera[i>>1])) {
chose->lod.inCounter++; chose->lod.inCounter++;
split[2*i].insert(NegateEven(chose->lod.splitBox[i],i), chose); splitIn[i].insert(chose->lod.splitBox[i], chose);
} else { } else {
split[2*i+1].insert(NegateOdd(chose->lod.splitBox[i],i), chose); splitOut[i].insert(chose->lod.splitBox[i], chose);
} }
} }
// TODO : si chose->inCounter == 6, il faut le split immédiatement. // TODO : plutôt que d'ajouter puis enlever, précalculer puis enlever si nécessaire.
if (chose->lod.inCounter == 6) { if (chose->lod.inCounter == 6) {
for(int i = 0; i < 6; i++) { for(int i = 0; i < 6; i++)
split[2*i].remove(chose); splitIn[i].remove(chose);
}
doSplit(chose); doSplit(chose);
} }
} }

11
lod.hh
View File

@ -4,16 +4,11 @@
class Lod { class Lod {
private : private :
Heap merge[6]; // {xMin, xMax, yMin, yMax, zMin, zMax}. Heap merge[6]; // {xMin, xMax, yMin, yMax, zMin, zMax}.
Heap split[12]; // {xMinIn, xMinOut, xMaxIn, xMaxOut, yMinIn, yMaxOut, yMaxIn, yMaxOut, zMinIn, zMinOut, zMaxIn, zMaxOut}. Heap splitIn[6]; // {xMinIn, xMaxIn, yMinIn, yMaxIn, zMinIn, zMaxIn}.
Heap splitOut[6]; // {xMinOut, xMaxOut, yMinOut, yMaxOut, zMinOut, zMaxOut}.
float camera[3]; float camera[3];
private: private:
inline float NegateEven(float value, int evenodd) {
return (value*((evenodd&1) ? 1 : -1));
}
inline float NegateOdd(float value, int evenodd) {
return (value*((evenodd&1) ? -1 : 1));
}
void doSplit(Chose* c); void doSplit(Chose* c);
public : public :
Lod(Vertex camera, Chose* root); Lod(Vertex camera, Chose* root);