Initial commit

This commit is contained in:
Paolo Cignoni 2004-03-08 09:24:59 +00:00
parent 42e0406b07
commit b91d8334d5
5 changed files with 1325 additions and 1 deletions

View File

@ -7,4 +7,4 @@ This module contains the documentation for the type and the functions used for r
/** \defgroup face Faces /** \defgroup face Faces
*/ */
/** \defgroup trimesh Triangular Meshes /** \defgroup trimesh Triangular Meshes
*/ */

View File

@ -0,0 +1 @@
/** Main namespace */ namespace vcg {} /** Everything about meshes lie in this namespace */ namespace vcg::tri {} /** Wrapper for symbols and structs defind in the old ply library */ namespace vcg::ply {} /** For all the functions and classes used to read and write meshes */ namespace vcg::tri::io {}

655
vcg/space/index/ugrid.h Normal file
View File

@ -0,0 +1,655 @@
/****************************************************************************
* 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 $
****************************************************************************/
#ifndef __VCGLIB_UGRID
#define __VCGLIB_UGRID
namespace vcg {
/** Static Uniform Grid
A spatial search structure for a accessing a container of objects. It is based on a uniform grid overlayed over a protion of space.
The grid partion the space into cells. Cells contains just pointers to the object that are stored elsewhere.
The set of object is meant to be static and pointer stable.
Useful for situation were many space related query are issued over the same dataset (ray tracing, measuring distances between meshes, re-detailing ecc.). Works well for distribution that ar reasonably uniform.
How to use it:
*/
template < class ContainerType >
class UGrid
{
public:
/** Internal class for keeping the first pointer of object.
Definizione Link dentro la griglia. Classe di supporto per UGrid.
*/
class Link
{
public:
/// Costruttore di default
inline Link(){};
/// Costruttore con inizializzatori
inline Link( ContainerType::iterator const nt, const int ni ){
assert(ni>=0);
t = nt;
i = ni;
};
inline bool operator < ( const Link & l ) const{ return i < l.i; }
inline bool operator <= ( const Link & l ) const{ return i <= l.i; }
inline bool operator > ( const Link & l ) const{ return i > l.i; }
inline bool operator >= ( const Link & l ) const{ return i >= l.i; }
inline bool operator == ( const Link & l ) const{ return i == l.i; }
inline bool operator != ( const Link & l ) const{ return i != l.i; }
inline ContainerType::iterator & Elem() {
return t;
}
inline int & Index() {
return i;
}
private:
/// Puntatore all'elemento T
ContainerType::iterator t;
/// Indirizzo del voxel dentro la griglia
int i;
};//end class Link
typedef ContainerType::value_type ObjType;
typedef ObjType::ScalarType ScalarType;
typedef Point3<ScalarType> Point3x;
typedef Box3<ScalarType> Box3x;
typedef Line3<ScalarType> Line3x;
Box3x bbox;
Point3x dim; /// Dimensione spaziale (lunghezza lati) del bbox
Point3i siz; /// Dimensioni griglia in celle
Point3x voxel; /// Dimensioni di una cella
/// Insieme di tutti i links
vector<Link> links;
/// Griglia vera e propria
vector<Link *> grid;
/// Dato un punto, ritorna la cella che lo contiene
inline Link ** Grid( const Point3d & p )
{
int x = int( (p[0]-bbox.min[0])/voxel[0] );
int y = int( (p[1]-bbox.min[1])/voxel[1] );
int z = int( (p[2]-bbox.min[2])/voxel[2] );
#ifndef NDEBUG
if ( x<0 || x>=siz[0] || y<0 || y>=siz[1] || z<0 || z>=siz[2] )
return NULL;
else
#endif
return grid.begin() + ( x+siz[0]*(y+siz[1]*z) );
}
/// Date le coordinate ritorna la cella
inline Link ** Grid( const int x, const int y, const int z )
{
#ifndef NDEBUG
if ( x<0 || x>=siz[0] || y<0 || y>=siz[1] || z<0 || z>=siz[2] )
assert(0);
//return NULL;
else
#endif
assert(x+siz[0]*(y+siz[1]*z<grid.size()));
return &*grid.begin() + ( x+siz[0]*(y+siz[1]*z) );
}
void Grid( const Point3d & p, Link * & first, Link * & last )
{
Link ** g = Grid(s);
first = *g;
last = *(g+1);
}
void Grid( const int x, const int y, const int z, Link * & first, Link * & last )
{
Link ** g = Grid(x,y,z);
first = *g;
last = *(g+1);
}
/// Setta il bounding box della griglia
void SetBBox( const Box3x & b )
{
bbox = b;
dim = b.max - b.min;
}
void SetSafeBBox( const Box3x & b )
{
Box3x btmp=b;
btmp.InflateFix(0.01);
bbox = btmp;
dim = bbox.max - bbox.min;
}
/// Dato un punto 3d ritorna l'indice del box corrispondente
inline void PToIP(const Point3x & p, Point3i &pi ) const
{
Point3x t = p - bbox.min;
pi[0] = int( t[0]/voxel[0] );
pi[1] = int( t[1]/voxel[1] );
pi[2] = int( t[2]/voxel[2] );
}
/// Dato un box reale ritorna gli indici dei voxel compresi dentro un ibox
void BoxToIBox( const Box3x & b, Box3i & ib ) const
{
PToIP(b.min,ib.min);
PToIP(b.max,ib.max);
}
#ifdef MONITOR_GRID
void ShowRayCastingStats() {
if (n_rays>0) {
printf("\n%d rays (%f faces in %f voxel per ray)\n",
n_rays,
double(n_traversed_elem)/n_rays,
double(n_traversed_voxel)/n_rays);
printf("HIT: %d rays (%d%%) (%f faces in %f voxel per ray)\n",
n_rays_hit,
(n_rays_hit*100)/n_rays,
double(n_traversed_elem_hit)/n_rays_hit,
double(n_traversed_voxel_hit)/n_rays_hit);
}
}
#endif
void ShowStats(FILE *fp)
{
// Conto le entry
int nentry = 0;
Hist H;
H.SetRange(0,1000,1000);
int pg;
for(pg=0;pg<grid.size()-1;++pg)
if( grid[pg]!=grid[pg+1] )
{
++nentry;
H.Add(grid[pg+1]-grid[pg]);
}
fprintf(fp,"Uniform Grid: %d x %d x %d (%d voxels), %.1f%% full, %d links \nNon empty Cell Occupancy Distribution Avg: %f (%4.0f %4.0f %4.0f) \n",
siz[0],siz[1],siz[2],grid.size()-1,
double(nentry)*100.0/(grid.size()-1),links.size(),H.Avg(),H.Percentile(.25),H.Percentile(.5),H.Percentile(.75)
);
}
void SlicedPPM( const char * filename )
{
xstring basename=filename;
xstring name;
int ix,iy,iz;
for(iz=0;iz<siz[2];++iz)
{
name.format("%s%03i.ppm",filename,iz);
FILE * fp = fopen(name,"wb");
fprintf(fp,
"P6\n"
"%d %d\n"
"255\n"
,siz[0]
,siz[1]
);
for(ix=0;ix<siz[0];++ix)
{
for(iy=0;iy<siz[1];++iy)
{
Link ** ii= Grid(ix,iy,iz);
if( *ii != *(ii+1) )
{
unsigned char c = 255;
fwrite(&c,1,1,fp);
fwrite(&c,1,1,fp);
fwrite(&c,1,1,fp);
}
else
{
unsigned char c = 0;
fwrite(&c,1,1,fp);
fwrite(&c,1,1,fp);
fwrite(&c,1,1,fp);
}
}
}
fclose(fp);
}
}
void PPM( const char * filename )
{
int ix,iy,iz;
FILE * fp = fopen(filename,"wb");
fprintf(fp,
"P6\n"
"%d %d\n"
"255\n"
,(siz[1]+1)*siz[0]
,siz[2]
);
for(iz=0;iz<siz[2];++iz)
for(ix=0;ix<siz[0];++ix)
{
for(iy=0;iy<siz[1];++iy)
{
int i = ix+siz[0]*(iy+siz[1]*iz);
if( grid[i]!=grid[i+1] )
{
unsigned char c = 255;
fwrite(&c,1,1,fp);
fwrite(&c,1,1,fp);
fwrite(&c,1,1,fp);
}
else
{
unsigned char c = 0;
fwrite(&c,1,1,fp);
fwrite(&c,1,1,fp);
fwrite(&c,1,1,fp);
}
}
{
unsigned char c = 0;
fwrite(&c,1,1,fp);
fwrite(&c,1,1,fp);
c = 255;
fwrite(&c,1,1,fp);
}
}
fclose(fp);
}
/** Returns the closest posistion of a point p and its distance
@param p a 3d point
@return The closest element
*/
T * GetClosest( const Point3x & p, ScalarType & min_dist, Point3x & res)
{
ScalarType dx = ( (p[0]-bbox.min[0])/voxel[0] );
ScalarType dy = ( (p[1]-bbox.min[1])/voxel[1] );
ScalarType dz = ( (p[2]-bbox.min[2])/voxel[2] );
int ix = int( dx );
int iy = int( dy );
int iz = int( dz );
double voxel_min=voxel[0];
if (voxel_min<voxel[1]) voxel_min=voxel[1];
if (voxel_min<voxel[2]) voxel_min=voxel[2];
ScalarType radius=(dx-ScalarType(ix));
if (radius>0.5) radius=(1.0-radius); radius*=voxel[0];
/*ScalarType radio_if[6];
radio_if[0]= (dx-double(ix) )*voxel[0] ;
radio_if[1]= (dy-double(iy) )*voxel[1] ;
radio_if[2]= (dz-double(iz) )*voxel[2] ;
radio_if[3]= (1.0+double(ix)-dx)*voxel[0] ;
radio_if[4]= (1.0+double(iy)-dy)*voxel[1] ;
radio_if[5]= (1.0+double(iz)-dz)*voxel[2] ;*/
ScalarType
tmp=dy-ScalarType(iy); if (tmp>0.5) tmp=1.0-tmp; tmp*=voxel[1]; if (radius>tmp) radius=tmp;
tmp=dz-ScalarType(iz); if (tmp>0.5) tmp=1.0-tmp; tmp*=voxel[2]; if (radius>tmp) radius=tmp;
Point3x t_res;
//ScalarType min_dist=1e10;
T* winner=NULL;
Link *first, *last, *l;
if ((ix>=0) && (iy>=0) && (iz>=0) && (ix<siz[0]) && (iy<siz[1]) && (iz<siz[2])) {
Grid( ix, iy, iz, first, last );
for(l=first;l!=last;++l)
{
if (l->Elem()->Dist(p,min_dist,t_res)) {
winner=&*(l->Elem());
res=t_res;
}
};
};
//return winner;
Point3i done_min=Point3i(ix,iy,iz), done_max=Point3i(ix,iy,iz);
//printf(".");
while (min_dist>radius) {
//if (dy-ScalarType(iy))
done_min[0]--; if (done_min[0]<0) done_min[0]=0;
done_min[1]--; if (done_min[1]<0) done_min[1]=0;
done_min[2]--; if (done_min[2]<0) done_min[2]=0;
done_max[0]++; if (done_max[0]>=siz[0]-1) done_max[0]=siz[0]-1;
done_max[1]++; if (done_max[1]>=siz[1]-1) done_max[1]=siz[1]-1;
done_max[2]++; if (done_max[2]>=siz[2]-1) done_max[2]=siz[2]-1;
radius+=voxel_min;
//printf("+");
for (ix=done_min[0]; ix<=done_max[0]; ix++)
for (iy=done_min[1]; iy<=done_max[1]; iy++)
for (iz=done_min[2]; iz<=done_max[2]; iz++)
{
Grid( ix, iy, iz, first, last );
for(l=first;l!=last;++l)
{
if (l->Elem()->Dist(p,min_dist,t_res)) {
winner=&*(l->Elem());
res=t_res;
};
};
}
};
return winner;
};
T * DoRay( Line3x & ray, double & dist , double &p_a, double &p_b)
{
int ix,iy,iz;
double gx,gy,gz;
if(!bbox.IsIn(ray.orig))
{
//printf(".");
Point3x ip;
if(Intersection(bbox,ray,ip))
{
ix = int( (ip.x() - bbox.min.x())/voxel.x() );
iy = int( (ip.y() - bbox.min.y())/voxel.y() );
iz = int( (ip.z() - bbox.min.z())/voxel.z() );
if(ix<0) ix = 0;
if(iy<0) iy = 0;
if(iz<0) iz = 0;
if(ix>=siz[0]) ix = siz[0]-1;
if(iy>=siz[1]) iy = siz[1]-1;
if(iz>=siz[2]) iz = siz[2]-1;
}
else
return 0;
}
else
{
/* Indici di voxel */
ix = int( (ray.orig.x() - bbox.min.x())/voxel.x() );
iy = int( (ray.orig.y() - bbox.min.y())/voxel.y() );
iz = int( (ray.orig.z() - bbox.min.z())/voxel.z() );
}
/* Punti goal */
if(ray.dire.x()>0.0) gx=double(ix+1)*voxel.x()+bbox.min.x();
else gx=double(ix )*voxel.x()+bbox.min.x();
if(ray.dire.y()>0.0) gy=double(iy+1)*voxel.y()+bbox.min.y();
else gy=double(iy )*voxel.y()+bbox.min.y();
if(ray.dire.z()>0.0) gz=double(iz+1)*voxel.z()+bbox.min.z();
else gz=double( iz )*voxel.z()+bbox.min.z();
const ScalarType MAXFLOAT = 1e50;
const ScalarType EPSILON = 1e-50;
/* Parametri della linea */
double tx,ty,tz;
if( fabs(ray.dire.x())>EPSILON ) tx = (gx-ray.orig.x())/ray.dire.x();
else tx = MAXFLOAT;
if( fabs(ray.dire.y())>EPSILON ) ty = (gy-ray.orig.y())/ray.dire.y();
else ty = MAXFLOAT;
if( fabs(ray.dire.z())>EPSILON ) tz = (gz-ray.orig.z())/ray.dire.z();
else tz = MAXFLOAT;
T * bestf = NULL;
#ifdef MONITOR_GRID
int n_traversed_voxel0=0,n_traversed_elem0=0;
n_rays++;
#endif
for(;;)
{
Link *first, *last, *l;
Grid( ix, iy, iz, first, last );
#ifdef MONITOR_GRID
n_traversed_voxel++;n_traversed_voxel0++;
#endif
for(l=first;l!=last;++l)
{
#ifdef MONITOR_GRID
n_traversed_elem++;n_traversed_elem0++;
#endif
//return &(*(l->Elem()));
if(l->Elem()->Intersect(ray,dist, p_a, p_b)) {
#ifdef MONITOR_GRID
n_traversed_voxel_hit+=n_traversed_voxel0;
n_traversed_elem_hit+=n_traversed_elem0;
n_rays_hit++;
#endif
return &(*(l->Elem()));
//{
// bestf = &(*(l->Elem())); break;
//}
}
//if(bestf) break;
}
if( tx<ty && tx<tz ){
if(ray.dire.x()<0.0) { gx -= voxel.x(); --ix; if(ix<0 ) break; }
else { gx += voxel.x(); ++ix; if(ix>=siz[0]) break; }
tx = (gx-ray.orig.x())/ray.dire.x();
} else if( ty<tz ){
if(ray.dire.y()<0.0) { gy -= voxel.y(); --iy; if(iy<0 ) break; }
else { gy += voxel.y(); ++iy; if(iy>=siz[1]) break; }
ty = (gy-ray.orig.y())/ray.dire.y();
} else {
if(ray.dire.z()<0.0) { gz -= voxel.z(); --iz; if(iz<0 ) break; }
else { gz += voxel.z(); ++iz; if(iz>=siz[2]) break; }
tz = (gz-ray.orig.z())/ray.dire.z();
}
}
return bestf;
}
/// Inserisce una mesh nella griglia. Nota: prima bisogna
/// chiamare SetBBox che setta dim in maniera corretta
void Set( S & s )
{
Set(s,s.size());
}
/// Inserisce una mesh nella griglia. Nota: prima bisogna
/// chiamare SetBBox che setta dim in maniera corretta
void Set( S & s,int _size )
{
Point3i _siz;
BestDim( _size, dim, _siz );
Set(s,_siz);
}
void Set(S & s, Point3i _siz)
{
siz=_siz;
// Calcola la dimensione della griglia
voxel[0] = dim[0]/siz[0];
voxel[1] = dim[1]/siz[1];
voxel[2] = dim[2]/siz[2];
// "Alloca" la griglia: +1 per la sentinella
grid.resize( siz[0]*siz[1]*siz[2]+1 );
// Ciclo inserimento dei tetraedri: creazione link
links.clear();
S::iterator pt;
for(pt=s.begin(); pt!=s.end(); ++pt)
{
Box3x bb; // Boundig box del tetraedro corrente
(*pt).GetBBox(bb);
bb.Intersect(bbox);
if(! bb.IsNull() )
{
Box3i ib; // Boundig box in voxels
BoxToIBox( bb,ib );
/*ib.min-=Point3i(1,1,1);
ib.max+=Point3i(1,1,1);
if (ib.min[0]<0) ib.min[0]=0;
if (ib.min[1]<0) ib.min[1]=0;
if (ib.min[2]<0) ib.min[2]=0;
if (ib.max[0]>siz[0]) ib.max[0]=siz[0];
if (ib.max[1]>siz[1]) ib.max[1]=siz[1];
if (ib.max[2]>siz[2]) ib.max[2]=siz[2];*/
int x,y,z;
for(z=ib.min[2];z<=ib.max[2];++z)
{
int bz = z*siz[1];
for(y=ib.min[1];y<=ib.max[1];++y)
{
int by = (y+bz)*siz[0];
for(x=ib.min[0];x<=ib.max[0];++x)
// Inserire calcolo cella corrente
// if( pt->Intersect( ... )
links.push_back( Link(pt,by+x) );
}
}
}
}
// Push della sentinella
links.push_back( Link(NULL,grid.size()-1) );
// Ordinamento dei links
sort( links.begin(), links.end() );
// Creazione puntatori ai links
vector<Link>::iterator pl;
int pg;
pl = links.begin();
for(pg=0;pg<grid.size();++pg)
{
assert(pl!=links.end());
grid[pg] = &*pl;
while( pg == pl->Index() ) // Trovato inizio
{
++pl; // Ricerca prossimo blocco
if(pl==links.end())
break;
}
}
}
/** Calcolo dimensioni griglia.
Calcola la dimensione della griglia in funzione
della ratio del bounding box e del numero di elementi
*/
static void BestDim( const int elems, const Point3x & size, Point3i & dim )
{
const int mincells = 27; // Numero minimo di celle
const double GFactor = 1.0; // GridEntry = NumElem*GFactor
double diag = size.Norm(); // Diagonale del box
double eps = diag*1e-4; // Fattore di tolleranza
assert(elems>0);
assert(size[0]>=0.0);
assert(size[1]>=0.0);
assert(size[2]>=0.0);
int ncell = int(elems*GFactor); // Calcolo numero di voxel
if(ncell<mincells)
ncell = mincells;
dim[0] = 1;
dim[1] = 1;
dim[2] = 1;
if(size[0]>eps)
{
if(size[1]>eps)
{
if(size[2]>eps)
{
double k = pow(ncell/(size[0]*size[1]*size[2]),1.0/3.0);
dim[0] = int(size[0] * k);
dim[1] = int(size[1] * k);
dim[2] = int(size[2] * k);
}
else
{
dim[0] = int(::sqrt(ncell*size[0]/size[1]));
dim[1] = int(::sqrt(ncell*size[1]/size[0]));
}
}
else
{
if(size[2]>eps)
{
dim[0] = int(::sqrt(ncell*size[0]/size[2]));
dim[2] = int(::sqrt(ncell*size[2]/size[0]));
}
else
dim[0] = int(ncell);
}
}
else
{
if(size[1]>eps)
{
if(size[2]>eps)
{
dim[1] = int(::sqrt(ncell*size[1]/size[2]));
dim[2] = int(::sqrt(ncell*size[2]/size[1]));
}
else
dim[1] = int(ncell);
}
else if(size[2]>eps)
dim[2] = int(ncell);
}
}
int MemUsed()
{
return sizeof(UGrid)+ sizeof(Link)*links.size() + sizeof(Link *) * grid.size();
}
}; //end class UGrid
} // end namespace
#endif

View File

@ -0,0 +1,564 @@
/****************************************************************************
* 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.1 2004/03/03 15:00:51 cignoni
Initial commit
****************************************************************************/
/**
@name Load and Save in Ply format
*/
//@{
#ifndef __VCGLIB_EXPORT_PLY
#define __VCGLIB_EXPORT_PLY
#include<wrap/io_trimesh/io_mask.h>
#include<wrap/io_trimesh/io_ply.h>
#include <stdio.h>
namespace vcg {
namespace tri {
namespace io {
template <class SaveMeshType>
class ExporterPLY
{
public:
typedef ::vcg::ply::PropDescriptor PropDescriptor ;
typedef typename SaveMeshType::VertexPointer VertexPointer;
typedef typename SaveMeshType::ScalarType ScalarType;
typedef typename SaveMeshType::VertexType VertexType;
typedef typename SaveMeshType::FaceType FaceType;
typedef typename SaveMeshType::VertexIterator VertexIterator;
typedef typename SaveMeshType::FaceIterator FaceIterator;
static bool Save(SaveMeshType &m, const char * filename, bool binary=true)
{
PlyInfo pi;
return SavePly(m,filename,binary,pi);
}
static bool SavePly(SaveMeshType &m, const char * filename, int savemask )
{
PlyInfo pi;
pi.mask=savemask;
return SavePly(m,filename,true,pi);
}
static bool SavePly(SaveMeshType &m, const char * filename, bool binary, PlyInfo &pi ) // V1.0
{
FILE * fpout;
int i;
const char * hbin = "binary_little_endian";
const char * hasc = "ascii";
const char * h;
bool multit = false;
if(binary) h=hbin;
else h=hasc;
fpout = fopen(filename,"wb");
if(fpout==NULL) {
pi.status=::vcg::ply::E_CANTOPEN;
return false;
}
fprintf(fpout,
"ply\n"
"format %s 1.0\n"
"comment VCGLIB generated\n"
,h
);
if( pi.mask & PLYMask::PM_WEDGTEXCOORD )
{
//const char * TFILE = "TextureFile";
//for(i=0;i<textures.size();++i)
// fprintf(fpout,"comment %s %s\n", TFILE, (const char *)(textures[i]) );
//if(textures.size()>1 && (HasPerWedgeTexture() || HasPerVertexTexture())) multit = true;
}
//if( (pi.mask & PLYMask::PM_CAMERA) && camera.IsValid() )
/*{
fprintf(fpout,
"element camera 1\n"
"property float view_px\n"
"property float view_py\n"
"property float view_pz\n"
"property float x_axisx\n"
"property float x_axisy\n"
"property float x_axisz\n"
"property float y_axisx\n"
"property float y_axisy\n"
"property float y_axisz\n"
"property float z_axisx\n"
"property float z_axisy\n"
"property float z_axisz\n"
"property float focal\n"
"property float scalex\n"
"property float scaley\n"
"property float centerx\n"
"property float centery\n"
"property int viewportx\n"
"property int viewporty\n"
"property float k1\n"
"property float k2\n"
"property float k3\n"
"property float k4\n"
);
}*/
fprintf(fpout,
"element vertex %d\n"
"property float x\n"
"property float y\n"
"property float z\n"
,m.vn
);
if( pi.mask & PLYMask::PM_VERTFLAGS )
{
fprintf(fpout,
"property int flags\n"
);
}
if( HasPerVertexColor() && (pi.mask & PLYMask::PM_VERTCOLOR) )
{
fprintf(fpout,
"property uchar red\n"
"property uchar green\n"
"property uchar blue\n"
"property uchar alpha\n"
);
}
if( HasPerVertexQuality() && (pi.mask & PLYMask::PM_VERTQUALITY) )
{
fprintf(fpout,
"property float quality\n"
);
}
for(i=0;i<pi.vdn;i++)
fprintf(fpout,"property %s %s\n",pi.VertexData[i].stotypename(),pi.VertexData[i].propname);
fprintf(fpout,
"element face %d\n"
"property list uchar int vertex_indices\n"
,m.fn
);
if( pi.mask & PLYMask::PM_FACEFLAGS )
{
fprintf(fpout,
"property int flags\n"
);
}
if( ( (vertex_type::OBJ_TYPE & vertex_type::OBJ_TYPE_T ) && (pi.mask & PLYMask::PM_VERTTEXCOORD) ) ||
( (face_type:: OBJ_TYPE & face_type:: OBJ_TYPE_WT) && (pi.mask & PLYMask::PM_WEDGTEXCOORD) ) )
{
fprintf(fpout,
"property list uchar float texcoord\n"
);
if(multit)
fprintf(fpout,
"property int texnumber\n"
);
}
if( HasPerFaceColor() && (pi.mask & PLYMask::PM_FACECOLOR) )
{
fprintf(fpout,
"property uchar red\n"
"property uchar green\n"
"property uchar blue\n"
"property uchar alpha\n"
);
}
if ( HasPerWedgeColor() && (pi.mask & PLYMask::PM_WEDGCOLOR) )
{
fprintf(fpout,
"property list uchar float color\n"
);
}
if( HasPerFaceQuality() && (pi.mask & PLYMask::PM_FACEQUALITY) )
{
fprintf(fpout,
"property float quality\n"
);
}
for(i=0;i<pi.fdn;i++)
fprintf(fpout,"property %s %s\n",pi.FaceData[i].stotypename(),pi.FaceData[i].propname);
fprintf(fpout, "end_header\n" );
// Salvataggio camera
if( (pi.mask & PLYMask::PM_CAMERA) && camera.IsValid() )
{
//if(binary)
//{
// float t[17];
// t[ 0] = camera.view_p[0];
// t[ 1] = camera.view_p[1];
// t[ 2] = camera.view_p[2];
// t[ 3] = camera.x_axis[0];
// t[ 4] = camera.x_axis[1];
// t[ 5] = camera.x_axis[2];
// t[ 6] = camera.y_axis[0];
// t[ 7] = camera.y_axis[1];
// t[ 8] = camera.y_axis[2];
// t[ 9] = camera.z_axis[0];
// t[10] = camera.z_axis[1];
// t[11] = camera.z_axis[2];
// t[12] = camera.f;
// t[13] = camera.s[0];
// t[14] = camera.s[1];
// t[15] = camera.c[0];
// t[16] = camera.c[1];
// fwrite(t,sizeof(float),17,fpout);
// fwrite( camera.viewport,sizeof(int),2,fpout );
// t[ 0] = camera.k[0];
// t[ 1] = camera.k[1];
// t[ 2] = camera.k[2];
// t[ 3] = camera.k[3];
// fwrite(t,sizeof(float),4,fpout);
//}
//else
//{
// fprintf(fpout,"%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %d %d %g %g %g %g\n"
// ,camera.view_p[0]
// ,camera.view_p[1]
// ,camera.view_p[2]
// ,camera.x_axis[0]
// ,camera.x_axis[1]
// ,camera.x_axis[2]
// ,camera.y_axis[0]
// ,camera.y_axis[1]
// ,camera.y_axis[2]
// ,camera.z_axis[0]
// ,camera.z_axis[1]
// ,camera.z_axis[2]
// ,camera.f
// ,camera.s[0]
// ,camera.s[1]
// ,camera.c[0]
// ,camera.c[1]
// ,camera.viewport[0]
// ,camera.viewport[1]
// ,camera.k[0]
// ,camera.k[1]
// ,camera.k[2]
// ,camera.k[3]
// );
//}
}
int j;
vector<int> FlagV;
MVTYPE * vp;
vertex_iterator vi;
for(j=0,vi=m.vert.begin();vi!=m.vert.end();++vi)
{
vp=&(*vi);
FlagV.push_back(vp->Supervisor_Flags()); // Salva in ogni caso flag del vertice
if( ! vp->IsDeleted() )
{
if(binary)
{
float t;
t = float(vp->Supervisor_P()[0]); fwrite(&t,sizeof(float),1,fpout);
t = float(vp->Supervisor_P()[1]); fwrite(&t,sizeof(float),1,fpout);
t = float(vp->Supervisor_P()[2]); fwrite(&t,sizeof(float),1,fpout);
if( pi.mask & PLYMask::PM_VERTFLAGS )
fwrite(&(vp->Supervisor_Flags()),sizeof(int),1,fpout);
if( HasPerVertexColor() && (pi.mask & PLYMask::PM_VERTCOLOR) )
fwrite(&( vp->C() ),sizeof(char),4,fpout);
if( HasPerVertexQuality() && (pi.mask & PLYMask::PM_VERTQUALITY) )
fwrite(&( vp->Q() ),sizeof(float),1,fpout);
for(i=0;i<vdn;i++)
{
double td; float tf;int ti;short ts; char tc; unsigned char tuc;
switch (VertexData[i].stotype1)
{
case T_FLOAT : PlyConv(VertexData[i].memtype1, ((char *)vp)+VertexData[i].offset1, tf ); fwrite(&tf, sizeof(float),1,fpout); break;
case T_DOUBLE : PlyConv(VertexData[i].memtype1, ((char *)vp)+VertexData[i].offset1, td ); fwrite(&td, sizeof(double),1,fpout); break;
case T_INT : PlyConv(VertexData[i].memtype1, ((char *)vp)+VertexData[i].offset1, ti ); fwrite(&ti, sizeof(int),1,fpout); break;
case T_SHORT : PlyConv(VertexData[i].memtype1, ((char *)vp)+VertexData[i].offset1, ts ); fwrite(&ts, sizeof(short),1,fpout); break;
case T_CHAR : PlyConv(VertexData[i].memtype1, ((char *)vp)+VertexData[i].offset1, tc ); fwrite(&tc, sizeof(char),1,fpout); break;
case T_UCHAR : PlyConv(VertexData[i].memtype1, ((char *)vp)+VertexData[i].offset1, tuc); fwrite(&tuc,sizeof(unsigned char),1,fpout); break;
default : assert(0);
}
}
}
else // ***** ASCII *****
{
fprintf(fpout,"%g %g %g " ,vp->P()[0],vp->P()[1],vp->P()[2]);
if( pi.mask & PLYMask::PM_VERTFLAGS )
fprintf(fpout,"%d ",vp->Supervisor_Flags());
if( (vertex_type::OBJ_TYPE & vertex_type::OBJ_TYPE_C) && (pi.mask & PLYMask::PM_VERTCOLOR) )
fprintf(fpout,"%d %d %d %d ",vp->C()[0],vp->C()[1],vp->C()[2],vp->C()[3] );
if( (vertex_type::OBJ_TYPE & vertex_type::OBJ_TYPE_Q) && (pi.mask & PLYMask::PM_VERTQUALITY) )
fprintf(fpout,"%g ",vp->Q());
for(i=0;i<vdn;i++)
{
float tf;
int ti;
switch (VertexData[i].memtype1)
{
case T_FLOAT : tf=*( (float *) (((char *)vp)+VertexData[i].offset1)); fprintf(fpout,"%g ",tf); break;
case T_DOUBLE : tf=*( (double *) (((char *)vp)+VertexData[i].offset1)); fprintf(fpout,"%g ",tf); break;
case T_INT : ti=*( (int *) (((char *)vp)+VertexData[i].offset1)); fprintf(fpout,"%i ",ti); break;
case T_SHORT : ti=*( (short *) (((char *)vp)+VertexData[i].offset1)); fprintf(fpout,"%i ",ti); break;
case T_CHAR : ti=*( (char *) (((char *)vp)+VertexData[i].offset1)); fprintf(fpout,"%i ",ti); break;
case T_UCHAR : ti=*( (unsigned char *) (((char *)vp)+VertexData[i].offset1)); fprintf(fpout,"%i ",ti); break;
default : assert(0);
}
}
fprintf(fpout,"\n");
}
vp->Supervisor_Flags()=j; // Trucco! Nascondi nei flags l'indice del vertice non deletato!
j++;
}
}
assert(j==vn);
char c = 3;
char k = 9;
unsigned char b9 = 9;
unsigned char b6 = 6;
const MFTYPE * fp;
int vv[3];
face_iterator fi;
int fcnt=0;
for(j=0,fi=face.begin();fi!=face.end();++fi)
{
fp=&(*fi);
if( ! fp->IsDeleted() )
{ fcnt++;
if(binary)
{
vv[0]=fp->cV(0)->Supervisor_Flags();
vv[1]=fp->cV(1)->Supervisor_Flags();
vv[2]=fp->cV(2)->Supervisor_Flags();
fwrite(&c,1,1,fpout);
fwrite(vv,sizeof(int),3,fpout);
if( pi.mask & PLYMask::PM_FACEFLAGS )
fwrite(&(fp->Flags()),sizeof(int),1,fpout);
if( (vertex_type::OBJ_TYPE & vertex_type::OBJ_TYPE_T) && (pi.mask & PLYMask::PM_VERTTEXCOORD) )
{
fwrite(&b6,sizeof(char),1,fpout);
float t[6];
for(int k=0;k<3;++k)
{
t[k*2+0] = fp->V(k)->T().u();
t[k*2+1] = fp->V(k)->T().v();
}
fwrite(t,sizeof(float),6,fpout);
}
else if( (face_type:: OBJ_TYPE & face_type:: OBJ_TYPE_WT) && (pi.mask & PLYMask::PM_WEDGTEXCOORD) )
{
fwrite(&b6,sizeof(char),1,fpout);
float t[6];
for(int k=0;k<3;++k)
{
t[k*2+0] = fp->WT(k).u();
t[k*2+1] = fp->WT(k).v();
}
fwrite(t,sizeof(float),6,fpout);
}
if(multit)
{
int t = fp->WT(0).n();
fwrite(&t,sizeof(int),1,fpout);
}
if( HasPerFaceColor() && (pi.mask & PLYMask::PM_FACECOLOR) )
fwrite(&( fp->C() ),sizeof(char),4,fpout);
if( HasPerWedgeColor() && (pi.mask & PLYMask::PM_WEDGCOLOR) )
{
fwrite(&b9,sizeof(char),1,fpout);
float t[3];
for(int z=0;z<3;++z)
{
t[0] = float(fp->WC(z)[0])/255;
t[1] = float(fp->WC(z)[1])/255;
t[2] = float(fp->WC(z)[2])/255;
fwrite( t,sizeof(float),3,fpout);
}
}
if( (face_type::OBJ_TYPE & face_type::OBJ_TYPE_Q) && (pi.mask & PLYMask::PM_FACEQUALITY) )
fwrite( &(fp->Q()),sizeof(float),1,fpout);
for(i=0;i<fdn;i++)
{
double td; float tf;int ti;short ts; char tc; unsigned char tuc;
switch (FaceData[i].stotype1){
case T_FLOAT : PlyConv(FaceData[i].memtype1, ((char *)fp)+FaceData[i].offset1, tf ); fwrite(&tf, sizeof(float),1,fpout); break;
case T_DOUBLE : PlyConv(FaceData[i].memtype1, ((char *)fp)+FaceData[i].offset1, td ); fwrite(&td, sizeof(double),1,fpout); break;
case T_INT : PlyConv(FaceData[i].memtype1, ((char *)fp)+FaceData[i].offset1, ti ); fwrite(&ti, sizeof(int),1,fpout); break;
case T_SHORT : PlyConv(FaceData[i].memtype1, ((char *)fp)+FaceData[i].offset1, ts ); fwrite(&ts, sizeof(short),1,fpout); break;
case T_CHAR : PlyConv(FaceData[i].memtype1, ((char *)fp)+FaceData[i].offset1, tc ); fwrite(&tc, sizeof(char),1,fpout); break;
case T_UCHAR : PlyConv(FaceData[i].memtype1, ((char *)fp)+FaceData[i].offset1, tuc); fwrite(&tuc,sizeof(unsigned char),1,fpout); break;
default : assert(0);
}
}
}
else // ***** ASCII *****
{
fprintf(fpout,"3 %d %d %d ",
fp->cV(0)->Supervisor_Flags(), fp->cV(1)->Supervisor_Flags(), fp->cV(2)->Supervisor_Flags() );
if( pi.mask & PLYMask::PM_FACEFLAGS )
fprintf(fpout,"%d ",fp->Flags());
if( (vertex_type::OBJ_TYPE & vertex_type::OBJ_TYPE_T) && (pi.mask & PLYMask::PM_VERTTEXCOORD) )
{
fprintf(fpout,"6 ");
for(int k=0;k<3;++k)
fprintf(fpout,"%g %g "
,fp->V(k)->T().u()
,fp->V(k)->T().v()
);
}
else if( (face_type:: OBJ_TYPE & face_type:: OBJ_TYPE_WT) && (pi.mask & PLYMask::PM_WEDGTEXCOORD) )
{
fprintf(fpout,"6 ");
for(int k=0;k<3;++k)
fprintf(fpout,"%g %g "
,fp->WT(k).u()
,fp->WT(k).v()
);
}
if(multit)
{
fprintf(fpout,"%d ",fp->WT(0).n());
}
if( (face_type::OBJ_TYPE & face_type::OBJ_TYPE_C) && (pi.mask & PLYMask::PM_FACECOLOR) )
{
float t[3];
t[0] = float(fp->C()[0])/255;
t[1] = float(fp->C()[1])/255;
t[2] = float(fp->C()[2])/255;
fprintf(fpout,"9 ");
fprintf(fpout,"%g %g %g ",t[0],t[1],t[2]);
fprintf(fpout,"%g %g %g ",t[0],t[1],t[2]);
fprintf(fpout,"%g %g %g ",t[0],t[1],t[2]);
}
else if( (face_type::OBJ_TYPE & face_type::OBJ_TYPE_WC) && (pi.mask & PLYMask::PM_WEDGCOLOR) )
{
fprintf(fpout,"9 ");
for(int z=0;z<3;++z)
fprintf(fpout,"%g %g %g "
,double(fp->WC(z)[0])/255
,double(fp->WC(z)[1])/255
,double(fp->WC(z)[2])/255
);
}
if( (face_type::OBJ_TYPE & face_type::OBJ_TYPE_Q) && (pi.mask & PLYMask::PM_FACEQUALITY) )
fprintf(fpout,"%g ",fp->Q());
for(i=0;i<fdn;i++)
{
float tf;
int ti;
switch (FaceData[i].memtype1)
{
case T_FLOAT : tf=*( (float *) (((char *)fp)+FaceData[i].offset1)); fprintf(fpout,"%g ",tf); break;
case T_DOUBLE : tf=*( (double *) (((char *)fp)+FaceData[i].offset1)); fprintf(fpout,"%g ",tf); break;
case T_INT : ti=*( (int *) (((char *)fp)+FaceData[i].offset1)); fprintf(fpout,"%i ",ti); break;
case T_SHORT : ti=*( (short *) (((char *)fp)+FaceData[i].offset1)); fprintf(fpout,"%i ",ti); break;
case T_CHAR : ti=*( (char *) (((char *)fp)+FaceData[i].offset1)); fprintf(fpout,"%i ",ti); break;
case T_UCHAR : ti=*( (unsigned char *) (((char *)fp)+FaceData[i].offset1)); fprintf(fpout,"%i ",ti); break;
default : assert(0);
}
}
fprintf(fpout,"\n");
}
}
}
assert(fcnt==fn);
fclose(fpout);
// Recupera i flag originali
for(j=0,vi=vert.begin();vi!=vert.end();++vi)
(*vi).Supervisor_Flags()=FlagV[j++];
return 0;
}
}; // end class
} // end namespace tri
} // end namespace io
} // end namespace vcg
#endif

104
wrap/io_trimesh/io_ply.h Normal file
View File

@ -0,0 +1,104 @@
/****************************************************************************
* 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.1 2004/03/03 15:00:51 cignoni
Initial commit
****************************************************************************/
#ifndef __VCGLIB_IOTRIMESH_IO_PLY
#define __VCGLIB_IOTRIMESH_IO_PLY
/**
@name Load and Save in Ply format
*/
//@{
#include<wrap/callback.h>
#include<wrap/ply/plylib.h>
namespace vcg {
namespace tri {
namespace io {
/** Additional data needed or useful for parsing a ply mesh.
This class can be passed to the ImporterPLY::Open() function for
- retrieving additional per-vertex per-face data
- specifying a callback for long ply parsing
- knowing what data is contained in a ply file
*/
class PlyInfo
{
public:
typedef ::vcg::ply::PropDescriptor PropDescriptor ;
PlyInfo()
{
status=0;
mask=0;
cb=0;
vdn=fdn=0;
VertexData=FaceData=0;
}
/// Store the error codes enconutered when parsing a ply
int status;
/// It returns a bit mask describing the field preesnt in the ply file
int mask;
/// a Simple callback that can be used for long ply parsing.
// it returns the current position, and formats a string with a description of what th efunction is doing (loading vertexes, faces...)
CallBackPos *cb;
/// the number of per-vertex descriptor (usually 0)
int vdn;
/// The additional vertex descriptor that a user can specify to load additional per-vertex non-standard data stored in a ply
PropDescriptor *VertexData;
/// the number of per-face descriptor (usually 0)
int fdn;
/// The additional vertex descriptor that a user can specify to load additional per-face non-standard data stored in a ply
PropDescriptor *FaceData;
/// a string containing the current ply header. Useful for showing it to the user.
std::string header;
enum Error
{
// Funzioni superiori
E_NO_VERTEX, // 14
E_NO_FACE, // 15
E_SHORTFILE, // 16
E_NO_3VERTINFACE, // 17
E_BAD_VERT_INDEX, // 18
E_NO_6TCOORD, // 19
E_DIFFER_COLORS, // 20
};
}; // end class
} // end namespace tri
} // end namespace io
} // end namespace vcg
#endif