From c65e4840b12eba763ba81a1d3b860813debdc499 Mon Sep 17 00:00:00 2001 From: ponchio Date: Thu, 14 Oct 2004 13:42:33 +0000 Subject: [PATCH] Added ram buffer size in extraction. --- apps/nexus/nexusmt.cpp | 218 ++++++++++++++++++++++++++++++----------- apps/nexus/nexusmt.h | 89 ++++++++++++----- 2 files changed, 229 insertions(+), 78 deletions(-) diff --git a/apps/nexus/nexusmt.cpp b/apps/nexus/nexusmt.cpp index 507b55c5..a19ec473 100644 --- a/apps/nexus/nexusmt.cpp +++ b/apps/nexus/nexusmt.cpp @@ -8,7 +8,7 @@ using namespace nxs; using namespace vcg; using namespace std; -void Policy::Visit(Node *node, std::queue &qnode) { +/*void Policy::Visit(Node *node, std::queue &qnode) { std::vector::iterator n; for(n = node->in.begin(); n != node->in.end(); n++) if(!(*n)->visited) @@ -21,22 +21,80 @@ void Policy::Visit(Node *node, std::queue &qnode) { bool FrustumPolicy::Expand(unsigned int patch, Nexus::PatchInfo &entry) { if(entry.error == 0) return false; float dist = Distance(entry.sphere, frustum.ViewPoint()); - /*Point3f line = frustum.viewPoint() - cell->sphere.center; - float dist = line.Norm() - cell->sphere.radius; */ if(dist < 0) return true; // dist = pow(dist, 1.2); - /* cerr << "Dist: " << dist << endl; - cerr << "Entry error: " << entry.error << endl; - cerr << "error: " << error << endl; - cerr << "resolution at dist: " << frustum.Resolution(dist) << endl;*/ return entry.error > error * frustum.Resolution(dist); +} */ + +float FrustumMetric::GetError(Node *node) { + float max_error = 0; + std::vector::iterator frag; + for(frag = node->frags.begin(); frag != node->frags.end(); frag++) { + vector::iterator cell; + for(cell = (*frag).begin(); cell != (*frag).end(); cell++) { + Nexus::PatchInfo &entry = (*index)[*cell]; + Sphere3f &sphere = entry.sphere; + float dist = Distance(sphere, frustum.ViewPoint()); + if(dist < 0) break; + float error = entry.error/frustum.Resolution(dist); + if(frustum.IsOutside(sphere.Center(), sphere.Radius())) + error *= 4; + if(max_error < error) max_error = error; + } + } + return max_error; } +void Policy::Init() { + ram_used = 0; +} + +bool Policy::Expand(TNode &node) { + //expand if node error > target error + if(ram_used >= ram_size) return false; + //cerr << "Error: " << error << " node.error: " << node.error << endl; + return node.error > error; +} + +void Policy::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 rr = frag.size(); + unsigned int tmp = frag[k]; + unsigned int sz = entries->size(); + assert(tmp < sz); + PatchEntry &entry = (*entries)[frag[k]]; + ram_used += entry.ram_size; + } + } + + vector::iterator from; + for(from = node->in.begin(); from != node->in.end(); from++) { + assert((*from)->visited); + vector &frags = (*from)->frags; + for(unsigned int i = 0; i < frags.size(); i++) { + if((*from)->out[i] == node) { + vector &frag = frags[i]; + for(unsigned int k = 0; k < frag.size(); k++) { + PatchEntry &entry = (*entries)[frag[k]]; + ram_used -= entry.ram_size; + } + } + } + } +} NexusMt::NexusMt(): vbo(VBO_AUTO), vbo_size(0), - policy(NULL), error(4), realtime(true), - mode(SMOOTH) { - policy = new FrustumPolicy(); + metric(NULL), mode(SMOOTH) { + metric = new FrustumMetric(); + metric->index = &index; + policy.error = 4; + policy.ram_size = 64000000; } NexusMt::~NexusMt() {} @@ -45,6 +103,8 @@ bool NexusMt::Load(const string &filename, bool readonly) { if(!Nexus::Load(filename, readonly)) return false; LoadHistory(); + policy.entries = &patches.patches; + use_colors = false; use_normals = false; use_textures = false; @@ -71,13 +131,14 @@ void NexusMt::Render() { frustum.GetView(); vector cells; - if(policy) { - policy->GetView(); - Extract(cells, policy); - } else { - ExtractFixed(cells, error); - } + metric->GetView(); + policy.Init(); + tri_total = 0; + tri_rendered = 0; + + Extract(cells); + glEnableClientState(GL_VERTEX_ARRAY); if(use_colors) glEnableClientState(GL_COLOR_ARRAY); @@ -87,12 +148,14 @@ void NexusMt::Render() { for(unsigned int i = 0; i < cells.size(); i++) { unsigned int cell = cells[i]; - Nexus::PatchInfo &entry = index[cell]; - + Nexus::PatchInfo &entry = index[cell]; + tri_total += entry.nface; //frustum culling if(frustum.IsOutside(entry.sphere.Center(), entry.sphere.Radius())) continue; + tri_rendered += entry.nface; + Patch &patch = GetPatch(cell); assert(patch.start); @@ -127,20 +190,17 @@ void NexusMt::Render() { glDisableClientState(GL_NORMAL_ARRAY); } -void NexusMt::SetPolicy(Policy *_policy, bool _realtime) { - policy = _policy; - realtime = _realtime; +void NexusMt::SetRamSize(unsigned int r_size) { + policy.ram_size = r_size/patches.chunk_size; } -void NexusMt::SetPolicy(PolicyKind kind, float _error, bool _realtime) { - if(policy) delete policy; - switch(kind) { - case FRUSTUM: policy = new FrustumPolicy(error); break; - case GEOMETRY: policy = NULL; break; - default: policy = NULL; break; - } - error = _error; - realtime = _realtime; +void NexusMt::SetMetric(NexusMt::MetricKind kind) { + //do nothing at the moment. + +} + +void NexusMt::SetError(float error) { + policy.error = error; } void NexusMt::SetVbo(Vbo _vbo, unsigned int _vbo_size, @@ -235,18 +295,18 @@ void NexusMt::LoadHistory() { vector &cells = (*e).second; vector::iterator k; for(k = cells.begin(); k != cells.end(); k++) { - unsigned int cell = (*k); - fr.push_back(cell); - if(index[cell].error > max_err) - max_err = index[cell].error; - } - + unsigned int cell = (*k); + assert(cell < index.size()); + fr.push_back(cell); + if(index[cell].error > max_err) + max_err = index[cell].error; + } //Add the new Frag to the node. unsigned int floor_node = (*e).first; Node &oldnode = nodes[floor_node]; oldnode.frags.push_back(fr); if(node.error < max_err) - node.error = max_err; + node.error = max_err; //Update in and out of the nodes. node.in.push_back(&oldnode); @@ -260,7 +320,7 @@ void NexusMt::ClearHistory() { nodes.clear(); } -void NexusMt::ExtractFixed(vector &selected, float error) { +/*void NexusMt::ExtractFixed(vector &selected, float error) { std::vector::iterator n; for(n = nodes.begin(); n != nodes.end(); n++) (*n).visited = false; @@ -275,23 +335,50 @@ void NexusMt::ExtractFixed(vector &selected, float error) { std::vector::iterator fragment; std::vector::iterator on; for(on = node.out.begin(), fragment = node.frags.begin(); - on != node.out.end(); ++on, ++fragment) { + on != node.out.end(); ++on, ++fragment) { if((*on)->visited) continue; if(error < (*on)->error) { //need to expand this node. - qnodo.push(*on); - (*on)->visited = 1; + qnodo.push(*on); + (*on)->visited = 1; } else { - vector::iterator cell; - for(cell=(*fragment).begin(); cell != (*fragment).end(); ++cell) - selected.push_back(*cell); + vector::iterator cell; + for(cell=(*fragment).begin(); cell != (*fragment).end(); ++cell) + selected.push_back(*cell); } } } -} +} */ -void NexusMt::Extract(std::vector &selected, Policy *policy) { +void NexusMt::Extract(std::vector &selected) { + std::vector::iterator n; + for(n = nodes.begin(); n != nodes.end(); n++) { + (*n).visited = false; + (*n).pushed = false; + } + + std::vector heap; + Node *root = &nodes[0]; + VisitNode(root, heap); + + while(heap.size()) { + pop_heap(heap.begin(), heap.end()); + TNode tnode = heap.back(); + heap.pop_back(); + + Node *node = tnode.node; + if(node->visited) continue; + + bool expand = policy.Expand(tnode); + + if(expand) + VisitNode(node, heap); + } + Select(selected); +} + +/*void NexusMt::Extract(std::vector &selected, Policy *policy) { std::vector::iterator n; for(n = nodes.begin(); n != nodes.end(); n++) (*n).visited = false; @@ -306,18 +393,18 @@ void NexusMt::Extract(std::vector &selected, Policy *policy) { std::vector::iterator i; std::vector::iterator on; for(i = node.frags.begin(), on = node.out.begin(); - i != node.frags.end(); i++, on++) { + i != node.frags.end(); i++, on++) { if((*on)->visited) continue; Frag &frag = (*i); std::vector::iterator cell; for(cell = frag.begin(); cell != frag.end(); cell++) { - if(policy->Expand(*cell, index[*cell])) - policy->Visit(*on, qnodo); + if(policy->Expand(*cell, index[*cell])) + policy->Visit(*on, qnodo); } } } Select(selected); -} +}*/ void NexusMt::Select(vector &selected) { selected.clear(); @@ -330,14 +417,35 @@ void NexusMt::Select(vector &selected) { std::vector::iterator n; std::vector::iterator f; for(n = node.out.begin(), f = node.frags.begin(); - n != node.out.end(); n++, f++) { + n != node.out.end(); n++, f++) { if(!(*n)->visited || (*n)->error == 0) { - vector::iterator c; - Frag &frag = (*f); - for(c = frag.begin(); c != frag.end(); c++) - selected.push_back(*c); + vector::iterator c; + Frag &frag = (*f); + for(c = frag.begin(); c != frag.end(); c++) + selected.push_back(*c); } } } } +void NexusMt::PushNode(Node *node, vector &heap) { + if(node->pushed) return; + + float error = metric->GetError(node); + heap.push_back(TNode(node, error)); + push_heap(heap.begin(), heap.end()); +} + +void NexusMt::VisitNode(Node *node, vector &heap) { + if(node->visited) return; + + vector::iterator i; + for(i = node->in.begin(); i != node->in.end(); i++) + VisitNode(*i, heap); + + for(i = node->out.begin(); i != node->out.end(); i++) + PushNode(*i, heap); + + node->visited = true; + policy.NodeVisited(node); +} \ No newline at end of file diff --git a/apps/nexus/nexusmt.h b/apps/nexus/nexusmt.h index 9775067b..dcd9ae74 100644 --- a/apps/nexus/nexusmt.h +++ b/apps/nexus/nexusmt.h @@ -11,31 +11,64 @@ namespace nxs { - class Frag:public std::vector {}; + typedef std::vector Frag; struct Node { std::vector in; std::vector out; std::vector frags; float error; - bool visited; + bool visited; + bool pushed; + }; + + struct TNode { + float error; + Node *node; + TNode(Node *n, float e): node(n), error(e) {} + bool operator<(const TNode &n) { return error < n.error; } }; - class Policy { + class Metric { public: - virtual bool Expand(unsigned int patch, Nexus::PatchInfo &entry) = 0; - virtual void GetView() {} - virtual void Visit(Node *node, std::queue &qnode); + vector *index; + + virtual float GetError(Node *node) = 0; + virtual void GetView() {} }; - class FrustumPolicy: public Policy { + class FlatMetric: public Metric { public: - vcg::Frustumf frustum; - float error; + void GetView() {} + float GetError(Node *node); + }; + + class DeltaMetric: public Metric { + public: + vcg::Point3f delta; + void GetView() {} + float GetError(Node *node); + }; + + class FrustumMetric: public Metric { + public: + vcg::Frustumf frustum; - FrustumPolicy(float _err = 4): error(_err) {} void GetView() { frustum.GetView(); } - bool Expand(unsigned int patch, Nexus::PatchInfo &entry); + float GetError(Node *node); + }; + + class Policy { + public: + float error; + int ram_used; + int ram_size; + + vector *entries; + + void Init(); + bool Expand(TNode &node); + void NodeVisited(Node *node); }; class NexusMt: public Nexus { @@ -49,9 +82,10 @@ class NexusMt: public Nexus { VBO_OFF, //no vertex buffer object VBO_FIXED }; //user supplied size - enum PolicyKind { FRUSTUM, //screen error extraction - GEOMETRY }; //geometry error extraction - + enum MetricKind { FRUSTUM, //screen error extraction + GEOMETRY, //geometry error extraction + DELTA }; //delta error + enum Mode { POINTS, SMOOTH, XRAY, @@ -68,10 +102,9 @@ class NexusMt: public Nexus { Vbo vbo; unsigned int vbo_size; - Policy *policy; - float error; - bool realtime; - + Metric *metric; + Policy policy; + Mode mode; unsigned int components; @@ -79,6 +112,10 @@ class NexusMt: public Nexus { bool use_colors; bool use_textures; bool use_data; + + //statistics: + unsigned int tri_rendered; + unsigned int tri_total; NexusMt(); ~NexusMt(); @@ -87,20 +124,26 @@ class NexusMt: public Nexus { bool InitGL(); void Render(); - void SetPolicy(Policy *policy, bool realtime = true); - void SetPolicy(PolicyKind kind, float error, bool realtime = true); + + void SetMetric(MetricKind kind); + void SetError(float error); + void SetRamSize(unsigned int ram_size); void SetVbo(Vbo mode, unsigned int vbo_size = 0, - unsigned int ram_size = 128000000); + unsigned int ram_size = 128000000); + bool SetMode(Mode mode); bool SetComponent(Component c, bool on); bool SetComponents(unsigned int mask); - void ExtractFixed(std::vector &selected, float error); - void Extract(std::vector &selected, Policy *policy); + + //void ExtractFixed(std::vector &selected, float error); + void Extract(std::vector &selected); protected: void LoadHistory(); void ClearHistory(); + void PushNode(Node *node, std::vector &heap); + void VisitNode(Node *node, std::vector &heap); void Select(std::vector &selected); Patch &LoadPatch(unsigned int p); };