Small changes and adding realtime extr.

This commit is contained in:
Federico Ponchio 2005-01-17 17:35:48 +00:00
parent 90e4d33361
commit 7f31d74240
12 changed files with 573 additions and 1073 deletions

View File

@ -24,6 +24,9 @@
History
$Log: not supported by cvs2svn $
Revision 1.7 2005/01/14 15:49:42 ponchio
VertRemap removed.
Revision 1.6 2004/12/01 03:24:30 ponchio
Level 2.
@ -77,8 +80,6 @@ bool fullscreen = false;
int width =1024;
int height = 768;
//TrackHand hand;
SDL_Surface *screen = NULL;
bool init() {
@ -102,8 +103,7 @@ bool init() {
return false;
}
SDL_WM_SetIcon(SDL_LoadBMP("inspector.bmp"), NULL);
SDL_WM_SetCaption(" Inspector", "Inspector");
SDL_WM_SetCaption("Crudeview", "Crudeview");
glDisable(GL_DITHER);
@ -225,13 +225,10 @@ int main(int argc, char *argv[]) {
float scale = 3/box.Diag();
glScalef(0.4, 0.4, 0.4);
// glRotatef(alpha, 0, 1, 0);
// alpha++;
// if(alpha > 360) alpha = 0;
glScalef(scale, scale, scale);
Point3f center = box.Center();
glTranslatef(-center[0], -center[1], -center[2]);
// render.render();
glColor3f(0, 1, 0);
glBegin(GL_TRIANGLES);
@ -260,8 +257,6 @@ int main(int argc, char *argv[]) {
SDL_GL_SwapBuffers();
}
// Clean up
SDL_Quit();
return -1;
}

View File

@ -93,8 +93,6 @@ float nxs::Decimate(Decimation mode,
for(unsigned int i = 0; i < newbord.size(); i++)
mesh.vert[newbord[i].start_vert].ClearW();
// vcg::tri::io::ExporterPLY<MyMesh>::Save(mesh, "ribum.ply");
float error;
switch(mode) {
case CLUSTER: error = Cluster(mesh, target_faces); break;
@ -129,13 +127,6 @@ float nxs::Decimate(Decimation mode,
v = vert_remap[v];
}
//Temporary test again:
/* for(unsigned int i = 0; i < newface.size(); i+= 3) {
assert(newface[i] != newface[i+1]);
assert(newface[i] != newface[i+2]);
assert(newface[i+1] != newface[i+2]);
}*/
return error;
}
@ -191,7 +182,7 @@ float Cluster(MyMesh &mesh, unsigned int target_faces) {
}
}
unsigned int nborder = part.size();
//Dovrei supersamplare prima....
//Todo I should supersample before
while(nseeds > 0 && part.size() < mesh.vn) {
unsigned int i = rand() % mesh.vert.size();
if(mesh.vert[i].IsW() && !mesh.vert[i].IsV()) {

View File

@ -18,6 +18,8 @@ Extraction::~Extraction() {
void Extraction::Extract(NexusMt *_mt) {
mt = _mt;
root = mt->history.Root();
sink = root + (mt->history.n_nodes()-1);
//clear statistics
extr_used = draw_used = disk_used = 0;
@ -28,13 +30,6 @@ void Extraction::Extract(NexusMt *_mt) {
heap.clear();
History::Node *root = mt->history.Root();
HeapNode hroot(root, 0);
Diff(hroot);
extr_used += hroot.extr;
draw_used += hroot.draw;
disk_used += hroot.disk;
Visit(root);
while(heap.size()) {
@ -42,36 +37,250 @@ void Extraction::Extract(NexusMt *_mt) {
HeapNode hnode = heap.back();
heap.pop_back();
History::Node *node = hnode.node;
unsigned int id = node - root;
if(visited[id]) continue;
Node *node = hnode.node;
if(visited[node - root]) continue;
if(Expand(hnode)) {
extr_used += hnode.extr;
draw_used += hnode.draw;
disk_used += hnode.disk;
if(Expand(hnode))
Visit(node);
}
Select();
draw_size = selected.size();
}
void Extraction::Init() {
front.clear();
back.clear();
Cost cost;
Node *nodes = mt->history.nodes;
for(unsigned int i = 0; i < visited.size(); i++) {
if(!visited[i]) continue;
Node &node = nodes[i];
bool cancoarse = true;
Node::iterator n;
for(n = node.out_begin(); n != node.out_end(); n++) {
if(!visited[(*n).node - root]) {
float maxerror = 0;
Link &link = *n;
for(Link::iterator k = link.begin(); k != link.end(); k++) {
unsigned int patch = (*k).patch;
Entry &entry = (*mt)[patch];
float error = metric->GetError(entry);
if(error > maxerror) maxerror = error;
cost.extr += entry.ram_size;
vcg::Sphere3f &sphere = entry.sphere;
if(!frustum.IsOutside(sphere.Center(), sphere.Radius()))
cost.draw += entry.ram_size;
if(!entry.patch)
cost.disk += entry.disk_size;
}
if((*n).node != sink && maxerror > target_error)
front.push_back(HeapNode((*n).node, maxerror));
} else
cancoarse = false;
}
if(cancoarse && &node != root) {
float error = GetRefineError(&node);
back.push_back(HeapNode(&node, error));
}
}
make_heap(front.begin(), front.end());
make_heap(back.begin(), back.end(), greater<HeapNode>());
extr_used = cost.extr;
draw_used = cost.draw;
disk_used = cost.disk;
}
void Extraction::Update(NexusMt *_mt) {
mt = _mt;
root = mt->history.Root();
sink = root + (mt->history.n_nodes()-1);
//clear statistics
if(!visited.size()) {
visited.resize(mt->history.n_nodes(), false);
visited[0] = true;
}
Init();
//first we coarse
while(back.size()) {
if(draw_used <= draw_max &&
extr_used <= extr_max &&
(front.size() && back.front().error > front.front().error))
break;
pop_heap(back.begin(), back.end(), greater<HeapNode>());
HeapNode hnode = back.back();
if(Visited(hnode.node)) {
if(!Coarse(hnode)) { //push back on heap the heapnode
push_heap(back.begin(), back.end(), greater<HeapNode>());
break;
}
}
back.pop_back();
}
while(front.size() && (*front.begin()).error > target_error) {
pop_heap(front.begin(), front.end());
HeapNode hnode = front.back();
if(!Visited(hnode.node)) {
if(!Refine(hnode.node)) {
push_heap(front.begin(), front.end());
break;
}
}
front.pop_back();
}
Select();
draw_size = selected.size();
//Preloading now
for(unsigned int i = 0; i < 100; i++) {
if(!front.size() && !back.size()) break;
if((i%2) && front.size()) {
pop_heap(front.begin(), front.end());
HeapNode hnode = front.back();
Node *node = hnode.node;
front.pop_back();
Node::iterator i;
for(i = node->out_begin(); i != node->out_end(); i++) {
Link &link = (*i);
for(Link::iterator k = link.begin(); k != link.end(); k++) {
selected.push_back((*k).patch);
}
}
} else if(back.size()) {
pop_heap(back.begin(), back.end(), greater<HeapNode>());
HeapNode hnode = back.back();
Node *node = hnode.node;
back.pop_back();
Node::iterator i;
for(i = node->in_begin(); i != node->in_end(); i++) {
Link &link = (*i);
for(Link::iterator k = link.begin(); k != link.end(); k++) {
selected.push_back((*k).patch);
}
}
}
}
}
float Extraction::GetRefineError(Node *node) {
float maxerror = 0;
Node::iterator i;
for(i = node->in_begin(); i != node->in_end(); i++) {
Link &link = *i;
for(Link::iterator k = link.begin(); k != link.end(); k++) {
Entry &entry = (*mt)[(*k).patch];
float error = metric->GetError(entry);
if(error > maxerror) maxerror = error;
}
}
return maxerror;
}
bool Extraction::Refine(Node *node) {
//recursively refine parent if applicable.
Node::iterator i;
for(i = node->in_begin(); i != node->in_end(); i++) {
Node *parent = (*i).node;
if(!Visited(parent))
if(!Refine(parent))
return false;
}
Cost cost;
Diff(node, cost);
if(disk_used + cost.disk > disk_max) return false;
if(extr_used + cost.extr > extr_max) return false;
if(draw_used + cost.draw > draw_max) return false;
extr_used += cost.extr;
draw_used += cost.draw;
disk_used += cost.disk;
visited[node - root] = true;
//now add to the front children (unless sink node)
for(i = node->out_begin(); i != node->out_end(); i++) {
Link &link = *i;
if(link.node == sink) continue;
float maxerror = GetRefineError(link.node);
if(maxerror > target_error)
front.push_back(HeapNode((*i).node, maxerror));
}
push_heap(front.begin(), front.end());
return true;
}
bool Extraction::Coarse(HeapNode &hnode) {
Node *node = hnode.node;
//recursively coarse children if applicable.
Node::iterator i;
for(i = node->out_begin(); i != node->out_end(); i++) {
Node *child = (*i).node;
float error = GetRefineError(child);
HeapNode hchild(child, error);
if(Visited(child))
if(!Coarse(hchild)) return false;
}
Cost cost;
Diff(node, cost);
extr_used -= cost.extr;
draw_used -= cost.draw;
disk_used -= cost.disk;
if(disk_used > disk_max) return false;
visited[node - root] = false;
//now add to the back parents (unless root node)
for(i = node->in_begin(); i != node->in_end(); i++) {
Link &link = *i;
if(link.node == root) continue;
float maxerror = GetRefineError(link.node);
back.push_back(HeapNode(link.node, maxerror));
push_heap(back.begin(), back.end(), greater<HeapNode>());
}
front.push_back(hnode);
push_heap(front.begin(), front.end());
return true;
}
void Extraction::Select() {
selected.clear();
History::Node *root = mt->history.Root();
Node *root = mt->history.Root();
History::Node *nodes = mt->history.nodes;
Node *nodes = mt->history.nodes;
for(unsigned int i = 0; i < visited.size(); i++) {
if(!visited[i]) continue;
History::Node &node = nodes[i];
Node &node = nodes[i];
History::Node::iterator n;
Node::iterator n;
for(n = node.out_begin(); n != node.out_end(); n++) {
unsigned int n_out = (*n).node - root;
if(!visited[n_out]) {
History::Link &link = *n;
for(History::Link::iterator k = link.begin(); k != link.end(); k++) {
Link &link = *n;
for(Link::iterator k = link.begin(); k != link.end(); k++) {
unsigned int patch = (*k).patch;
selected.push_back(patch);
}
@ -80,29 +289,28 @@ void Extraction::Select() {
}
}
void Extraction::Visit(History::Node *node) {
History::Node *root = mt->history.Root();
unsigned int n_node = node - root;
if(visited[n_node]) return;
void Extraction::Visit(Node *node) {
if(visited[node - root]) return;
visited[n_node] = true;
visited[node - root] = true;
History::Node::iterator i;
Node::iterator i;
for(i = node->in_begin(); i != node->in_end(); i++) {
unsigned int n_in = (*i).node - root;
if(visited[n_in]) continue;
HeapNode hin((*i).node, 0);
Diff(hin);
extr_used += hin.extr;
draw_used += hin.draw;
disk_used += hin.disk;
Visit((*i).node);
}
Cost cost;
Diff(node, cost);
extr_used += cost.extr;
draw_used += cost.draw;
disk_used += cost.disk;
for(i = node->out_begin(); i != node->out_end(); i++) {
float maxerror = 0;
History::Link &link = *i;
for(History::Link::iterator k = link.begin(); k != link.end(); k++) {
Link &link = *i;
for(Link::iterator k = link.begin(); k != link.end(); k++) {
Entry &entry = (*mt)[(*k).patch];
float error = metric->GetError(entry);
if(error > maxerror) maxerror = error;
@ -110,7 +318,6 @@ void Extraction::Visit(History::Node *node) {
//TODO this check may be dangerous for non saturating things...
if(maxerror > target_error) {
HeapNode hnode((*i).node, maxerror);
Diff(hnode);
heap.push_back(hnode);
push_heap(heap.begin(), heap.end());
}
@ -124,34 +331,34 @@ bool Extraction::Expand(HeapNode &node) {
return node.error > target_error;
}
void Extraction::Diff(HeapNode &hnode) {
History::Node &node = *(hnode.node);
History::Node::iterator i;
for(i = node.in_begin(); i != node.in_end(); i++) {
History::Link &link = *i;
for(History::Link::iterator k = link.begin(); k != link.end(); k++) {
void Extraction::Diff(Node *node, Cost &cost) {
Node::iterator i;
for(i = node->in_begin(); i != node->in_end(); i++) {
Link &link = *i;
for(Link::iterator k = link.begin(); k != link.end(); k++) {
unsigned int patch = (*k).patch;
Entry &entry = (*mt)[patch];
hnode.extr -= entry.ram_size;
cost.extr -= entry.ram_size;
vcg::Sphere3f &sphere = entry.sphere;
if(!frustum.IsOutside(sphere.Center(), sphere.Radius()))
hnode.draw -= entry.ram_size;
cost.draw -= entry.ram_size;
if(!entry.patch)
hnode.disk -= entry.disk_size;
cost.disk -= entry.disk_size;
}
}
for(i = node.out_begin(); i != node.out_end(); i++) {
History::Link &link = *i;
for(History::Link::iterator k = link.begin(); k != link.end(); k++) {
for(i = node->out_begin(); i != node->out_end(); i++) {
Link &link = *i;
for(Link::iterator k = link.begin(); k != link.end(); k++) {
unsigned int patch = (*k).patch;
Entry &entry = (*mt)[patch];
hnode.extr += entry.ram_size;
cost.extr += entry.ram_size;
vcg::Sphere3f &sphere = entry.sphere;
if(!frustum.IsOutside(sphere.Center(), sphere.Radius()))
hnode.draw += entry.ram_size;
cost.draw += entry.ram_size;
if(!entry.patch)
hnode.disk += entry.disk_size;
cost.disk += entry.disk_size;
}
}
}

View File

@ -1,10 +1,13 @@
#ifndef NXS_EXTRACTION_H
#define NXS_EXTRACTION_H
#include "history.h"
#include <set>
#include <vector>
#include <wrap/gui/frustum.h>
#include "history.h"
namespace nxs {
class Metric;
@ -12,16 +15,25 @@ class NexusMt;
class Extraction {
public:
struct HeapNode {
History::Node *node;
float error;
typedef History::Node Node;
typedef History::Link Link;
struct Cost {
unsigned int extr;
unsigned int draw;
unsigned int disk;
HeapNode(History::Node *_node, float _error): node(_node), error(_error),
extr(0), draw(0), disk(0) {}
Cost(): extr(0), draw(0), disk(0) {}
};
struct HeapNode {
Node *node;
float error;
HeapNode(Node *_node, float _error): node(_node), error(_error) {}
bool operator<(const HeapNode &node) const {
return error < node.error; }
bool operator>(const HeapNode &node) const {
return error > node.error; }
};
Metric *metric;
@ -36,23 +48,44 @@ class Extraction {
std::vector<bool> visited;
std::vector<HeapNode> heap;
std::vector<unsigned int> selected;
unsigned int draw_size; //first in selected should be drawn
//nodes that i can expand to
std::vector<HeapNode> front;
//nodes that i can contract
std::vector<HeapNode> back;
unsigned int tot_budget;
Extraction();
~Extraction();
void Extract(NexusMt *mt);
// void Update(std::vector<unsigned int> &selected);
void Update(NexusMt *mt);
protected:
protected:
void Select();
void Visit(History::Node *node);
void Visit(Node *node);
bool Expand(HeapNode &node);
void Diff(HeapNode &node);
void Diff(Node *node, Cost &cost);
bool Refine(Node *node);
bool Coarse(HeapNode &node);
void Init();
private:
NexusMt *mt;
Node *root;
Node *sink;
bool Visited(Node *node) {
return visited[node - root];
}
float GetRefineError(Node *node);
};

View File

@ -1,7 +1,10 @@
#include <set>
#include <iostream>
#include "fragment.h"
#include "border.h"
#include "pvoronoi.h"
#include <iostream>
//#include "pvoronoi.h"
using namespace std;
using namespace vcg;
@ -211,76 +214,6 @@ void nxs::Join(Fragment &in,
exit(0);
}
}
/* old code (more general.. but not parallelizable)
//L(a, b): Exist link between a, b
//An external link L(e, v) where v belongs to the patches (and e not)
//is valid only if: for every x in patches L(v, x) => L(e, x)
//this means the number of internal links for the same shared
//vertex is E = (n * (n-1)) where n is the number of duplicated vertices
//and n must be the number of externa links.
vector<unsigned int> internal_links;
internal_links.resize(vcount, 0);
map<BigLink, unsigned int> newborders;
for(unsigned int i = 0; i < in.pieces.size(); i++) {
unsigned int offset = offsets[i];
vector<Link> &bord = in.pieces[i].bord;
for(unsigned int k = 0; k < bord.size(); k++) {
Link llink = bord[k];
if(llink.IsNull()) continue;
if(!patch_remap.count(llink.end_patch)) {//external...may be erased
BigLink link;
link.orig_vert = llink.start_vert;
link.orig_patch = in.pieces[i].patch;
link.start_vert = remap[offset + llink.start_vert];
link.end_patch = llink.end_patch;
link.end_vert = llink.end_vert;
if(!newborders.count(link))
newborders[link] = 1;
else
newborders[link]++;
} else { //internal
internal_links[remap[offset + llink.start_vert]]++;
}
}
}
newvert.resize(vcount);
newface.resize(fcount*3);
newbord.resize(0);
fcount = 0;
for(unsigned int i = 0; i < in.pieces.size(); i++) {
unsigned int offset = offsets[i];
vector<Point3f> &vert = in.pieces[i].vert;
vector<unsigned short> &face = in.pieces[i].face;
vector<Link> &bord = in.pieces[i].bord;
for(unsigned int i = 0; i < vert.size(); i++) {
assert(offset + i < remap.size());
assert(remap[offset + i] < vcount);
newvert[remap[offset + i]] = vert[i];
}
for(unsigned int i = 0; i < face.size(); i++) {
assert(offset + face[i] < remap.size());
assert(remap[offset + face[i]] < newvert.size());
assert(fcount < newface.size());
newface[fcount++] = remap[offset + face[i]];
}
}
map<BigLink, unsigned int>::iterator b;
for(b = newborders.begin(); b != newborders.end(); b++) {
//test that number of links on this vertex is equal to
//number of internal links of the internal vertex
const BigLink &link = (*b).first;
unsigned int n = (*b).second;
if(n * (n-1) == internal_links[link.start_vert])
newbord.push_back(link);
}*/
}
void nxs::Split(Fragment &out,
@ -422,12 +355,6 @@ void nxs::Split(Fragment &out,
}
}
}
/* cerr << "patch seed: " << patch.patch << endl;
for(unsigned int i = 0; i < bords.size(); i++) {
Link &link = bords[i];
cerr << "link: " << link.start_vert << " "
<< link.end_patch << " " << link.end_vert << endl;
}*/
}
}

View File

@ -5,15 +5,12 @@
#include <ptypes/pstreams.h>
#include "nexus.h"
#include "pvoronoi.h"
namespace nxs {
class VoronoiPartition;
struct BigLink {
// unsigned int orig_vert;
// unsigned int orig_patch;
unsigned int start_vert;
unsigned int end_patch;
unsigned int end_vert;

View File

@ -205,7 +205,7 @@ unsigned int Nexus::AddPatch(unsigned int nvert, unsigned int nface,
return size() - 1;
}
void Nexus::Unify(float threshold) {
/*void Nexus::Unify(float threshold) {
//TODO what if colors or normals or strips?
unsigned int duplicated = 0;
unsigned int degenerate = 0;
@ -318,7 +318,7 @@ void Nexus::Unify(float threshold) {
cerr << "Found " << duplicated << " duplicated vertices" << endl;
if(degenerate)
cerr << "Found " << degenerate << " degenerate face while unmifying\n";
}
}*/
Patch *Nexus::LoadPatch(unsigned int idx) {
assert(idx < size());

View File

@ -22,110 +22,9 @@ void Stats::Init() {
count++;
}
/*float ExtractContest::GetError(PatchInfo &entry) {
Sphere3f &sphere = entry.sphere;
float dist = Distance(sphere, frustum.ViewPoint());
if(dist < 0)
return 1e20f;
if(frustum.IsOutside(sphere.Center(), sphere.Radius()))
return -1;
return entry.error/frustum.Resolution(dist);
}*/
/*
float Metric::GetError(Node *node) {
float max_error = 0;
vector<Frag>::iterator frag;
for(frag = node->frags.begin(); frag != node->frags.end(); frag++) {
float error = GetError(*frag);
if(max_error < error) max_error = error;
}
return max_error;
}
float Metric::GetError(Frag &frag) {
float max_error = 0;
vector<unsigned int>::iterator cell;
for(cell = frag.begin(); cell != frag.end(); cell++) {
float error = GetError(*cell);
if(max_error < error) max_error = error;
}
return max_error;
}
float FrustumMetric::GetError(unsigned int cell) {
float max_error = 0;
PatchInfo &entry = (*index)[cell];
Sphere3f &sphere = entry.sphere;
float dist = Distance(sphere, frustum.ViewPoint());
if(dist < 0) return 1e20f;
float error = entry.error/frustum.Resolution(dist);
if(frustum.IsOutside(sphere.Center(), sphere.Radius()))
error /= 32;
return error;
}
bool NexusMt::Expand(TNode &tnode) {
//expand if node error > target error
if(extraction_used >= extraction_max) return false;
if(draw_used >= draw_max) return false;
if(disk_used >= disk_max) {
float ratio = disk_max / (float)disk_used;
float error = tnode.error * ratio;
return error > target_error;
}
return tnode.error > target_error;
}*/
/*void NexusMt::NodeVisited(Node *node) {
//TODO write this a bit more elegant.
//first we process arcs removed:
for(unsigned int i = 0; i < node->out.size(); i++) {
//assert(!(node->out[i]->visited));
Frag &frag = node->frags[i];
for(unsigned int k = 0; k < frag.size(); k++) {
unsigned int patch = frag[k];
PServer::Entry &entry = patches.entries[patch];
unsigned int ram_size = entry.ram_size;
extraction_used += ram_size;
PatchInfo &info = index[patch];
if(!frustum.IsOutside(info.sphere.Center(), info.sphere.Radius()))
draw_used += ram_size;
if(!patches.entries[patch].patch)
disk_used += ram_size;
}
}
vector<Node *>::iterator from;
for(from = node->in.begin(); from != node->in.end(); from++) {
assert((*from)->visited);
vector<Frag> &frags = (*from)->frags;
for(unsigned int i = 0; i < frags.size(); i++) {
if((*from)->out[i] == node) {
vector<unsigned int> &frag = frags[i];
for(unsigned int k = 0; k < frag.size(); k++) {
unsigned int patch = frag[k];
PServer::Entry &entry = patches.entries[patch];
extraction_used -= entry.ram_size;
PatchInfo &info = index[patch];
if(!frustum.IsOutside(info.sphere.Center(), info.sphere.Radius()))
draw_used -= entry.ram_size;
if(!patches.entries[patch].patch)
disk_used -= entry.ram_size;
}
}
}
}
}*/
NexusMt::NexusMt() {
preload.mt = this;
preload.start();
cerr << "Ramsize: " << ram_max << endl;
// SetPrefetchSize(patches.ram_max/2);
// prefetch.start();
}
NexusMt::~NexusMt() {
@ -180,9 +79,9 @@ void NexusMt::Render(Extraction &extraction, DrawContest &contest,
vector<unsigned int> skipped;
vector<unsigned int>::iterator i;
for(i = extraction.selected.begin(); i != extraction.selected.end(); i++) {
Entry &entry = operator[](*i);
for(unsigned int i = 0; i < extraction.draw_size; i++) {
unsigned int patch = extraction.selected[i];
Entry &entry = operator[](patch);
vcg::Sphere3f &sphere = entry.sphere;
if(extraction.frustum.IsOutside(sphere.Center(), sphere.Radius()))
continue;
@ -190,91 +89,27 @@ void NexusMt::Render(Extraction &extraction, DrawContest &contest,
if(stats) stats->ktri += entry.nface;
if(!entry.patch) {
skipped.push_back(*i);
skipped.push_back(patch);
continue;
}
Draw(*i, contest);
Draw(patch, contest);
}
preload.lock.enter();
for(i = skipped.begin(); i != skipped.end(); i++) {
for(vector<unsigned int>::iterator i = skipped.begin();
i != skipped.end(); i++) {
GetPatch(*i);
Draw(*i, contest);
}
// Flush(false); //not useful now
Flush(false); //in case there are no skipped... :P
preload.lock.leave();
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
//flushing mem
}
/*void NexusMt::Draw(vector<unsigned int> &cells) {
stats.start();
todraw.clear();
vector<QueuePServer::Data> flush;
for(unsigned int i = 0; i < cells.size(); i++) {
PatchInfo &entry = index[cells[i]];
QueuePServer::Data &data = patches.Lookup(cells[i], entry.nvert,
entry.nface, flush);
todraw.push_back(&data);
}
glEnableClientState(GL_VERTEX_ARRAY);
if(draw_cnt.use_colors)
glEnableClientState(GL_COLOR_ARRAY);
if(draw_cnt.use_normals)
glEnableClientState(GL_NORMAL_ARRAY);
//TODO textures and data.
// unsigned int count = draw.size();
unsigned int count = todraw.size();
while(count > 0 || prefetch.draw.get_count()) {
if(todraw.size()) {
QueuePServer::Data *data = todraw.back();
todraw.pop_back();
Draw((unsigned int)(data->patch), *data);
} else {
// cerr << "Getting message: " << count << endl;
pt::message *msg = prefetch.draw.getmessage();
QueuePServer::Data *data = (QueuePServer::Data *)(msg->param);
if(msg->id == Prefetch::FLUSH) {
patches.FlushVbo(*data);
// if(data->vbo_element) {
//glDeleteBuffersARB(1, &(data->vbo_element));
//glDeleteBuffersARB(1, &(data->vbo_array));
delete data;
delete msg;
continue;
}
if(msg->id != Prefetch::DRAW) {
cerr << "Unknown message!\n";
continue;
}
unsigned int cell = msg->result;
Draw(cell, *data);
delete msg;
}
count--;
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
}*/
void NexusMt::Draw(unsigned int cell, DrawContest &contest) {
Entry &entry = operator[](cell);
Patch &patch = *(entry.patch);
@ -400,70 +235,7 @@ void NexusMt::FlushVbo(Entry &entry) {
vbo_used -= sizeof(float) * patch.dstart;
}
/*void NexusMt::SetExtractionSize(unsigned int r_size) {
extract_cnt.extraction_max = r_size/patches.chunk_size;
}
//void NexusMt::SetMetric(NexusMt::MetricKind kind) {
//do nothing at the moment.
//}
void NexusMt::SetError(float error) {
extract_cnt.target_error = error;
}
//void NexusMt::SetVboSize(unsigned int _vbo_max) {
//WORKING patches.vbo_max = _vbo_max;
//}
void NexusMt::SetPrefetchSize(unsigned int size) {
//TODO do something reasonable with this.
}
bool NexusMt::SetMode(DrawContest::Mode _mode) {
draw_cnt.mode = _mode;
return true;
}
bool NexusMt::SetComponent(DrawContest::Component c, bool on) {
if(c == DrawContest::COLOR && (signature & NXS_COLORS))
draw_cnt.use_colors = on;
if(c == DrawContest::NORMAL && (signature & NXS_NORMALS_SHORT))
draw_cnt.use_normals = on;
if(c == DrawContest::TEXTURE && (signature & NXS_TEXTURES_SHORT))
draw_cnt.use_textures = on;
if(c == DrawContest::DATA && (signature & NXS_DATA32))
draw_cnt.use_data = on;
// unsigned int components = DrawContest::COLOR * use_colors +
// DrawContest::NORMAL * use_normals +
// DrawContest::TEXTURE * use_textures +
// DrawContest::DATA * use_data;
return true;
}
bool NexusMt::SetComponents(unsigned int mask) {
SetComponent(DrawContest::COLOR, (mask & DrawContest::COLOR) != 0);
SetComponent(DrawContest::NORMAL, (mask & DrawContest::NORMAL) != 0);
SetComponent(DrawContest::TEXTURE, (mask & DrawContest::TEXTURE) != 0);
SetComponent(DrawContest::DATA, (mask & DrawContest::DATA) != 0);
// unsigned int components = mask;
if( ((mask & DrawContest::COLOR) && !(signature & NXS_COLORS)) ||
((mask & DrawContest::NORMAL) && !(signature & NXS_NORMALS_SHORT)) ||
((mask & DrawContest::TEXTURE) && !(signature & NXS_TEXTURES_SHORT)) ||
((mask & DrawContest::DATA) && !(signature & NXS_DATA32)) )
return false;
return true;
}*/
//TODO: nodes and fragment sholuld be kept in another way,
// so we can save that structure instead of the history!
//Kept for historical reasons.
/*void NexusMt::ExtractFixed(vector<unsigned int> &selected, float error) {
std::vector<Node>::iterator n;
for(n = nodes.begin(); n != nodes.end(); n++)
@ -493,525 +265,3 @@ bool NexusMt::SetComponents(unsigned int mask) {
}
}
} */
/*void NexusMt::Expand(Node &node, vector<HeapNode> &expand) {
if(node.visited) return;
cerr << "Expanding\n";
for(unsigned int i = 0; i < node.in_size; i++) {
Link &link = innodes[node.in + i];
Node &parent = nodes[link.node];
if(!parent.visited)
Expand(parent, expand);
}
for(unsigned int o = 0; o < node.out_size; o++) {
Link &link = outnodes[node.out + o];
Node &outnode = nodes[link.node];
if(outnode.visited) continue;
assert(link.error != -1);
if(link.error > extract_cnt.target_error) {
HeapNode hnode(&outnode, node.error - extract_cnt.target_error);
expand.push_back(hnode);
push_heap(expand.begin(), expand.end());
}
}
unsigned int d_extr = 0;
unsigned int d_draw = 0;
unsigned int d_disk = 0;
Diff(node, d_extr, d_draw, d_disk);
extract_cnt.extraction_used += d_extr;
extract_cnt.draw_used += d_draw;
extract_cnt.disk_used += d_disk;
node.visited = true;
}
void NexusMt::Contract(Node &node) {
if(!node.visited) return;
cerr << "Contracting...\n";
for(unsigned int i = 0; i < node.out_size; i++) {
Link &link = outnodes[node.out + i];
Node &child = nodes[link.node];
if(child.visited)
Contract(child);
}
unsigned int d_extr = 0;
unsigned int d_draw = 0;
unsigned int d_disk = 0;
Diff(node, d_extr, d_draw, d_disk);
extract_cnt.extraction_used -= d_extr;
extract_cnt.draw_used -= d_draw;
extract_cnt.disk_used -= d_disk;
node.visited = false;
}
void NexusMt::GetErrorLink(Node &node, Link &link) {
if(link.error != -1) return;
for(unsigned int c = link.frag; frags[c].patch != 0xffffffff; c++) {
Cell &cell = frags[c];
if(cell.error != -1) continue;
PatchInfo &info = index[cell.patch];
cell.error = extract_cnt.GetError(info);
cerr << "Cell.error: " << cell.error << endl;
if(link.error < cell.error) link.error = cell.error;
}
}
void NexusMt::GetErrorNode(Node &node) {
if(node.error != -1) return;
for(unsigned int o = 0; o < node.out_size; o++) {
Link &link = outnodes[node.out + o];
GetErrorLink(node, link);
if(node.error < link.error) node.error = link.error;
}
}
void NexusMt::NodeExplore(Node &node,
vector<HeapNode> &expand,
vector<HeapNode> &contract) {
assert(node.visited);
GetErrorNode(node);
cerr << "node.error: " << node.error <<
" target: " << extract_cnt.target_error << endl;
if(node.error > extract_cnt.target_error) {
cerr << "Expandible node...\n";
for(unsigned int o = 0; o < node.out_size; o++) {
Link &link = outnodes[node.out + o];
assert(link.error != -1);
Node &outnode = nodes[link.node];
if(outnode.visited) continue;
if(link.error > extract_cnt.target_error) {
HeapNode hnode(&outnode, node.error - extract_cnt.target_error);
expand.push_back(hnode);
push_heap(expand.begin(), expand.end());
}
}
}
float max_err = -1;
bool can_contract = true;
for(unsigned int o = 0; o < node.out_size; o++) {
Link &link = outnodes[node.out + o];
Node &outnode = nodes[link.node];
if(node.visited) {
can_contract = false;
break;
}
}
if(can_contract) {
for(unsigned int o = 0; o < node.in_size; o++) {
Link &link = innodes[node.in + o];
GetErrorLink(node, link);
if(max_err < link.error) max_err = link.error;
}
HeapNode hnode(&node, extract_cnt.target_error - max_err);
contract.push_back(hnode);
push_heap(contract.begin(), contract.end());
}
}
void NexusMt::FrontExplore(vector<HeapNode> &expand,
vector<HeapNode> &contract) {
extract_cnt.extraction_used = 0;
extract_cnt.draw_used = 0;
extract_cnt.disk_used = 0;
std::vector<Node>::iterator i;
for(i = nodes.begin(); i != nodes.end(); i++) {
Node &node = *i;
if(!node.visited)
continue;
for(int k = 0; k < node.out_size; k++) {
Link &link = outnodes[node.out + k];
assert(link.node < nodes.size());
Node &children = nodes[link.node];
if(!children.visited) {
cerr << "Exploting child...\n";
NodeExplore(node, expand, contract);
for(unsigned int c = link.frag; frags[c].patch != 0xffffffff; c++) {
PServer::Entry &entry = patches.entries[c];
if(!entry.patch) extract_cnt.disk_used += entry.disk_size;
extract_cnt.extraction_used += entry.ram_size;
vcg::Sphere3f &sphere = index[c].sphere;
if(!extract_cnt.frustum.IsOutside(sphere.Center(), sphere.Radius()))
extract_cnt.draw_used += entry.ram_size;
}
}
}
}
}
void NexusMt::Diff(Node &node,
unsigned int &d_extr,
unsigned int &d_draw,
unsigned int &d_disk) {
d_extr = 0;
d_draw = 0;
d_disk = 0;
for(unsigned int o = 0; o < node.out_size; o++) {
Link &link = outnodes[node.out + o];
for(unsigned int c = link.frag; frags[c].patch != 0xffffffff; c++) {
PServer::Entry &entry = patches.entries[c];
if(!entry.patch) d_disk += entry.disk_size;
d_extr += entry.ram_size;
Sphere3f &sphere = index[c].sphere;
if(!extract_cnt.frustum.IsOutside(sphere.Center(), sphere.Radius()))
d_draw += entry.ram_size;
}
}
for(unsigned int o = 0; o < node.in_size; o++) {
Link &link = innodes[node.in + o];
for(unsigned int c = link.frag; frags[c].patch != 0xffffffff; c++) {
PServer::Entry &entry = patches.entries[c];
if(!entry.patch) d_disk -= entry.disk_size;
d_extr -= entry.ram_size;
if(!extract_cnt.frustum.IsOutside(sphere.Center(), sphere.Radius()))
d_draw -= entry.ram_size;
}
}
}*/
/*void NexusMt::Extract(std::vector<unsigned int> &selected) {
extract_cnt.frustum.GetView();
//clear error (no more valid...)
for(unsigned int i = 0; i < nodes.size(); i++)
nodes[i].error = -1;
for(unsigned int i = 0; i < outnodes.size(); i++)
outnodes[i].error = -1;
for(unsigned int i = 0; i < innodes.size(); i++)
innodes[i].error = -1;
for(unsigned int i = 0; i < frags.size(); i++)
frags[i].error = -1;
std::vector<HeapNode> expand;
std::vector<HeapNode> contract;
if(!nodes[0].visited)
nodes[0].visited = true;
//explore front
FrontExplore(expand, contract);
bool can_expand = true;
bool can_contract = true;
float current_error = 1e30;
while(can_expand || can_contract) {
if(can_expand) {
if(!expand.size()) {
can_expand = false;
continue;
}
cerr << "trying to expand..\n";
pop_heap(expand.begin(), expand.end());
HeapNode hnode = expand.back();
Node *node = hnode.node;
// if(node->visited) {
//cerr << "Failed cause already visited\n";
// expand.pop_back();
//continue; //already expanded...
// }
unsigned int d_extr = 0;
unsigned int d_draw = 0;
unsigned int d_disk = 0;
Diff(*node, d_extr, d_draw, d_disk);
if(extract_cnt.disk_used + d_disk > extract_cnt.disk_max) {
cerr << "Failed cause disk...\n";
cerr << "d_disl: " << d_disk << " extract_cnt.disk_max "
<< extract_cnt.disk_max << endl;
expand.pop_back();
continue;
}
if(extract_cnt.extraction_used + d_extr > extract_cnt.extraction_max ||
extract_cnt.draw_used + d_draw > extract_cnt.draw_max) {
cerr << "Failed...\n";
can_expand = false;
push_heap(expand.begin(), expand.end());
continue;
} else {
cerr << "Expanding...\n";
current_error = hnode.error;
expand.pop_back();
Expand(*node, expand);
}
} else if(can_contract) {
if(!contract.size()) {
can_contract = false;
continue;
}
pop_heap(contract.begin(), contract.end());
HeapNode hnode = contract.back();
if(hnode.error < extract_cnt.target_error - current_error) {
can_contract = false;
continue;
}
Node *node = hnode.node;
if(!node->visited) {
contract.pop_back();
continue;//already contracted
}
unsigned int d_extr = 0;
unsigned int d_draw = 0;
unsigned int d_disk = 0;
Diff(*node, d_extr, d_draw, d_disk);
if(extract_cnt.disk_used - d_disk > extract_cnt.disk_max) {
expand.pop_back();
continue;
}
if(extract_cnt.extraction_used - d_extr < extract_cnt.extraction_max &&
extract_cnt.draw_used - d_draw < extract_cnt.draw_max) {
can_expand = true;
}
current_error = hnode.error;
contract.pop_back();
Contract(*node);
}
}
Select(selected);
}*/
/*void NexusMt::Extract(std::vector<unsigned int> &selected, Policy *policy) {
std::vector<Node>::iterator n;
for(n = nodes.begin(); n != nodes.end(); n++)
(*n).visited = false;
std::queue<Node *> qnodo;
qnodo.push(&nodes[0]);
nodes[0].visited = true;
for( ; !qnodo.empty(); qnodo.pop()) {
Node &node = *qnodo.front();
std::vector<Frag>::iterator i;
std::vector<Node *>::iterator on;
for(i = node.frags.begin(), on = node.out.begin();
i != node.frags.end(); i++, on++) {
if((*on)->visited) continue;
Frag &frag = (*i);
std::vector<unsigned int>::iterator cell;
for(cell = frag.begin(); cell != frag.end(); cell++) {
if(policy->Expand(*cell, index[*cell]))
policy->Visit(*on, qnodo);
}
}
}
Select(selected);
} */
/*void NexusMt::Select(vector<unsigned int> &selected) {
selected.clear();
std::vector<Node>::iterator i;
for(i = nodes.begin(); i != nodes.end(); i++) {
Node &node = *i;
if(!node.visited)
continue;
for(unsigned int o = 0; o < node.out_size; o++) {
Link &link = outnodes[node.out + o];
for(unsigned int c = link.frag; frags[c].patch != 0xffffffff; c++) {
Cell &cell = frags[c];
selected.push_back(cell.patch);
}
}
}*/
// for(unsigned int i = 0; i < selected.size(); i++) {
// cerr << "Sel: " << selected[i] << endl;
// }
/* std::vector<Node *>::iterator n;
std::vector<>::iterator f;
for(n = node.out.begin(), f = node.frags.begin();
n != node.out.end(); n++, f++) {
if(!(*n)->visited || (*n)->error == 0) {
vector<unsigned int>::iterator c;
Frag &frag = (*f);
for(c = frag.begin(); c != frag.end(); c++)
selected.push_back(*c);
}
}
}*/
//}
/*bool NexusMt::TestCurrent(Node *node) {
if(!visited) return;
for(unsigned int i = 0; i < node->out.size(); i++)
if(!node->out[k].visited) {
node->current = true;
return true;
}
node->current = false;
return false;
} */
/*void NexusMt::VisitNode(Node *node, vector<TNode> &heap) {
//TestCurrent(*i);
if(node->visited) return;
node->visited = true;
vector<Node *>::iterator i;
for(i = node->in.begin(); i != node->in.end(); i++) {
VisitNode(*i, heap);
}
for(unsigned int k = 0; k < node->out.size(); k++) {
Node *outnode = node->out[k];
float max_error = metric->GetError(outnode);
for(unsigned int j = 0; j < node->frags[k].size(); j++) {
unsigned int patch = node->frags[k][j];
float error = metric->GetError(patch);
if(max_error < error) max_error = error;
visited.push_back(PServer::Item(patch, fabs(error - target_error)));
// push_heap(visited.begin(), visited.end());
}
heap.push_back(TNode(outnode, max_error));
push_heap(heap.begin(), heap.end());
}
sequence.push_back(node);
NodeVisited(node);
}*/
/*void NexusMt::UnvisitNode(Node *node, vector<TNode> &heap) {
node->current = false;
vector<Node *>::iterator i;
for(i = node->in.begin(); i != node->in.end(); i++)
if(TestCurrent(*i)) {
float error = metric->GetError(*i);
heap.push_back(TNode(*i, error));
push_heap(heap.begin(), heap.end());
}
} */
/*void NexusMt::LoadHistory() {
//The last update erases everything.
assert(history[0].erased.size() == 0);
//maps cell -> node containing it
map<unsigned int, unsigned int> cell_node;
//maps node -> Links
map<unsigned int, vector<Link> > node_inlinks;
map<unsigned int, vector<Link> > node_outlinks;
nodes.resize(history.size());
//building fragments and nodes.
unsigned int current_node = 0;
vector<Update>::iterator u;
for(u = history.begin(); u != history.end(); u++) {
Node &node = nodes[current_node];
node.error = 0;
//created cells belong to this node, we look also for max error.
for(unsigned int i = 0; i < (*u).created.size(); i++) {
unsigned int cell = (*u).created[i];
if(index[cell].error > node.error)
node.error = index[cell].error;
cell_node[cell] = current_node;
}
//Every erased cell already belonged to a node.
//we record for each node its cells.
map<unsigned int, vector<unsigned int> > node_erased;
for(unsigned int i = 0; i < (*u).erased.size(); i++) {
unsigned int cell = (*u).erased[i];
assert(cell_node.count(cell));
node_erased[cell_node[cell]].push_back(cell);
}
//for every node with erased cells we build a frag and
//put the corresponding cells in it.
map<unsigned int, vector<unsigned int> >::iterator e;
for(e = node_erased.begin(); e != node_erased.end(); e++) {
//node.in.push_back(innodes.size());
unsigned int floor_node = (*e).first;
Node &oldnode = nodes[floor_node];
Link inlink;
inlink.node = floor_node;
inlink.frag = frags.size();
Link outlink;
outlink.node = current_node;
outlink.frag = frags.size();
float max_err = -1;
//Fill it with erased cells.
vector<unsigned int> &cells = (*e).second;
vector<unsigned int>::iterator k;
for(k = cells.begin(); k != cells.end(); k++) {
Cell cell;
cell.patch = (*k);
assert(cell.patch < index.size());
frags.push_back(cell);
if(index[cell.patch].error > max_err)
max_err = index[cell.patch].error;
}
Cell cell;
cell.patch = 0xffffffff;
cell.error = -1;
frags.push_back(cell);
inlink.error = max_err;
outlink.error = max_err;
//Add the new Frag to the node.
node_outlinks[floor_node].push_back(outlink);
node_outlinks[current_node].push_back(inlink);
if(node.error < max_err)
node.error = max_err;
//Update in and out of the nodes.
}
current_node++;
}
map<unsigned int, vector<Link> >::iterator k;
for(k = node_outlinks.begin(); k != node_outlinks.end(); k++) {
unsigned int inode = (*k).first;
vector<Link> &links = (*k).second;
nodes[inode].out = outnodes.size();
nodes[inode].out_size = links.size();
for(unsigned int i = 0; i < links.size(); i++)
outnodes.push_back(links[i]);
}
for(k = node_inlinks.begin(); k != node_inlinks.end(); k++) {
unsigned int inode = (*k).first;
vector<Link> &links = (*k).second;
nodes[inode].in = innodes.size();
nodes[inode].in_size = links.size();
for(unsigned int i = 0; i < links.size(); i++)
innodes.push_back(links[i]);
}
}
void NexusMt::ClearHistory() {
nodes.clear();
innodes.clear();
outnodes.clear();
frags.clear();
}*/

View File

@ -1,29 +1,32 @@
/****************************************************************************
* VCGLib o o *
* Visual and Computer Graphics Library o o *
* _ O _ *
* Copyright(C) 2004 \/)\/ *
* Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
* VCGLib o o *
* Visual and Computer Graphics Library o o *
* _ O _ *
* Copyright(C) 2004 \/)\/ *
* Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
/****************************************************************************
History
$Log: not supported by cvs2svn $
Revision 1.28 2005/01/14 15:25:29 ponchio
Revolution.
Revision 1.27 2004/12/15 16:37:55 ponchio
Optimizing realtime vis.
@ -197,7 +200,7 @@ int main(int argc, char *argv[]) {
float error = 4;
Trackball track;
// int option;
// int option;
if(argc != 2) {
cerr << "Usage: " << argv[0] << " <nexus file>\n"; return -1;
@ -250,12 +253,10 @@ int main(int argc, char *argv[]) {
bool show_normals = true;
bool show_statistics = true;
bool extract = true;
bool realtime = true;
bool stepping = true;
bool step = true;
// NexusMt::MetricKind metric;
//DrawContest::Mode mode = DrawContest::SMOOTH;
//nexus.SetError(error);
// nexus.SetMetric(NexusMt::FRUSTUM);
if(!nexus.InitGL()) {
cerr << "Could not init glew.\n";
}
@ -288,88 +289,91 @@ int main(int argc, char *argv[]) {
}
if(anything) {
switch( event.type ) {
case SDL_QUIT: quit = 1; break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym) {
case SDLK_RCTRL:
case SDLK_LCTRL: track.ButtonDown(Trackball::KEY_CTRL); break;
case SDLK_q: exit(0); break;
case SDLK_k: keepdrawing = !keepdrawing; break;
case SDLK_e: extract = !extract; break;
case SDLK_c: show_colors = !show_colors; break;
case SDLK_n: show_normals = !show_normals; break;
case SDL_QUIT: quit = 1; break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym) {
case SDLK_RCTRL:
case SDLK_LCTRL: track.ButtonDown(Trackball::KEY_CTRL); break;
case SDLK_q: exit(0); break;
case SDLK_k: keepdrawing = !keepdrawing; break;
case SDLK_e: extract = !extract; break;
case SDLK_c: show_colors = !show_colors; break;
case SDLK_n: show_normals = !show_normals; break;
case SDLK_LEFT: nexus.MaxRam() *= 0.8; break;
case SDLK_RIGHT: nexus.MaxRam() *= 1.3; break;
case SDLK_UP: extraction.draw_max *= 1.3; break;
case SDLK_DOWN: extraction.draw_max *= 0.8; break;
case SDLK_PAGEUP: extraction.disk_max *= 1.3; break;
case SDLK_PAGEDOWN: extraction.disk_max *= 0.8; break;
case SDLK_0: extraction.extr_max *= 1.3; break;
case SDLK_9: extraction.extr_max *= 0.8; break;
case SDLK_LEFT: nexus.MaxRam() *= 0.8; break;
case SDLK_RIGHT: nexus.MaxRam() *= 1.3; break;
case SDLK_UP: extraction.draw_max *= 1.3; break;
case SDLK_DOWN: extraction.draw_max *= 0.8; break;
case SDLK_PAGEUP: extraction.disk_max *= 1.3; break;
case SDLK_PAGEDOWN: extraction.disk_max *= 0.8; break;
case SDLK_0: extraction.extr_max *= 1.3; break;
case SDLK_9: extraction.extr_max *= 0.8; break;
// case SDLK_s: metric = NexusMt::FRUSTUM; break;
case SDLK_p: contest.mode = DrawContest::POINTS; break;
case SDLK_d: contest.mode = DrawContest::PATCHES; break;
case SDLK_f: contest.mode = DrawContest::FLAT; break;
case SDLK_m: contest.mode = DrawContest::SMOOTH; break;
case SDLK_r:
case SDLK_SPACE: rotate = !rotate; break;
case SDLK_MINUS:
extraction.target_error *= 0.9f;
cerr << "Error: " << extraction.target_error << endl;
break;
case SDLK_EQUALS:
case SDLK_PLUS:
extraction.target_error *= 1.1f;
cerr << "Error: " << extraction.target_error << endl;
break;
}
break;
case SDL_KEYUP:
switch(event.key.keysym.sym) {
case SDLK_RCTRL:
case SDLK_LCTRL:
track.ButtonUp(Trackball::KEY_CTRL); break;
}
break;
case SDL_MOUSEBUTTONDOWN:
x = event.button.x;
y = height - event.button.y;
#ifdef SDL_BUTTON_WHEELUP
if(event.button.button == SDL_BUTTON_WHEELUP)
track.MouseWheel(1);
else if(event.button.button == SDL_BUTTON_WHEELDOWN)
track.MouseWheel(-1);
else
#endif
if(event.button.button == SDL_BUTTON_LEFT)
track.MouseDown(x, y, Trackball::BUTTON_LEFT);
else if(event.button.button == SDL_BUTTON_RIGHT)
track.MouseDown(x, y, Trackball::BUTTON_RIGHT);
break;
case SDL_MOUSEBUTTONUP:
x = event.button.x;
y = height - event.button.y;
if(event.button.button == SDL_BUTTON_LEFT)
track.MouseUp(x, y, Trackball::BUTTON_LEFT);
else if(event.button.button == SDL_BUTTON_RIGHT)
track.MouseUp(x, y, Trackball::BUTTON_RIGHT);
break;
case SDL_MOUSEMOTION:
while(SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEMOTIONMASK));
x = event.motion.x;
y = height - event.motion.y;
track.MouseMove(x, y);
break;
case SDL_VIDEOEXPOSE:
default: break;
}
// case SDLK_s: metric = NexusMt::FRUSTUM; break;
case SDLK_p: contest.mode = DrawContest::POINTS; break;
case SDLK_d: contest.mode = DrawContest::PATCHES; break;
case SDLK_f: contest.mode = DrawContest::FLAT; break;
case SDLK_m: contest.mode = DrawContest::SMOOTH; break;
case SDLK_o: realtime = !realtime; break;
case SDLK_s: step = true; break;
case SDLK_r:
case SDLK_SPACE: rotate = !rotate; break;
case SDLK_MINUS:
extraction.target_error *= 0.9f;
cerr << "Error: " << extraction.target_error << endl;
break;
case SDLK_EQUALS:
case SDLK_PLUS:
extraction.target_error *= 1.1f;
cerr << "Error: " << extraction.target_error << endl;
break;
}
break;
case SDL_KEYUP:
switch(event.key.keysym.sym) {
case SDLK_RCTRL:
case SDLK_LCTRL:
track.ButtonUp(Trackball::KEY_CTRL); break;
}
break;
case SDL_MOUSEBUTTONDOWN:
x = event.button.x;
y = height - event.button.y;
#ifdef SDL_BUTTON_WHEELUP
if(event.button.button == SDL_BUTTON_WHEELUP)
track.MouseWheel(1);
else if(event.button.button == SDL_BUTTON_WHEELDOWN)
track.MouseWheel(-1);
else
#endif
if(event.button.button == SDL_BUTTON_LEFT)
track.MouseDown(x, y, Trackball::BUTTON_LEFT);
else if(event.button.button == SDL_BUTTON_RIGHT)
track.MouseDown(x, y, Trackball::BUTTON_RIGHT);
break;
case SDL_MOUSEBUTTONUP:
x = event.button.x;
y = height - event.button.y;
if(event.button.button == SDL_BUTTON_LEFT)
track.MouseUp(x, y, Trackball::BUTTON_LEFT);
else if(event.button.button == SDL_BUTTON_RIGHT)
track.MouseUp(x, y, Trackball::BUTTON_RIGHT);
break;
case SDL_MOUSEMOTION:
while(SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEMOTIONMASK));
x = event.motion.x;
y = height - event.motion.y;
track.MouseMove(x, y);
break;
case SDL_VIDEOEXPOSE:
default: break;
}
redraw = true;
}
redraw = true;
//if(!redraw && !keepdrawing) continue;
@ -411,26 +415,30 @@ int main(int argc, char *argv[]) {
if(extract) {
extraction.frustum.GetView();
extraction.metric->GetView();
extraction.Extract(&nexus);
if(!realtime) {
extraction.Extract(&nexus);
} else {
extraction.Update(&nexus);
}
}
nexus.Render(extraction, contest, &stats);
/* if(show_borders) {
for(unsigned int i = 0; i < cells.size(); i++) {
Border border = nexus.GetBorder(cells[i]);
Patch &patch = nexus.GetPatch(cells[i]);
glPointSize(4);
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_POINTS);
for(unsigned int b = 0; b < border.Size(); b++) {
for(unsigned int i = 0; i < cells.size(); i++) {
Border border = nexus.GetBorder(cells[i]);
Patch &patch = nexus.GetPatch(cells[i]);
glPointSize(4);
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_POINTS);
for(unsigned int b = 0; b < border.Size(); b++) {
Link &link = border[b];
Point3f &p = patch.Vert(link.start_vert);
glVertex3f(p[0], p[1], p[2]);
}
glEnd();
glPointSize(1);
}
}*/
}
glEnd();
glPointSize(1);
}
}*/
//cerr Do some reporting:
if(show_statistics) {
@ -494,8 +502,6 @@ int main(int argc, char *argv[]) {
}
// Clean up
SDL_Quit();
return -1;
}

View File

@ -1,5 +1,6 @@
#include <vector>
#include <map>
#include <set>
#include <iostream>
//#include <wrap/strip/tristrip.h>
@ -198,36 +199,6 @@ void nxs::ComputeNormals(Nexus &nexus) {
nexus.borders.SetReadOnly(false);
}
/*void nxs::ComputeTriStrip(unsigned short nfaces, unsigned short *faces,
vector<unsigned short> &strip) {
vector<unsigned int> indices;
indices.resize(nfaces*3);
for(unsigned int i = 0; i < nfaces*3; i++) {
indices[i] = faces[i];
}
vector<unsigned int> restrip;
ComputeStrip(indices, restrip);
unsigned int len = 0;
for(unsigned int i = 0; i < restrip.size(); i++) {
if(restrip[i] != 0xffffffff) {
strip.push_back(restrip[i]);
len++;
} else {
if(i < restrip.size()-1) { //not the last primitive.
strip.push_back(restrip[i-1]);
//TODO optimize this!
if((len%2) == 1) //do not change orientation....
strip.push_back(restrip[i-1]);
strip.push_back(restrip[i+1]);
}
len = 0;
}
}
}*/
void nxs::ComputeTriStrip(unsigned short nfaces, unsigned short *faces,
vector<unsigned short> &strip) {
@ -313,3 +284,119 @@ void nxs::Reorder(unsigned int signature, Patch &patch) {
for(int i = 0; i < patch.nv; i++)
patch.Vert(remap[i]) = vert[i];
}
//TODO actually use threshold
void nxs::Unify(Nexus &nexus, float threshold) {
//TODO what if colors or normals or strips?
unsigned int duplicated = 0;
unsigned int degenerate = 0;
for(unsigned int p = 0; p < nexus.size(); p++) {
Entry &entry = nexus[p];
Patch &patch = nexus.GetPatch(p);
unsigned int vcount = 0;
map<Point3f, unsigned short> vertices;
vector<unsigned short> remap;
remap.resize(patch.nv);
for(unsigned int i = 0; i < patch.nv; i++) {
Point3f &point = patch.Vert(i);
if(!vertices.count(point))
vertices[point] = vcount++;
else
duplicated++;
remap[i] = vertices[point];
}
assert(vertices.size() <= patch.nv);
if(vertices.size() == patch.nv) //no need to unify
continue;
vector<Point3f> newvert;
newvert.resize(vertices.size());
map<Point3f, unsigned short>::iterator k;
for(k = vertices.begin(); k != vertices.end(); k++) {
newvert[(*k).second] = (*k).first;
}
vector<unsigned short> newface;
//check no degenerate faces get created.
for(unsigned int f = 0; f < entry.nface; f++) {
unsigned short *face = patch.Face(f);
if(face[0] != face[1] && face[1] != face[2] && face[0] != face[2] &&
newvert[remap[face[0]]] != newvert[remap[face[1]]] &&
newvert[remap[face[0]]] != newvert[remap[face[2]]] &&
newvert[remap[face[1]]] != newvert[remap[face[2]]]) {
newface.push_back(remap[face[0]]);
newface.push_back(remap[face[1]]);
newface.push_back(remap[face[2]]);
} else {
degenerate++;
}
}
//rewrite patch now.
entry.nvert = newvert.size();
entry.nface = newface.size()/3;
patch.Init(nexus.signature, entry.nvert, entry.nface);
memcpy(patch.VertBegin(), &(newvert[0]), entry.nvert*sizeof(Point3f));
memcpy(patch.FaceBegin(), &(newface[0]), entry.nface*3*sizeof(short));
//testiamo il tutto... TODO remove this of course
for(unsigned int i =0; i < patch.nf; i++) {
for(int k =0 ; k < 3; k++)
if(patch.Face(i)[k] >= patch.nv) {
cerr <<" Unify has problems\n";
exit(0);
}
}
//fix patch borders now
set<unsigned int> close; //bordering pathes
Border border = nexus.GetBorder(p);
for(unsigned int b = 0; b < border.Size(); b++) {
if(border[b].IsNull()) continue;
close.insert(border[b].end_patch);
border[b].start_vert = remap[border[b].start_vert];
}
set<unsigned int>::iterator c;
for(c = close.begin(); c != close.end(); c++) {
Border bord = nexus.GetBorder(*c);
for(unsigned int b = 0; b < bord.Size(); b++) {
if(bord[b].IsNull()) continue;
if(bord[b].end_patch == p) {
bord[b].end_vert = remap[bord[b].end_vert];
}
}
}
}
//better to compact directly borders than setting them null.
//finally: there may be duplicated borders
for(unsigned int p = 0; p < nexus.size(); p++) {
Border border = nexus.GetBorder(p);
set<Link> links;
for(unsigned int b = 0; b < border.Size(); b++) {
Link &link = border[b];
assert(!link.IsNull());
//if(border[b].IsNull()) continue;
links.insert(link);
}
int count = 0;
for(set<Link>::iterator k = links.begin(); k != links.end(); k++)
border[count++] = *k;
nexus.borders[p].used = links.size();
}
nexus.totvert -= duplicated;
if(duplicated)
cerr << "Found " << duplicated << " duplicated vertices" << endl;
if(degenerate)
cerr << "Found " << degenerate << " degenerate face while unmifying\n";
}

View File

@ -12,6 +12,7 @@ namespace nxs {
void ComputeTriStrip(unsigned short nfaces, unsigned short *faces,
std::vector<unsigned short> &strip);
void Reorder(unsigned int signature, nxs::Patch &patch);
void Unify(Nexus &nexus, float threshold);
}
#endif

View File

@ -24,6 +24,9 @@
History
$Log: not supported by cvs2svn $
Revision 1.12 2005/01/14 15:25:29 ponchio
Revolution.
Revision 1.11 2004/12/13 00:44:48 ponchio
Lotsa changes...
@ -75,11 +78,13 @@ Level 0.
#include <iostream>
#include "nxstypes.h"
#include "crude.h"
#include "remapping.h"
#include "decimate.h"
#include "fragment.h"
#include "nxsalgo.h"
#include "nxsdispatcher.h"
#include "watch.h"
@ -488,7 +493,8 @@ void FifthStep(const string &crudefile, const string &output,
patch_levels.push_back(0);
}
nexus.history.updates.push_back(update);
nexus.Unify();
Unify(nexus, 0.0f);
// nexus.Unify();
nexus.Flush();