From d97593d9995fc6dcdcd44d68bb7375896e8ec62e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Georges=20Dup=C3=A9ron?= Date: Sun, 27 Nov 2011 00:26:05 +0100 Subject: [PATCH] =?UTF-8?q?Notes=20sur=20l'algo=20permettant=20de=20d?= =?UTF-8?q?=C3=A9cider=20quels=20objets=20seront=20split()=20ou=20merge(),?= =?UTF-8?q?=20et=20la=20r=C3=A9cup=C3=A9ration=20de=20tous=20les=20triangl?= =?UTF-8?q?es=20dans=20un=20tableau=20=C3=A0=20envoyer=20au=20GPU.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++++ rules/chose.cpp | 34 ++++++++++++++++++++++++++++++++-- rules/chose.hh | 4 ++++ 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/main.cpp b/main.cpp index 27fcd6f..9fbd4b2 100644 --- a/main.cpp +++ b/main.cpp @@ -14,5 +14,52 @@ int main() { RectangleRoutes r(ne, sw); r.subdivide(); // tile.subdivide tant qu'on n'a pas le niveau de détail désiré. + + // TODO : diviser l'errorVolume par nbTriangles, pour avoir le gain/perte par triangle. + // Cela devrait donner des choix plus justes pour les split/merge. + + // TODO : comment une tile peut-elle s'adapter à ses voisins (lors de la triangulation) ? + // Solution bof : maintenir une liste des voisins sur chaque segment/face, et lorsqu'un nouveau voisin est créé, + // mettre à jour la triangulation de notre tile. + + // Invariants : + // * tile.errorVolume ≤ somme(tile.children.errorVolume) + // * tile.nbTriangles < somme(tile.children.nbTriangles) + + // Pour calculer le gain d'une Chose : + // Lorsqu'on utilise une Chose c, on la split d'abbord (on n'utilisera pas les fils tout de suite, donc pas de récursion), + // Calculer c.errorVolume dans le constructeur (idem pour chaque fils donc). + // // Calcul d'une approximation de la surface d'erreur, en considérant que l'objet est plaqué sur un plan perpendiculaire au sol. + // gainVolumeErreurParTriangle = (c.errorVolume / c.nbTriangles) - sum(x in c.children : x.errorVolume / x.nbTriangles) + // c.gainSurfaceErreurParTriangle = pow(volumeErreurParTriangle, 2.f/3.f); + // Pour calculer son gain : + // int gainParTriangle(distance) + // // Calcul de la surface de la projection de la surface d'erreur sur l'écran : + // return c.gainSurfaceErreurParTriangle * (frontFrustumDist * frontFrustumDist) / (dist * dist) + + // Pour trouver le split() qui rapportera le plus : + // Set ensemble = { racine } + // Calculer le gain min et max des fils de toutes les Chose d'ensemble. + // Chose* best = la Chose avec le plus grand gain max + // if (best est une feuille) return best; + // ensemble = { c | c.max ≥ best.min } + + // Pour optimiser les Chose : + // while (42) { + // Trouver la Chose dont le split() rapportera le plus + // if (GPUTriangles::current + nbNewTriangles > GPUTriangles::aim) { + // Trouver les choses avec le merge() qui coûtera le moins, + // En ayant suffisemment de triangles pour que + // (GPUTriangles::current + nbNewTriangles - nbDeleteTriangles <= GPUTriangles::aim) + // Faire autant de split() (qui rapportent le plus) que possible sans dépasser le nombre de triangles autorisés + // => De cette manière, si on a dû faire un gros merge() qui coûte cher, il sera peut-être compensé par plein de petits split(). + // if (somme des coûts >= gain) { + // break; // while (42) + // } + // } + // Supprimer les triangles du tableau, en les insérant dans une freelist + // Ajouter les triangles en consommant de la freelist + // } + // Consommer la freeList en créant des triangles "bidon" (les trois sommets en (0,0,0) par ex.) return 0; } diff --git a/rules/chose.cpp b/rules/chose.cpp index e618724..7d584c5 100644 --- a/rules/chose.cpp +++ b/rules/chose.cpp @@ -21,10 +21,40 @@ void Chose::initTriangles(int n) { 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::useTriangles() { + // TODO + // Ajouter t dans la liste des triangles à envoyer au GPU. + + + // Maintenir une liste "add" et une liste "delete". + // Quand on flush les triangles, s'il y a plus de delete que de add : + // * trier la liste delete. + // * Choisir l'extrémité (début ou fin) vers laquelle on va rappatrier les éléments de l'autre extrémité. + // * Écraser les delete avec les add en partant du côté vers lequel on rappatrie. + // * Copier des éléments de l'extrémité vers les cases libres. + // * Enregistrer l'indice min et l'indice max. + // Problème : Pas real-time : on ne peut pas arrêter le processus n'importe quand… } void Chose::addTriangle(Triangle* t) { triangles.push_back(t); - // TODO : Ajouter t dans la liste des triangles à envoyer au GPU. } + +/* TODO : quand on se rend compte qu'on peut utiliser plus de + triangles (le GPU suit sans problème au FPS voulu), allouer un + autre tableau plus grand, vers lequel on déplacera les triangles + petit à petit (pour rester real-time). + + Pour l'instant, on alloue simplement un tableau suffisemment grand. + */ + +Triangle* Chose::resetGPUTriangles(int n) { + Chose::GPUTriangles = static_cast(operator new[](n * sizeof(Triangle))); + return Chose::GPUTriangles; +} + +int Chose::nGPUTriangles = 1000; +// http://stackoverflow.com/questions/4754763/c-object-array-initialization-without-default-constructor +Triangle* Chose::GPUTriangles = Chose::resetGPUTriangles(Chose::nGPUTriangles); diff --git a/rules/chose.hh b/rules/chose.hh index 0956306..b28f1f6 100644 --- a/rules/chose.hh +++ b/rules/chose.hh @@ -10,6 +10,9 @@ public: unsigned int seed; std::vector children; std::vector triangles; + static Triangle* resetGPUTriangles(int n); + static int nGPUTriangles; + static Triangle* GPUTriangles; public: Chose(); inline void addEntropy(unsigned int x1) { seed = hash2(seed, x1); } @@ -24,6 +27,7 @@ public: void initTriangles(int n); void addChild(Chose* c); void addTriangle(Triangle* t); + void useTriangles(); // triangulation() doit déjà avoir été appelé. virtual void subdivide() = 0; virtual void triangulation() = 0; };