This commit is contained in:
Federico Ponchio 2005-01-14 15:55:32 +00:00
parent e66a97ffd0
commit 90e4d33361
22 changed files with 0 additions and 3285 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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);
}
}*/
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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();
}
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}
*/

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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];
}

View File

@ -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

View File

@ -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> &centroids,
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);
}

View File

@ -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> &centroids,
std::vector<unsigned int> &counts, bool join);
};
}
#endif

View File

@ -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;
}