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++
# -ansi -pedantic -Wconversion
CCWARN=-Wall -Wextra -Werror
# -flto (nécessite GCC 4.5) -m32 ou -m64
CFLAGS=-O0 -I. $(CCWARN)
# TODO : -O3 -m32 ou -m64
# -g -rdynamic uniquement pour le debug.
CFLAGS=-O0 -I. $(CCWARN) -g -rdynamic
SOURCES = $(shell echo *.cpp rules/*.cpp rules/*/*.cpp)
HEADERS = $(shell echo *.hh rules/*.hh rules/*/*.hh)

View File

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

View File

@ -3,9 +3,9 @@ Heap::Heap()
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
int _d_node = value->lod.heaps[id];
if (_d_node <= lastNode && _d_node >= 0 &&
@ -23,8 +23,6 @@ void Heap::insert(int key, Chose* value) {
siftUp(lastNode);
}
void handler();
int global = 0;
void Heap::remove(Chose* value) {
int node = value->lod.heaps[id];
@ -57,8 +55,12 @@ void Heap::remove(Chose* value) {
siftDown(node);
}
Chose* Heap::popIfLessThan(int key) {
if (lastNode >= 0 && buckets[0][0].key < key) {
bool Heap::lessThan(float a, float b) {
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;
remove(ret);
return ret;
@ -75,7 +77,7 @@ void Heap::siftUp(int node) {
break;
int p = parent(node);
np = &(buckets[getBucket(p)][getIndex(p)]);
if (n->key >= np->key)
if (n->key * factor <= np->key * factor)
break;
HeapNode temp = *n;
*n = *np;
@ -102,8 +104,9 @@ void Heap::siftDown(int node) {
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);
bool exchLeft = (lc <= lastNode) && (n->key * factor < nlc->key * factor);
bool exchRight = (rc <= lastNode) && (n->key * factor < nrc->key * factor);
exchRight = exchRight && (nlc->key * factor < nrc->key * factor);
if ((!exchLeft) && (!exchRight))
break;
HeapNode temp = *n;

14
heap.hh
View File

@ -1,5 +1,5 @@
struct HeapNode {
int key;
float key;
Chose* value;
};
@ -19,17 +19,19 @@ private:
inline int getIndex(int node) {
return (node & (bucketSize - 1));
}
void allocateBucket(); // Allocate into last+1
void freeBucket(); // free last
void allocateBucket(); // Allocate into lastAllocatedBucket+1
void freeBucket(); // free lastAllocatedBucket
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:
int factor;
Heap();
void insert(int key, Chose* value);
void insert(float key, Chose* value);
void remove(Chose* value);
Chose* popIfLessThan(int key);
void setId(int id);
Chose* popIfLessThan(float key);
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"
Lod::Lod(Vertex camera, Chose* root) {
for (int i = 0; i < 6; i++) merge[i].setId(i);
for (int i = 0; i < 12; i++) split[i].setId(6+i);
for (int i = 0; i < 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[1] = camera.y;
this->camera[2] = camera.z;
@ -18,8 +21,7 @@ void Lod::setCamera(Vertex newCamera) {
// Merge.
for(int i = 0; i < 6; i++) {
Chose* c;
int pos = NegateEven(camera[i>>1], i);
while((c = merge[i].popIfLessThan(pos))) {
while((c = merge[i].popIfLessThan(camera[i>>1]))) {
for(int j = 0; j < 6; j++) {
if(i == j) continue;
merge[j].remove(c);
@ -30,18 +32,19 @@ void Lod::setCamera(Vertex newCamera) {
// Split out vers split in.
for(int i = 0; i < 6; i++) {
Chose* c;
int pos = NegateOdd(camera[i>>1], i);
while((c = split[2*i+1].popIfLessThan(pos))) {
while((c = splitOut[i].popIfLessThan(camera[i>>1]))) {
// std::cout << "soi " << c->lod.inCounter + 1 << " ";
// std::cout << typeid(*c).name() << " " << c << std::endl;
if(c->lod.inCounter == 5) {
for(int j = 0; j < 6; j++) {
if(i == j) continue;
split[2*j].remove(c);
splitIn[j].remove(c);
}
doSplit(c);
}
else {
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.
for(int i = 0; i < 6; i++) {
Chose* c;
int pos = NegateEven(camera[i>>1], i);
while((c = split[2*i].popIfLessThan(pos))) {
while((c = splitIn[i].popIfLessThan(camera[i>>1]))) {
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) {
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) {
chose->lod.inCounter = 0;
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++;
split[2*i].insert(NegateEven(chose->lod.splitBox[i],i), chose);
splitIn[i].insert(chose->lod.splitBox[i], chose);
} 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) {
for(int i = 0; i < 6; i++) {
split[2*i].remove(chose);
}
for(int i = 0; i < 6; i++)
splitIn[i].remove(chose);
doSplit(chose);
}
}

9
lod.hh
View File

@ -5,15 +5,10 @@
class Lod {
private :
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];
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);
public :
Lod(Vertex camera, Chose* root);