Cleanup.
This commit is contained in:
parent
e66a97ffd0
commit
90e4d33361
|
@ -1,67 +0,0 @@
|
|||
#ifndef NXS_LRU_PSERVER_H
|
||||
#define NXS_LRU_PSERVER_H
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include "pserver.h"
|
||||
|
||||
namespace nxs {
|
||||
|
||||
class LruPServer: public PServer {
|
||||
public:
|
||||
//TODO change name to Item
|
||||
typedef std::pair<unsigned int, Patch *> Item;
|
||||
std::list<Item> items;
|
||||
typedef std::list<Item> Items;
|
||||
std::map<unsigned int, Items::iterator> index;
|
||||
|
||||
~LruPServer() {
|
||||
Flush();
|
||||
}
|
||||
|
||||
Patch &Lookup(unsigned int patch) {
|
||||
if(index.count(patch)) {
|
||||
Items::iterator &i = index[patch];
|
||||
Item item = *i;
|
||||
items.erase(i);
|
||||
items.push_front(item);
|
||||
i = items.begin();
|
||||
return *((*i).second);
|
||||
} else {
|
||||
while(ram_used > ram_max) {
|
||||
Item item = items.back();
|
||||
index.erase(item.first);
|
||||
FlushPatch(item.first);
|
||||
items.pop_back();
|
||||
}
|
||||
Item item;
|
||||
item.first = patch;
|
||||
item.second = LoadPatch(patch);
|
||||
items.push_front(item);
|
||||
Items::iterator i = items.begin();
|
||||
index[patch] = i;
|
||||
return *((*i).second);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsLoaded(unsigned int patch) {
|
||||
return index.count(patch);
|
||||
}
|
||||
void Flush() {
|
||||
std::map<unsigned int, Items::iterator>::iterator i;
|
||||
for(i = index.begin(); i != index.end(); i++) {
|
||||
Item &item = *((*i).second);
|
||||
FlushPatch((*i).first);
|
||||
}
|
||||
for(int k = 0; k < size(); k++)
|
||||
operator[](k).patch = NULL;
|
||||
|
||||
items.clear();
|
||||
index.clear();
|
||||
}
|
||||
};
|
||||
|
||||
}//namespace
|
||||
|
||||
#endif
|
|
@ -1,161 +0,0 @@
|
|||
/****************************************************************************
|
||||
* 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.5 2004/07/05 15:49:39 ponchio
|
||||
Windows (DevCpp, mingw) port.
|
||||
|
||||
Revision 1.4 2004/07/04 14:23:14 ponchio
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.3 2004/07/02 17:40:30 ponchio
|
||||
Debug.
|
||||
|
||||
Revision 1.2 2004/07/01 21:34:04 ponchio
|
||||
Rehash bug.
|
||||
|
||||
Revision 1.1 2004/06/24 14:32:45 ponchio
|
||||
Moved from wrap/nexus
|
||||
|
||||
Revision 1.1 2004/06/24 14:18:58 ponchio
|
||||
Created
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include "mfhash.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace nxs;
|
||||
|
||||
bool MFHash::Create(const string &file, unsigned int reserved) {
|
||||
if(!buffer.Create(file)) return false;
|
||||
|
||||
buffer.Resize(reserved);
|
||||
Bucket empty;
|
||||
for(unsigned int i = 0; i < buffer.Size(); i++)
|
||||
buffer[i] = empty;
|
||||
space = reserved;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MFHash::Load(const string &file, unsigned int used) {
|
||||
if(!buffer.Load(file)) return false;
|
||||
if(used != 0xffffffff) {
|
||||
space = buffer.Size() - used;
|
||||
} else {
|
||||
space = 0;
|
||||
for(unsigned int i = 0; i < buffer.Size(); i++)
|
||||
if(buffer[i].Empty()) space++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MFHash::Delete() {
|
||||
buffer.Flush();
|
||||
buffer.Delete();
|
||||
}
|
||||
|
||||
void MFHash::Resize(unsigned int n) {
|
||||
assert(buffer.Size() - space <= n);
|
||||
//lets dump actual content
|
||||
FILE *fp = tmpfile();
|
||||
unsigned int count = 0;
|
||||
for(unsigned int i = 0; i < buffer.Size(); i++) {
|
||||
Bucket &bucket = buffer[i];
|
||||
if(!bucket.Empty()) {
|
||||
fwrite(&bucket, sizeof(Bucket), 1, fp);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
buffer.Resize(n);
|
||||
Clear();
|
||||
|
||||
rewind(fp);
|
||||
Bucket bucket;
|
||||
for(unsigned int i = 0; i < count; i++) {
|
||||
fread(&bucket, sizeof(Bucket), 1, fp);
|
||||
Insert(bucket.key, bucket.value, false);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void MFHash::Insert(unsigned int key, unsigned int value, bool rehash) {
|
||||
if(buffer.Size() < 5)
|
||||
Resize(5);
|
||||
assert(space > 0);
|
||||
unsigned int hash_size = buffer.Size();
|
||||
unsigned int j = key % hash_size;
|
||||
Bucket bucket = buffer[j];
|
||||
while(!bucket.Empty()) {
|
||||
if(bucket.key == key && bucket.value == value) //already here
|
||||
return;
|
||||
j++;
|
||||
if(j >= hash_size) j = 0;
|
||||
bucket = buffer[j];
|
||||
}
|
||||
buffer[j] = Bucket(key, value);
|
||||
space--;
|
||||
|
||||
if(rehash) {
|
||||
float ratio = space / (float)buffer.Size();
|
||||
if(ratio < 0.4) { //need to resize
|
||||
Resize(buffer.Size() * 2 + 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int MFHash::Count(unsigned int key) {
|
||||
unsigned int count = 0;
|
||||
unsigned int hash_size = buffer.Size();
|
||||
unsigned int j = key % hash_size;
|
||||
|
||||
while(!buffer[j].Empty()) {
|
||||
if(buffer[j].key == key)
|
||||
count++;
|
||||
j++;
|
||||
if(j >= hash_size) j = 0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void MFHash::Clear() {
|
||||
Bucket empty;
|
||||
for(unsigned int i = 0; i < buffer.Size(); i++)
|
||||
buffer[i] = empty;
|
||||
space = buffer.Size();
|
||||
}
|
||||
|
||||
void MFHash::Close() {
|
||||
buffer.Close();
|
||||
}
|
||||
|
||||
unsigned int MFHash::Size() {
|
||||
return buffer.Size() - space;
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
/****************************************************************************
|
||||
* 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.4 2004/07/02 17:40:30 ponchio
|
||||
Debug.
|
||||
|
||||
Revision 1.3 2004/07/02 13:08:43 ponchio
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.2 2004/07/01 21:34:29 ponchio
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.1 2004/06/24 14:32:45 ponchio
|
||||
Moved from wrap/nexus
|
||||
|
||||
Revision 1.1 2004/06/24 14:18:58 ponchio
|
||||
Created
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef NXS_MFHASH_H
|
||||
#define NXS_MFHASH_H
|
||||
|
||||
#include "vfile.h"
|
||||
#include <stdio.h>
|
||||
|
||||
namespace nxs {
|
||||
|
||||
|
||||
|
||||
class MFHash {
|
||||
public:
|
||||
struct Bucket {
|
||||
unsigned int key;
|
||||
unsigned int value;
|
||||
Bucket(): key(0xffffffff) {}
|
||||
Bucket(unsigned int k, unsigned int v): key(k), value(v) {}
|
||||
bool Empty() { return key == 0xffffffff; }
|
||||
};
|
||||
|
||||
MFHash() {}
|
||||
bool Create(const std::string &file, unsigned int reserved = 32);
|
||||
bool Load(const std::string &file, unsigned int used = 0xffffffff);
|
||||
void Delete();
|
||||
|
||||
void Resize(unsigned int n);
|
||||
void Insert(unsigned int key, unsigned int value, bool rehash = true);
|
||||
template <class C> void GetValues(unsigned int key, C &container) {
|
||||
container.clear();
|
||||
unsigned int hash_size = buffer.Size();
|
||||
unsigned int j = key % hash_size;
|
||||
while(!buffer[j].Empty()) {
|
||||
if(buffer[j].key == key) {
|
||||
//container.push_back(buffer[j].value);
|
||||
container.insert(buffer[j].value);
|
||||
}
|
||||
j++;
|
||||
if(j >= hash_size) j = 0;
|
||||
}
|
||||
}
|
||||
unsigned int Count(unsigned int key);
|
||||
void Clear();
|
||||
unsigned int Size();
|
||||
void Close();
|
||||
|
||||
VFile<Bucket> buffer;
|
||||
unsigned int space;
|
||||
};
|
||||
}//namespace
|
||||
#endif
|
|
@ -1,63 +0,0 @@
|
|||
#ifndef NXS_NEXUS_BASE_H
|
||||
#define NXS_NEXUS_BASE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "pserver.h"
|
||||
|
||||
namespace nxs {
|
||||
|
||||
/*struct PatchInfo {
|
||||
unsigned short nvert;
|
||||
unsigned short nface;
|
||||
|
||||
vcg::Sphere3f sphere;
|
||||
float error;
|
||||
};*/
|
||||
|
||||
|
||||
class NexusBase {
|
||||
public:
|
||||
|
||||
//TODO optimize to be vector with offset.
|
||||
struct Update {
|
||||
std::vector<unsigned int> erased;
|
||||
std::vector<unsigned int> created;
|
||||
};
|
||||
|
||||
NexusBase(): index_file(NULL) {}
|
||||
|
||||
// bool Create(const std::string &filename, Signature signature,
|
||||
// unsigned int chunk_size = 1024);
|
||||
// bool Load(const std::string &filename, bool readonly = false);
|
||||
// void Close();
|
||||
|
||||
bool IsCompressed() { return (signature & NXS_COMPRESSED) != 0; }
|
||||
bool HasStrips() { return (signature & NXS_STRIP) != 0; }
|
||||
bool HasColors() { return (signature & NXS_COLORS) != 0; }
|
||||
bool HasNormalsShort() { return (signature & NXS_NORMALS_SHORT) != 0; }
|
||||
bool HasNormalsFloat() { return (signature & NXS_NORMALS_FLOAT) != 0; }
|
||||
|
||||
|
||||
//BE CAREFUL: this 2 members get replicated into patchserver
|
||||
//TODO fix this nasty thing it is dangerous as it is.
|
||||
Signature signature;
|
||||
unsigned int chunk_size;
|
||||
|
||||
unsigned int totvert;
|
||||
unsigned int totface;
|
||||
vcg::Sphere3f sphere;
|
||||
|
||||
// std::vector<PatchInfo> index;
|
||||
std::vector<Update> history;
|
||||
|
||||
bool readonly;
|
||||
|
||||
protected:
|
||||
FILE *index_file;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,230 +0,0 @@
|
|||
#include "nxsbuild.h"
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
using namespace nxs;
|
||||
using namespace vcg;
|
||||
using namespace std;
|
||||
|
||||
void nxs::RemapVertices(Crude &crude,
|
||||
VertRemap &vert_remap,
|
||||
VFile<unsigned int> &face_remap,
|
||||
vector<unsigned int> &patch_verts) {
|
||||
|
||||
for(unsigned int i = 0; i < crude.Faces(); i++) {
|
||||
Crude::Face &face = crude.GetFace(i);
|
||||
unsigned int patch = face_remap[i];
|
||||
for(int k = 0; k < 3; k++) {
|
||||
set<unsigned int> pp;
|
||||
vert_remap.GetValues(face[k], pp);
|
||||
if(!pp.count(patch)) {
|
||||
vert_remap.Insert(face[k], patch);
|
||||
patch_verts[patch]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nxs::NexusAllocate(Crude &crude,
|
||||
Nexus &nexus,
|
||||
VFile<unsigned int> &face_remap,
|
||||
vector<unsigned int> &patch_faces,
|
||||
vector<unsigned int> &patch_verts) {
|
||||
|
||||
|
||||
nexus.index.resize(patch_faces.size());
|
||||
|
||||
// unsigned int totchunks = 0;
|
||||
//now that we know various sizes, lets allocate space
|
||||
cerr << "Fixing entries\n";
|
||||
for(unsigned int i = 0; i < nexus.index.size(); i++) {
|
||||
Nexus::PatchInfo &entry = nexus.index[i];
|
||||
|
||||
if(patch_faces[i] == 0 || patch_verts[i] == 0)
|
||||
cerr << "Warning! Empty patch.\n";
|
||||
|
||||
nexus.patches.AddPatch(patch_verts[i], patch_faces[i]);
|
||||
|
||||
entry.nvert = patch_verts[i];
|
||||
entry.nface = patch_faces[i];
|
||||
entry.error = 0;
|
||||
}
|
||||
|
||||
patch_faces.clear();
|
||||
patch_faces.resize(nexus.index.size(), 0);
|
||||
|
||||
//now we sort the faces into the patches (but still using absolute indexing
|
||||
//instead of relative indexing
|
||||
cerr << "Moving faces into patches\n";
|
||||
|
||||
for(unsigned int i = 0; i < crude.face.Size(); i++) {
|
||||
Crude::Face &face = crude.face[i];
|
||||
unsigned int npatch = face_remap[i];
|
||||
#ifdef CONTROLS
|
||||
if(npatch > nexus.index.size()) {
|
||||
cerr << "INvalid index\n";
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
Nexus::PatchInfo &entry = nexus.index[npatch];
|
||||
//TODO this is slow because we have to initialize patch.
|
||||
//just get patch.start.
|
||||
Patch patch = nexus.GetPatch(npatch);
|
||||
|
||||
Crude::Face *faces = (Crude::Face *)patch.start;
|
||||
|
||||
//REMOVING degenerate faces
|
||||
if(face[0] == face[1] || face[1] == face[2] || face[0] == face[2]) {
|
||||
cerr << "Found degenerate.\n";
|
||||
continue;
|
||||
}
|
||||
#ifdef CONTROLS
|
||||
if(patch_faces[npatch] > entry.nface) {
|
||||
cerr << "patch_faces[npatch]: " << patch_faces[npatch]
|
||||
<< " should be <= " << entry.nface << endl;
|
||||
cerr << "something not workin here!\n";
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
faces[patch_faces[npatch]++] = face;
|
||||
}
|
||||
cerr << "Fixing entry faces\n";
|
||||
for(unsigned int i = 0; i < nexus.index.size(); i++) {
|
||||
Nexus::PatchInfo &entry = nexus.index[i];
|
||||
entry.nface = patch_faces[i];
|
||||
}
|
||||
}
|
||||
|
||||
void nxs::NexusFill(Crude &crude,
|
||||
Nexus &nexus,
|
||||
VertRemap &vert_remap,
|
||||
VFile<RemapLink> &border_remap) {
|
||||
|
||||
|
||||
//TODO: is it faster to collect faces and vertices
|
||||
//from all around or better to pass linearly all the dataset
|
||||
//and write where needed? i wonder.
|
||||
//finally for every patch we collect the vertices
|
||||
//and fill the patch.
|
||||
//we need to remember start and size in border_remap;
|
||||
|
||||
for(unsigned int i = 0; i < nexus.index.size(); i++) {
|
||||
Patch patch = nexus.GetPatch(i);
|
||||
Nexus::PatchInfo &entry = nexus.index[i];
|
||||
|
||||
//make a copy of faces (we need to write there :P)
|
||||
Crude::Face *faces = new Crude::Face[patch.nf];
|
||||
//Test for degenerate faces?
|
||||
memcpy(faces, (Crude::Face *)patch.start,
|
||||
patch.nf * sizeof(Crude::Face));
|
||||
|
||||
//collect all vertices we need.
|
||||
//TODO an hash_map would be faster?
|
||||
unsigned int count = 0;
|
||||
map<unsigned int, unsigned short> remap;
|
||||
|
||||
assert(patch.nf != 0);
|
||||
for(unsigned int k = 0; k < patch.nf; k++) {
|
||||
Crude::Face &face = faces[k];
|
||||
for(int j = 0; j < 3; j++) {
|
||||
if(!remap.count(face[j])) {
|
||||
Point3f &v = crude.vert[face[j]];
|
||||
patch.Vert(remap.size()) = v;
|
||||
entry.sphere.Add(v);
|
||||
remap[face[j]] = count++;
|
||||
}
|
||||
patch.Face(k)[j] = remap[face[j]];
|
||||
}
|
||||
}
|
||||
assert(count == remap.size());
|
||||
assert(entry.nvert == remap.size());
|
||||
|
||||
//record start of border:
|
||||
unsigned int border_start = border_remap.Size();
|
||||
|
||||
//TODO hash_set?
|
||||
set<unsigned int> border_patches;
|
||||
map<unsigned int, unsigned short>::iterator m;
|
||||
for(m = remap.begin(); m != remap.end(); m++) {
|
||||
RemapLink link;
|
||||
link.abs_vert = (*m).first;
|
||||
link.rel_vert = (*m).second;
|
||||
|
||||
vert_remap.GetValues(link.abs_vert, border_patches);
|
||||
assert(border_patches.size() >= 1);
|
||||
if(border_patches.size() == 1) continue; //its not a border
|
||||
|
||||
set<unsigned int>::iterator s;
|
||||
for(s = border_patches.begin(); s != border_patches.end(); s++) {
|
||||
if((*s) == i) continue;
|
||||
link.patch = *s;
|
||||
border_remap.PushBack(link);
|
||||
}
|
||||
}
|
||||
unsigned int needed = border_remap.Size() - border_start;
|
||||
nexus.borders.AddBorder(2 * needed, needed);
|
||||
delete []faces;
|
||||
}
|
||||
|
||||
//we can now update bounding sphere.
|
||||
for(unsigned int i = 0; i < nexus.index.size(); i++)
|
||||
nexus.sphere.Add(nexus.index[i].sphere);
|
||||
|
||||
//and last convert RemapLinks into Links
|
||||
|
||||
//TODO probably this part is really slow
|
||||
for(unsigned int i = 0; i < nexus.borders.borders.size(); i++) {
|
||||
BorderEntry &local = nexus.borders.borders[i];
|
||||
//* 2 is to accomodate future borders
|
||||
unsigned int remap_start = local.border_start/2;
|
||||
|
||||
// K is the main iterator (where we write to in nexus.borders)
|
||||
for(unsigned int k = 0; k < local.border_used; k++) {
|
||||
|
||||
|
||||
RemapLink start_link = border_remap[k + remap_start];
|
||||
|
||||
BorderEntry &remote = nexus.borders.borders[start_link.patch];
|
||||
|
||||
bool found = false;
|
||||
|
||||
unsigned int remote_remap_start = remote.border_start/2;
|
||||
for(unsigned int j = 0; j < remote.border_used; j++) {
|
||||
|
||||
RemapLink end_link = border_remap[j + remote_remap_start];
|
||||
// assert(end_link.rel_vert < remote.nvert);
|
||||
|
||||
if(start_link.abs_vert == end_link.abs_vert &&
|
||||
end_link.patch == i) { //found the match
|
||||
// assert(!found);
|
||||
nexus.borders[k + local.border_start] = Link(start_link.rel_vert,
|
||||
end_link.rel_vert,
|
||||
start_link.patch);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nexus.borders.Flush();
|
||||
|
||||
//Checking border consistency:
|
||||
/* for(unsigned int i = 0; i < nexus.index.size(); i++) {
|
||||
Border border = nexus.GetBorder(i);
|
||||
Nexus::PatchInfo &entry = nexus.index[i];
|
||||
for(unsigned int k = 0; k < border.Size(); k++) {
|
||||
Link &link = border[k];
|
||||
if(link.start_vert >= entry.nvert) {
|
||||
cerr << "K: " << k << endl;
|
||||
cerr << "patch: " << i << " nvert: " << entry.nvert << " startv: "
|
||||
<< link.start_vert << endl;
|
||||
// cerr << "bstart: " << entry.border_start
|
||||
// << "bsize: " << entry.border_size << endl;
|
||||
}
|
||||
assert(link.end_patch < nexus.index.size());
|
||||
assert(link.start_vert < entry.nvert);
|
||||
Nexus::PatchInfo &remote = nexus.index[link.end_patch];
|
||||
assert(link.end_vert < remote.nvert);
|
||||
}
|
||||
}*/
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
#ifndef NXS_BUILD_H
|
||||
#define NXS_BUILD_H
|
||||
|
||||
#include "vert_remap.h"
|
||||
#include "crude.h"
|
||||
#include "nexus.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace nxs {
|
||||
|
||||
struct RemapLink {
|
||||
unsigned int rel_vert;
|
||||
unsigned int patch;
|
||||
unsigned int abs_vert;
|
||||
};
|
||||
|
||||
void RemapVertices(Crude &crude,
|
||||
VertRemap &vert_remap,
|
||||
VFile<unsigned int> &face_remap,
|
||||
std::vector<unsigned int> &patch_verts);
|
||||
|
||||
void NexusAllocate(Crude &crude,
|
||||
nxs::Nexus &nexus,
|
||||
VFile<unsigned int> &face_remap,
|
||||
std::vector<unsigned int> &patch_faces,
|
||||
std::vector<unsigned int> &patch_verts);
|
||||
|
||||
void NexusFill(Crude &crude,
|
||||
Nexus &nexus,
|
||||
VertRemap &vert_remap,
|
||||
VFile<RemapLink> &border_remap);
|
||||
|
||||
void NexusFixBorder(Nexus &nexus,
|
||||
VFile<RemapLink> &border_remap);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,302 +0,0 @@
|
|||
#include "patchserver.h"
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace nxs;
|
||||
using namespace pt;
|
||||
|
||||
|
||||
bool PatchServer::Create(const std::string &filename,
|
||||
Signature sig,
|
||||
unsigned int csize,
|
||||
unsigned int rsize) {
|
||||
signature = sig;
|
||||
chunk_size = csize;
|
||||
|
||||
ram_size = rsize/chunk_size + 1;
|
||||
ram_used = 0;
|
||||
vbo_size = 0;
|
||||
vbo_used = 0;
|
||||
|
||||
frame = 0;
|
||||
ram_readed = 0;
|
||||
ram_flushed = 0;
|
||||
|
||||
lru.clear();
|
||||
return MFile::Create(filename);
|
||||
}
|
||||
|
||||
bool PatchServer::Load(const std::string &filename, Signature sig,
|
||||
unsigned int csize, bool readonly,
|
||||
unsigned int rsize) {
|
||||
|
||||
signature = sig;
|
||||
chunk_size = csize;
|
||||
|
||||
ram_size = rsize/chunk_size + 1;
|
||||
ram_used = 0;
|
||||
vbo_size = 0;
|
||||
vbo_used = 0;
|
||||
|
||||
frame = 0;
|
||||
ram_readed = 0;
|
||||
ram_flushed = 0;
|
||||
|
||||
lru.clear();
|
||||
return MFile::Load(filename, readonly);
|
||||
}
|
||||
|
||||
void PatchServer::Close() {
|
||||
FlushAll();
|
||||
MFile::Close();
|
||||
}
|
||||
|
||||
//TODO add error checking.
|
||||
bool PatchServer::ReadEntries(FILE *fp) {
|
||||
unsigned int n;
|
||||
fread(&n, 1, sizeof(int), fp);
|
||||
patches.resize(n);
|
||||
for(unsigned int i = 0; i < n; i++) {
|
||||
fread(&(patches[i].patch_start), 1, sizeof(unsigned int), fp);
|
||||
fread(&(patches[i].ram_size), 1, sizeof(unsigned short), fp);
|
||||
fread(&(patches[i].disk_size), 1, sizeof(unsigned short), fp);
|
||||
patches[i].lru_pos = 0xffffffff;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PatchServer::WriteEntries(FILE *fp) {
|
||||
unsigned int n = patches.size();
|
||||
fwrite(&n, 1, sizeof(int), fp);
|
||||
for(unsigned int i = 0; i < patches.size(); i++) {
|
||||
fwrite(&(patches[i].patch_start), 1, sizeof(unsigned int), fp);
|
||||
fwrite(&(patches[i].ram_size), 1, sizeof(unsigned short), fp);
|
||||
fwrite(&(patches[i].disk_size), 1, sizeof(unsigned short), fp);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PatchServer::AddPatch(unsigned short nvert, unsigned short nface) {
|
||||
PatchEntry entry;
|
||||
|
||||
entry.patch_start = 0xffffffff;
|
||||
entry.ram_size = Patch::ChunkSize(signature, nvert, nface, chunk_size);
|
||||
entry.disk_size = 0xffff;
|
||||
entry.lru_pos = 0xffffffff;
|
||||
patches.push_back(entry);
|
||||
}
|
||||
|
||||
Patch &PatchServer::GetPatch(unsigned int idx,
|
||||
unsigned short nvert, unsigned short nface,
|
||||
bool flush) {
|
||||
// ramlock.rdlock();
|
||||
|
||||
assert(idx < patches.size());
|
||||
PatchEntry &entry = patches[idx];
|
||||
|
||||
if(entry.lru_pos == 0xffffffff) { //not on buffer
|
||||
// scopewrite dlock(disklock);
|
||||
|
||||
if(entry.lru_pos == 0xffffffff) { //still not read!
|
||||
if(flush) Flush();
|
||||
PTime nptime(idx);
|
||||
|
||||
char *ram = new char[entry.ram_size * chunk_size];
|
||||
#ifdef CONTROLS
|
||||
if(!ram) {
|
||||
cerr << "COuld not allocate ram!\n";
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
nptime.patch = new Patch(signature, ram, nvert, nface);
|
||||
|
||||
if(entry.patch_start != 0xffffffff) { //was allocated.
|
||||
assert(entry.disk_size != 0xffff);
|
||||
|
||||
SetPosition((int64)entry.patch_start * (int64)chunk_size);
|
||||
|
||||
if((signature & NXS_COMPRESSED) == 0) { //not compressed
|
||||
ReadBuffer(ram, entry.disk_size * chunk_size);
|
||||
} else {
|
||||
unsigned char *disk = new unsigned char[entry.disk_size * chunk_size];
|
||||
ReadBuffer(disk, entry.disk_size * chunk_size);
|
||||
|
||||
nptime.patch->Decompress(entry.ram_size * chunk_size,
|
||||
disk, entry.disk_size * chunk_size);
|
||||
delete []disk;
|
||||
}
|
||||
}
|
||||
// ramlock.unlock();
|
||||
// ramlock.wrlock();
|
||||
entry.lru_pos = lru.size();
|
||||
lru.push_back(nptime);
|
||||
ram_used += entry.ram_size;
|
||||
ram_readed += entry.ram_size;
|
||||
// ramlock.unlock();
|
||||
// ramlock.rdlock();
|
||||
}
|
||||
}
|
||||
|
||||
PTime &ptime = lru[entry.lru_pos];
|
||||
//pexchange(&(ptime.frame), frame++);
|
||||
ptime.frame = frame++;
|
||||
|
||||
// ramlock.unlock();
|
||||
|
||||
//avoid frame overflow!
|
||||
if(frame > (1<<29)) {
|
||||
// ramlock.wrlock();
|
||||
cerr << "oVERFLOW! (nothing dangerous... just warning." << endl;;
|
||||
for(unsigned int i = 0; i < lru.size(); i++) {
|
||||
if(lru[i].frame < (1<<28)) lru[i].frame = 0;
|
||||
else lru[i].frame -= (1<<28);
|
||||
}
|
||||
make_heap(lru.begin(), lru.end());
|
||||
for(unsigned int i = 0; i < lru.size(); i++)
|
||||
patches[lru[i].npatch].lru_pos = i;
|
||||
// ramlock.unlock();
|
||||
}
|
||||
|
||||
return *(ptime.patch);
|
||||
}
|
||||
|
||||
|
||||
void PatchServer::GetVbo(unsigned int p,
|
||||
unsigned int &element, unsigned int &array) {
|
||||
PatchEntry &entry = patches[p];
|
||||
assert(entry.lru_pos != 0xffffffff);
|
||||
PTime &ptime = lru[entry.lru_pos];
|
||||
if(!ptime.vbo_element) {
|
||||
//TODO cerr << "Adding vbo: " << p << endl;
|
||||
assert(ptime.patch);
|
||||
|
||||
Patch &patch = *ptime.patch;
|
||||
|
||||
glGenBuffersARB(1, &ptime.vbo_element);
|
||||
assert(ptime.vbo_element);
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ptime.vbo_element);
|
||||
|
||||
unsigned int size = patch.nf * sizeof(unsigned short);
|
||||
if((signature & NXS_FACES) != 0) size *= 3;
|
||||
|
||||
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, size, patch.FaceBegin(),
|
||||
GL_STATIC_DRAW_ARB);
|
||||
|
||||
//TODO fix this when we allow data :p
|
||||
size = sizeof(float) * patch.dstart;
|
||||
|
||||
glGenBuffersARB(1, &ptime.vbo_array);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, ptime.vbo_array);
|
||||
|
||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, patch.VertBegin(),
|
||||
GL_STATIC_DRAW_ARB);
|
||||
|
||||
vbo_used += patches[p].ram_size;
|
||||
}
|
||||
|
||||
element = ptime.vbo_element;
|
||||
array = ptime.vbo_array;
|
||||
}
|
||||
|
||||
|
||||
void PatchServer::Flush() {
|
||||
|
||||
if(ram_used < ram_size * 1.1) return;
|
||||
// ramlock.wrlock();
|
||||
|
||||
make_heap(lru.begin(), lru.end());
|
||||
for(unsigned int i = 0; i < lru.size(); i++)
|
||||
patches[lru[i].npatch].lru_pos = i;
|
||||
|
||||
while(ram_used > ram_size) {
|
||||
pop_heap(lru.begin(), lru.end());
|
||||
PTime &ptime = lru.back();
|
||||
Flush(ptime);
|
||||
lru.pop_back();
|
||||
}
|
||||
for(unsigned int i = 0; i < lru.size(); i++)
|
||||
patches[lru[i].npatch].lru_pos = i;
|
||||
|
||||
// ramlock.unlock();
|
||||
}
|
||||
|
||||
void PatchServer::FlushAll() {
|
||||
for(unsigned int i = 0; i < lru.size(); i++) {
|
||||
PTime &ptime = lru[i];
|
||||
Flush(ptime);
|
||||
}
|
||||
assert(ram_used == 0);
|
||||
lru.clear();
|
||||
}
|
||||
|
||||
void PatchServer::Flush(PTime &ptime) {
|
||||
|
||||
|
||||
PatchEntry &entry = patches[ptime.npatch];
|
||||
assert(ptime.patch);
|
||||
if(!readonly) { //write back patch
|
||||
|
||||
|
||||
if((signature & NXS_COMPRESSED)) {
|
||||
unsigned int compressed_size;
|
||||
char *compressed = ptime.patch->Compress(entry.ram_size * chunk_size,
|
||||
compressed_size);
|
||||
if(entry.disk_size == 0xffff) {//allocate space
|
||||
assert(entry.patch_start == 0xffffffff);
|
||||
entry.disk_size = (unsigned int)((compressed_size-1)/chunk_size) + 1;
|
||||
entry.patch_start = (unsigned int)(Length()/chunk_size);
|
||||
Redim(Length() + entry.disk_size * chunk_size);
|
||||
} else {
|
||||
cerr << "OOOOPSPPPS not supported!" << endl;
|
||||
exit(-1);
|
||||
}
|
||||
SetPosition((int64)entry.patch_start * (int64)chunk_size);
|
||||
WriteBuffer(compressed, entry.disk_size * chunk_size);
|
||||
delete []compressed;
|
||||
} else {
|
||||
if(entry.disk_size == 0xffff) {
|
||||
entry.disk_size = entry.ram_size;
|
||||
entry.patch_start = (unsigned int)(Length()/chunk_size);
|
||||
Redim(Length() + entry.disk_size * chunk_size);
|
||||
}
|
||||
SetPosition((int64)entry.patch_start * (int64)chunk_size);
|
||||
WriteBuffer(ptime.patch->start, entry.disk_size * chunk_size);
|
||||
}
|
||||
/* FILE *fo = fopen("tmp", "wb+");
|
||||
fwrite(entry.patch->start, 1, entry.disk_size * chunk_size, fo);
|
||||
fclose(fo);
|
||||
exit(0);*/
|
||||
}
|
||||
|
||||
if(FlushVbo(ptime))
|
||||
vbo_used -= entry.ram_size;
|
||||
|
||||
delete [](ptime.patch->start);
|
||||
delete ptime.patch;
|
||||
ptime.patch = NULL;
|
||||
|
||||
|
||||
|
||||
entry.lru_pos = 0xffffffff;
|
||||
ram_used -= entry.ram_size;
|
||||
ram_flushed += entry.ram_size;
|
||||
}
|
||||
|
||||
bool PatchServer::FlushVbo(PTime &ptime) {
|
||||
//TODO
|
||||
//cerr << "Flushing vbo: " << patch << endl;
|
||||
if(!ptime.vbo_element) return false;
|
||||
|
||||
glDeleteBuffersARB(1, &ptime.vbo_element);
|
||||
glDeleteBuffersARB(1, &ptime.vbo_array);
|
||||
ptime.vbo_element = 0;
|
||||
ptime.vbo_array = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PatchServer::SetRamBufferSize(unsigned int r_buffer) {
|
||||
ram_size = (unsigned int)(r_buffer/chunk_size) + 1;
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
#ifndef NXS_PATCH_SERVER_H
|
||||
#define NXS_PATCH_SERVER_H
|
||||
|
||||
#include "patch.h"
|
||||
#include "mfile.h"
|
||||
#include <ptypes/pasync.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace nxs {
|
||||
|
||||
struct PatchEntry {
|
||||
unsigned int patch_start; //granularita' Chunk
|
||||
unsigned short ram_size; //in chunks
|
||||
unsigned short disk_size; // in chunks (used when compressed)
|
||||
unsigned int lru_pos;
|
||||
};
|
||||
|
||||
class PatchServer: public MFile {
|
||||
public:
|
||||
|
||||
struct PTime {
|
||||
unsigned int npatch;
|
||||
int frame;
|
||||
|
||||
Patch *patch;
|
||||
unsigned int vbo_array;
|
||||
unsigned int vbo_element;
|
||||
//bool locked;
|
||||
|
||||
PTime(unsigned int p = 0xffffffff, unsigned int f = 0xffffffff):
|
||||
npatch(p), frame(f), patch(NULL),
|
||||
vbo_array(0), vbo_element(0) {}
|
||||
|
||||
bool operator<(const PTime &p) const { return frame > p.frame; }
|
||||
};
|
||||
|
||||
|
||||
Signature signature;
|
||||
unsigned int chunk_size;
|
||||
|
||||
unsigned int ram_size;
|
||||
unsigned int ram_used;
|
||||
unsigned int vbo_size;
|
||||
unsigned int vbo_used;
|
||||
unsigned int frame;
|
||||
|
||||
//pt::rwlock ramlock; //read only thread safety...
|
||||
//pt::rwlock disklock; //read only thread safety...
|
||||
|
||||
//statistics:
|
||||
unsigned int ram_readed;
|
||||
unsigned int ram_flushed;
|
||||
|
||||
|
||||
PatchServer(): chunk_size(1024), ram_size(128000000),
|
||||
ram_used(0), vbo_size(32000000) {}
|
||||
bool Create(const std::string &filename, Signature signature,
|
||||
unsigned int chunk_size, unsigned int ram_size = 128000000);
|
||||
bool Load(const std::string &filename, Signature sig,
|
||||
unsigned int chunk_size, bool readonly,
|
||||
unsigned int ram_size = 128000000);
|
||||
|
||||
void Close();
|
||||
|
||||
bool ReadEntries(FILE *fp);
|
||||
bool WriteEntries(FILE *fp);
|
||||
|
||||
void AddPatch(unsigned short nvert, unsigned short nface);
|
||||
Patch &GetPatch(unsigned int patch,
|
||||
unsigned short nvert, unsigned short nface,
|
||||
bool flush = true);
|
||||
|
||||
void GetVbo(unsigned int patch, unsigned int &element, unsigned int &array);
|
||||
|
||||
void Flush(PTime &ptime);
|
||||
//return false if was not allocated.
|
||||
bool FlushVbo(PTime &ptime);
|
||||
void Flush();
|
||||
void FlushAll();
|
||||
|
||||
void SetRamBufferSize(unsigned int ram_buffer);
|
||||
|
||||
std::vector<PatchEntry> patches;
|
||||
std::vector<PTime> lru;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,84 +0,0 @@
|
|||
/****************************************************************************
|
||||
* 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.5 2004/09/21 00:53:23 ponchio
|
||||
Lotsa changes.
|
||||
|
||||
Revision 1.4 2004/08/27 00:39:28 ponchio
|
||||
Rewrote.
|
||||
|
||||
Revision 1.3 2004/07/20 14:06:02 ponchio
|
||||
Changed filename saving.
|
||||
|
||||
Revision 1.2 2004/06/25 16:47:13 ponchio
|
||||
Various debug
|
||||
|
||||
Revision 1.1 2004/06/24 14:32:45 ponchio
|
||||
Moved from wrap/nexus
|
||||
|
||||
Revision 1.2 2004/06/24 14:19:20 ponchio
|
||||
Debugged
|
||||
|
||||
Revision 1.1 2004/06/23 17:17:46 ponchio
|
||||
Created
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef NXS_PCHAIN_H
|
||||
#define NXS_PCHAIN_H
|
||||
|
||||
#include <vcg/space/point3.h>
|
||||
#include "crude.h"
|
||||
|
||||
namespace nxs {
|
||||
|
||||
class PChain {
|
||||
public:
|
||||
|
||||
// virtual void Init(Crude &crude, unsigned int max_level) = 0;
|
||||
|
||||
/* Return an unique uint for couple of patch level, level+1 */
|
||||
virtual unsigned int Locate(unsigned int level, const vcg::Point3f &p) = 0;
|
||||
|
||||
|
||||
virtual void RemapFaces(VFile<vcg::Point3f> &baricenters,
|
||||
VFile<unsigned int> &face_remap,
|
||||
std::vector<unsigned int> &patch_faces,
|
||||
float scaling, int steps) = 0;
|
||||
|
||||
/* virtual unsigned int Levels() = 0;
|
||||
|
||||
virtual unsigned int Locate(unsigned int level,
|
||||
const vcg::Point3f &p) = 0;
|
||||
|
||||
virtual float Priority(unsigned int level,
|
||||
const vcg::Point3f &p, unsigned int key) = 0;*/
|
||||
};
|
||||
|
||||
}//namespace
|
||||
|
||||
#endif
|
|
@ -1,144 +0,0 @@
|
|||
#include <set>
|
||||
|
||||
#include "prefetch.h"
|
||||
#include "nexusmt.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace nxs;
|
||||
|
||||
|
||||
void Prefetch::init(NexusMt *m, std::vector<unsigned int> &selected,
|
||||
std::vector<PServer::Item> &visited) {
|
||||
|
||||
// cerr << "Init\n";
|
||||
|
||||
safety.lock();
|
||||
mt = m;
|
||||
missing.clear();
|
||||
mt->todraw.clear();
|
||||
float loaded = 0;
|
||||
unsigned int notloaded = 0;
|
||||
set<unsigned int> tmp;
|
||||
//std::map<unsigned int, float> tmp;
|
||||
vector<QueuePServer::Data> flush;
|
||||
for(unsigned int i = 0; i < selected.size(); i++) {
|
||||
unsigned int patch = selected[i];
|
||||
tmp.insert(patch);
|
||||
|
||||
if(!mt->patches.entries[patch].patch) {
|
||||
PServer::Entry &entry = mt->patches.entries[patch];
|
||||
load.post(patch);
|
||||
loaded += entry.disk_size;
|
||||
} else {
|
||||
PatchInfo &info = mt->index[patch];
|
||||
//WORKING QueuePServer::Data &data = mt->patches.Lookup(patch, info.nvert, info.nface, 0.0f, flush);
|
||||
QueuePServer::Data &data = mt->patches.Lookup(patch, info.nvert, info.nface, flush);
|
||||
for(unsigned int i = 0; i < flush.size(); i++) {
|
||||
QueuePServer::Data *data = new QueuePServer::Data;
|
||||
*data = flush[i];
|
||||
draw.post(QueuePServer::FLUSH, (unsigned int)data);
|
||||
}
|
||||
/* WORKING if(flush.size() != 0) {
|
||||
cerr << "Flushing!\n";
|
||||
exit(0);
|
||||
} */
|
||||
mt->todraw.push_back(&data);
|
||||
}
|
||||
//missing.push_back(PServer::Item(patch, 0.0f));
|
||||
}
|
||||
loading = 0.2 * loaded + 0.8 * loading;
|
||||
|
||||
for(unsigned int i = 0; i < visited.size(); i++) {
|
||||
PServer::Item &item = visited[i];
|
||||
if(tmp.count(item.patch)) continue;
|
||||
// if(mt->patches.entries[item.patch].patch)
|
||||
// tmp[item.patch] = item.priority;
|
||||
if(item.priority != 0.0f)
|
||||
missing.push_back(item);
|
||||
}
|
||||
|
||||
/* WORKING QueuePServer &ps = mt->patches;
|
||||
for(unsigned int i = 0; i < ps.heap.size(); i++) {
|
||||
PServer::Item &item = ps.heap[i];
|
||||
if(tmp.count(item.patch))
|
||||
item.priority = 0;
|
||||
else {
|
||||
if(item.priority == 0)
|
||||
item.priority = 1;
|
||||
item.priority *= 1.1;
|
||||
}
|
||||
}
|
||||
make_heap(ps.heap.begin(), ps.heap.end());*/
|
||||
|
||||
sort(missing.begin(), missing.end()); //CRITICAL reverse pero'!
|
||||
reverse(missing.begin(), missing.end());
|
||||
load.post(0xffffffff);
|
||||
|
||||
safety.unlock();
|
||||
}
|
||||
|
||||
void Prefetch::execute() {
|
||||
|
||||
float prefetch;
|
||||
prefetching = 0;
|
||||
loading = 0;
|
||||
while(1) {
|
||||
if(get_signaled()) return;
|
||||
vector<QueuePServer::Data> flush;
|
||||
|
||||
if(load.get_count() || missing.size() == 0) {
|
||||
prefetch = 0;
|
||||
pt::message *msg = load.getmessage();
|
||||
if(msg->id != 0xffffffff) {
|
||||
safety.lock();
|
||||
PatchInfo &info = mt->index[msg->id];
|
||||
PServer::Entry &entry = mt->patches.entries[msg->id];
|
||||
loading += entry.disk_size;
|
||||
//posting draw message
|
||||
//WORKING QueuePServer::Data &data = mt->patches.Lookup(msg->id, info.nvert, info.nface, 0.0f, flush);
|
||||
QueuePServer::Data &data = mt->patches.Lookup(msg->id, info.nvert, info.nface, flush);
|
||||
pt::message *msg = new pt::message(QueuePServer::DRAW, (unsigned int)&data);
|
||||
msg->result = msg->id;
|
||||
draw.post(msg);
|
||||
|
||||
//p;osting flush messages
|
||||
for(unsigned int i = 0; i < flush.size(); i++) {
|
||||
QueuePServer::Data *data = new QueuePServer::Data;
|
||||
*data = flush[i];
|
||||
draw.post(QueuePServer::FLUSH, (unsigned int)data);
|
||||
}
|
||||
safety.unlock();
|
||||
} else {
|
||||
prefetching = 0.2 * prefetch + 0.8 * prefetching;
|
||||
}
|
||||
delete msg;
|
||||
} else {
|
||||
safety.lock();
|
||||
if(missing.size() != 0) {
|
||||
PServer::Item item = missing.back();
|
||||
missing.pop_back();
|
||||
|
||||
/*Working if(item.priority > mt->patches.MaxPriority()) {
|
||||
missing.clear();
|
||||
|
||||
} else { */
|
||||
PatchInfo &info = mt->index[item.patch];
|
||||
//cerr << "prefetching: " << item.patch << endl;
|
||||
//WORKING mt->patches.Lookup(item.patch, info.nvert, info.nface, item.priority, flush);
|
||||
if(!mt->patches.entries[item.patch].patch) {
|
||||
PServer::Entry &entry = mt->patches.entries[item.patch];
|
||||
prefetch += entry.disk_size;
|
||||
|
||||
mt->patches.Lookup(item.patch, info.nvert, info.nface, flush);
|
||||
for(unsigned int i = 0; i < flush.size(); i++) {
|
||||
QueuePServer::Data *data = new QueuePServer::Data;
|
||||
*data = flush[i];
|
||||
draw.post(QueuePServer::FLUSH, (unsigned int)data);
|
||||
}
|
||||
}
|
||||
// }
|
||||
}
|
||||
safety.unlock();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
#ifndef NXS_PREFETCH_H
|
||||
#define NXS_PREFETCH_H
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include <ptypes/pasync.h>
|
||||
|
||||
#include "queuepserver.h"
|
||||
|
||||
namespace nxs {
|
||||
|
||||
class NexusMt;
|
||||
|
||||
class Prefetch: public pt::thread{
|
||||
public:
|
||||
|
||||
pt::mutex safety;
|
||||
//unsigned int ram_max;
|
||||
//unsigned int ram_used;
|
||||
|
||||
NexusMt *mt;
|
||||
std::vector<PServer::Item> missing;
|
||||
pt::jobqueue draw;
|
||||
pt::jobqueue load;
|
||||
float prefetching;
|
||||
float loading;
|
||||
|
||||
Prefetch(): thread(false), draw(20000), load(64000) {}
|
||||
~Prefetch() {
|
||||
waitfor();
|
||||
}
|
||||
|
||||
void init(NexusMt *m,
|
||||
std::vector<unsigned int> &selected,
|
||||
std::vector<PServer::Item> &visited);
|
||||
void execute();
|
||||
void cleanup() {}
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
|
@ -1,231 +0,0 @@
|
|||
#include <iostream>
|
||||
#include "pserver.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace nxs;
|
||||
|
||||
bool PServer::Create(const std::string &_filename,
|
||||
Signature _signature,
|
||||
unsigned int _chunk_size) {
|
||||
signature = _signature;
|
||||
chunk_size = _chunk_size;
|
||||
|
||||
ram_used = 0;
|
||||
|
||||
return MFile::Create(filename);
|
||||
}
|
||||
|
||||
bool PServer::Load(const std::string &filename, Signature _signature,
|
||||
bool _readonly, unsigned int _chunk_size) {
|
||||
|
||||
signature = _signature;
|
||||
chunk_size = _chunk_size;
|
||||
|
||||
ram_used = 0;
|
||||
|
||||
return MFile::Load(filename, _readonly);
|
||||
}
|
||||
|
||||
void PServer::Close() {
|
||||
Flush();
|
||||
MFile::Close();
|
||||
}
|
||||
|
||||
//TODO add error checking.
|
||||
bool PServer::ReadEntries(FILE *fp) {
|
||||
unsigned int n;
|
||||
fread(&n, 1, sizeof(int), fp);
|
||||
resize(n);
|
||||
for(unsigned int i = 0; i < n; i++) {
|
||||
Entry &entry = operator[](i);
|
||||
fread(&entry, sizeof(Entry), 1, fp);
|
||||
entry.patch = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PServer::WriteEntries(FILE *fp) {
|
||||
unsigned int n = size();
|
||||
fwrite(&n, 1, sizeof(int), fp);
|
||||
for(unsigned int i = 0; i < size(); i++) {
|
||||
Entry &entry = operator[](i);
|
||||
fwrite(&entry, sizeof(Entry), 1, fp);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PServer::AddPatch(unsigned short nvert, unsigned short nface) {
|
||||
Entry entry;
|
||||
entry.patch_start = 0xffffffff;
|
||||
entry.ram_size = Patch::ChunkSize(signature, nvert, nface, chunk_size);
|
||||
entry.disk_size = 0xffff;
|
||||
entry.nvert = nvert;
|
||||
entry.nface = nface;
|
||||
//sphere and error undefined.
|
||||
entry.patch = NULL;
|
||||
entry.vbo_array = 0;
|
||||
entry.vbo_element = 0;
|
||||
|
||||
push_back(entry);
|
||||
}
|
||||
|
||||
Patch *PServer::LoadPatch(unsigned int idx) {
|
||||
assert(idx < size());
|
||||
Entry &entry = operator[](idx);
|
||||
if(entry.patch) return entry.patch;
|
||||
|
||||
char *ram = new char[entry.ram_size * chunk_size];
|
||||
#ifndef NDEBUG
|
||||
if(!ram) {
|
||||
cerr << "COuld not allocate ram!\n";
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
Patch *patch = new Patch(signature, ram, entry.nvert, entry.nface);
|
||||
|
||||
if(entry.patch_start != 0xffffffff) { //was allocated.
|
||||
assert(entry.disk_size != 0xffff);
|
||||
|
||||
MFile::SetPosition((int64)entry.patch_start * (int64)chunk_size);
|
||||
|
||||
if((signature & NXS_COMPRESSED) == 0) { //not compressed
|
||||
MFile::ReadBuffer(ram, entry.disk_size * chunk_size);
|
||||
} else {
|
||||
unsigned char *disk = new unsigned char[entry.disk_size * chunk_size];
|
||||
MFile::ReadBuffer(disk, entry.disk_size * chunk_size);
|
||||
|
||||
patch->Decompress(entry.ram_size * chunk_size,
|
||||
disk, entry.disk_size * chunk_size);
|
||||
delete []disk;
|
||||
}
|
||||
}
|
||||
ram_used += entry.ram_size;
|
||||
entry.patch = patch;
|
||||
return patch;
|
||||
}
|
||||
|
||||
void PServer::FlushPatch(unsigned int id) {
|
||||
Entry &entry = operator[](id);
|
||||
//TODO move this into an assert!!!!
|
||||
if(!entry.patch) return;
|
||||
|
||||
|
||||
if(!MFile::IsReadOnly()) { //write back patch
|
||||
if((signature & NXS_COMPRESSED)) {
|
||||
unsigned int compressed_size;
|
||||
char *compressed = entry.patch->Compress(entry.ram_size * chunk_size,
|
||||
compressed_size);
|
||||
if(entry.disk_size == 0xffff) {//allocate space
|
||||
assert(entry.patch_start == 0xffffffff);
|
||||
entry.disk_size = (unsigned int)((compressed_size-1)/chunk_size) + 1;
|
||||
entry.patch_start = (unsigned int)( MFile::Length()/chunk_size);
|
||||
MFile::Redim(MFile::Length() + entry.disk_size * chunk_size);
|
||||
} else {
|
||||
//cerr << "OOOOPSPPPS not supported!" << endl;
|
||||
exit(-1);
|
||||
}
|
||||
MFile::SetPosition((int64)entry.patch_start * (int64)chunk_size);
|
||||
MFile::WriteBuffer(compressed, entry.disk_size * chunk_size);
|
||||
delete []compressed;
|
||||
} else {
|
||||
if(entry.disk_size == 0xffff) {
|
||||
entry.disk_size = entry.ram_size;
|
||||
entry.patch_start = (unsigned int)(MFile::Length()/chunk_size);
|
||||
MFile::Redim(MFile::Length() + entry.disk_size * chunk_size);
|
||||
}
|
||||
MFile::SetPosition((int64)entry.patch_start * (int64)chunk_size);
|
||||
MFile::WriteBuffer(entry.patch->start, entry.disk_size * chunk_size);
|
||||
}
|
||||
}
|
||||
|
||||
delete [](entry.patch->start);
|
||||
delete entry.patch;
|
||||
entry.patch = NULL;
|
||||
ram_used -= entry.ram_size;
|
||||
}
|
||||
|
||||
bool PServer::IsLoaded(unsigned int patch) {
|
||||
return operator[](patch).patch != NULL;
|
||||
}
|
||||
|
||||
Entry &PServer::Lookup(unsigned int patch, std::vector<unsigned int> &flush) {
|
||||
Entry &entry = operator[](patch);
|
||||
if(index.count(patch)) {
|
||||
list<unsigned int>::iterator &i = index[patch];
|
||||
pqueue.erase(i);
|
||||
pqueue.push_front(patch);
|
||||
assert(entry.patch);
|
||||
} else {
|
||||
while(ram_used > ram_max) {
|
||||
unsigned int to_flush = pqueue.back();
|
||||
pqueue.pop_back();
|
||||
//TODO i should not flush current extraction!
|
||||
//CRITICAL actually works just if ram_max is big enough.
|
||||
index.erase(to_flush);
|
||||
FlushPatch(to_flush);
|
||||
flush.push_back(to_flush);
|
||||
}
|
||||
assert(!entry.patch);
|
||||
entry.patch = LoadPatch(patch);
|
||||
pqueue.push_front(patch);
|
||||
list<unsigned int>::iterator i = pqueue.begin();
|
||||
index[patch] = i;
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
void PServer::Flush() {
|
||||
std::map<unsigned int, list<unsigned int>::iterator>::iterator i;
|
||||
for(i = index.begin(); i != index.end(); i++) {
|
||||
unsigned int patch = *((*i).second);
|
||||
Item &item = *((*i).second);
|
||||
FlushVbo(patch);
|
||||
FlushPatch(patch);
|
||||
}
|
||||
|
||||
pqueue.clear();
|
||||
index.clear();
|
||||
}
|
||||
|
||||
void PServer::LoadVbo(unsigned int npatch) {
|
||||
//WORKING if(!vbo_max) return;
|
||||
Entryg &entry = operator[](npatch);
|
||||
Patch &patch = *entry.patch;
|
||||
glGenBuffersARB(1, &entry.vbo_element);
|
||||
assert(entry.vbo_element);
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, entry.vbo_element);
|
||||
|
||||
unsigned int size = patch.nf * sizeof(unsigned short);
|
||||
if((signature & NXS_FACES) != 0) size *= 3;
|
||||
|
||||
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, size, patch.FaceBegin(),
|
||||
GL_STATIC_DRAW_ARB);
|
||||
vbo_used += size;
|
||||
|
||||
//TODO fix this when we allow data :p
|
||||
size = sizeof(float) * patch.dstart;
|
||||
|
||||
glGenBuffersARB(1, &entry.vbo_array);
|
||||
assert(entry.vbo_array);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, entry.vbo_array);
|
||||
|
||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, patch.VertBegin(),
|
||||
GL_STATIC_DRAW_ARB);
|
||||
|
||||
vbo_used += size;
|
||||
}
|
||||
void PServer::FlushVbo(unsigned int npatch) {
|
||||
Entryg &entry = operator[](npatch);
|
||||
if(!entry.vbo_element) return;
|
||||
glDeleteBuffersARB(1, &entry.vbo_element);
|
||||
glDeleteBuffersARB(1, &entry.vbo_array);
|
||||
entry.vbo_element = 0;
|
||||
entry.vbo_array = 0;
|
||||
|
||||
Patch &patch = *entry.patch;
|
||||
vbo_used -= patch.nf * sizeof(unsigned short);
|
||||
vbo_used -= sizeof(float) * patch.dstart;
|
||||
}
|
||||
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
#ifndef NXS_PSERVER_H
|
||||
#define NXS_PSERVER_H
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
#include "patch.h"
|
||||
#include "mfile.h"
|
||||
|
||||
namespace nxs {
|
||||
|
||||
/* HEader fo pserver
|
||||
1Kb riservato per dati globali:
|
||||
Magic: 'n' 'x' 's' 0x00
|
||||
Signature: unsigned int (maschera di bit)
|
||||
Chunk size: unsigned int
|
||||
Index offset: unsigned int (offset to the index begin,
|
||||
must be a multiple of chunk size)
|
||||
Index size: unsigned int (in number of entryies)
|
||||
History mode: unsigned int 0 means erased and created
|
||||
1 means ready for drawing
|
||||
History offset: unsigned int: multiple of chunk_size
|
||||
History size: unsigned int (in chars)
|
||||
|
||||
Tot vert: unsigned int
|
||||
Tot face: unsigned int
|
||||
Bound sphere: Sphere3f (4 float: Point3f center (x, y, z), (radius))*/
|
||||
|
||||
|
||||
|
||||
struct Entry {
|
||||
unsigned int patch_start; //granularita' Chunk
|
||||
unsigned short ram_size; //in chunks
|
||||
unsigned short disk_size; // in chunks (used when compressed)
|
||||
|
||||
unsigned short nvert;
|
||||
unsigned short nface;
|
||||
|
||||
vcg::Sphere3f sphere;
|
||||
float error;
|
||||
|
||||
Patch *patch;
|
||||
unsigned int vbo_array;
|
||||
unsigned int vbo_element;
|
||||
};
|
||||
|
||||
class PServer: public IndexFile<Entry,
|
||||
public:
|
||||
|
||||
std::list<unsigned int> pqueue;
|
||||
std::map<unsigned int, std::list<unsigned int>::iterator> index;
|
||||
|
||||
Signature signature;
|
||||
unsigned int chunk_size;
|
||||
|
||||
unsigned int ram_max;
|
||||
unsigned int ram_used;
|
||||
|
||||
PServer(): chunk_size(1024),
|
||||
ram_max(128000000),
|
||||
ram_used(0) {}
|
||||
|
||||
~PServer() { PServer::Close(); }
|
||||
|
||||
bool Create(const std::string &filename, Signature signature,
|
||||
unsigned int chunk_size = 1024);
|
||||
bool Load(const std::string &filename, Signature signature,
|
||||
bool readonly = true, unsigned int chunk_size = 1024);
|
||||
void Close();
|
||||
|
||||
bool ReadEntries(FILE *fp);
|
||||
bool WriteEntries(FILE *fp);
|
||||
|
||||
|
||||
void AddPatch(unsigned short nvert, unsigned short nface);
|
||||
Patch *LoadPatch(unsigned int id);
|
||||
void FlushPatch(unsigned int id);
|
||||
void Flush();
|
||||
|
||||
bool IsLoaded(unsigned int patch);
|
||||
Entry &Lookup(unsigned int patch, std::vector<unsigned int> &flushed);
|
||||
void LoadVbo(unsigned int patch);
|
||||
void FlushVbo(unsigned int patch);
|
||||
|
||||
bool IsCompressed() { return (signature & NXS_COMPRESSED) != 0; }
|
||||
bool HasStrips() { return (signature & NXS_STRIP) != 0; }
|
||||
bool HasColors() { return (signature & NXS_COLORS) != 0; }
|
||||
bool HasNormalsShort() { return (signature & NXS_NORMALS_SHORT) != 0; }
|
||||
bool HasNormalsFloat() { return (signature & NXS_NORMALS_FLOAT) != 0; }
|
||||
|
||||
void MaxRamBuffer(unsigned int ram_buffer);
|
||||
};
|
||||
|
||||
|
||||
}//namespace
|
||||
#endif
|
|
@ -1,191 +0,0 @@
|
|||
/****************************************************************************
|
||||
* 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.8 2004/11/03 16:31:38 ponchio
|
||||
Trying to fix big patches.
|
||||
|
||||
Revision 1.7 2004/10/30 20:17:03 ponchio
|
||||
Fixed big patches problem.
|
||||
|
||||
Revision 1.6 2004/10/15 11:41:03 ponchio
|
||||
Tests and small changes.
|
||||
|
||||
Revision 1.5 2004/09/28 10:26:21 ponchio
|
||||
Rewrote.
|
||||
|
||||
Revision 1.4 2004/09/21 00:53:23 ponchio
|
||||
Lotsa changes.
|
||||
|
||||
Revision 1.3 2004/08/27 00:39:28 ponchio
|
||||
Rewrote.
|
||||
|
||||
Revision 1.2 2004/07/01 21:35:34 ponchio
|
||||
int -> Key
|
||||
|
||||
Revision 1.1 2004/06/24 14:32:45 ponchio
|
||||
Moved from wrap/nexus
|
||||
|
||||
Revision 1.2 2004/06/24 14:19:20 ponchio
|
||||
Debugged
|
||||
|
||||
Revision 1.1 2004/06/23 17:17:46 ponchio
|
||||
Created
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "pvoronoi.h"
|
||||
#include <ANN/ANN.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
using namespace vcg;
|
||||
using namespace nxs;
|
||||
|
||||
void VoronoiPartition::Init() {
|
||||
if(bd) delete bd;
|
||||
buffer.resize(size() * 3);
|
||||
for(unsigned int i = 0; i < size(); i++) {
|
||||
for(int k = 0; k < 3; k++)
|
||||
buffer[i*3+k] = operator[](i)[k];
|
||||
}
|
||||
points.resize(size());
|
||||
for(unsigned int i = 0; i < size(); i++) {
|
||||
points[i] = &buffer[i*3];
|
||||
}
|
||||
/*FILE *ft = fopen("points.txt", "wb+");
|
||||
if(!ft) {
|
||||
std::cerr <<" AHOI!" << endl;
|
||||
exit(0);
|
||||
}
|
||||
for(unsigned int i = 0; i < size(); i++) {
|
||||
fprintf(ft, "%f\t%f\t%f\n", operator[](i)[0], operator[](i)[1], operator[](i)[2]);
|
||||
}
|
||||
fclose(ft);*/
|
||||
//std::cerr << "Building kd!\n";
|
||||
bd = new ANNkd_tree(&*points.begin(), size(), 3);
|
||||
//std::cerr << "Done!\n";
|
||||
}
|
||||
void VoronoiPartition::Closest(const vcg::Point3f &p, unsigned int nsize,
|
||||
vector<int> &nears,
|
||||
vector<float> &dist) {
|
||||
double point[3];
|
||||
point[0] = p[0];
|
||||
point[1] = p[1];
|
||||
point[2] = p[2];
|
||||
|
||||
nears.resize(nsize);
|
||||
dist.resize(nsize);
|
||||
vector<double> dists;
|
||||
dists.resize(nsize);
|
||||
bd->annkSearch(&point[0], nsize, &*nears.begin(), &*dists.begin());
|
||||
for(unsigned int i = 0; i < nsize; i++)
|
||||
dist[i] = (float)dists[i];
|
||||
}
|
||||
|
||||
void VoronoiPartition::Closest(const vcg::Point3f &p,
|
||||
int &target, float &dist) {
|
||||
double point[3];
|
||||
point[0] = p[0];
|
||||
point[1] = p[1];
|
||||
point[2] = p[2];
|
||||
double dists;
|
||||
bd->annkSearch(&point[0], 1, &target, &dists, 1);
|
||||
assert(target >= 0);
|
||||
assert(target < size());
|
||||
|
||||
dist = (float)dists;
|
||||
}
|
||||
|
||||
int VoronoiPartition::Locate(const vcg::Point3f &p) {
|
||||
int target = -2;
|
||||
float dist;
|
||||
Closest(p, target, dist);
|
||||
return target;
|
||||
}
|
||||
|
||||
/*bool Seed::Dist(const Point3f &point, float &mindist,
|
||||
Point3f &res) {
|
||||
float newdist = Distance(p, point) * weight;
|
||||
if(newdist < mindist) {
|
||||
mindist = newdist;
|
||||
res = p;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
void VoronoiPartition::Init() {
|
||||
assert(size() > 0);
|
||||
for(iterator i = begin(); i != end(); i++)
|
||||
box.Add((*i).p);
|
||||
|
||||
ug.SetBBox(box);
|
||||
ug.Set(*(vector<Seed> *)this);
|
||||
}
|
||||
|
||||
float VoronoiPartition::Closest(const vcg::Point3f &p,
|
||||
unsigned int &target, float radius) {
|
||||
Point3f res;
|
||||
float mindist = 1e20;
|
||||
target = 0xffffffff;
|
||||
|
||||
Seed *nsp = ug.GetClosest(p, mindist, res);
|
||||
if(nsp)
|
||||
target = nsp-&*begin();
|
||||
|
||||
return mindist;
|
||||
}
|
||||
|
||||
Point3f VoronoiPartition::FindBorder(vcg::Point3f &p, float radius) {
|
||||
Point3f a = p;
|
||||
unsigned int atarget = Locate(a);
|
||||
Point3f &seed = operator[](atarget).p;
|
||||
|
||||
if((a - seed).Norm() < radius/100) return p; //Bad luck.
|
||||
|
||||
Point3f dir = (a - seed).Normalize();
|
||||
Point3f b = seed + dir*radius*1.1;
|
||||
unsigned int btarget = Locate(b);
|
||||
|
||||
if(atarget == btarget) {
|
||||
//probably nothing on the side we are looking gor;
|
||||
return p;
|
||||
}
|
||||
Point3f m;
|
||||
for(unsigned int i = 0; i < 10; i++) {
|
||||
m = (a + b)/2;
|
||||
unsigned int mtarget = Locate(m);
|
||||
if(mtarget == atarget) a = m;
|
||||
else if(mtarget == btarget) b = m;
|
||||
else break; //something in the middle
|
||||
}
|
||||
return m;
|
||||
}
|
||||
*/
|
|
@ -1,143 +0,0 @@
|
|||
/****************************************************************************
|
||||
* 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.9 2004/10/30 20:17:03 ponchio
|
||||
Fixed big patches problem.
|
||||
|
||||
Revision 1.8 2004/10/15 11:41:03 ponchio
|
||||
Tests and small changes.
|
||||
|
||||
Revision 1.7 2004/09/28 10:26:21 ponchio
|
||||
Rewrote.
|
||||
|
||||
Revision 1.6 2004/09/21 00:53:23 ponchio
|
||||
Lotsa changes.
|
||||
|
||||
Revision 1.5 2004/08/27 00:39:28 ponchio
|
||||
Rewrote.
|
||||
|
||||
Revision 1.4 2004/07/20 14:17:51 ponchio
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.3 2004/07/01 21:34:59 ponchio
|
||||
int -> Key
|
||||
|
||||
Revision 1.2 2004/06/25 16:47:13 ponchio
|
||||
Various debug
|
||||
|
||||
Revision 1.1 2004/06/24 14:32:45 ponchio
|
||||
Moved from wrap/nexus
|
||||
|
||||
Revision 1.2 2004/06/24 14:19:20 ponchio
|
||||
Debugged
|
||||
|
||||
Revision 1.1 2004/06/23 17:17:46 ponchio
|
||||
Created
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef NXS_NET_GRID_H
|
||||
#define NXS_NET_GRID_H
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <vcg/space/point3.h>
|
||||
|
||||
|
||||
//TODO provide a Sort function, to sort spatially the seeds.
|
||||
|
||||
class ANNkd_tree;
|
||||
class ANNbd_tree;
|
||||
class ANNbruteForce;
|
||||
namespace nxs {
|
||||
|
||||
|
||||
|
||||
class VoronoiPartition: public std::vector<vcg::Point3f> {
|
||||
public:
|
||||
VoronoiPartition(): bd(NULL) {}
|
||||
void Init();
|
||||
void Closest(const vcg::Point3f &p, unsigned int nsize,
|
||||
std::vector<int> &nears,
|
||||
std::vector<float> &dist);
|
||||
void Closest(const vcg::Point3f &p,
|
||||
int &target, float &dist);
|
||||
|
||||
int Locate(const vcg::Point3f &p);
|
||||
|
||||
ANNkd_tree *bd;
|
||||
std::vector<double> buffer;
|
||||
std::vector<double *> points;
|
||||
};
|
||||
/* class Seed {
|
||||
public:
|
||||
vcg::Point3f p;
|
||||
float weight;
|
||||
typedef float ScalarType;
|
||||
bool Dist(const vcg::Point3f & point, float &mindist, vcg::Point3f &res);
|
||||
void GetBBox(vcg::Box3f &b) {b.Set(p);}
|
||||
bool IsD() { return false; }
|
||||
|
||||
Seed(): weight(1) {}
|
||||
Seed(const vcg::Point3f &point): p(point), weight(1) {}
|
||||
Seed(const vcg::Point3f &point, const float w):
|
||||
p(point), weight(w) {}
|
||||
|
||||
inline float Dist(const vcg::Point3f &q) const {
|
||||
return weight * vcg::Distance(p,q);
|
||||
}
|
||||
inline float SquaredDist(const vcg::Point3f &q) const {
|
||||
return weight * weight *vcg::SquaredDistance(p,q);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class VoronoiPartition: public std::vector<Seed> {
|
||||
public:
|
||||
vcg::GridStaticPtr< std::vector<Seed> > ug;
|
||||
|
||||
void SetBox(const vcg::Box3f &b) { box = b; }
|
||||
//call this before starting queries.
|
||||
void Init();
|
||||
float Closest(const vcg::Point3f &p,
|
||||
unsigned int &target, float radius = 0);
|
||||
|
||||
vcg::Point3f FindBorder(vcg::Point3f &p, float radius);
|
||||
unsigned int Locate(const vcg::Point3f &p) {
|
||||
unsigned int target;
|
||||
Closest(p, target);
|
||||
return target;
|
||||
}
|
||||
vcg::Box3f box;
|
||||
};*/
|
||||
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
#include <GL/glew.h>
|
||||
|
||||
#include "queuepserver.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace nxs;
|
||||
using namespace pt;
|
||||
|
||||
/*
|
||||
QueuePServer::Data &QueuePServer::Lookup(unsigned int patch,
|
||||
unsigned short nv, unsigned short nf,
|
||||
float priority,
|
||||
vector<QueuePServer::Data> &flush) {
|
||||
flush.clear();
|
||||
if(index.count(patch)) {
|
||||
return index[patch];
|
||||
} else {
|
||||
while(ram_used > ram_max) {
|
||||
if(MaxPriority() == 0) break;
|
||||
pop_heap(heap.begin(), heap.end());
|
||||
Item item = heap.back();
|
||||
heap.pop_back();
|
||||
assert(item.priority != 0);
|
||||
Data &data = index[item.patch];
|
||||
flush.push_back(data);
|
||||
FlushPatch(item.patch, data.patch);
|
||||
index.erase(item.patch);
|
||||
}
|
||||
Item item(patch, priority);
|
||||
heap.push_back(item);
|
||||
push_heap(heap.begin(), heap.end());
|
||||
Data &data = index[patch];
|
||||
// cerr << "Loading: " << patch << endl;
|
||||
data.patch = LoadPatch(patch, nv, nf);
|
||||
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool QueuePServer::IsLoaded(unsigned int patch) {
|
||||
return index.count(patch);
|
||||
}
|
||||
|
||||
float QueuePServer::MaxPriority() {
|
||||
if(!heap.size()) return 0;
|
||||
return heap.front().priority;
|
||||
}
|
||||
|
||||
void QueuePServer::Flush() {
|
||||
std::map<unsigned int, Data>::iterator i;
|
||||
for(i = index.begin(); i != index.end(); i++) {
|
||||
FlushVbo((*i).second);
|
||||
FlushPatch((*i).first, (*i).second.patch);
|
||||
}
|
||||
} */
|
||||
|
||||
void QueuePServer::LoadVbo(Data &data) {
|
||||
//WORKING if(!vbo_max) return;
|
||||
Patch &patch = *data.patch;
|
||||
glGenBuffersARB(1, &data.vbo_element);
|
||||
assert(data.vbo_element);
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, data.vbo_element);
|
||||
|
||||
unsigned int size = patch.nf * sizeof(unsigned short);
|
||||
if((signature & NXS_FACES) != 0) size *= 3;
|
||||
|
||||
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, size, patch.FaceBegin(),
|
||||
GL_STATIC_DRAW_ARB);
|
||||
vbo_used += size;
|
||||
|
||||
//TODO fix this when we allow data :p
|
||||
size = sizeof(float) * patch.dstart;
|
||||
|
||||
glGenBuffersARB(1, &data.vbo_array);
|
||||
assert(data.vbo_array);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, data.vbo_array);
|
||||
|
||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, patch.VertBegin(),
|
||||
GL_STATIC_DRAW_ARB);
|
||||
|
||||
vbo_used += size;
|
||||
}
|
||||
void QueuePServer::FlushVbo(Data &data) {
|
||||
//WORKING if(!vbo_max) return;
|
||||
if(!data.vbo_element) return;
|
||||
//glDeleteBuffersARB(1, &data.vbo_element);
|
||||
//glDeleteBuffersARB(1, &data.vbo_array);
|
||||
//data.vbo_element = 0;
|
||||
// data.vbo_array = 0;
|
||||
|
||||
Patch &patch = *data.patch;
|
||||
vbo_used -= patch.nf * sizeof(unsigned short);
|
||||
vbo_used -= sizeof(float) * patch.dstart;
|
||||
}
|
||||
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
#ifndef NXS_QUEUE_PSERVER_H
|
||||
#define NXS_QUEUE_PSERVER_H
|
||||
|
||||
#include <map>
|
||||
#include <hash_map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include <ptypes/pasync.h>
|
||||
|
||||
#include "pserver.h"
|
||||
|
||||
namespace nxs {
|
||||
|
||||
|
||||
class QueuePServer: public PServer {
|
||||
public:
|
||||
|
||||
enum Action { DRAW = 1, FLUSH = 0 };
|
||||
struct Data {
|
||||
Patch *patch;
|
||||
unsigned int vbo_array;
|
||||
unsigned int vbo_element;
|
||||
Data(): patch(NULL), vbo_array(0), vbo_element(0) {}
|
||||
};
|
||||
|
||||
pt::jobqueue queue;
|
||||
unsigned int vbo_used;
|
||||
|
||||
typedef std::pair<unsigned int, Data> Item;
|
||||
std::list<Item> items;
|
||||
typedef std::list<Item> Items;
|
||||
std::map<unsigned int, Items::iterator> index;
|
||||
|
||||
QueuePServer(): queue(64000), vbo_used(0) {}
|
||||
~QueuePServer() {
|
||||
Flush();
|
||||
}
|
||||
|
||||
Data &Lookup(unsigned int patch, unsigned short nv, unsigned short nf,
|
||||
std::vector<Data> &flush) {
|
||||
if(index.count(patch)) {
|
||||
Items::iterator &i = index[patch];
|
||||
Item item = *i;
|
||||
items.erase(i);
|
||||
items.push_front(item);
|
||||
i = items.begin();
|
||||
return ((*i).second);
|
||||
} else {
|
||||
while(ram_used > ram_max) {
|
||||
Data &data = items.back().second;
|
||||
//TODO i should not flush current extraction!
|
||||
index.erase(items.back().first);
|
||||
FlushPatch(items.back().first, data.patch);
|
||||
flush.push_back(data);
|
||||
items.pop_back();
|
||||
}
|
||||
Item item;
|
||||
item.first = patch;
|
||||
item.second.patch = LoadPatch(patch, nv, nf);
|
||||
items.push_front(item);
|
||||
Items::iterator i = items.begin();
|
||||
index[patch] = i;
|
||||
return ((*i).second);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//return flushing too.
|
||||
//Data &Lookup(unsigned int patch, unsigned short nv, unsigned short nf, float priority,
|
||||
// std::vector<QueuePServer::Data> &data);
|
||||
|
||||
//bool IsLoaded(unsigned int patch);
|
||||
//float MaxPriority();
|
||||
|
||||
|
||||
bool IsLoaded(unsigned int patch) {
|
||||
return index.count(patch);
|
||||
}
|
||||
void Flush() {
|
||||
std::map<unsigned int, Items::iterator>::iterator i;
|
||||
for(i = index.begin(); i != index.end(); i++) {
|
||||
Item &item = *((*i).second);
|
||||
FlushVbo(item.second);
|
||||
FlushPatch((*i).first, item.second.patch);
|
||||
}
|
||||
for(int k = 0; k < entries.size(); k++)
|
||||
entries[k].patch = NULL;
|
||||
|
||||
items.clear();
|
||||
index.clear();
|
||||
}
|
||||
void LoadVbo(Data &data);
|
||||
void FlushVbo(Data &data);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,107 +0,0 @@
|
|||
/****************************************************************************
|
||||
* 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.5 2004/07/05 15:49:39 ponchio
|
||||
Windows (DevCpp, mingw) port.
|
||||
|
||||
Revision 1.4 2004/07/02 17:41:37 ponchio
|
||||
Debug.
|
||||
|
||||
Revision 1.3 2004/07/02 13:01:28 ponchio
|
||||
Changed file extensions to .rmv, .rmb
|
||||
|
||||
Revision 1.2 2004/07/01 21:36:30 ponchio
|
||||
Various debug
|
||||
|
||||
Revision 1.1 2004/06/24 14:32:45 ponchio
|
||||
Moved from wrap/nexus
|
||||
|
||||
Revision 1.1 2004/06/24 14:18:58 ponchio
|
||||
Created
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include "vert_remap.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace nxs;
|
||||
|
||||
bool VertRemap::Create(const std::string &file) {
|
||||
if(!all.Create(file + ".rmv")) return false;
|
||||
if(!borders.Create(file + ".rmb")) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VertRemap::Load(const std::string &file) {
|
||||
if(!all.Load(file + ".rmv")) return false;
|
||||
if(!borders.Load(file + ".rmb")) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void VertRemap::Close() {
|
||||
all.Close();
|
||||
borders.Close();
|
||||
}
|
||||
|
||||
void VertRemap::Delete() {
|
||||
all.Flush();
|
||||
all.Delete();
|
||||
borders.Delete();
|
||||
}
|
||||
|
||||
void VertRemap::Resize(unsigned int n_vert) {
|
||||
all.Resize(n_vert);
|
||||
for(unsigned int i = 0; i < n_vert; i++)
|
||||
all[i] = 0xffffffff;
|
||||
borders.Clear();
|
||||
borders.Resize(n_vert/10);
|
||||
}
|
||||
|
||||
unsigned int VertRemap::Size() {
|
||||
return all.Size();
|
||||
}
|
||||
|
||||
unsigned int VertRemap::Count(unsigned int key) {
|
||||
assert(key < Size());
|
||||
if(all[key] == 0xffffffff) return 0;
|
||||
return 1 + borders.Count(key);
|
||||
}
|
||||
|
||||
void VertRemap::Insert(unsigned int key, unsigned int value) {
|
||||
if(all[key] == 0xffffffff) {
|
||||
all[key] = value;
|
||||
} else if(all[key] != value) {
|
||||
borders.Insert(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int VertRemap::GetValue(unsigned int key) { //return first value
|
||||
assert(key < Size());
|
||||
return all[key];
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
/****************************************************************************
|
||||
* 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.4 2004/10/01 15:59:52 ponchio
|
||||
Added include <assert.h>
|
||||
|
||||
Revision 1.3 2004/07/02 17:41:37 ponchio
|
||||
Debug.
|
||||
|
||||
Revision 1.2 2004/07/02 13:02:00 ponchio
|
||||
Backup.
|
||||
|
||||
Revision 1.1 2004/06/24 14:32:45 ponchio
|
||||
Moved from wrap/nexus
|
||||
|
||||
Revision 1.1 2004/06/24 14:18:58 ponchio
|
||||
Created
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
#ifndef NXS_VERTEX_REMAP_H
|
||||
#define NXS_VERTEX_REMAP_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <string>
|
||||
#include "vfile.h"
|
||||
#include "mfhash.h"
|
||||
|
||||
namespace nxs {
|
||||
|
||||
class VertRemap {
|
||||
public:
|
||||
~VertRemap() { Close(); }
|
||||
bool Create(const std::string &file);
|
||||
bool Load(const std::string &file);
|
||||
void Close();
|
||||
void Delete();
|
||||
void Resize(unsigned int n_vert);
|
||||
|
||||
unsigned int Size();
|
||||
unsigned int Count(unsigned int key);
|
||||
void Insert(unsigned int key, unsigned int value);
|
||||
unsigned int GetValue(unsigned int key); //return first value
|
||||
template <class C> void GetValues(unsigned int key,
|
||||
C &container) {
|
||||
assert(key < Size());
|
||||
container.clear();
|
||||
if(all[key] == 0xffffffff) return;
|
||||
// container.push_back(all[key]);
|
||||
borders.GetValues(key, container);
|
||||
container.insert(all[key]);
|
||||
}
|
||||
|
||||
VFile<unsigned int> all;
|
||||
MFHash borders;
|
||||
};
|
||||
} //namespace bmt
|
||||
|
||||
#endif
|
|
@ -1,595 +0,0 @@
|
|||
/****************************************************************************
|
||||
* 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.23 2004/11/28 07:58:49 ponchio
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.22 2004/11/28 04:14:12 ponchio
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.21 2004/11/28 01:23:26 ponchio
|
||||
Fixing borders... let's hope.
|
||||
|
||||
Revision 1.20 2004/11/18 18:30:14 ponchio
|
||||
Using baricenters... lotsa changes.
|
||||
|
||||
Revision 1.19 2004/11/03 16:31:38 ponchio
|
||||
Trying to fix big patches.
|
||||
|
||||
Revision 1.18 2004/10/30 20:17:03 ponchio
|
||||
Fixed big patches problem.
|
||||
|
||||
Revision 1.17 2004/10/29 16:33:29 ponchio
|
||||
Trying to fix big patches.
|
||||
|
||||
Revision 1.16 2004/10/22 14:31:56 ponchio
|
||||
Some controls added.
|
||||
|
||||
Revision 1.15 2004/10/21 12:22:21 ponchio
|
||||
Small change
|
||||
Revision 1.14 2004/10/19 04:23:29 ponchio
|
||||
*** empty log message ***
|
||||
|
||||
Revision 1.13 2004/10/15 16:45:27 ponchio
|
||||
Vbo added.
|
||||
|
||||
Revision 1.12 2004/10/15 11:41:03 ponchio
|
||||
Tests and small changes.
|
||||
|
||||
Revision 1.11 2004/10/10 17:19:42 ponchio
|
||||
Added compression and debugged.
|
||||
|
||||
Revision 1.10 2004/10/09 14:46:47 ponchio
|
||||
Windows porting small changes.
|
||||
|
||||
Revision 1.9 2004/10/08 15:12:04 ponchio
|
||||
Working version (maybe)
|
||||
|
||||
Revision 1.8 2004/10/04 16:49:54 ponchio
|
||||
Daily backup. Preparing for compression.
|
||||
|
||||
Revision 1.7 2004/10/01 16:54:57 ponchio
|
||||
Daily backup.
|
||||
|
||||
Revision 1.6 2004/09/30 00:27:42 ponchio
|
||||
Lot of changes. Backup.
|
||||
|
||||
Revision 1.5 2004/09/28 10:26:07 ponchio
|
||||
Voronoi partition changes.
|
||||
|
||||
Revision 1.4 2004/09/21 00:53:23 ponchio
|
||||
Lotsa changes.
|
||||
|
||||
Revision 1.3 2004/09/17 15:25:09 ponchio
|
||||
First working (hopefully) release.
|
||||
|
||||
Revision 1.2 2004/09/16 14:25:16 ponchio
|
||||
Backup. (lot of changes).
|
||||
|
||||
Revision 1.1 2004/08/26 18:03:47 ponchio
|
||||
First draft.
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "voronoichain.h"
|
||||
#include "watch.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace vcg;
|
||||
using namespace nxs;
|
||||
|
||||
|
||||
void print(Point3f p) {
|
||||
cerr << p[0] << " " << p[1] << " " << p[2] << endl;
|
||||
}
|
||||
|
||||
//return first non zero distance point.
|
||||
float getClosest(const Point3f &seed, VoronoiPartition &part) {
|
||||
vector<int> nears;
|
||||
vector<float> dists;
|
||||
float dist = 0;
|
||||
int count = 1;
|
||||
while(dist == 0) {
|
||||
if(count > part.size()) {
|
||||
cerr << "This should never happen!!!!\n";
|
||||
exit(0);
|
||||
}
|
||||
part.Closest(seed, count, nears, dists);
|
||||
for(int k = 0; k < count; k++) {
|
||||
int c = nears[k];
|
||||
assert(c >= 0);
|
||||
assert(c < part.size());
|
||||
if(dists[k] > 0 && (dist == 0 || dists[k] < dist)) {
|
||||
dist = dists[k];
|
||||
}
|
||||
}
|
||||
count++;
|
||||
}
|
||||
return (float)sqrt(dist);
|
||||
}
|
||||
|
||||
int getBest(const Point3f &seed, VoronoiPartition &part,
|
||||
vector<bool> &mark,
|
||||
vector<unsigned int> &counts) {
|
||||
|
||||
vector<int> nears;
|
||||
vector<float> dist;
|
||||
int nnear = 7;
|
||||
if(part.size() < 7) nnear = part.size()/2;
|
||||
if(!nnear) return -1;
|
||||
|
||||
part.Closest(seed, nnear, nears, dist);
|
||||
int best = -1;
|
||||
int bestcount = -1;
|
||||
int bestdist = -1;
|
||||
for(int k = 0; k < nnear; k++) {
|
||||
int c = nears[k];
|
||||
assert(c >= 0);
|
||||
assert(c < part.size()); if(mark[c]) continue;
|
||||
if(part[c] == seed) continue;
|
||||
if(bestcount < 0 ||
|
||||
(counts[c] < bestcount)) {
|
||||
best = c;
|
||||
bestcount = counts[c];
|
||||
}
|
||||
/*if(bestdist < 0 ||
|
||||
Distance(seed, part[c]) < bestdist) {
|
||||
best = c;
|
||||
bestdist = Distance(seed, part[c]);
|
||||
}*/
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
//return false if still not ok
|
||||
bool VoronoiChain::Optimize(int mean, VoronoiPartition &part,
|
||||
vector<Point3f> ¢roids,
|
||||
vector<unsigned int> &counts,
|
||||
bool join) {
|
||||
|
||||
|
||||
|
||||
//remove small or really big patches.
|
||||
unsigned int failed = 0;
|
||||
vector<Point3f> seeds;
|
||||
vector<bool> mark;
|
||||
mark.resize(part.size(), false);
|
||||
|
||||
//first pass we check only big ones
|
||||
for(unsigned int i = 0; i < part.size(); i++) {
|
||||
if(counts[i] > max_size || counts[i] > 2 * mean) {
|
||||
failed++;
|
||||
//cerr << "Failed> " << counts[i] << endl;
|
||||
float radius= getClosest(part[i], part);
|
||||
//cerr << "RADIUS: " << radius << endl;
|
||||
if(radius == 0) {
|
||||
cerr << "Radius zero???\n";
|
||||
exit(0);
|
||||
}
|
||||
radius /= 3;
|
||||
if(radius < 0) continue;
|
||||
seeds.push_back(part[i] + Point3f(1, -1, 1) * radius);
|
||||
seeds.push_back(part[i] + Point3f(-1, 1, 1) * radius);
|
||||
seeds.push_back(part[i] + Point3f(-1, -1, -1) * radius);
|
||||
seeds.push_back(part[i] + Point3f(1, 1, -1) * radius);
|
||||
mark[i];
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < part.size(); i++) {
|
||||
if(mark[i]) continue;
|
||||
if(join && counts[i] < min_size) {
|
||||
failed++;
|
||||
int best = getBest(part[i], part, mark, counts);
|
||||
if(best < 0) {
|
||||
cerr << "Best not found! how strange!\n";
|
||||
continue;
|
||||
}
|
||||
if(best >= part.size()) {
|
||||
cerr << "Invalid best!!!\n";
|
||||
exit(0);
|
||||
}
|
||||
assert(mark[best] == false);
|
||||
mark[best] = true;
|
||||
mark[i] = true;
|
||||
seeds.push_back((part[i] + part[best])/2);
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < part.size(); i++) {
|
||||
if(mark[i]) continue;
|
||||
if(join) {
|
||||
if(counts[i] < min_size) {
|
||||
cerr << "Qualche problema serio!\n";
|
||||
} else {
|
||||
part[i] = centroids[i]/(float)counts[i];
|
||||
}
|
||||
}
|
||||
seeds.push_back(part[i]);
|
||||
}
|
||||
|
||||
part.clear();
|
||||
for(unsigned int i = 0; i < seeds.size(); i++)
|
||||
part.push_back(seeds[i]);
|
||||
|
||||
if(part.size() == 0) part.push_back(Point3f(0,0,0));
|
||||
part.Init();
|
||||
return failed == 0;
|
||||
}
|
||||
|
||||
void VoronoiChain::Init(VFile<Point3f> &baricenters,
|
||||
float scaling, int steps) {
|
||||
|
||||
unsigned int f_cells = baricenters.Size() / mean_size;
|
||||
unsigned int c_cells = (unsigned int)(scaling * f_cells);
|
||||
|
||||
levels.push_back(VoronoiPartition());
|
||||
levels.push_back(VoronoiPartition());
|
||||
VoronoiPartition &fine = levels[0];
|
||||
VoronoiPartition &coarse = levels[1];
|
||||
|
||||
srand(0);
|
||||
|
||||
float coarse_vmean = mean_size/scaling;
|
||||
|
||||
for(unsigned int i = 0; i < baricenters.Size(); i++) {
|
||||
int f = (int)(mean_size * (float)rand()/(RAND_MAX + 1.0));
|
||||
int c = (int)(coarse_vmean * (float)rand()/(RAND_MAX + 1.0));
|
||||
if(f == 2) {
|
||||
Point3f &point = baricenters[i];
|
||||
fine.push_back(point);
|
||||
}
|
||||
if(c == 2) {
|
||||
Point3f &point = baricenters[i];
|
||||
coarse.push_back(point);
|
||||
}
|
||||
}
|
||||
//TODO! Check for duplicates (use the closest :P)
|
||||
// cerr << "fine_seeds.size: " << fine.size() << endl;
|
||||
//cerr << "coarse_seeds.size: " << coarse.size() << endl;
|
||||
fine.Init();
|
||||
coarse.Init();
|
||||
|
||||
//here goes some optimization pass.
|
||||
//Fine optimization.
|
||||
Report report;
|
||||
vector<Point3f> centroids;
|
||||
vector<unsigned int> counts;
|
||||
for(int step = 0; step < steps; step++) {
|
||||
cerr << "Optimization step: " << step+1 << "/" << steps << endl;
|
||||
centroids.clear();
|
||||
counts.clear();
|
||||
centroids.resize(fine.size(), Point3f(0, 0, 0));
|
||||
counts.resize(fine.size(), 0);
|
||||
|
||||
report.Init(baricenters.Size());
|
||||
for(unsigned int v = 0; v < baricenters.Size(); v++) {
|
||||
report.Step(v);
|
||||
unsigned int target = fine.Locate(baricenters[v]);
|
||||
centroids[target] += baricenters[v];
|
||||
counts[target]++;
|
||||
}
|
||||
if(step == steps-1) {
|
||||
if(!Optimize(mean_size, fine, centroids, counts, false))
|
||||
step--;
|
||||
} else
|
||||
Optimize(mean_size, fine, centroids, counts, true);
|
||||
}
|
||||
cerr << "Optimized (fine)!\n";
|
||||
//here goes some optimization pass.
|
||||
//Coarse optimization.
|
||||
//vector<float> radius;
|
||||
for(int step = 0; step < steps; step++) {
|
||||
cerr << "Optimization step: " << step+1 << "/" << steps << endl;
|
||||
centroids.clear();
|
||||
counts.clear();
|
||||
centroids.resize(coarse.size(), Point3f(0, 0, 0));
|
||||
counts.resize(coarse.size(), 0);
|
||||
//radius.resize(coarse.size(), 0);
|
||||
|
||||
report.Init(baricenters.Size());
|
||||
for(unsigned int v = 0; v < baricenters.Size(); v++) {
|
||||
if(v & 0xffff) report.Step(v);
|
||||
unsigned int ctarget = 0xffffffff;
|
||||
ctarget = coarse.Locate(baricenters[v]);
|
||||
// float dist;
|
||||
// coarse.Closest(crude.vert[v], ctarget, dist);
|
||||
assert(ctarget != 0xffffffff);
|
||||
centroids[ctarget] += baricenters[v];
|
||||
counts[ctarget]++;
|
||||
//if(dist > radius[ctarget]) radius[ctarget] = dist;
|
||||
}
|
||||
if(step == steps-1) {
|
||||
if(!Optimize((int)coarse_vmean, coarse, centroids, counts, false))
|
||||
step --;
|
||||
} else
|
||||
Optimize((int)coarse_vmean, coarse, centroids, counts, true);
|
||||
}
|
||||
cerr << "Optimized coarse!\n";
|
||||
}
|
||||
|
||||
unsigned int VoronoiChain::Locate(unsigned int level,
|
||||
const vcg::Point3f &p) {
|
||||
return levels[level].Locate(p);
|
||||
}
|
||||
|
||||
//TODO move this to nxsbuild
|
||||
void VoronoiChain::RemapFaces(VFile<Point3f> &baricenters,
|
||||
VFile<unsigned int> &face_remap,
|
||||
vector<unsigned int> &patch_faces,
|
||||
float scaling, int steps) {
|
||||
|
||||
Init(baricenters, scaling, steps);
|
||||
|
||||
//TODO: improve quality of patches and implement threshold.
|
||||
typedef map<pair<unsigned int, unsigned int>, unsigned int> FragIndex;
|
||||
|
||||
// map<pair<unsigned int, unsigned int>, unsigned int> patches;
|
||||
FragIndex patches;
|
||||
|
||||
unsigned int totpatches = 0;
|
||||
|
||||
Point3f bari;
|
||||
for(unsigned int i = 0; i < baricenters.Size(); i++) {
|
||||
bari = baricenters[i];
|
||||
|
||||
unsigned int fine = Locate(0, bari);
|
||||
unsigned int coarse = Locate(1, bari);
|
||||
|
||||
unsigned int patch;
|
||||
|
||||
if(!patches.count(make_pair(coarse, fine))) {
|
||||
patch = totpatches;
|
||||
patches[make_pair(coarse, fine)] = totpatches++;
|
||||
} else
|
||||
patch = patches[make_pair(coarse, fine)];
|
||||
|
||||
face_remap[i] = patch;
|
||||
//face_remap[i] = fine;
|
||||
|
||||
while(patch_faces.size() <= patch)
|
||||
patch_faces.push_back(0);
|
||||
patch_faces[patch]++;
|
||||
}
|
||||
|
||||
//prune faces (now only 0 faces);
|
||||
//TODO prune really small faces
|
||||
unsigned int tot_patches = 0;
|
||||
vector<int> patch_remap;
|
||||
for(unsigned int i = 0; i < patch_faces.size(); i++) {
|
||||
//if below threshold (and can join faces)
|
||||
if(patch_faces[i] == 0)
|
||||
patch_remap.push_back(-1);
|
||||
else
|
||||
patch_remap.push_back(tot_patches++);
|
||||
|
||||
if(patch_faces[i] > 32000) {
|
||||
//TODO do something to reduce patch size... :P
|
||||
cerr << "Found a patch too big... sorry\n";
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//building fragments
|
||||
FragIndex::iterator f;
|
||||
for(f = patches.begin(); f != patches.end(); f++) {
|
||||
unsigned int coarse = (*f).first.first;
|
||||
unsigned int fine = (*f).first.second;
|
||||
unsigned int patch = (*f).second;
|
||||
oldfragments[coarse].insert(patch_remap[patch]);
|
||||
}
|
||||
|
||||
//remapping faces
|
||||
patch_faces.clear();
|
||||
patch_faces.resize(totpatches, 0);
|
||||
for(unsigned int i = 0; i < face_remap.Size(); i++) {
|
||||
unsigned int patch = face_remap[i];
|
||||
#ifdef CONTROLS
|
||||
if(patch == 0xffffffff) {
|
||||
cerr << "RESIGH\n";
|
||||
exit(0);
|
||||
}
|
||||
if(patch_remap[patch] == -1) {
|
||||
cerr << "SIGH!\n";
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
unsigned int newpatch = patch_remap[patch];
|
||||
face_remap[i] = newpatch;
|
||||
patch_faces[newpatch]++;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void VoronoiChain::BuildLevel(Nexus &nexus, unsigned int offset,
|
||||
float scaling, int steps) {
|
||||
unsigned int totface = 0;
|
||||
unsigned int totvert = 0;
|
||||
for(unsigned int idx = offset; idx < nexus.index.size(); idx++) {
|
||||
totface += nexus.index[idx].nface;
|
||||
totvert += nexus.index[idx].nvert;
|
||||
}
|
||||
|
||||
|
||||
levels.push_back(VoronoiPartition());
|
||||
VoronoiPartition &coarse = levels[levels.size()-1];
|
||||
VoronoiPartition &fine = levels[levels.size()-2];
|
||||
fine.Init();
|
||||
|
||||
unsigned int tot_coarse = (unsigned int)(fine.size() * scaling);
|
||||
|
||||
//TODO this method for selecting the seeds is ugly!
|
||||
float ratio = tot_coarse/(float)(nexus.index.size() - offset);
|
||||
float cratio = 0;
|
||||
for(unsigned int idx = offset; idx < nexus.index.size(); idx++) {
|
||||
cratio += ratio;
|
||||
if(cratio > 1) {
|
||||
Patch patch = nexus.GetPatch(idx);
|
||||
Point3f &v = patch.Vert(0);
|
||||
coarse.push_back(v);
|
||||
cratio -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(coarse.size() == 0) {
|
||||
Patch patch = nexus.GetPatch(0);
|
||||
coarse.push_back(patch.Vert(0));
|
||||
}
|
||||
|
||||
float coarse_vmean = totface/(float)coarse.size();
|
||||
|
||||
coarse.Init();
|
||||
cerr << "Coarse size: " << coarse.size() << endl;
|
||||
cerr << "Coarse mean: " << coarse_vmean << " mean_size: " << mean_size << endl;
|
||||
|
||||
Report report;
|
||||
//here goes some optimization pass.
|
||||
//Coarse optimization.
|
||||
vector<Point3f> centroids;
|
||||
vector<unsigned int> counts;
|
||||
|
||||
for(int step = 0; step < steps; step++) {
|
||||
cerr << "Optimization step: " << step+1 << "/" << steps << endl;
|
||||
centroids.clear();
|
||||
counts.clear();
|
||||
centroids.resize(coarse.size(), Point3f(0, 0, 0));
|
||||
counts.resize(coarse.size(), 0);
|
||||
|
||||
report.Init(nexus.index.size());
|
||||
for(unsigned int idx = offset; idx < nexus.index.size(); idx++) {
|
||||
report.Step(idx);
|
||||
Patch patch = nexus.GetPatch(idx);
|
||||
for(unsigned int i = 0; i < patch.nf; i++) {
|
||||
unsigned short *face = patch.Face(i);
|
||||
Point3f bari = (patch.Vert(face[0]) + patch.Vert(face[1]) + patch.Vert(face[2]))/3;
|
||||
unsigned int ctarget = coarse.Locate(bari);
|
||||
assert(ctarget < coarse.size());
|
||||
centroids[ctarget] += bari;
|
||||
counts[ctarget]++;
|
||||
}
|
||||
}
|
||||
if(step == steps-1) {
|
||||
if(!Optimize((int)coarse_vmean, coarse, centroids, counts, false))
|
||||
step--;
|
||||
} else
|
||||
Optimize((int)coarse_vmean, coarse, centroids, counts, true);
|
||||
}
|
||||
|
||||
newfragments.clear();
|
||||
}
|
||||
bool VoronoiChain::Save(const string &file) {
|
||||
FILE *fp = fopen((output + ".remap").c_str(), "wb+");
|
||||
if(!fp) {
|
||||
cerr << "Could not create remapping info\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned int nlevels = levels.size();
|
||||
fwrite(&nlevels, sizeof(unsigned int), 1, fp);
|
||||
for(int i = 0; i < nlevels; i++) {
|
||||
VoronoiPartition &level = levels[i];
|
||||
unsigned int npoints = level.size();
|
||||
fwrite(&npoints, sizeof(unsigned int), 1, fp);
|
||||
fwrite(&(level[0]), sizeof(Point3f), npoints, fp);
|
||||
}
|
||||
//writing fragments
|
||||
|
||||
unsigned int nfrag = newfragments.size();
|
||||
fwrite(&nfrag, sizeof(unsigned int), 1, fp);
|
||||
std::map<unsigned int, std::set<unsigned int> >::iterator i;
|
||||
for(i = newfragments.begin(); i != newfragments.end(); i++) {
|
||||
unsigned int n = (*i).second.size();
|
||||
fwrite(&((*i).first), sizeof(unsigned int), 1, fp);
|
||||
fwrite(&n, sizeof(unsigned int), 1, fp);
|
||||
set<unsigned int>::iterator k;
|
||||
for(k = (*i).second.begin(); k != (*i).second.end(); k++)
|
||||
fwrite(&*k, sizeof(unsigned int), 1, fp);
|
||||
}
|
||||
nfrag = oldfragments.size();
|
||||
fwrite(&nfrag, sizeof(unsigned int), 1, fp);
|
||||
for(i = oldfragments.begin(); i != oldfragments.end(); i++) {
|
||||
unsigned int n = (*i).second.size();
|
||||
fwrite(&((*i).first), sizeof(unsigned int), 1, fp);
|
||||
fwrite(&n, sizeof(unsigned int), 1, fp);
|
||||
set<unsigned int>::iterator k;
|
||||
for(k = (*i).second.begin(); k != (*i).second.end(); k++)
|
||||
fwrite(&*k, sizeof(unsigned int), 1, fp);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
bool VoronoiChain::Load(const string &file) {
|
||||
FILE *fp = fopen(file.c_str(), "rb");
|
||||
if(!fp) {
|
||||
cerr << "Could not open remapping info\n";
|
||||
return -1;
|
||||
}
|
||||
unsigned int nlevels;
|
||||
fread(&nlevels, sizeof(unsigned int), 1, fp);
|
||||
for(int i = 0; i < nlevels; i++) {
|
||||
levels.push_back(VoronoiPartition());
|
||||
VoronoiPartition &level = levels.back();
|
||||
|
||||
unsigned int npoints;
|
||||
fread(&npoints, sizeof(unsigned int), 1, fp);
|
||||
level.resize(npoints);
|
||||
fread(&(level[0]), sizeof(Point3f), npoints, fp);
|
||||
level.Init();
|
||||
}
|
||||
//reading fragments
|
||||
unsigned int nfrag;
|
||||
fread(&nfrag, sizeof(unsigned int), 1, fp);
|
||||
for(unsigned int i = 0; i < nfrag; i++) {
|
||||
unsigned int p, n;
|
||||
fread(&p, sizeof(unsigned int), 1, fp);
|
||||
set<unsigned int> &s = newfragments[p];
|
||||
fread(&n, sizeof(unsigned int), 1, fp);
|
||||
for(unsigned int k = 0; k < n; k++) {
|
||||
unsigned int j;
|
||||
fread(&j, sizeof(unsigned int), 1, fp);
|
||||
s.insert(j);
|
||||
}
|
||||
}
|
||||
|
||||
fread(&nfrag, sizeof(unsigned int), 1, fp);
|
||||
for(unsigned int i = 0; i < nfrag; i++) {
|
||||
unsigned int p, n;
|
||||
fread(&p, sizeof(unsigned int), 1, fp);
|
||||
set<unsigned int> &s = oldfragments[p];
|
||||
fread(&n, sizeof(unsigned int), 1, fp);
|
||||
for(unsigned int k = 0; k < n; k++) {
|
||||
unsigned int j;
|
||||
fread(&j, sizeof(unsigned int), 1, fp);
|
||||
s.insert(j);
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
/****************************************************************************
|
||||
* 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.6 2004/11/18 18:30:15 ponchio
|
||||
Using baricenters... lotsa changes.
|
||||
|
||||
Revision 1.5 2004/10/30 20:17:03 ponchio
|
||||
Fixed big patches problem.
|
||||
|
||||
Revision 1.4 2004/09/30 00:27:42 ponchio
|
||||
Lot of changes. Backup.
|
||||
|
||||
Revision 1.3 2004/09/21 00:53:23 ponchio
|
||||
Lotsa changes.
|
||||
|
||||
Revision 1.2 2004/09/16 14:25:16 ponchio
|
||||
Backup. (lot of changes).
|
||||
|
||||
Revision 1.1 2004/08/26 18:03:48 ponchio
|
||||
First draft.
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef NXS_VORONOI_CHAIN_H
|
||||
#define NXS_VORONOI_CHAIN_H
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <vcg/space/box3.h>
|
||||
|
||||
#include "pchain.h"
|
||||
#include "pvoronoi.h"
|
||||
#include "nexus.h"
|
||||
#include "vfile.h"
|
||||
|
||||
namespace nxs {
|
||||
|
||||
class VoronoiChain: public PChain {
|
||||
public:
|
||||
unsigned int mean_size; //mean number of faces per patch
|
||||
unsigned int min_size; //minimum number of faces per patch (soft)
|
||||
unsigned int max_size; //max number of faces per patch (hard);
|
||||
|
||||
VoronoiChain(unsigned int mean_s,
|
||||
unsigned int min_s,
|
||||
unsigned int max_s = 32000):
|
||||
mean_size(mean_s), min_size(min_s), max_size(max_s) {}
|
||||
virtual ~VoronoiChain() {}
|
||||
|
||||
void Init(VFile<vcg::Point3f> &baricenters, float scaling, int steps);
|
||||
virtual unsigned int Locate(unsigned int level, const vcg::Point3f &p);
|
||||
void RemapFaces(VFile<vcg::Point3f> &baricenters,
|
||||
VFile<unsigned int> &face_remap,
|
||||
std::vector<unsigned int> &patch_faces, float scaling,
|
||||
int steps);
|
||||
|
||||
void BuildLevel(Nexus &nexus, unsigned int offset, float scaling, int steps);
|
||||
bool Save(const std::string &file);
|
||||
bool Load(const std::string &file);
|
||||
|
||||
|
||||
|
||||
std::vector<VoronoiPartition> levels;
|
||||
|
||||
// coarse partition -> associated patches
|
||||
std::map<unsigned int, std::set<unsigned int> > newfragments;
|
||||
std::map<unsigned int, std::set<unsigned int> > oldfragments;
|
||||
// private:
|
||||
|
||||
float radius;
|
||||
vcg::Box3f box;
|
||||
|
||||
bool Optimize(int mean, VoronoiPartition &part,
|
||||
std::vector<vcg::Point3f> ¢roids,
|
||||
std::vector<unsigned int> &counts, bool join);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,217 +0,0 @@
|
|||
/****************************************************************************
|
||||
* 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 $
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef WIN32
|
||||
#include <wrap/system/getopt.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "nxstypes.h"
|
||||
#include "crude.h"
|
||||
#include "remapping.h"
|
||||
#include "decimate.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace vcg;
|
||||
using namespace nxs;
|
||||
|
||||
/*struct PIndex {
|
||||
int64 offset;
|
||||
unsigned int lenght;
|
||||
};
|
||||
|
||||
class FaceIndex: public std::vector<PIndex> {};*/
|
||||
|
||||
|
||||
void usage() {
|
||||
cerr << "Usage: voronoinxs <crude> <output> [options]\n"
|
||||
" Options:\n"
|
||||
" -f N: use N faces per patch (default 1000, max 32000)\n"
|
||||
" -t N: mini faces per patch (default 200)\n"
|
||||
" -l N: number of levels\n"
|
||||
" -s F: scaling factor (0 < F < 1, default 0.5)\n"
|
||||
" -o N: number of optimization steps\n"
|
||||
" -d <method>: decimation method: quadric, cluster. (default quadric)\n"
|
||||
" -b N: ram buffer size (in bytes)\n"
|
||||
" -p N: which fase perform:\n"
|
||||
" 0) Remap faces\n"
|
||||
" 1) Sort faces\n"
|
||||
" 2) Build patches\n"
|
||||
" 3) Build borders\n"
|
||||
" 4) Build levels\n\n"
|
||||
" If you use the step option, all other parameters MUST stay the same\n\n";
|
||||
|
||||
}
|
||||
|
||||
void FirstStep(const string &crudefile, const string &output,
|
||||
unsigned int patch_size, unsigned int patch_threshold,
|
||||
float scaling, unsigned int optimization_steps) {
|
||||
Crude crude;
|
||||
|
||||
if(!crude.Load(crudefile, true)) {
|
||||
cerr << "Could not open crude input: " << crudefile << endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if(patch_size > crude.vert.Size()/2) {
|
||||
cerr << "Patch size too big: " << patch_size << " * 2 > "
|
||||
<< crude.vert.Size() << endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if(patch_threshold == 0xffffffff)
|
||||
patch_threshold = patch_size/4;
|
||||
|
||||
|
||||
VChain vchain;
|
||||
|
||||
VFile<unsigned int> face_remap;
|
||||
if(!face_remap.Create(output + ".rmf")) {
|
||||
cerr << "Could not create remap files: " << output << ".rmf\n";
|
||||
exit(0);
|
||||
}
|
||||
face_remap.Resize(crude.Faces());
|
||||
|
||||
VFile<Point3f> baricenters;
|
||||
if(!baricenters.Create(output + string(".bvr"))) {
|
||||
cerr << "Could not create temporary baricenters file\n";
|
||||
exit(0);
|
||||
}
|
||||
baricenters.Resize(crude.Faces());
|
||||
for(unsigned int i = 0; i < crude.Faces(); i++) {
|
||||
baricenters[i] = crude.GetBari(i);
|
||||
}
|
||||
|
||||
BlockIndex face_index;
|
||||
|
||||
Remap(vchain, baricenters, face_remap, face_index,
|
||||
patch_size, patch_threshold, 65000, scaling,
|
||||
optimization_steps);
|
||||
|
||||
if(!vchain.Save(output + ".vchain")) {
|
||||
cerr << "Could not save file: " << output << ".vchain\n";
|
||||
exit(0);
|
||||
}
|
||||
if(!face_index.Save(output + ".rmi")) {
|
||||
cerr << "Could not save file: " << output << ".rmi\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
baricenters.Delete();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
/* Parameters: */
|
||||
unsigned int patch_size = 1000; //step 0
|
||||
unsigned int patch_threshold = 0xffffffff; //Step 0
|
||||
float scaling = 0.5; //step 0, 4
|
||||
unsigned int optimization_steps = 5; //step 0, 4
|
||||
|
||||
Decimation decimation = CLUSTER; //step 4
|
||||
unsigned int max_level = 0xffffffff; //step 4
|
||||
|
||||
unsigned int ram_buffer = 128000000; //step 2, 3, 4
|
||||
unsigned int chunk_size = 1024; //step 2, 3, 4
|
||||
int step = -1; //means all of them.
|
||||
|
||||
int option;
|
||||
while((option = getopt(argc, argv, "f:t:l:s:d:o:b:c:p:")) != EOF) {
|
||||
switch(option) {
|
||||
case 'f': patch_size = atoi(optarg);
|
||||
if(patch_size == 0 || patch_size > 32000) {
|
||||
cerr << "Invalid number of faces per patch: " << optarg << endl;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 't': patch_threshold = atoi(optarg);
|
||||
if(patch_threshold == 0 || patch_threshold > patch_size) {
|
||||
cerr << "Invalid patch threshold: " << optarg << endl;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'l': max_level = atoi(optarg);
|
||||
if(max_level == 0) {
|
||||
cerr << "Invalid number of levels: " << optarg << endl;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 's': scaling = (float)atof(optarg);
|
||||
if(scaling <= 0 || scaling >= 1) {
|
||||
cerr << "Invalid scaling: " << optarg << endl;
|
||||
cerr << "Must be 0 < scaling < 1" << endl;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
if(!strcmp("quadric", optarg))
|
||||
decimation = QUADRIC;
|
||||
else if(!strcmp("cluster", optarg))
|
||||
decimation = CLUSTER;
|
||||
else {
|
||||
cerr << "Unknown decimation method: " << optarg << endl;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'o': optimization_steps = atoi(optarg); break;
|
||||
case 'p': step = atoi(optarg); break;
|
||||
case 'b': ram_buffer = atoi(optarg);
|
||||
if(ram_buffer == 0) {
|
||||
cerr << "Invalid ram buffer: " << optarg << endl;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'c': chunk_size = atoi(optarg);
|
||||
if(chunk_size == 0) {
|
||||
cerr << "Invalid chunk size: " << optarg << endl;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default: cerr << "Unknown option: " << (char)option << endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(optind != argc -2) {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
string crudefile = argv[optind];
|
||||
string output = argv[optind+1];
|
||||
|
||||
if(step < 0 || step == 0)
|
||||
FirstStep(crudefile, output, patch_size, patch_threshold,
|
||||
scaling, optimization_steps);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue