Merge branch 'devel' of https://github.com/cnr-isti-vclab/vcglib into devel
This commit is contained in:
commit
58a9b0eefe
|
@ -19,3 +19,9 @@ release/
|
||||||
*.vcxproj
|
*.vcxproj
|
||||||
*.vcxproj.filters
|
*.vcxproj.filters
|
||||||
*.suo
|
*.suo
|
||||||
|
*.ply
|
||||||
|
wrap/nanoply/nanoply_vcg/nanoply_vcg.sln
|
||||||
|
*.db
|
||||||
|
wrap/nanoply/nanoply_vcg/nanoply_vcg.VC.VC.opendb
|
||||||
|
wrap/nanoply/nanoply_vcg/.vs/nanoply_vcg/v15/ipch/AutoPCH/NANOPLY_VCG-1b6b1a83/MAIN-5f62d91f/MAIN.ipch
|
||||||
|
*.sln
|
||||||
|
|
|
@ -296,15 +296,14 @@ int main(int argc, char**argv)
|
||||||
// save error files.
|
// save error files.
|
||||||
if(flags & SamplingFlags::SAVE_ERROR)
|
if(flags & SamplingFlags::SAVE_ERROR)
|
||||||
{
|
{
|
||||||
vcg::tri::io::PlyInfo p;
|
int saveMask = vcg::tri::io::Mask::IOM_VERTCOLOR | vcg::tri::io::Mask::IOM_VERTQUALITY /* | vcg::ply::PLYMask::PM_VERTQUALITY*/ ;
|
||||||
p.mask|=vcg::tri::io::Mask::IOM_VERTCOLOR | vcg::tri::io::Mask::IOM_VERTQUALITY /* | vcg::ply::PLYMask::PM_VERTQUALITY*/ ;
|
|
||||||
//p.mask|=vcg::ply::PLYMask::PM_VERTCOLOR|vcg::ply::PLYMask::PM_VERTQUALITY;
|
//p.mask|=vcg::ply::PLYMask::PM_VERTCOLOR|vcg::ply::PLYMask::PM_VERTQUALITY;
|
||||||
if(ColorMax!=0 || ColorMin != 0){
|
if(ColorMax!=0 || ColorMin != 0){
|
||||||
vcg::tri::UpdateColor<CMesh>::PerVertexQualityRamp(S1,ColorMin,ColorMax);
|
vcg::tri::UpdateColor<CMesh>::PerVertexQualityRamp(S1,ColorMin,ColorMax);
|
||||||
vcg::tri::UpdateColor<CMesh>::PerVertexQualityRamp(S2,ColorMin,ColorMax);
|
vcg::tri::UpdateColor<CMesh>::PerVertexQualityRamp(S2,ColorMin,ColorMax);
|
||||||
}
|
}
|
||||||
tri::io::ExporterPLY<CMesh>::Save( S1,S1NewName.c_str(),true,p);
|
tri::io::ExporterPLY<CMesh>::Save( S1,S1NewName.c_str(),saveMask);
|
||||||
tri::io::ExporterPLY<CMesh>::Save( S2,S2NewName.c_str(),true,p);
|
tri::io::ExporterPLY<CMesh>::Save( S2,S2NewName.c_str(),saveMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
// save error files.
|
// save error files.
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
TEMPLATE = subdirs
|
TEMPLATE = subdirs
|
||||||
SUBDIRS = trimesh_allocate \
|
SUBDIRS = trimesh_allocate \
|
||||||
trimesh_attribute \
|
trimesh_attribute \
|
||||||
|
trimesh_attribute_saving \
|
||||||
trimesh_ball_pivoting \
|
trimesh_ball_pivoting \
|
||||||
trimesh_base \
|
trimesh_base \
|
||||||
trimesh_closest \
|
trimesh_closest \
|
||||||
|
@ -37,6 +38,7 @@ SUBDIRS = trimesh_allocate \
|
||||||
trimesh_smooth \
|
trimesh_smooth \
|
||||||
trimesh_split_vertex \
|
trimesh_split_vertex \
|
||||||
trimesh_texture \
|
trimesh_texture \
|
||||||
|
trimesh_texture_clean \
|
||||||
trimesh_topology \
|
trimesh_topology \
|
||||||
trimesh_topological_cut \
|
trimesh_topological_cut \
|
||||||
trimesh_voronoi \
|
trimesh_voronoi \
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
include(../common.pri)
|
include(../common.pri)
|
||||||
TARGET = trimesh_attribute
|
TARGET = trimesh_attribute
|
||||||
SOURCES += trimesh_attribute.cpp ../../../wrap/ply/plylib.cpp
|
SOURCES += trimesh_attribute.cpp
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* VCGLib o o *
|
||||||
|
* Visual and Computer Graphics Library o o *
|
||||||
|
* _ O _ *
|
||||||
|
* Copyright(C) 2004-2016 \/)\/ *
|
||||||
|
* 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. *
|
||||||
|
* *
|
||||||
|
****************************************************************************/
|
||||||
|
/*! \file trimesh_attribute.cpp
|
||||||
|
\ingroup code_sample
|
||||||
|
|
||||||
|
\brief the minimal example of using the attributes
|
||||||
|
|
||||||
|
Attributes are a simple mechanism to associate user-defined 'attributes' to the simplicies and to the mesh.
|
||||||
|
See the page '\ref attributes' for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include<vcg/complex/complex.h>
|
||||||
|
#include<vcg/complex/algorithms/create/platonic.h>
|
||||||
|
#include<wrap/io_trimesh/export_ply.h>
|
||||||
|
class MyEdge;
|
||||||
|
class MyFace;
|
||||||
|
class MyVertex;
|
||||||
|
struct MyUsedTypes : public vcg::UsedTypes< vcg::Use<MyVertex>::AsVertexType,
|
||||||
|
vcg::Use<MyFace> ::AsFaceType>{};
|
||||||
|
|
||||||
|
class MyVertex : public vcg::Vertex< MyUsedTypes, vcg::vertex::Coord3f,vcg::vertex::Normal3f, vcg::vertex::BitFlags>{};
|
||||||
|
class MyFace : public vcg::Face< MyUsedTypes, vcg::face::VertexRef, vcg::face::Normal3f, vcg::face::BitFlags> {};
|
||||||
|
|
||||||
|
class MyMesh : public vcg::tri::TriMesh< std::vector<MyVertex>, std::vector<MyFace> > {};
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
MyMesh m;
|
||||||
|
Torus<MyMesh>(m, 3.0f, 1.0f);
|
||||||
|
//! [Adding a few attributes]
|
||||||
|
// add a per-vertex attribute with type float named "GaussianCurvature"
|
||||||
|
MyMesh::PerVertexAttributeHandle<float>
|
||||||
|
hvf = vcg::tri::Allocator<MyMesh>:: GetPerVertexAttribute<float> (m,std::string("GaussianCurvature"));
|
||||||
|
|
||||||
|
MyMesh::PerVertexAttributeHandle<vcg::Point3f>
|
||||||
|
hv3f = vcg::tri::Allocator<MyMesh>:: GetPerVertexAttribute<vcg::Point3f> (m,std::string("InvertedNormal"));
|
||||||
|
|
||||||
|
// add a per-face attribute with type float named "FaceArea"
|
||||||
|
MyMesh::PerFaceAttributeHandle<float>
|
||||||
|
hff = vcg::tri::Allocator<MyMesh>:: GetPerFaceAttribute<float> (m,std::string("FaceArea"));
|
||||||
|
//! [filling the attribute]
|
||||||
|
vcg::tri::Allocator<MyMesh>::ClearPerVertexAttribute<float>(m,hvf, float(M_PI*2));
|
||||||
|
vcg::tri::Allocator<MyMesh>::ClearPerVertexAttribute<vcg::Point3f>(m,hv3f, vcg::Point3f(0,0,0));
|
||||||
|
|
||||||
|
ForEachFace(m, [&](MyFace &f){
|
||||||
|
hff[&f]=vcg::DoubleArea(f)*0.5f;
|
||||||
|
for(int i=0;i<3;++i){
|
||||||
|
hvf[f.V(i)] -= vcg::Angle(f.P1(i)-f.P0(i),f.P2(i)-f.P0(i));
|
||||||
|
hv3f[f.V(i)] -= vcg::NormalizedTriangleNormal(f);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//! [Saving 3 attributes in ply, one of the 3 disguised as quality]
|
||||||
|
vcg::tri::io::PlyInfo pi;
|
||||||
|
pi.AddPerVertexFloatAttribute("GaussianCurvature","quality");
|
||||||
|
pi.AddPerFaceFloatAttribute("FaceArea");
|
||||||
|
pi.AddPerVertexPoint3fAttribute(m,"InvertedNormal");
|
||||||
|
vcg::tri::io::ExporterPLY<MyMesh>::Save(m,"MeshWithCurvature.ply",false,pi);
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
include(../common.pri)
|
||||||
|
TARGET = trimesh_attribute_saving
|
||||||
|
SOURCES += trimesh_attribute_saving.cpp ../../../wrap/ply/plylib.cpp
|
|
@ -102,8 +102,7 @@ int main(int argc, char **argv)
|
||||||
printf("Output mesh vn:%i fn:%i\n",m.VN(),m.FN());
|
printf("Output mesh vn:%i fn:%i\n",m.VN(),m.FN());
|
||||||
printf("Created in :%i msec (%i+%i)\n",t2-t0,t1-t0,t2-t1);
|
printf("Created in :%i msec (%i+%i)\n",t2-t0,t1-t0,t2-t1);
|
||||||
|
|
||||||
vcg::tri::io::PlyInfo pi;
|
vcg::tri::io::ExporterPLY<MyMesh>::Save(m,argv[2]);
|
||||||
vcg::tri::io::ExporterPLY<MyMesh>::Save(m,argv[2],pi.mask);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,8 +137,6 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
printf("Output mesh vn:%i fn:%i\n",m.VN(),m.FN());
|
printf("Output mesh vn:%i fn:%i\n",m.VN(),m.FN());
|
||||||
|
|
||||||
vcg::tri::io::PlyInfo pi;
|
vcg::tri::io::Exporter<MyMesh>::Save(m,argv[2],vcg::tri::io::Mask::IOM_BITPOLYGONAL);
|
||||||
pi.mask|=vcg::tri::io::Mask::IOM_BITPOLYGONAL;
|
|
||||||
vcg::tri::io::Exporter<MyMesh>::Save(m,argv[2],pi.mask);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* VCGLib o o *
|
||||||
|
* Visual and Computer Graphics Library o o *
|
||||||
|
* _ O _ *
|
||||||
|
* Copyright(C) 2004-2016 \/)\/ *
|
||||||
|
* 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. *
|
||||||
|
* *
|
||||||
|
****************************************************************************/
|
||||||
|
#include<vcg/complex/complex.h>
|
||||||
|
|
||||||
|
#include <wrap/io_trimesh/export_obj.h>
|
||||||
|
#include <vcg/complex/algorithms/update/texture.h>
|
||||||
|
#include <vcg/complex/algorithms/create/platonic.h>
|
||||||
|
|
||||||
|
/*! \file trimesh_texture_clean.cpp
|
||||||
|
\ingroup code_sample
|
||||||
|
|
||||||
|
\brief a small example about removing fake texture seams eventually generated by rounding error in a texture param
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
using namespace vcg;
|
||||||
|
|
||||||
|
class MyEdge;
|
||||||
|
class MyFace;
|
||||||
|
class MyVertex;
|
||||||
|
struct MyUsedTypes : public UsedTypes< Use<MyVertex>::AsVertexType, Use<MyFace>::AsFaceType>{};
|
||||||
|
|
||||||
|
class MyVertex : public Vertex< MyUsedTypes, vertex::Coord3f, vertex::VFAdj, vertex::Normal3f, vertex::BitFlags >{};
|
||||||
|
class MyFace : public Face < MyUsedTypes, face::VertexRef, face::VFAdj, face::WedgeTexCoord2f, face::Mark, face::BitFlags > {};
|
||||||
|
class MyMesh : public tri::TriMesh< std::vector<MyVertex>, std::vector<MyFace > >{};
|
||||||
|
|
||||||
|
|
||||||
|
int main(int ,char ** )
|
||||||
|
{
|
||||||
|
MyMesh m;
|
||||||
|
int mask = tri::io::Mask::IOM_WEDGTEXCOORD;
|
||||||
|
|
||||||
|
// generate a simple 2D grid
|
||||||
|
Grid(m,20,20,1,1);
|
||||||
|
// assign it a simple planar parametrization
|
||||||
|
tri:UpdateTexture<MyMesh>::WedgeTexFromPlane(m,Point3f(1.0f,0,0),Point3f(0,1.0f,0),true);
|
||||||
|
tri::io::ExporterOBJ<MyMesh>::Save(m,"grid_0.obj",mask);
|
||||||
|
|
||||||
|
// randomly perturb a few coord textures introducing fake seams
|
||||||
|
for(MyFace &f : m.face)
|
||||||
|
{
|
||||||
|
for(int i=0;i<3;++i)
|
||||||
|
if(rand()%20==0)
|
||||||
|
{
|
||||||
|
f.WT(i).U()+=0.0000001;
|
||||||
|
f.WT(i).V()-=0.0000001;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tri::io::ExporterOBJ<MyMesh>::Save(m,"grid_1.obj",mask);
|
||||||
|
|
||||||
|
// Merge texture coords that very close
|
||||||
|
tri::UpdateTopology<MyMesh>::VertexFace(m);
|
||||||
|
tri::UpdateTexture<MyMesh>::WedgeTexMergeClose(m);
|
||||||
|
|
||||||
|
tri::io::ExporterOBJ<MyMesh>::Save(m,"grid_2.obj",mask);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
include(../common.pri)
|
||||||
|
TARGET = trimesh_texture_clean
|
||||||
|
SOURCES += trimesh_texture_clean.cpp
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#ifndef __VCGLIB_CLEAN
|
#ifndef __VCGLIB_CLEAN
|
||||||
#define __VCGLIB_CLEAN
|
#define __VCGLIB_CLEAN
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
// VCG headers
|
// VCG headers
|
||||||
#include <vcg/complex/complex.h>
|
#include <vcg/complex/complex.h>
|
||||||
#include <vcg/complex/algorithms/closest.h>
|
#include <vcg/complex/algorithms/closest.h>
|
||||||
|
@ -310,7 +312,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** This function removes that are not referenced by any face or by any edge.
|
/** This function removes vertices that are not referenced by any face or by any edge.
|
||||||
@param m The mesh
|
@param m The mesh
|
||||||
@param DeleteVertexFlag if false prevent the vertex deletion and just count it.
|
@param DeleteVertexFlag if false prevent the vertex deletion and just count it.
|
||||||
@return The number of removed vertices
|
@return The number of removed vertices
|
||||||
|
@ -583,7 +585,7 @@ public:
|
||||||
firstVp++;
|
firstVp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ToSplitVec.size();
|
return int(ToSplitVec.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1369,7 +1371,7 @@ public:
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
||||||
ScalarType NormalThrRad = math::ToRad(normalThresholdDeg);
|
ScalarType NormalThrRad = math::ToRad(normalThresholdDeg);
|
||||||
ScalarType eps = 0.0001; // this epsilon value is in absolute value. It is a distance from edge in baricentric coords.
|
ScalarType eps = ScalarType(0.0001); // this epsilon value is in absolute value. It is a distance from edge in baricentric coords.
|
||||||
//detection stage
|
//detection stage
|
||||||
for(FaceIterator fi=m.face.begin();fi!= m.face.end();++fi ) if(!(*fi).IsV())
|
for(FaceIterator fi=m.face.begin();fi!= m.face.end();++fi ) if(!(*fi).IsV())
|
||||||
{ Point3<ScalarType> NN = vcg::TriangleNormal((*fi)).Normalize();
|
{ Point3<ScalarType> NN = vcg::TriangleNormal((*fi)).Normalize();
|
||||||
|
@ -1790,6 +1792,7 @@ public:
|
||||||
*/
|
*/
|
||||||
static void SelectFoldedFaceFromOneRingFaces(MeshType &m, ScalarType cosThreshold)
|
static void SelectFoldedFaceFromOneRingFaces(MeshType &m, ScalarType cosThreshold)
|
||||||
{
|
{
|
||||||
|
typedef std::unordered_set<VertexPointer> VertexSet;
|
||||||
tri::RequireVFAdjacency(m);
|
tri::RequireVFAdjacency(m);
|
||||||
tri::RequirePerFaceNormal(m);
|
tri::RequirePerFaceNormal(m);
|
||||||
tri::RequirePerVertexNormal(m);
|
tri::RequirePerVertexNormal(m);
|
||||||
|
@ -1803,33 +1806,33 @@ public:
|
||||||
#pragma omp parallel for schedule(dynamic, 10)
|
#pragma omp parallel for schedule(dynamic, 10)
|
||||||
for (int i = 0; i < m.face.size(); i++)
|
for (int i = 0; i < m.face.size(); i++)
|
||||||
{
|
{
|
||||||
std::vector<typename MeshType::VertexPointer> nearVertex;
|
VertexSet nearVertex;
|
||||||
std::vector<typename MeshType::CoordType> point;
|
std::vector<CoordType> pointVec;
|
||||||
typename MeshType::FacePointer f = &m.face[i];
|
FacePointer f = &m.face[i];
|
||||||
for (int j = 0; j < 3; j++)
|
for (int j = 0; j < 3; j++)
|
||||||
{
|
{
|
||||||
std::vector<typename MeshType::VertexPointer> temp;
|
std::vector<VertexPointer> temp;
|
||||||
vcg::face::VVStarVF<typename MeshType::FaceType>(f->V(j), temp);
|
vcg::face::VVStarVF<FaceType>(f->V(j), temp);
|
||||||
typename std::vector<typename MeshType::VertexPointer>::iterator iter = temp.begin();
|
typename std::vector<VertexPointer>::iterator iter = temp.begin();
|
||||||
for (; iter != temp.end(); iter++)
|
for (; iter != temp.end(); iter++)
|
||||||
{
|
{
|
||||||
if ((*iter) != f->V1(j) && (*iter) != f->V2(j))
|
if ((*iter) != f->V1(j) && (*iter) != f->V2(j))
|
||||||
{
|
{
|
||||||
nearVertex.push_back((*iter));
|
if (nearVertex.insert((*iter)).second)
|
||||||
point.push_back((*iter)->P());
|
pointVec.push_back((*iter)->P());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nearVertex.push_back(f->V(j));
|
nearVertex.insert(f->V(j));
|
||||||
point.push_back(f->P(j));
|
pointVec.push_back(f->P(j));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (point.size() > 3)
|
if (pointVec.size() > 3)
|
||||||
{
|
{
|
||||||
vcg::Plane3<typename MeshType::ScalarType> plane;
|
vcg::Plane3<ScalarType> plane;
|
||||||
vcg::FitPlaneToPointSet(point, plane);
|
vcg::FitPlaneToPointSet(pointVec, plane);
|
||||||
float avgDot = 0;
|
float avgDot = 0;
|
||||||
for (int j = 0; j < nearVertex.size(); j++)
|
for (auto nvp : nearVertex)
|
||||||
avgDot += plane.Direction().dot(nearVertex[j]->N());
|
avgDot += plane.Direction().dot(nvp->N());
|
||||||
avgDot /= nearVertex.size();
|
avgDot /= nearVertex.size();
|
||||||
typename MeshType::VertexType::NormalType normal;
|
typename MeshType::VertexType::NormalType normal;
|
||||||
if (avgDot < 0)
|
if (avgDot < 0)
|
||||||
|
|
|
@ -398,7 +398,7 @@ public:
|
||||||
{
|
{
|
||||||
visible.vert[i].P() = m.vert[ind].P();
|
visible.vert[i].P() = m.vert[ind].P();
|
||||||
m.vert[ind].SetS();
|
m.vert[ind].SetS();
|
||||||
m.vert[ind].C() = Color4b::LightBlue;
|
//m.vert[ind].C() = Color4b::LightBlue;
|
||||||
selCnt++;
|
selCnt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,6 +416,8 @@ public:
|
||||||
|
|
||||||
tri::Allocator<CHMesh>::CompactEveryVector(visible);
|
tri::Allocator<CHMesh>::CompactEveryVector(visible);
|
||||||
tri::Clean<CHMesh>::FlipMesh(visible);
|
tri::Clean<CHMesh>::FlipMesh(visible);
|
||||||
|
tri::UpdateNormal<CHMesh>::PerFaceNormalized(visible);
|
||||||
|
tri::UpdateNormal<CHMesh>::PerVertexNormalized(visible);
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -99,7 +99,7 @@ template <class MESH> class AdvancingFront {
|
||||||
void BuildMesh(CallBackPos call = NULL, int interval = 512)
|
void BuildMesh(CallBackPos call = NULL, int interval = 512)
|
||||||
{
|
{
|
||||||
float finalfacesext = mesh.vert.size() * 2.0f;
|
float finalfacesext = mesh.vert.size() * 2.0f;
|
||||||
if(call) call(0, "Advancing front");
|
if (call) (*call)(0, "Advancing front");
|
||||||
while(1) {
|
while(1) {
|
||||||
|
|
||||||
for(int i = 0; i < interval; i++) {
|
for(int i = 0; i < interval; i++) {
|
||||||
|
|
|
@ -120,7 +120,7 @@ template <class MESH> class BallPivoting: public AdvancingFront<MESH> {
|
||||||
targets.push_back(vp);
|
targets.push_back(vp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int n = targets.size();
|
int n = int(targets.size());
|
||||||
if(n<3) continue;
|
if(n<3) continue;
|
||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
@ -205,10 +205,10 @@ template <class MESH> class BallPivoting: public AdvancingFront<MESH> {
|
||||||
Mark(vv1);
|
Mark(vv1);
|
||||||
Mark(vv2);
|
Mark(vv2);
|
||||||
|
|
||||||
v0 = tri::Index(this->mesh,vv0);
|
v0 = int(tri::Index(this->mesh, vv0));
|
||||||
v1 = tri::Index(this->mesh,vv1);
|
v1 = int(tri::Index(this->mesh, vv1));
|
||||||
v2 = tri::Index(this->mesh,vv2);
|
v2 = int(tri::Index(this->mesh, vv2));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ template <class MESH> class BallPivoting: public AdvancingFront<MESH> {
|
||||||
if(nn==0) return -1;
|
if(nn==0) return -1;
|
||||||
|
|
||||||
VertexType *candidate = NULL;
|
VertexType *candidate = NULL;
|
||||||
ScalarType min_angle = M_PI;
|
ScalarType min_angle = ScalarType(M_PI);
|
||||||
//
|
//
|
||||||
// Loop over all the nearest vertexes and choose the best one according the ball pivoting strategy.
|
// Loop over all the nearest vertexes and choose the best one according the ball pivoting strategy.
|
||||||
//
|
//
|
||||||
|
@ -312,7 +312,7 @@ template <class MESH> class BallPivoting: public AdvancingFront<MESH> {
|
||||||
assert((candidate->P() - v1).Norm() > min_edge);
|
assert((candidate->P() - v1).Norm() > min_edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
int candidateIndex = tri::Index(this->mesh,candidate);
|
int candidateIndex = int(tri::Index(this->mesh,candidate));
|
||||||
assert(candidateIndex != edge.v0 && candidateIndex != edge.v1);
|
assert(candidateIndex != edge.v0 && candidateIndex != edge.v1);
|
||||||
|
|
||||||
Point3x newnormal = ((candidate->P() - v0)^(v1 - v0)).Normalize();
|
Point3x newnormal = ((candidate->P() - v0)^(v1 - v0)).Normalize();
|
||||||
|
|
|
@ -59,7 +59,7 @@ namespace tri {
|
||||||
|
|
||||||
// Simple prototype for later use...
|
// Simple prototype for later use...
|
||||||
template<class MeshType>
|
template<class MeshType>
|
||||||
void MCSimplify( MeshType &m, float perc, bool preserveBB=true, vcg::CallBackPos *cb=0);
|
int MCSimplify( MeshType &m, float perc, bool preserveBB=true, vcg::CallBackPos *cb=0);
|
||||||
|
|
||||||
|
|
||||||
/** Surface Reconstruction
|
/** Surface Reconstruction
|
||||||
|
@ -550,63 +550,66 @@ template < class MeshType, class VertexPair>
|
||||||
|
|
||||||
|
|
||||||
template< class MeshType>
|
template< class MeshType>
|
||||||
void MCSimplify( MeshType &m, float absoluteError, bool preserveBB, vcg::CallBackPos *cb)
|
int MCSimplify( MeshType &m, float absoluteError, bool preserveBB, vcg::CallBackPos *cb)
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef PlyMCTriEdgeCollapse<MeshType,BasicVertexPair<typename MeshType::VertexType> > MyColl;
|
typedef PlyMCTriEdgeCollapse<MeshType,BasicVertexPair<typename MeshType::VertexType> > MyColl;
|
||||||
typedef typename MeshType::FaceIterator FaceIterator;
|
typedef typename MeshType::FaceIterator FaceIterator;
|
||||||
typedef typename MeshType::CoordType CoordType;
|
typedef typename MeshType::CoordType CoordType;
|
||||||
|
|
||||||
|
|
||||||
tri::UpdateBounding<MeshType>::Box(m);
|
tri::UpdateBounding<MeshType>::Box(m);
|
||||||
tri::UpdateTopology<MeshType>::VertexFace(m);
|
tri::UpdateTopology<MeshType>::VertexFace(m);
|
||||||
TriEdgeCollapseMCParameter pp;
|
TriEdgeCollapseMCParameter pp;
|
||||||
pp.bb.Import(m.bbox);
|
pp.bb.Import(m.bbox);
|
||||||
pp.preserveBBox=preserveBB;
|
pp.preserveBBox=preserveBB;
|
||||||
vcg::LocalOptimization<MeshType> DeciSession(m,&pp);
|
vcg::LocalOptimization<MeshType> DeciSession(m,&pp);
|
||||||
if(absoluteError==0)
|
if(absoluteError==0)
|
||||||
{
|
{
|
||||||
// guess the mc side.
|
// guess the mc side.
|
||||||
// In a MC mesh the vertices are on the egdes of the cells. and the edges are (mostly) on face of the cells.
|
// In a MC mesh the vertices are on the egdes of the cells. and the edges are (mostly) on face of the cells.
|
||||||
// If you have 2 vert over the same face xy they share z
|
// If you have 2 vert over the same face xy they share z
|
||||||
|
|
||||||
std::vector<float> ZSet;
|
std::vector<float> ZSet;
|
||||||
for(FaceIterator fi = m.face.begin();fi!=m.face.end();++fi)
|
for(FaceIterator fi = m.face.begin();fi!=m.face.end();++fi)
|
||||||
if(!(*fi).IsD())
|
if(!(*fi).IsD())
|
||||||
{
|
{
|
||||||
CoordType v0=(*fi).V(0)->P();
|
CoordType v0=(*fi).V(0)->P();
|
||||||
CoordType v1=(*fi).V(1)->P();
|
CoordType v1=(*fi).V(1)->P();
|
||||||
CoordType v2=(*fi).V(2)->P();
|
CoordType v2=(*fi).V(2)->P();
|
||||||
if(v0[2]==v1[2] && v0[1]!=v1[1] && v0[0]!=v1[0]) ZSet.push_back(v0[2]);
|
if(v0[2]==v1[2] && v0[1]!=v1[1] && v0[0]!=v1[0]) ZSet.push_back(v0[2]);
|
||||||
if(v0[2]==v2[2] && v0[1]!=v1[1] && v2[0]!=v2[0]) ZSet.push_back(v0[2]);
|
if(v0[2]==v2[2] && v0[1]!=v2[1] && v0[0]!=v2[0]) ZSet.push_back(v0[2]);
|
||||||
if(v1[2]==v2[2] && v1[1]!=v1[1] && v2[0]!=v2[0]) ZSet.push_back(v0[2]);
|
if(v1[2]==v2[2] && v1[1]!=v2[1] && v1[0]!=v2[0]) ZSet.push_back(v1[2]);
|
||||||
if(ZSet.size()>100) break;
|
if(ZSet.size()>100) break;
|
||||||
}
|
}
|
||||||
std::sort(ZSet.begin(),ZSet.end());
|
if (ZSet.size() == 0) return -1; //no straight edges found. exit with error
|
||||||
std::vector<float>::iterator lastV = std::unique(ZSet.begin(),ZSet.end());
|
std::sort(ZSet.begin(),ZSet.end());
|
||||||
ZSet.resize(lastV-ZSet.begin());
|
std::vector<float>::iterator lastV = std::unique(ZSet.begin(),ZSet.end());
|
||||||
float Delta=0;
|
ZSet.resize(lastV-ZSet.begin());
|
||||||
for(size_t i = 0; i< ZSet.size()-1;++i)
|
float Delta=0;
|
||||||
{
|
for(size_t i = 0; i< ZSet.size()-1;++i)
|
||||||
Delta = std::max(ZSet[i+1]-ZSet[i],Delta);
|
{
|
||||||
// qDebug("%f",Delta);
|
Delta = std::max(ZSet[i+1]-ZSet[i],Delta);
|
||||||
}
|
//qDebug("%f",Delta);
|
||||||
absoluteError= Delta/4.0f;
|
}
|
||||||
}
|
absoluteError= Delta/4.0f;
|
||||||
// qDebug("Simplifying at absoluteError=%f",absoluteError);
|
}
|
||||||
|
//qDebug("Simplifying at absoluteError=%f",absoluteError);
|
||||||
|
|
||||||
float TargetError = absoluteError;
|
float TargetError = absoluteError;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
DeciSession.template Init< MyColl > ();
|
DeciSession.template Init< MyColl > ();
|
||||||
|
|
||||||
pp.areaThr=TargetError*TargetError;
|
pp.areaThr=TargetError*TargetError;
|
||||||
DeciSession.SetTimeBudget(1.0f);
|
DeciSession.SetTimeBudget(1.0f);
|
||||||
if(TargetError < std::numeric_limits<float>::max() ) DeciSession.SetTargetMetric(TargetError);
|
if(TargetError < std::numeric_limits<float>::max() ) DeciSession.SetTargetMetric(TargetError);
|
||||||
while(DeciSession.DoOptimization() && DeciSession.currMetric < TargetError)
|
while(DeciSession.DoOptimization() && DeciSession.currMetric < TargetError)
|
||||||
{
|
{
|
||||||
sprintf(buf,"Simplyfing %7i err %9g \r",m.fn,DeciSession.currMetric);
|
sprintf(buf,"Simplyfing %7i err %9g \r",m.fn,DeciSession.currMetric);
|
||||||
if (cb) cb(int(100.0f*DeciSession.currMetric/TargetError),buf);
|
if (cb) cb(int(100.0f*DeciSession.currMetric/TargetError),buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 1; //success
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,9 @@
|
||||||
#include <vcg/complex/algorithms/update/bounding.h>
|
#include <vcg/complex/algorithms/update/bounding.h>
|
||||||
#include <vcg/complex/algorithms/update/component_ep.h>
|
#include <vcg/complex/algorithms/update/component_ep.h>
|
||||||
#include <vcg/complex/algorithms/create/marching_cubes.h>
|
#include <vcg/complex/algorithms/create/marching_cubes.h>
|
||||||
#include <vcg/space/index/grid_static_ptr.h>
|
//#include <vcg/space/index/grid_static_ptr.h>
|
||||||
#include <vcg/complex/algorithms/closest.h>
|
//#include <vcg/complex/algorithms/closest.h>
|
||||||
|
#include <vcg/space/index/kdtree/kdtree_face.h>
|
||||||
|
|
||||||
namespace vcg {
|
namespace vcg {
|
||||||
namespace tri {
|
namespace tri {
|
||||||
|
@ -63,13 +64,15 @@ class Resampler : public BasicGrid<typename NewMeshType::ScalarType>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
typedef int VertexIndex;
|
typedef int VertexIndex;
|
||||||
typedef typename vcg::GridStaticPtr<OldFaceType, OldScalarType> GridType;
|
//typedef typename vcg::GridStaticPtr<OldFaceType, OldScalarType> GridType;
|
||||||
|
typedef vcg::KdTreeFace<OldMeshType> GridType;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
int SliceSize;
|
int SliceSize;
|
||||||
int CurrentSlice;
|
int CurrentSlice;
|
||||||
typedef tri::FaceTmark<OldMeshType> MarkerFace;
|
//typedef tri::FaceTmark<OldMeshType> MarkerFace;
|
||||||
|
typedef vcg::tri::EmptyTMark<OldMeshType> MarkerFace;
|
||||||
MarkerFace markerFunctor;
|
MarkerFace markerFunctor;
|
||||||
|
|
||||||
VertexIndex *_x_cs; // indici dell'intersezioni della superficie lungo gli Xedge della fetta corrente
|
VertexIndex *_x_cs; // indici dell'intersezioni della superficie lungo gli Xedge della fetta corrente
|
||||||
|
@ -159,6 +162,7 @@ class Resampler : public BasicGrid<typename NewMeshType::ScalarType>
|
||||||
OldCoordType closestPt;
|
OldCoordType closestPt;
|
||||||
DISTFUNCTOR PDistFunct;
|
DISTFUNCTOR PDistFunct;
|
||||||
OldFaceType *f = _g.GetClosest(PDistFunct,markerFunctor,testPt,max_dist,dist,closestPt);
|
OldFaceType *f = _g.GetClosest(PDistFunct,markerFunctor,testPt,max_dist,dist,closestPt);
|
||||||
|
|
||||||
if (f==NULL) return field_value(false,0);
|
if (f==NULL) return field_value(false,0);
|
||||||
if(AbsDistFlag) return field_value(true,dist);
|
if(AbsDistFlag) return field_value(true,dist);
|
||||||
assert(!f->IsD());
|
assert(!f->IsD());
|
||||||
|
@ -230,6 +234,7 @@ class Resampler : public BasicGrid<typename NewMeshType::ScalarType>
|
||||||
/// the distance of the bb
|
/// the distance of the bb
|
||||||
void ComputeSliceValues(int slice,field_value *slice_values)
|
void ComputeSliceValues(int slice,field_value *slice_values)
|
||||||
{
|
{
|
||||||
|
#pragma omp parallel for schedule(dynamic, 10)
|
||||||
for (int i=0; i<=this->siz.X(); i++)
|
for (int i=0; i<=this->siz.X(); i++)
|
||||||
{
|
{
|
||||||
for (int k=0; k<=this->siz.Z(); k++)
|
for (int k=0; k<=this->siz.Z(); k++)
|
||||||
|
|
|
@ -283,7 +283,7 @@ public:
|
||||||
template<class MESH> class MinimumWeightEar : public TrivialEar<MESH>
|
template<class MESH> class MinimumWeightEar : public TrivialEar<MESH>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static float &DiedralWeight() { static float _dw=0.1; return _dw;}
|
static float &DiedralWeight() { static float _dw=0.1f; return _dw;}
|
||||||
typedef TrivialEar<MESH> TE;
|
typedef TrivialEar<MESH> TE;
|
||||||
typename MESH::ScalarType dihedralRad;
|
typename MESH::ScalarType dihedralRad;
|
||||||
typename MESH::ScalarType aspectRatio;
|
typename MESH::ScalarType aspectRatio;
|
||||||
|
|
|
@ -179,7 +179,7 @@ public:
|
||||||
this->optimalPos = newPos;
|
this->optimalPos = newPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute(TriMeshType &m, BaseParameterClass */*_pp*/)
|
void Execute(TriMeshType &m, BaseParameterClass * /*_pp*/)
|
||||||
{
|
{
|
||||||
CoordType newPos = this->optimalPos;
|
CoordType newPos = this->optimalPos;
|
||||||
QH::Qd(this->pos.V(1))+=QH::Qd(this->pos.V(0)); // v0 is deleted and v1 take the new position
|
QH::Qd(this->pos.V(1))+=QH::Qd(this->pos.V(0)); // v0 is deleted and v1 take the new position
|
||||||
|
|
|
@ -241,7 +241,7 @@ public:
|
||||||
{
|
{
|
||||||
tri::RequireCompactness(m);
|
tri::RequireCompactness(m);
|
||||||
h.resize(m.vn);
|
h.resize(m.vn);
|
||||||
for(int i=0;i<m.vn;++i) h[i]=0;
|
fill(h.begin(),h.end(),0);
|
||||||
for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi)
|
for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi)
|
||||||
{
|
{
|
||||||
ScalarType a = DoubleArea(*fi)/6.0;
|
ScalarType a = DoubleArea(*fi)/6.0;
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
#include <vcg/space/index/kdtree/kdtree.h>
|
#include <vcg/space/index/kdtree/kdtree.h>
|
||||||
|
|
||||||
|
|
||||||
namespace vcg
|
namespace vcg
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -94,7 +93,7 @@ class OutlierRemoval
|
||||||
dem += 0.230389 * value * value;
|
dem += 0.230389 * value * value;
|
||||||
dem += 0.000972 * value * value * value;
|
dem += 0.000972 * value * value * value;
|
||||||
dem += 0.078108 * value * value * value * value;
|
dem += 0.078108 * value * value * value * value;
|
||||||
ScalarType op = max(0.0, 1.0 - 1.0 / dem);
|
ScalarType op = std::max(0.0, 1.0 - 1.0 / dem);
|
||||||
outlierScore[i] = op;
|
outlierScore[i] = op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -162,7 +162,7 @@ public:
|
||||||
for (vi = m.vert.begin(); vi != m.vert.end(); ++vi)
|
for (vi = m.vert.begin(); vi != m.vert.end(); ++vi)
|
||||||
if (!(*vi).IsD())
|
if (!(*vi).IsD())
|
||||||
{
|
{
|
||||||
ScalarType weight = useQualityAsWeight ? (*vi).Q() : 1.0;
|
ScalarType weight = useQualityAsWeight ? (*vi).Q() : 1.0f;
|
||||||
accumulator[0] += (double)((*vi).P()[0] * weight);
|
accumulator[0] += (double)((*vi).P()[0] * weight);
|
||||||
accumulator[1] += (double)((*vi).P()[1] * weight);
|
accumulator[1] += (double)((*vi).P()[1] * weight);
|
||||||
accumulator[2] += (double)((*vi).P()[2] * weight);
|
accumulator[2] += (double)((*vi).P()[2] * weight);
|
||||||
|
@ -212,6 +212,21 @@ public:
|
||||||
return area/ScalarType(2.0);
|
return area/ScalarType(2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ScalarType ComputeBorderLength(MeshType & m)
|
||||||
|
{
|
||||||
|
RequireFFAdjacency(m);
|
||||||
|
ScalarType sum = 0;
|
||||||
|
tri::UpdateTopology<MeshType>::FaceFace(m);
|
||||||
|
ForEachFace(m, [&](FaceType &f) {
|
||||||
|
for (int k=0; k<f.VN(); k++)
|
||||||
|
if (face::IsBorder(f, k))
|
||||||
|
{
|
||||||
|
sum += Distance(f.cP(k), f.cP(1));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
static void ComputePerVertexQualityDistribution( MeshType & m, Distribution<ScalarType> &h, bool selectionOnly = false) // V1.0
|
static void ComputePerVertexQualityDistribution( MeshType & m, Distribution<ScalarType> &h, bool selectionOnly = false) // V1.0
|
||||||
{
|
{
|
||||||
tri::RequirePerVertexQuality(m);
|
tri::RequirePerVertexQuality(m);
|
||||||
|
|
|
@ -790,6 +790,7 @@ static Color4b ColorDesaturate(Color4b c, int method)
|
||||||
}
|
}
|
||||||
default: assert(0);
|
default: assert(0);
|
||||||
}
|
}
|
||||||
|
return Color4b(255, 255, 255, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
//ausiliary function to compute average lightness. value = (R+G+B)/3
|
//ausiliary function to compute average lightness. value = (R+G+B)/3
|
||||||
|
|
|
@ -48,6 +48,7 @@ typedef typename MeshType::VertexIterator VertexIterator;
|
||||||
typedef typename MeshType::FaceType FaceType;
|
typedef typename MeshType::FaceType FaceType;
|
||||||
typedef typename MeshType::FacePointer FacePointer;
|
typedef typename MeshType::FacePointer FacePointer;
|
||||||
typedef typename MeshType::FaceIterator FaceIterator;
|
typedef typename MeshType::FaceIterator FaceIterator;
|
||||||
|
typedef typename vcg::Point2<ScalarType> UVCoordType;
|
||||||
|
|
||||||
static void WedgeTexFromPlane(ComputeMeshType &m, const Point3<ScalarType> &uVec, const Point3<ScalarType> &vVec, bool aspectRatio, ScalarType sideGutter=0.0)
|
static void WedgeTexFromPlane(ComputeMeshType &m, const Point3<ScalarType> &uVec, const Point3<ScalarType> &vVec, bool aspectRatio, ScalarType sideGutter=0.0)
|
||||||
{
|
{
|
||||||
|
@ -70,7 +71,7 @@ static void WedgeTexFromPlane(ComputeMeshType &m, const Point3<ScalarType> &uVec
|
||||||
|
|
||||||
if (sideGutter>0.0)
|
if (sideGutter>0.0)
|
||||||
{
|
{
|
||||||
ScalarType deltaGutter = std::min(wideU, wideV) * min(sideGutter, (ScalarType)0.5);
|
ScalarType deltaGutter = std::min(wideU, wideV) * std::min(sideGutter, (ScalarType)0.5);
|
||||||
|
|
||||||
bb.max[0] += deltaGutter;
|
bb.max[0] += deltaGutter;
|
||||||
bb.min[0] -= deltaGutter;
|
bb.min[0] -= deltaGutter;
|
||||||
|
@ -138,6 +139,40 @@ static void WedgeTexRemoveNull(ComputeMeshType &m, const std::string &texturenam
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
/** \brief Merge supposedly wrong texcoords
|
||||||
|
* It can happens that for rounding errors texcoords on different wedges but on the same vertex have different tex coords.
|
||||||
|
* This function merges them according a threshold. It requires initialized VF adjacency.
|
||||||
|
* the default for merging is if two textures dist less than one 16th of texel on a 4k texture...
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int WedgeTexMergeClose(ComputeMeshType &m, ScalarType mergeThr = ScalarType(1.0/65536.0) )
|
||||||
|
{
|
||||||
|
tri::RequireVFAdjacency(m);
|
||||||
|
int mergedCnt=0;
|
||||||
|
ForEachVertex(m, [&](VertexType &v){
|
||||||
|
face::VFIterator<FaceType> vfi(&v);
|
||||||
|
std::vector<UVCoordType> clusterVec;
|
||||||
|
clusterVec.push_back(vfi.F()->WT(vfi.I()).P());
|
||||||
|
++vfi;
|
||||||
|
while(!vfi.End())
|
||||||
|
{
|
||||||
|
UVCoordType cur= vfi.F()->WT(vfi.I()).P();
|
||||||
|
bool merged=false;
|
||||||
|
for(auto p:clusterVec) {
|
||||||
|
if(p!=cur && Distance(p,cur) < mergeThr){
|
||||||
|
vfi.F()->WT(vfi.I()).P()=p;
|
||||||
|
++mergedCnt;
|
||||||
|
merged=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!merged)
|
||||||
|
clusterVec.push_back(cur);
|
||||||
|
|
||||||
|
++vfi;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return mergedCnt;
|
||||||
|
}
|
||||||
|
|
||||||
}; // end class
|
}; // end class
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,7 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const int VoroRelaxationStep = 20;
|
static const int VoroRelaxationStep = 30;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Remesh the main function that remeshes a mesh preserving creases.
|
/// \brief Remesh the main function that remeshes a mesh preserving creases.
|
||||||
|
@ -355,7 +355,7 @@ protected:
|
||||||
|
|
||||||
// refine to obtain a base mesh
|
// refine to obtain a base mesh
|
||||||
VoronoiProcessingParameter vpp;
|
VoronoiProcessingParameter vpp;
|
||||||
vpp.refinementRatio = 4.0f;
|
vpp.refinementRatio = 5.0f;
|
||||||
Voronoi::PreprocessForVoronoi(baseMesh, samplingRadius, vpp);
|
Voronoi::PreprocessForVoronoi(baseMesh, samplingRadius, vpp);
|
||||||
|
|
||||||
// Poisson sampling preserving border
|
// Poisson sampling preserving border
|
||||||
|
@ -372,7 +372,15 @@ protected:
|
||||||
|
|
||||||
// Montecarlo oversampling
|
// Montecarlo oversampling
|
||||||
Mesh montecarloMesh;
|
Mesh montecarloMesh;
|
||||||
int poissonCount = SurfaceSampler::ComputePoissonSampleNum(original, samplingRadius) * 0.7;
|
// const int poissonCount = SurfaceSampler::ComputePoissonSampleNum(original, samplingRadius)/* * 0.7*/;
|
||||||
|
int poissonCount = 0;
|
||||||
|
{
|
||||||
|
const ScalarType meshArea = Stat<Mesh>::ComputeMeshArea(original);
|
||||||
|
const ScalarType meshBoundary = Stat<Mesh>::ComputeBorderLength(original);
|
||||||
|
const double factor = math::Sqrt(3)/2;
|
||||||
|
const ScalarType areaPerSample = samplingRadius*samplingRadius * factor;
|
||||||
|
poissonCount = meshArea / areaPerSample - meshBoundary * samplingRadius * factor * 0.5; // totalArea / (r^2 * sqrt(3)/2) - (totalBoundary * r * sqrt(3)/4)
|
||||||
|
}
|
||||||
|
|
||||||
// std::cout << "poisson Count: " << poissonCount << std::endl;
|
// std::cout << "poisson Count: " << poissonCount << std::endl;
|
||||||
if (poissonCount <= 0)
|
if (poissonCount <= 0)
|
||||||
|
@ -386,7 +394,7 @@ protected:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Montecarlo poisson sampling
|
// Montecarlo poisson sampling
|
||||||
SurfaceSampler::MontecarloPoisson(original, mps, poissonCount * 20);
|
SurfaceSampler::MontecarloPoisson(original, mps, poissonCount * 40);
|
||||||
BuildMeshFromCoordVector(montecarloMesh,sampleVec);
|
BuildMeshFromCoordVector(montecarloMesh,sampleVec);
|
||||||
|
|
||||||
#ifdef DEBUG_VORO
|
#ifdef DEBUG_VORO
|
||||||
|
@ -421,6 +429,7 @@ protected:
|
||||||
vpp.seedPerturbationProbability = 0.0f;
|
vpp.seedPerturbationProbability = 0.0f;
|
||||||
Voronoi::RestrictedVoronoiRelaxing(baseMesh, seedPointVec, seedFixedVec, VoroRelaxationStep, vpp);
|
Voronoi::RestrictedVoronoiRelaxing(baseMesh, seedPointVec, seedFixedVec, VoroRelaxationStep, vpp);
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG_VORO
|
#ifdef DEBUG_VORO
|
||||||
BuildMeshFromCoordVector(poissonMesh,seedPointVec);
|
BuildMeshFromCoordVector(poissonMesh,seedPointVec);
|
||||||
io::ExporterPLY<MeshType>::Save(poissonMesh, QString("relaxedMesh_%1.ply").arg(idx).toStdString().c_str());
|
io::ExporterPLY<MeshType>::Save(poissonMesh, QString("relaxedMesh_%1.ply").arg(idx).toStdString().c_str());
|
||||||
|
|
|
@ -1157,12 +1157,12 @@ public:
|
||||||
template <class ATTR_TYPE>
|
template <class ATTR_TYPE>
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
ClearPerVertexAttribute( MeshType & m,typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE> & h){
|
ClearPerVertexAttribute( MeshType & m,typename MeshType::template PerVertexAttributeHandle<ATTR_TYPE> & h, const ATTR_TYPE & initVal = ATTR_TYPE()){
|
||||||
typename std::set<PointerToAttribute > ::iterator i;
|
typename std::set<PointerToAttribute > ::iterator i;
|
||||||
for( i = m.vert_attr.begin(); i != m.vert_attr.end(); ++i)
|
for( i = m.vert_attr.begin(); i != m.vert_attr.end(); ++i)
|
||||||
if( (*i)._handle == h._handle ){
|
if( (*i)._handle == h._handle ){
|
||||||
for(typename MeshType::VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
|
for(typename MeshType::VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
|
||||||
h[vi] = ATTR_TYPE();
|
h[vi] = initVal;
|
||||||
return;}
|
return;}
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ static void UniformCone(int vn, std::vector<Point3<ScalarType > > &NN, ScalarTyp
|
||||||
|
|
||||||
printf("----------AngleRad %f Angledeg %f ratio %f vn %i vn2 %i \n",AngleRad,math::ToDeg(AngleRad),Ratio,vn,int(vn/Ratio));
|
printf("----------AngleRad %f Angledeg %f ratio %f vn %i vn2 %i \n",AngleRad,math::ToDeg(AngleRad),Ratio,vn,int(vn/Ratio));
|
||||||
Fibonacci(vn/Ratio,NNT);
|
Fibonacci(vn/Ratio,NNT);
|
||||||
printf("asked %i got %i (expecting %i instead of %i)\n", int(vn/Ratio), NNT.size(), int(NNT.size()*Ratio), vn);
|
printf("asked %i got %i (expecting %i instead of %i)\n", int(vn/Ratio), int(NNT.size()), int(NNT.size()*Ratio), vn);
|
||||||
typename std::vector<Point3<ScalarType> >::iterator vi;
|
typename std::vector<Point3<ScalarType> >::iterator vi;
|
||||||
|
|
||||||
ScalarType cosAngle = cos(AngleRad);
|
ScalarType cosAngle = cos(AngleRad);
|
||||||
|
|
|
@ -57,18 +57,23 @@ namespace vcg {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
KdTreeFace(MeshType& mesh, unsigned int maxObjPerCell = 64, unsigned int maxDepth = 64) : epsilon(std::numeric_limits<Scalar>::epsilon())
|
KdTreeFace():epsilon(std::numeric_limits<Scalar>::epsilon())
|
||||||
|
{
|
||||||
|
targetCellSize = 64;
|
||||||
|
targetMaxDepth = 64;
|
||||||
|
};
|
||||||
|
|
||||||
|
KdTreeFace(unsigned int maxObjPerCell, unsigned int maxDepth) : epsilon(std::numeric_limits<Scalar>::epsilon())
|
||||||
{
|
{
|
||||||
targetCellSize = maxObjPerCell;
|
targetCellSize = maxObjPerCell;
|
||||||
targetMaxDepth = maxDepth;
|
targetMaxDepth = maxDepth;
|
||||||
mNodes.resize(1);
|
};
|
||||||
Node& node = mNodes.back();
|
|
||||||
node.leaf = 0;
|
KdTreeFace(MeshType& mesh, unsigned int maxObjPerCell = 64, unsigned int maxDepth = 64, bool onlySelection = false) : epsilon(std::numeric_limits<Scalar>::epsilon())
|
||||||
node.aabb = mesh.bbox;
|
{
|
||||||
node.aabb.Offset(VectorType(epsilon, epsilon, epsilon));
|
targetCellSize = maxObjPerCell;
|
||||||
for (int i = 0; i < mesh.face.size(); i++)
|
targetMaxDepth = maxDepth;
|
||||||
node.list.push_back(&mesh.face[i]);
|
Set(mesh.face.begin(), mesh.face.end(), mesh.face.size(), onlySelection);
|
||||||
numLevel = createTree(0, 1);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
~KdTreeFace()
|
~KdTreeFace()
|
||||||
|
@ -76,10 +81,53 @@ namespace vcg {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class ObjIter>
|
||||||
template <class ObjectMarker> FacePointer doQueryClosest(const VectorType& queryPoint, VectorType& narestPoint, Scalar& dist, ObjectMarker& marker, Scalar maxDist = std::numeric_limits<Scalar>::max())
|
void Set(const ObjIter & _oBegin, const ObjIter & _oEnd, int size = 0, bool onlySelection = false)
|
||||||
{
|
{
|
||||||
if (maxDist < std::numeric_limits<Scalar>::max() && !mNodes[0].aabb.IsIn(queryPoint) && vcg::PointFilledBoxDistance(queryPoint, mNodes[0].aabb) >= maxDist)
|
mNodes.resize(1);
|
||||||
|
Node& node = mNodes.back();
|
||||||
|
node.leaf = 0;
|
||||||
|
node.aabb.Offset(VectorType(epsilon, epsilon, epsilon));
|
||||||
|
Box3<Scalar> box;
|
||||||
|
if (onlySelection)
|
||||||
|
{
|
||||||
|
for (ObjIter i = _oBegin; i != _oEnd; ++i)
|
||||||
|
{
|
||||||
|
if ((*i).IsS())
|
||||||
|
{
|
||||||
|
node.list.push_back(&(*i));
|
||||||
|
box.Add((*i).P(0));
|
||||||
|
box.Add((*i).P(1));
|
||||||
|
box.Add((*i).P(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (ObjIter i = _oBegin; i != _oEnd; ++i)
|
||||||
|
{
|
||||||
|
node.list.push_back(&(*i));
|
||||||
|
box.Add((*i).P(0));
|
||||||
|
box.Add((*i).P(1));
|
||||||
|
box.Add((*i).P(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node.aabb = box;
|
||||||
|
numLevel = CreateTree(0, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mNodes.size(); i++)
|
||||||
|
mNodes[i].list.clear();
|
||||||
|
mNodes.clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
//template <class ObjectMarker> FacePointer GetClosest(const VectorType& queryPoint, VectorType& narestPoint, Scalar& dist, ObjectMarker& marker, Scalar maxDist = std::numeric_limits<Scalar>::max())
|
||||||
|
template <class ObjPointDistFunction, class ObjectMarker>
|
||||||
|
FacePointer GetClosest(ObjPointDistFunction& pDistFunc, ObjectMarker& marker, const VectorType& queryPoint, Scalar maxDist, Scalar& dist, VectorType& narestPoint)
|
||||||
|
{
|
||||||
|
if (mNodes.size() == 0|| (maxDist < std::numeric_limits<Scalar>::max() && !mNodes[0].aabb.IsIn(queryPoint) && vcg::PointFilledBoxDistance(queryPoint, mNodes[0].aabb) >= maxDist))
|
||||||
{
|
{
|
||||||
dist = maxDist;
|
dist = maxDist;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -109,7 +157,7 @@ namespace vcg {
|
||||||
marker.Mark(node.list[i]);
|
marker.Mark(node.list[i]);
|
||||||
Scalar tempDist = minDist;
|
Scalar tempDist = minDist;
|
||||||
VectorType tempP;
|
VectorType tempP;
|
||||||
if (vcg::face::PointDistanceBase(*node.list[i], queryPoint, tempDist, tempP))
|
if (pDistFunc(*node.list[i], queryPoint, tempDist, tempP))
|
||||||
{
|
{
|
||||||
if (tempDist < minDist)
|
if (tempDist < minDist)
|
||||||
{
|
{
|
||||||
|
@ -176,7 +224,7 @@ namespace vcg {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int createTree(unsigned int nodeId, unsigned int level)
|
int CreateTree(unsigned int nodeId, unsigned int level)
|
||||||
{
|
{
|
||||||
Node& node = mNodes[nodeId];
|
Node& node = mNodes[nodeId];
|
||||||
VectorType diag = node.aabb.max - node.aabb.min;
|
VectorType diag = node.aabb.max - node.aabb.min;
|
||||||
|
@ -264,7 +312,7 @@ namespace vcg {
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
leftChild.leaf = 0;
|
leftChild.leaf = 0;
|
||||||
leftLevel = createTree(firstChildId, level + 1);
|
leftLevel = CreateTree(firstChildId, level + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,7 +326,7 @@ namespace vcg {
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rightChild.leaf = 0;
|
rightChild.leaf = 0;
|
||||||
rightLevel = createTree(firstChildId + 1, level + 1);
|
rightLevel = CreateTree(firstChildId + 1, level + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (leftLevel > rightLevel)
|
if (leftLevel > rightLevel)
|
||||||
|
|
|
@ -206,7 +206,7 @@ protected:
|
||||||
inSphVec.push_back(hi);
|
inSphVec.push_back(hi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return inSphVec.size();
|
return int(inSphVec.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t RemoveInSphere(const Point3<ScalarType> &p, const ScalarType radius)
|
size_t RemoveInSphere(const Point3<ScalarType> &p, const ScalarType radius)
|
||||||
|
|
|
@ -50,26 +50,26 @@ void ComputeCrossCovarianceMatrix(const std::vector<Point3<S> > &spVec, Point3<S
|
||||||
const std::vector<Point3<S> > &tpVec, Point3<S> &tpBarycenter,
|
const std::vector<Point3<S> > &tpVec, Point3<S> &tpBarycenter,
|
||||||
Eigen::Matrix3d &m)
|
Eigen::Matrix3d &m)
|
||||||
{
|
{
|
||||||
assert(spVec.size()==tpVec.size());
|
assert(spVec.size() == tpVec.size());
|
||||||
m.setZero();
|
m.setZero();
|
||||||
spBarycenter.SetZero();
|
spBarycenter.SetZero();
|
||||||
tpBarycenter.SetZero();
|
tpBarycenter.SetZero();
|
||||||
Eigen::Vector3d spe;
|
Eigen::Vector3d spe;
|
||||||
Eigen::Vector3d tpe;
|
Eigen::Vector3d tpe;
|
||||||
typename std::vector <Point3<S> >::const_iterator si,ti;
|
typename std::vector <Point3<S> >::const_iterator si, ti;
|
||||||
for(si=spVec.begin(),ti=tpVec.begin();si!=spVec.end();++si,++ti){
|
for (si = spVec.begin(), ti = tpVec.begin(); si != spVec.end(); ++si, ++ti){
|
||||||
spBarycenter+=*si;
|
spBarycenter += *si;
|
||||||
tpBarycenter+=*ti;
|
tpBarycenter += *ti;
|
||||||
si->ToEigenVector(spe);
|
si->ToEigenVector(spe);
|
||||||
ti->ToEigenVector(tpe);
|
ti->ToEigenVector(tpe);
|
||||||
m+=spe*tpe.transpose();
|
m += spe*tpe.transpose();
|
||||||
}
|
}
|
||||||
spBarycenter/=spVec.size();
|
spBarycenter /= double(spVec.size());
|
||||||
tpBarycenter/=tpVec.size();
|
tpBarycenter /= double(tpVec.size());
|
||||||
spBarycenter.ToEigenVector(spe);
|
spBarycenter.ToEigenVector(spe);
|
||||||
tpBarycenter.ToEigenVector(tpe);
|
tpBarycenter.ToEigenVector(tpe);
|
||||||
m/=spVec.size();
|
m /= double(spVec.size());
|
||||||
m-=spe*tpe.transpose();
|
m -= spe*tpe.transpose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Compute the roto-translation that applied to PMov bring them onto Pfix
|
/*! \brief Compute the roto-translation that applied to PMov bring them onto Pfix
|
||||||
|
|
|
@ -760,7 +760,7 @@ namespace Tags
|
||||||
class BindVertexInputTag : public XMLTag
|
class BindVertexInputTag : public XMLTag
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BindVertexInputTag(const QString& semantic,const QString& input_semantic,const QString& input_set)
|
BindVertexInputTag(const QString& semantic,const QString& input_semantic,const QString& /*input_set*/)
|
||||||
:XMLTag("bind_vertex_input")
|
:XMLTag("bind_vertex_input")
|
||||||
{
|
{
|
||||||
_attributes.push_back(TagAttribute("semantic",semantic));
|
_attributes.push_back(TagAttribute("semantic",semantic));
|
||||||
|
|
|
@ -97,7 +97,7 @@ namespace vcg
|
||||||
_perwire_noshading = true;
|
_perwire_noshading = true;
|
||||||
_persolid_noshading = false;
|
_persolid_noshading = false;
|
||||||
|
|
||||||
_perpoint_pointsize = 1.0f;
|
_perpoint_pointsize = 3.0f;
|
||||||
_perpoint_pointsmooth_enabled = false;
|
_perpoint_pointsmooth_enabled = false;
|
||||||
_perpoint_pointattenuation_enabled = true;
|
_perpoint_pointattenuation_enabled = true;
|
||||||
_perwire_wirewidth = 1.0f;
|
_perwire_wirewidth = 1.0f;
|
||||||
|
@ -296,7 +296,7 @@ namespace vcg
|
||||||
if (_glopts != NULL)
|
if (_glopts != NULL)
|
||||||
{
|
{
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
int size = _glopts->serialize(tmp);
|
size_t size = _glopts->serialize(tmp);
|
||||||
token[i] = str.substr(pos, size);
|
token[i] = str.substr(pos, size);
|
||||||
if (token[i].length() < size)
|
if (token[i].length() < size)
|
||||||
return false;
|
return false;
|
||||||
|
@ -1509,7 +1509,7 @@ namespace vcg
|
||||||
{
|
{
|
||||||
//qDebug("Indexed drawing");
|
//qDebug("Indexed drawing");
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_bohandle);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_bohandle);
|
||||||
glDrawElements(GL_TRIANGLES, _mesh.FN() * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_components, GL_UNSIGNED_INT, NULL);
|
glDrawElements(GL_TRIANGLES, GLsizei(_mesh.FN() * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_components), GL_UNSIGNED_INT, NULL);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1819,7 +1819,7 @@ namespace vcg
|
||||||
//qDebug("Indexed drawing");
|
//qDebug("Indexed drawing");
|
||||||
updateClientState(req);
|
updateClientState(req);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_bohandle);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_bohandle);
|
||||||
glDrawElements(GL_LINES, _edge.size() * _bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_components, GL_UNSIGNED_INT, NULL);
|
glDrawElements(GL_LINES, GLsizei(_edge.size() * _bo[INT_ATT_NAMES::ATT_EDGEINDICES]->_components), GL_UNSIGNED_INT, NULL);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
InternalRendAtts tmp;
|
InternalRendAtts tmp;
|
||||||
updateClientState(tmp);
|
updateClientState(tmp);
|
||||||
|
@ -2235,8 +2235,8 @@ namespace vcg
|
||||||
assert(nz >= 0);
|
assert(nz >= 0);
|
||||||
assert(nz < 2);
|
assert(nz < 2);
|
||||||
|
|
||||||
_v[0] = size_t(vcg::tri::Index(m, pe->V(nz)));;
|
_v[0] = GLuint(vcg::tri::Index(m, pe->V(nz)));;
|
||||||
_v[1] = size_t(vcg::tri::Index(m, pe->V((nz + 1) % 2)));
|
_v[1] = GLuint(vcg::tri::Index(m, pe->V((nz + 1) % 2)));
|
||||||
assert(_v[0] != _v[1]); // The face pointed by 'f' is Degenerate (two coincident vertexes)
|
assert(_v[0] != _v[1]); // The face pointed by 'f' is Degenerate (two coincident vertexes)
|
||||||
|
|
||||||
if (_v[0] > _v[1])
|
if (_v[0] > _v[1])
|
||||||
|
|
|
@ -226,7 +226,7 @@ public:
|
||||||
//err = glGetError();
|
//err = glGetError();
|
||||||
std::vector<FacePointer> result;
|
std::vector<FacePointer> result;
|
||||||
PickFace(x,y,m,result,width,height);
|
PickFace(x,y,m,result,width,height);
|
||||||
ScalarType LocalEpsilon(0.001);
|
ScalarType LocalEpsilon(ScalarType(0.001));
|
||||||
for(size_t i =0;i<result.size();++i)
|
for(size_t i =0;i<result.size();++i)
|
||||||
{
|
{
|
||||||
CoordType p = glProject(M,vp,CoordType::Construct(Barycenter(*(result[i])))) ;
|
CoordType p = glProject(M,vp,CoordType::Construct(Barycenter(*(result[i])))) ;
|
||||||
|
|
|
@ -139,7 +139,7 @@ void Rubberband::Render(QGLWidget* gla)
|
||||||
assert(!glGetError());
|
assert(!glGetError());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rubberband::RenderLine(QGLWidget* gla, Point3f AA, Point3f BB)
|
void Rubberband::RenderLine(QGLWidget* /*gla*/, Point3f AA, Point3f BB)
|
||||||
{
|
{
|
||||||
// Drawing of the line from AA to BB
|
// Drawing of the line from AA to BB
|
||||||
glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_LINE_BIT | GL_POINT_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT | GL_COLOR_BUFFER_BIT);
|
glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_LINE_BIT | GL_POINT_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT | GL_COLOR_BUFFER_BIT);
|
||||||
|
|
|
@ -234,7 +234,7 @@ namespace io {
|
||||||
if(AddDuplexVertexCoord(ListOfDuplexVert,Key(i,t)))
|
if(AddDuplexVertexCoord(ListOfDuplexVert,Key(i,t)))
|
||||||
{
|
{
|
||||||
VectorOfVertexType.push_back((*(*fi).V(k)));
|
VectorOfVertexType.push_back((*(*fi).V(k)));
|
||||||
ListOfDuplexVert[Key(i,t)] = VectorOfVertexType.size()-1;
|
ListOfDuplexVert[Key(i,t)] = int(VectorOfVertexType.size()-1);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,6 @@ namespace vcg {
|
||||||
static int Save(SaveMeshType &m, const char * filename, bool binary, PlyInfo &pi, CallBackPos *cb=0) // V1.0
|
static int Save(SaveMeshType &m, const char * filename, bool binary, PlyInfo &pi, CallBackPos *cb=0) // V1.0
|
||||||
{
|
{
|
||||||
FILE * fpout;
|
FILE * fpout;
|
||||||
int i;
|
|
||||||
const char * hbin = "binary_little_endian";
|
const char * hbin = "binary_little_endian";
|
||||||
const char * hasc = "ascii";
|
const char * hasc = "ascii";
|
||||||
const char * h;
|
const char * h;
|
||||||
|
@ -106,7 +105,7 @@ namespace vcg {
|
||||||
const int DGTVQ = vcg::tri::io::Precision<typename VertexType::QualityType>::digits();
|
const int DGTVQ = vcg::tri::io::Precision<typename VertexType::QualityType>::digits();
|
||||||
const int DGTVR = vcg::tri::io::Precision<typename VertexType::RadiusType>::digits();
|
const int DGTVR = vcg::tri::io::Precision<typename VertexType::RadiusType>::digits();
|
||||||
const int DGTFQ = vcg::tri::io::Precision<typename FaceType::QualityType>::digits();
|
const int DGTFQ = vcg::tri::io::Precision<typename FaceType::QualityType>::digits();
|
||||||
bool multit = false;
|
bool saveTexIndexFlag = false;
|
||||||
|
|
||||||
if(binary) h=hbin;
|
if(binary) h=hbin;
|
||||||
else h=hasc;
|
else h=hasc;
|
||||||
|
@ -127,10 +126,10 @@ namespace vcg {
|
||||||
{
|
{
|
||||||
const char * TFILE = "TextureFile";
|
const char * TFILE = "TextureFile";
|
||||||
|
|
||||||
for(i=0; i < static_cast<int>(m.textures.size()); ++i)
|
for(size_t i=0; i < m.textures.size(); ++i)
|
||||||
fprintf(fpout,"comment %s %s\n", TFILE, (const char *)(m.textures[i].c_str()) );
|
fprintf(fpout,"comment %s %s\n", TFILE, (const char *)(m.textures[i].c_str()) );
|
||||||
|
|
||||||
if(m.textures.size()>1 && (HasPerWedgeTexCoord(m) || HasPerVertexTexCoord(m))) multit = true;
|
if(m.textures.size()>1 && (HasPerWedgeTexCoord(m) || HasPerVertexTexCoord(m))) saveTexIndexFlag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((pi.mask & Mask::IOM_CAMERA))
|
if((pi.mask & Mask::IOM_CAMERA))
|
||||||
|
@ -211,8 +210,8 @@ namespace vcg {
|
||||||
"property float texture_v\n"
|
"property float texture_v\n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
for(i=0;i<pi.vdn;i++)
|
for(size_t i=0;i<pi.VertDescriptorVec.size();i++)
|
||||||
fprintf(fpout,"property %s %s\n",pi.VertexData[i].stotypename(),pi.VertexData[i].propname);
|
fprintf(fpout,"property %s %s\n",pi.VertDescriptorVec[i].stotypename(),pi.VertDescriptorVec[i].propname);
|
||||||
|
|
||||||
fprintf(fpout,
|
fprintf(fpout,
|
||||||
"element face %d\n"
|
"element face %d\n"
|
||||||
|
@ -226,14 +225,22 @@ namespace vcg {
|
||||||
"property int flags\n"
|
"property int flags\n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (HasPerWedgeTexCoord(m) || HasPerVertexTexCoord(m) ) && pi.mask & Mask::IOM_WEDGTEXCOORD ) // Note that you can save VT as WT if you really want it...
|
if( (HasPerWedgeTexCoord(m) && pi.mask & Mask::IOM_WEDGTEXCOORD ) ||
|
||||||
|
(HasPerVertexTexCoord(m) && (!HasPerWedgeTexCoord(m)) && pi.mask & Mask::IOM_WEDGTEXCOORD ) ) // Note that you can save VT as WT if you really really want it...
|
||||||
{
|
{
|
||||||
fprintf(fpout,
|
fprintf(fpout,
|
||||||
"property list uchar float texcoord\n"
|
"property list uchar float texcoord\n"
|
||||||
);
|
);
|
||||||
|
}
|
||||||
if(multit)
|
// The texture index information has to be saved for each face (if necessary) both for PerVert and PerWedg
|
||||||
|
if( saveTexIndexFlag &&
|
||||||
|
( ( HasPerWedgeTexCoord(m) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) ||
|
||||||
|
( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_VERTTEXCOORD) ) ||
|
||||||
|
( HasPerVertexTexCoord(m) && (!HasPerWedgeTexCoord(m)) && (pi.mask & Mask::IOM_WEDGTEXCOORD) )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
fprintf(fpout,
|
fprintf(fpout,
|
||||||
"property int texnumber\n"
|
"property int texnumber\n"
|
||||||
);
|
);
|
||||||
|
@ -262,8 +269,8 @@ namespace vcg {
|
||||||
fprintf(fpout,"property %s quality\n",fqtp);
|
fprintf(fpout,"property %s quality\n",fqtp);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i=0;i<pi.fdn;i++)
|
for(size_t i=0;i<pi.FaceDescriptorVec.size();i++)
|
||||||
fprintf(fpout,"property %s %s\n",pi.FaceData[i].stotypename(),pi.FaceData[i].propname);
|
fprintf(fpout,"property %s %s\n",pi.FaceDescriptorVec[i].stotypename(),pi.FaceDescriptorVec[i].propname);
|
||||||
// Saving of edges is enabled if requested
|
// Saving of edges is enabled if requested
|
||||||
if( m.en>0 && (pi.mask & Mask::IOM_EDGEINDEX) )
|
if( m.en>0 && (pi.mask & Mask::IOM_EDGEINDEX) )
|
||||||
fprintf(fpout,
|
fprintf(fpout,
|
||||||
|
@ -344,7 +351,59 @@ namespace vcg {
|
||||||
VertexPointer vp;
|
VertexPointer vp;
|
||||||
VertexIterator vi;
|
VertexIterator vi;
|
||||||
SimpleTempData<typename SaveMeshType::VertContainer,int> indices(m.vert);
|
SimpleTempData<typename SaveMeshType::VertContainer,int> indices(m.vert);
|
||||||
|
|
||||||
|
std::vector<typename SaveMeshType:: template PerVertexAttributeHandle<float > > thfv(pi.VertDescriptorVec.size());
|
||||||
|
std::vector<typename SaveMeshType:: template PerVertexAttributeHandle<double> > thdv(pi.VertDescriptorVec.size());
|
||||||
|
std::vector<typename SaveMeshType:: template PerVertexAttributeHandle<int > > thiv(pi.VertDescriptorVec.size());
|
||||||
|
std::vector<typename SaveMeshType:: template PerVertexAttributeHandle<short > > thsv(pi.VertDescriptorVec.size());
|
||||||
|
std::vector<typename SaveMeshType:: template PerVertexAttributeHandle<char > > thcv(pi.VertDescriptorVec.size());
|
||||||
|
std::vector<typename SaveMeshType:: template PerVertexAttributeHandle<unsigned char> > thuv(pi.VertDescriptorVec.size());
|
||||||
|
|
||||||
|
for(size_t i=0;i<pi.VertDescriptorVec.size();i++)
|
||||||
|
{
|
||||||
|
if(!pi.VertAttrNameVec.empty() && !pi.VertAttrNameVec[i].empty())
|
||||||
|
{ // trying to use named attribute to retrieve the value to store
|
||||||
|
assert(vcg::tri::HasPerVertexAttribute(m,pi.VertAttrNameVec[i]));
|
||||||
|
switch (pi.VertDescriptorVec[i].stotype1)
|
||||||
|
{
|
||||||
|
case ply::T_FLOAT : thfv[i] = vcg::tri::Allocator<SaveMeshType>::template FindPerVertexAttribute<float>(m,pi.VertAttrNameVec[i]); break;
|
||||||
|
case ply::T_DOUBLE : thdv[i] = vcg::tri::Allocator<SaveMeshType>::template FindPerVertexAttribute<double>(m,pi.VertAttrNameVec[i]); break;
|
||||||
|
case ply::T_INT : thiv[i] = vcg::tri::Allocator<SaveMeshType>::template FindPerVertexAttribute<int >(m,pi.VertAttrNameVec[i]); break;
|
||||||
|
case ply::T_SHORT : thsv[i] = vcg::tri::Allocator<SaveMeshType>::template FindPerVertexAttribute<short >(m,pi.VertAttrNameVec[i]); break;
|
||||||
|
case ply::T_CHAR : thcv[i] = vcg::tri::Allocator<SaveMeshType>::template FindPerVertexAttribute<char>(m,pi.VertAttrNameVec[i]); break;
|
||||||
|
case ply::T_UCHAR : thuv[i] = vcg::tri::Allocator<SaveMeshType>::template FindPerVertexAttribute<unsigned char>(m,pi.VertAttrNameVec[i]); break;
|
||||||
|
default : assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::vector<typename SaveMeshType:: template PerFaceAttributeHandle<float > > thff(pi.FaceDescriptorVec.size());
|
||||||
|
std::vector<typename SaveMeshType:: template PerFaceAttributeHandle<double> > thdf(pi.FaceDescriptorVec.size());
|
||||||
|
std::vector<typename SaveMeshType:: template PerFaceAttributeHandle<int > > thif(pi.FaceDescriptorVec.size());
|
||||||
|
std::vector<typename SaveMeshType:: template PerFaceAttributeHandle<short > > thsf(pi.FaceDescriptorVec.size());
|
||||||
|
std::vector<typename SaveMeshType:: template PerFaceAttributeHandle<char > > thcf(pi.FaceDescriptorVec.size());
|
||||||
|
std::vector<typename SaveMeshType:: template PerFaceAttributeHandle<unsigned char> > thuf(pi.FaceDescriptorVec.size());
|
||||||
|
|
||||||
|
for(size_t i=0;i<pi.FaceDescriptorVec.size();i++)
|
||||||
|
{
|
||||||
|
if(!pi.FaceAttrNameVec.empty() && !pi.FaceAttrNameVec[i].empty())
|
||||||
|
{ // trying to use named attribute to retrieve the value to store
|
||||||
|
assert(vcg::tri::HasPerFaceAttribute(m,pi.FaceAttrNameVec[i]));
|
||||||
|
switch (pi.FaceDescriptorVec[i].stotype1)
|
||||||
|
{
|
||||||
|
case ply::T_FLOAT : thff[i] = vcg::tri::Allocator<SaveMeshType>::template FindPerFaceAttribute<float>(m,pi.FaceAttrNameVec[i]); break;
|
||||||
|
case ply::T_DOUBLE : thdf[i] = vcg::tri::Allocator<SaveMeshType>::template FindPerFaceAttribute<double>(m,pi.FaceAttrNameVec[i]); break;
|
||||||
|
case ply::T_INT : thif[i] = vcg::tri::Allocator<SaveMeshType>::template FindPerFaceAttribute<int >(m,pi.FaceAttrNameVec[i]); break;
|
||||||
|
case ply::T_SHORT : thsf[i] = vcg::tri::Allocator<SaveMeshType>::template FindPerFaceAttribute<short >(m,pi.FaceAttrNameVec[i]); break;
|
||||||
|
case ply::T_CHAR : thcf[i] = vcg::tri::Allocator<SaveMeshType>::template FindPerFaceAttribute<char>(m,pi.FaceAttrNameVec[i]); break;
|
||||||
|
case ply::T_UCHAR : thuf[i] = vcg::tri::Allocator<SaveMeshType>::template FindPerFaceAttribute<unsigned char>(m,pi.FaceAttrNameVec[i]); break;
|
||||||
|
default : assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for(j=0,vi=m.vert.begin();vi!=m.vert.end();++vi){
|
for(j=0,vi=m.vert.begin();vi!=m.vert.end();++vi){
|
||||||
vp=&(*vi);
|
vp=&(*vi);
|
||||||
indices[vi] = j;
|
indices[vi] = j;
|
||||||
|
@ -381,22 +440,39 @@ namespace vcg {
|
||||||
|
|
||||||
if( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_VERTTEXCOORD) )
|
if( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_VERTTEXCOORD) )
|
||||||
{
|
{
|
||||||
t = float(vp->T().u()); fwrite(&t,sizeof(float),1,fpout);
|
t = ScalarType(vp->T().u()); fwrite(&t,sizeof(ScalarType),1,fpout);
|
||||||
t = float(vp->T().v()); fwrite(&t,sizeof(float),1,fpout);
|
t = ScalarType(vp->T().v()); fwrite(&t,sizeof(ScalarType),1,fpout);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i=0;i<pi.vdn;i++)
|
for(size_t i=0;i<pi.VertDescriptorVec.size();i++)
|
||||||
{
|
{
|
||||||
double td(0); float tf(0);int ti;short ts; char tc; unsigned char tuc;
|
double td(0); float tf(0);int ti;short ts; char tc; unsigned char tu;
|
||||||
switch (pi.VertexData[i].stotype1)
|
if(!pi.VertAttrNameVec.empty() && !pi.VertAttrNameVec[i].empty())
|
||||||
|
{ // trying to use named attribute to retrieve the value to store
|
||||||
|
assert(vcg::tri::HasPerVertexAttribute(m,pi.VertAttrNameVec[i]));
|
||||||
|
switch (pi.VertDescriptorVec[i].stotype1)
|
||||||
|
{
|
||||||
|
case ply::T_FLOAT : tf=thfv[i][vp]; fwrite(&tf, sizeof(float),1,fpout); break;
|
||||||
|
case ply::T_DOUBLE : td=thdv[i][vp]; fwrite(&td, sizeof(double),1,fpout); break;
|
||||||
|
case ply::T_INT : ti=thiv[i][vp]; fwrite(&ti, sizeof(int),1,fpout); break;
|
||||||
|
case ply::T_SHORT : ts=thsv[i][vp]; fwrite(&ts, sizeof(short),1,fpout); break;
|
||||||
|
case ply::T_CHAR : tc=thcv[i][vp]; fwrite(&tc, sizeof(char),1,fpout); break;
|
||||||
|
case ply::T_UCHAR : tu=thuv[i][vp]; fwrite(&tu,sizeof(unsigned char),1,fpout); break;
|
||||||
|
default : assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
case ply::T_FLOAT : PlyConv(pi.VertexData[i].memtype1, ((char *)vp)+pi.VertexData[i].offset1, tf ); fwrite(&tf, sizeof(float),1,fpout); break;
|
switch (pi.VertDescriptorVec[i].stotype1)
|
||||||
case ply::T_DOUBLE : PlyConv(pi.VertexData[i].memtype1, ((char *)vp)+pi.VertexData[i].offset1, td ); fwrite(&td, sizeof(double),1,fpout); break;
|
{
|
||||||
case ply::T_INT : PlyConv(pi.VertexData[i].memtype1, ((char *)vp)+pi.VertexData[i].offset1, ti ); fwrite(&ti, sizeof(int),1,fpout); break;
|
case ply::T_FLOAT : PlyConv(pi.VertDescriptorVec[i].memtype1, ((char *)vp)+pi.VertDescriptorVec[i].offset1, tf ); fwrite(&tf, sizeof(float),1,fpout); break;
|
||||||
case ply::T_SHORT : PlyConv(pi.VertexData[i].memtype1, ((char *)vp)+pi.VertexData[i].offset1, ts ); fwrite(&ts, sizeof(short),1,fpout); break;
|
case ply::T_DOUBLE : PlyConv(pi.VertDescriptorVec[i].memtype1, ((char *)vp)+pi.VertDescriptorVec[i].offset1, td ); fwrite(&td, sizeof(double),1,fpout); break;
|
||||||
case ply::T_CHAR : PlyConv(pi.VertexData[i].memtype1, ((char *)vp)+pi.VertexData[i].offset1, tc ); fwrite(&tc, sizeof(char),1,fpout); break;
|
case ply::T_INT : PlyConv(pi.VertDescriptorVec[i].memtype1, ((char *)vp)+pi.VertDescriptorVec[i].offset1, ti ); fwrite(&ti, sizeof(int),1,fpout); break;
|
||||||
case ply::T_UCHAR : PlyConv(pi.VertexData[i].memtype1, ((char *)vp)+pi.VertexData[i].offset1, tuc); fwrite(&tuc,sizeof(unsigned char),1,fpout); break;
|
case ply::T_SHORT : PlyConv(pi.VertDescriptorVec[i].memtype1, ((char *)vp)+pi.VertDescriptorVec[i].offset1, ts ); fwrite(&ts, sizeof(short),1,fpout); break;
|
||||||
default : assert(0);
|
case ply::T_CHAR : PlyConv(pi.VertDescriptorVec[i].memtype1, ((char *)vp)+pi.VertDescriptorVec[i].offset1, tc ); fwrite(&tc, sizeof(char),1,fpout); break;
|
||||||
|
case ply::T_UCHAR : PlyConv(pi.VertDescriptorVec[i].memtype1, ((char *)vp)+pi.VertDescriptorVec[i].offset1, tu ); fwrite(&tu,sizeof(unsigned char),1,fpout); break;
|
||||||
|
default : assert(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -422,19 +498,35 @@ namespace vcg {
|
||||||
if( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_VERTTEXCOORD) )
|
if( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_VERTTEXCOORD) )
|
||||||
fprintf(fpout,"%f %f",vp->T().u(),vp->T().v());
|
fprintf(fpout,"%f %f",vp->T().u(),vp->T().v());
|
||||||
|
|
||||||
for(i=0;i<pi.vdn;i++)
|
for(size_t i=0;i<pi.VertDescriptorVec.size();i++)
|
||||||
{
|
{
|
||||||
float tf(0); double td(0);
|
float tf(0); double td(0); int ti;
|
||||||
int ti;
|
if(!pi.VertAttrNameVec.empty() && !pi.VertAttrNameVec[i].empty())
|
||||||
switch (pi.VertexData[i].memtype1)
|
{ // trying to use named attribute to retrieve the value to store
|
||||||
|
assert(vcg::tri::HasPerVertexAttribute(m,pi.VertAttrNameVec[i]));
|
||||||
|
switch (pi.VertDescriptorVec[i].stotype1)
|
||||||
|
{
|
||||||
|
case ply::T_FLOAT : tf=thfv[i][vp]; fprintf(fpout,"%f ",tf); break;
|
||||||
|
case ply::T_DOUBLE : td=thdv[i][vp]; fprintf(fpout,"%lf ",td); break;
|
||||||
|
case ply::T_INT : ti=thiv[i][vp]; fprintf(fpout,"%i ",ti); break;
|
||||||
|
case ply::T_SHORT : ti=thsv[i][vp]; fprintf(fpout,"%i ",ti); break;
|
||||||
|
case ply::T_CHAR : ti=thcv[i][vp]; fprintf(fpout,"%i ",ti); break;
|
||||||
|
case ply::T_UCHAR : ti=thuv[i][vp]; fprintf(fpout,"%i ",ti); break;
|
||||||
|
default : assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
case ply::T_FLOAT : tf=*( (float *) (((char *)vp)+pi.VertexData[i].offset1)); fprintf(fpout,"%f ",tf); break;
|
switch (pi.VertDescriptorVec[i].memtype1)
|
||||||
case ply::T_DOUBLE : td=*( (double *) (((char *)vp)+pi.VertexData[i].offset1)); fprintf(fpout,"%f ",tf); break;
|
{
|
||||||
case ply::T_INT : ti=*( (int *) (((char *)vp)+pi.VertexData[i].offset1)); fprintf(fpout,"%i ",ti); break;
|
case ply::T_FLOAT : tf=*( (float *) (((char *)vp)+pi.VertDescriptorVec[i].offset1)); fprintf(fpout,"%f ",tf); break;
|
||||||
case ply::T_SHORT : ti=*( (short *) (((char *)vp)+pi.VertexData[i].offset1)); fprintf(fpout,"%i ",ti); break;
|
case ply::T_DOUBLE : td=*( (double *) (((char *)vp)+pi.VertDescriptorVec[i].offset1)); fprintf(fpout,"%f ",tf); break;
|
||||||
case ply::T_CHAR : ti=*( (char *) (((char *)vp)+pi.VertexData[i].offset1)); fprintf(fpout,"%i ",ti); break;
|
case ply::T_INT : ti=*( (int *) (((char *)vp)+pi.VertDescriptorVec[i].offset1)); fprintf(fpout,"%i ",ti); break;
|
||||||
case ply::T_UCHAR : ti=*( (unsigned char *) (((char *)vp)+pi.VertexData[i].offset1)); fprintf(fpout,"%i ",ti); break;
|
case ply::T_SHORT : ti=*( (short *) (((char *)vp)+pi.VertDescriptorVec[i].offset1)); fprintf(fpout,"%i ",ti); break;
|
||||||
default : assert(0);
|
case ply::T_CHAR : ti=*( (char *) (((char *)vp)+pi.VertDescriptorVec[i].offset1)); fprintf(fpout,"%i ",ti); break;
|
||||||
|
case ply::T_UCHAR : ti=*( (unsigned char *) (((char *)vp)+pi.VertDescriptorVec[i].offset1)); fprintf(fpout,"%i ",ti); break;
|
||||||
|
default : assert(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,9 +539,9 @@ namespace vcg {
|
||||||
// this assert triggers when the vn != number of vertexes in vert that are not deleted.
|
// this assert triggers when the vn != number of vertexes in vert that are not deleted.
|
||||||
assert(j==m.vn);
|
assert(j==m.vn);
|
||||||
|
|
||||||
char c = 3;
|
unsigned char b3char = 3;
|
||||||
unsigned char b9 = 9;
|
unsigned char b9char = 9;
|
||||||
unsigned char b6 = 6;
|
unsigned char b6char = 6;
|
||||||
FacePointer fp;
|
FacePointer fp;
|
||||||
int vv[3];
|
int vv[3];
|
||||||
FaceIterator fi;
|
FaceIterator fi;
|
||||||
|
@ -468,15 +560,15 @@ namespace vcg {
|
||||||
vv[0]=indices[fp->cV(0)];
|
vv[0]=indices[fp->cV(0)];
|
||||||
vv[1]=indices[fp->cV(1)];
|
vv[1]=indices[fp->cV(1)];
|
||||||
vv[2]=indices[fp->cV(2)];
|
vv[2]=indices[fp->cV(2)];
|
||||||
fwrite(&c,1,1,fpout);
|
fwrite(&b3char,sizeof(char),1,fpout);
|
||||||
fwrite(vv,sizeof(int),3,fpout);
|
fwrite(vv,sizeof(int),3,fpout);
|
||||||
|
|
||||||
if(HasPerFaceFlags(m)&&( pi.mask & Mask::IOM_FACEFLAGS) )
|
if(HasPerFaceFlags(m)&&( pi.mask & Mask::IOM_FACEFLAGS) )
|
||||||
fwrite(&(fp->Flags()),sizeof(int),1,fpout);
|
fwrite(&(fp->Flags()),sizeof(int),1,fpout);
|
||||||
|
|
||||||
if( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_VERTTEXCOORD) )
|
if( HasPerVertexTexCoord(m) && (!HasPerWedgeTexCoord(m)) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) // Note that you can save VT as WT if you really want it...
|
||||||
{
|
{
|
||||||
fwrite(&b6,sizeof(char),1,fpout);
|
fwrite(&b6char,sizeof(char),1,fpout);
|
||||||
float t[6];
|
float t[6];
|
||||||
for(int k=0;k<3;++k)
|
for(int k=0;k<3;++k)
|
||||||
{
|
{
|
||||||
|
@ -487,7 +579,7 @@ namespace vcg {
|
||||||
}
|
}
|
||||||
else if( HasPerWedgeTexCoord(m) && (pi.mask & Mask::IOM_WEDGTEXCOORD) )
|
else if( HasPerWedgeTexCoord(m) && (pi.mask & Mask::IOM_WEDGTEXCOORD) )
|
||||||
{
|
{
|
||||||
fwrite(&b6,sizeof(char),1,fpout);
|
fwrite(&b6char,sizeof(char),1,fpout);
|
||||||
float t[6];
|
float t[6];
|
||||||
for(int k=0;k<3;++k)
|
for(int k=0;k<3;++k)
|
||||||
{
|
{
|
||||||
|
@ -497,7 +589,7 @@ namespace vcg {
|
||||||
fwrite(t,sizeof(float),6,fpout);
|
fwrite(t,sizeof(float),6,fpout);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(multit)
|
if(saveTexIndexFlag)
|
||||||
{
|
{
|
||||||
int t = fp->WT(0).n();
|
int t = fp->WT(0).n();
|
||||||
fwrite(&t,sizeof(int),1,fpout);
|
fwrite(&t,sizeof(int),1,fpout);
|
||||||
|
@ -509,7 +601,7 @@ namespace vcg {
|
||||||
|
|
||||||
if( HasPerWedgeColor(m) && (pi.mask & Mask::IOM_WEDGCOLOR) )
|
if( HasPerWedgeColor(m) && (pi.mask & Mask::IOM_WEDGCOLOR) )
|
||||||
{
|
{
|
||||||
fwrite(&b9,sizeof(char),1,fpout);
|
fwrite(&b9char,sizeof(char),1,fpout);
|
||||||
float t[3];
|
float t[3];
|
||||||
for(int z=0;z<3;++z)
|
for(int z=0;z<3;++z)
|
||||||
{
|
{
|
||||||
|
@ -524,17 +616,34 @@ namespace vcg {
|
||||||
fwrite( &(fp->Q()),sizeof(typename FaceType::ScalarType),1,fpout);
|
fwrite( &(fp->Q()),sizeof(typename FaceType::ScalarType),1,fpout);
|
||||||
|
|
||||||
|
|
||||||
for(i=0;i<pi.fdn;i++)
|
for(size_t i=0;i<pi.FaceDescriptorVec.size();i++)
|
||||||
{
|
{
|
||||||
double td(0); float tf(0);int ti;short ts; char tc; unsigned char tuc;
|
double td(0); float tf(0);int ti;short ts; char tc; unsigned char tu;
|
||||||
switch (pi.FaceData[i].stotype1){
|
if(!pi.FaceAttrNameVec.empty() && !pi.FaceAttrNameVec[i].empty())
|
||||||
case ply::T_FLOAT : PlyConv(pi.FaceData[i].memtype1, ((char *)fp)+pi.FaceData[i].offset1, tf ); fwrite(&tf, sizeof(float),1,fpout); break;
|
{ // trying to use named attribute to retrieve the value to store
|
||||||
case ply::T_DOUBLE : PlyConv(pi.FaceData[i].memtype1, ((char *)fp)+pi.FaceData[i].offset1, td ); fwrite(&td, sizeof(double),1,fpout); break;
|
assert(vcg::tri::HasPerFaceAttribute(m,pi.FaceAttrNameVec[i]));
|
||||||
case ply::T_INT : PlyConv(pi.FaceData[i].memtype1, ((char *)fp)+pi.FaceData[i].offset1, ti ); fwrite(&ti, sizeof(int),1,fpout); break;
|
switch (pi.FaceDescriptorVec[i].stotype1)
|
||||||
case ply::T_SHORT : PlyConv(pi.FaceData[i].memtype1, ((char *)fp)+pi.FaceData[i].offset1, ts ); fwrite(&ts, sizeof(short),1,fpout); break;
|
{
|
||||||
case ply::T_CHAR : PlyConv(pi.FaceData[i].memtype1, ((char *)fp)+pi.FaceData[i].offset1, tc ); fwrite(&tc, sizeof(char),1,fpout); break;
|
case ply::T_FLOAT : tf=thff[i][fp]; fwrite(&tf, sizeof(float),1,fpout); break;
|
||||||
case ply::T_UCHAR : PlyConv(pi.FaceData[i].memtype1, ((char *)fp)+pi.FaceData[i].offset1, tuc); fwrite(&tuc,sizeof(unsigned char),1,fpout); break;
|
case ply::T_DOUBLE : td=thdf[i][fp]; fwrite(&td, sizeof(double),1,fpout); break;
|
||||||
default : assert(0);
|
case ply::T_INT : ti=thif[i][fp]; fwrite(&ti, sizeof(int),1,fpout); break;
|
||||||
|
case ply::T_SHORT : ts=thsf[i][fp]; fwrite(&ts, sizeof(short),1,fpout); break;
|
||||||
|
case ply::T_CHAR : tc=thcf[i][fp]; fwrite(&tc, sizeof(char),1,fpout); break;
|
||||||
|
case ply::T_UCHAR : tu=thuf[i][fp]; fwrite(&tu,sizeof(unsigned char),1,fpout); break;
|
||||||
|
default : assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (pi.FaceDescriptorVec[i].stotype1){
|
||||||
|
case ply::T_FLOAT : PlyConv(pi.FaceDescriptorVec[i].memtype1, ((char *)fp)+pi.FaceDescriptorVec[i].offset1, tf ); fwrite(&tf, sizeof(float),1,fpout); break;
|
||||||
|
case ply::T_DOUBLE : PlyConv(pi.FaceDescriptorVec[i].memtype1, ((char *)fp)+pi.FaceDescriptorVec[i].offset1, td ); fwrite(&td, sizeof(double),1,fpout); break;
|
||||||
|
case ply::T_INT : PlyConv(pi.FaceDescriptorVec[i].memtype1, ((char *)fp)+pi.FaceDescriptorVec[i].offset1, ti ); fwrite(&ti, sizeof(int),1,fpout); break;
|
||||||
|
case ply::T_SHORT : PlyConv(pi.FaceDescriptorVec[i].memtype1, ((char *)fp)+pi.FaceDescriptorVec[i].offset1, ts ); fwrite(&ts, sizeof(short),1,fpout); break;
|
||||||
|
case ply::T_CHAR : PlyConv(pi.FaceDescriptorVec[i].memtype1, ((char *)fp)+pi.FaceDescriptorVec[i].offset1, tc ); fwrite(&tc, sizeof(char),1,fpout); break;
|
||||||
|
case ply::T_UCHAR : PlyConv(pi.FaceDescriptorVec[i].memtype1, ((char *)fp)+pi.FaceDescriptorVec[i].offset1, tu ); fwrite(&tu, sizeof(unsigned char),1,fpout); break;
|
||||||
|
default : assert(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -566,7 +675,7 @@ namespace vcg {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(multit)
|
if(saveTexIndexFlag)
|
||||||
{
|
{
|
||||||
fprintf(fpout,"%d ",fp->WT(0).n());
|
fprintf(fpout,"%d ",fp->WT(0).n());
|
||||||
}
|
}
|
||||||
|
@ -589,20 +698,36 @@ namespace vcg {
|
||||||
if( HasPerFaceQuality(m) && (pi.mask & Mask::IOM_FACEQUALITY) )
|
if( HasPerFaceQuality(m) && (pi.mask & Mask::IOM_FACEQUALITY) )
|
||||||
fprintf(fpout,"%.*g ",DGTFQ,fp->Q());
|
fprintf(fpout,"%.*g ",DGTFQ,fp->Q());
|
||||||
|
|
||||||
for(i=0;i<pi.fdn;i++)
|
for(size_t i=0;i<pi.FaceDescriptorVec.size();i++)
|
||||||
{
|
{
|
||||||
float tf(0); double td(0);
|
float tf(0); double td(0); int ti;
|
||||||
int ti;
|
if(!pi.FaceAttrNameVec.empty() && !pi.FaceAttrNameVec[i].empty())
|
||||||
switch (pi.FaceData[i].memtype1)
|
{ // trying to use named attribute to retrieve the value to store
|
||||||
|
assert(vcg::tri::HasPerFaceAttribute(m,pi.FaceAttrNameVec[i]));
|
||||||
|
switch (pi.FaceDescriptorVec[i].stotype1)
|
||||||
{
|
{
|
||||||
case ply::T_FLOAT : tf=*( (float *) (((char *)fp)+pi.FaceData[i].offset1)); fprintf(fpout,"%g ",tf); break;
|
case ply::T_FLOAT : tf=thff[i][fp]; fprintf(fpout,"%f ",tf); break;
|
||||||
case ply::T_DOUBLE : td=*( (double *) (((char *)fp)+pi.FaceData[i].offset1)); fprintf(fpout,"%g ",tf); break;
|
case ply::T_DOUBLE : td=thdf[i][fp]; fprintf(fpout,"%g ",td); break;
|
||||||
case ply::T_INT : ti=*( (int *) (((char *)fp)+pi.FaceData[i].offset1)); fprintf(fpout,"%i ",ti); break;
|
case ply::T_INT : ti=thif[i][fp]; fprintf(fpout,"%i ",ti); break;
|
||||||
case ply::T_SHORT : ti=*( (short *) (((char *)fp)+pi.FaceData[i].offset1)); fprintf(fpout,"%i ",ti); break;
|
case ply::T_SHORT : ti=thsf[i][fp]; fprintf(fpout,"%i ",ti); break;
|
||||||
case ply::T_CHAR : ti=*( (char *) (((char *)fp)+pi.FaceData[i].offset1)); fprintf(fpout,"%i ",ti); break;
|
case ply::T_CHAR : ti=thcf[i][fp]; fprintf(fpout,"%i ",ti); break;
|
||||||
case ply::T_UCHAR : ti=*( (unsigned char *) (((char *)fp)+pi.FaceData[i].offset1)); fprintf(fpout,"%i ",ti); break;
|
case ply::T_UCHAR : ti=thuf[i][fp]; fprintf(fpout,"%i ",ti); break;
|
||||||
default : assert(0);
|
default : assert(0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (pi.FaceDescriptorVec[i].memtype1)
|
||||||
|
{
|
||||||
|
case ply::T_FLOAT : tf=*( (float *) (((char *)fp)+pi.FaceDescriptorVec[i].offset1)); fprintf(fpout,"%g ",tf); break;
|
||||||
|
case ply::T_DOUBLE : td=*( (double *) (((char *)fp)+pi.FaceDescriptorVec[i].offset1)); fprintf(fpout,"%g ",tf); break;
|
||||||
|
case ply::T_INT : ti=*( (int *) (((char *)fp)+pi.FaceDescriptorVec[i].offset1)); fprintf(fpout,"%i ",ti); break;
|
||||||
|
case ply::T_SHORT : ti=*( (short *) (((char *)fp)+pi.FaceDescriptorVec[i].offset1)); fprintf(fpout,"%i ",ti); break;
|
||||||
|
case ply::T_CHAR : ti=*( (char *) (((char *)fp)+pi.FaceDescriptorVec[i].offset1)); fprintf(fpout,"%i ",ti); break;
|
||||||
|
case ply::T_UCHAR : ti=*( (unsigned char *) (((char *)fp)+pi.FaceDescriptorVec[i].offset1)); fprintf(fpout,"%i ",ti); break;
|
||||||
|
default : assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fpout,"\n");
|
fprintf(fpout,"\n");
|
||||||
|
|
|
@ -65,7 +65,7 @@ namespace vcg {
|
||||||
typedef typename SaveMeshType::FaceIterator FaceIterator;
|
typedef typename SaveMeshType::FaceIterator FaceIterator;
|
||||||
|
|
||||||
///Standard call for saving a mesh
|
///Standard call for saving a mesh
|
||||||
static int Save(SaveMeshType &m, const char * filename, const int &mask, CallBackPos */*cb=0*/)
|
static int Save(SaveMeshType &m, const char * filename, const int &mask, CallBackPos * /*cb=0*/)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
fp = fopen(filename,"wb");
|
fp = fopen(filename,"wb");
|
||||||
|
|
|
@ -87,7 +87,7 @@ static const char* ErrorMsg(int error)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static int Open( OpenMeshType &m, const char * filename, int &loadmask, CallBackPos */*cb*/=0)
|
static int Open( OpenMeshType &m, const char * filename, int &loadmask, CallBackPos * /*cb*/=0)
|
||||||
{
|
{
|
||||||
CTMcontext context;
|
CTMcontext context;
|
||||||
|
|
||||||
|
|
|
@ -154,7 +154,7 @@ static int Open( OpenMeshType &m, std::vector<Shot<ScalarType> > & shots,
|
||||||
shots[i].Intrinsics.FocalMm = f/100.0f;
|
shots[i].Intrinsics.FocalMm = f/100.0f;
|
||||||
shots[i].Intrinsics.k[0] = 0.0;//k1; To be uncommented when distortion is taken into account reliably
|
shots[i].Intrinsics.k[0] = 0.0;//k1; To be uncommented when distortion is taken into account reliably
|
||||||
shots[i].Intrinsics.k[1] = 0.0;//k2;
|
shots[i].Intrinsics.k[1] = 0.0;//k2;
|
||||||
shots[i].Intrinsics.PixelSizeMm = vcg::Point2<ScalarType>(0.01,0.01);
|
shots[i].Intrinsics.PixelSizeMm = vcg::Point2<ScalarType>(ScalarType(0.01), ScalarType(0.01));
|
||||||
QImageReader sizeImg(QString::fromStdString(image_filenames[i]));
|
QImageReader sizeImg(QString::fromStdString(image_filenames[i]));
|
||||||
QSize size=sizeImg.size();
|
QSize size=sizeImg.size();
|
||||||
shots[i].Intrinsics.ViewportPx = vcg::Point2i(size.width(),size.height());
|
shots[i].Intrinsics.ViewportPx = vcg::Point2i(size.width(),size.height());
|
||||||
|
|
|
@ -615,6 +615,15 @@ namespace vcg {
|
||||||
}
|
}
|
||||||
else if ((header.compare("usemtl")==0) && (tokens.size() > 1)) // material usage
|
else if ((header.compare("usemtl")==0) && (tokens.size() > 1)) // material usage
|
||||||
{
|
{
|
||||||
|
// emergency check. If there are no materials, the materail library failed to load or was not specified
|
||||||
|
// but there are tools that save the material library with the same name of the file, but do not add the
|
||||||
|
// "mtllib" definition in the header. So, we can try to see if this is the case
|
||||||
|
if ((materials.size() == 1)&&(materials[0].materialName == "")){
|
||||||
|
std::string materialFileName(filename);
|
||||||
|
materialFileName.replace(materialFileName.end()-4, materialFileName.end(), ".mtl");
|
||||||
|
LoadMaterials(materialFileName.c_str(), materials, m.textures);
|
||||||
|
}
|
||||||
|
|
||||||
std::string materialName;
|
std::string materialName;
|
||||||
if (tokens.size() == 2)
|
if (tokens.size() == 2)
|
||||||
materialName = tokens[1]; //play it safe
|
materialName = tokens[1]; //play it safe
|
||||||
|
@ -887,6 +896,7 @@ namespace vcg {
|
||||||
oi.numNormals=0;
|
oi.numNormals=0;
|
||||||
int lineCount=0;
|
int lineCount=0;
|
||||||
int totRead=0;
|
int totRead=0;
|
||||||
|
bool firstV = true;
|
||||||
std::string line;
|
std::string line;
|
||||||
while (!stream.eof())
|
while (!stream.eof())
|
||||||
{
|
{
|
||||||
|
@ -899,11 +909,20 @@ namespace vcg {
|
||||||
{
|
{
|
||||||
if(line[0]=='v')
|
if(line[0]=='v')
|
||||||
{
|
{
|
||||||
if(line[1]==' ')
|
if ((line[1] == ' ') || (line[1] == '\t'))
|
||||||
{
|
{
|
||||||
oi.numVertices++;
|
oi.numVertices++;
|
||||||
if(line.size()>=7)
|
if (firstV)
|
||||||
bHasPerVertexColor = true;
|
{
|
||||||
|
int sepN = 0;
|
||||||
|
for (size_t lit = 0; lit < line.size(); lit++){
|
||||||
|
if ((line[lit] == ' ') || (line[lit] == '\t'))
|
||||||
|
sepN++;
|
||||||
|
}
|
||||||
|
if (sepN >= 6)
|
||||||
|
bHasPerVertexColor = true;
|
||||||
|
firstV = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(line[1]=='t') oi.numTexCoords++;
|
if(line[1]=='t') oi.numTexCoords++;
|
||||||
if(line[1]=='n') {
|
if(line[1]=='n') {
|
||||||
|
@ -930,8 +949,8 @@ namespace vcg {
|
||||||
// Usually if you have tex coords you also have materials
|
// Usually if you have tex coords you also have materials
|
||||||
oi.mask |= vcg::tri::io::Mask::IOM_FACECOLOR;
|
oi.mask |= vcg::tri::io::Mask::IOM_FACECOLOR;
|
||||||
}
|
}
|
||||||
if(bHasPerFaceColor) oi.mask |= vcg::tri::io::Mask::IOM_FACECOLOR;
|
if(bHasPerFaceColor) oi.mask |= vcg::tri::io::Mask::IOM_FACECOLOR;
|
||||||
if(bHasPerVertexColor) oi.mask |= vcg::tri::io::Mask::IOM_VERTCOLOR;
|
if(bHasPerVertexColor) oi.mask |= vcg::tri::io::Mask::IOM_VERTCOLOR;
|
||||||
if (bHasNormals) {
|
if (bHasNormals) {
|
||||||
if (oi.numNormals == oi.numVertices)
|
if (oi.numNormals == oi.numVertices)
|
||||||
oi.mask |= vcg::tri::io::Mask::IOM_VERTNORMAL;
|
oi.mask |= vcg::tri::io::Mask::IOM_VERTNORMAL;
|
||||||
|
|
|
@ -210,8 +210,8 @@ static const PropDescriptor &FaceDesc(int i)
|
||||||
/* 5 */ {"face", "texnumber", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,texcoordind), 0,0,0,0,0 ,0},
|
/* 5 */ {"face", "texnumber", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,texcoordind), 0,0,0,0,0 ,0},
|
||||||
/* 6 */ {"face", "red" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux,r), 0,0,0,0,0 ,0},
|
/* 6 */ {"face", "red" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux,r), 0,0,0,0,0 ,0},
|
||||||
/* 7 */ {"face", "green", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux,g), 0,0,0,0,0 ,0},
|
/* 7 */ {"face", "green", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux,g), 0,0,0,0,0 ,0},
|
||||||
/* 8 */ {"face", "blue", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux,b), 0,0,0,0,0 ,0},
|
/* 8 */ {"face", "blue", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux,b), 0,0,0,0,0 ,0},
|
||||||
/* 9 */ {"face", "alpha", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux,a), 0,0,0,0,0 ,0},
|
/* 9 */ {"face", "alpha", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux,a), 0,0,0,0,0 ,0},
|
||||||
/* 10 */ {"face", "vertex_index", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_UCHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
/* 10 */ {"face", "vertex_index", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_UCHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
||||||
/* 11 */ {"face", "vertex_index", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_CHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
/* 11 */ {"face", "vertex_index", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_CHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
||||||
/* 12 */ {"face", "vertex_index", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_INT, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
/* 12 */ {"face", "vertex_index", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_INT, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
||||||
|
@ -547,15 +547,15 @@ static int Open( OpenMeshType &m, const char * filename, PlyInfo &pi )
|
||||||
}
|
}
|
||||||
|
|
||||||
// User defined descriptors
|
// User defined descriptors
|
||||||
std::vector<PropDescriptor> VPV(pi.vdn); // property descriptor relative al tipo LoadPly_VertexAux
|
std::vector<PropDescriptor> VPV(pi.VertDescriptorVec.size()); // property descriptor relative al tipo LoadPly_VertexAux
|
||||||
std::vector<PropDescriptor> FPV(pi.fdn); // property descriptor relative al tipo LoadPly_FaceAux
|
std::vector<PropDescriptor> FPV(pi.FaceDescriptorVec.size()); // property descriptor relative al tipo LoadPly_FaceAux
|
||||||
if(pi.vdn>0){
|
if(pi.VertDescriptorVec.size()>0){
|
||||||
// Compute the total size needed to load additional per vertex data.
|
// Compute the total size needed to load additional per vertex data.
|
||||||
size_t totsz=0;
|
size_t totsz=0;
|
||||||
for(int i=0;i<pi.vdn;i++){
|
for(size_t i=0;i<pi.VertDescriptorVec.size();i++){
|
||||||
VPV[i] = pi.VertexData[i];
|
VPV[i] = pi.VertDescriptorVec[i];
|
||||||
VPV[i].offset1=offsetof(LoadPly_VertAux<ScalarType>,data)+totsz;
|
VPV[i].offset1=offsetof(LoadPly_VertAux<ScalarType>,data)+totsz;
|
||||||
totsz+=pi.VertexData[i].memtypesize();
|
totsz+=pi.VertDescriptorVec[i].memtypesize();
|
||||||
if( pf.AddToRead(VPV[i])==-1 ) { pi.status = pf.GetError(); return pi.status; }
|
if( pf.AddToRead(VPV[i])==-1 ) { pi.status = pf.GetError(); return pi.status; }
|
||||||
}
|
}
|
||||||
if(totsz > MAX_USER_DATA)
|
if(totsz > MAX_USER_DATA)
|
||||||
|
@ -564,12 +564,12 @@ static int Open( OpenMeshType &m, const char * filename, PlyInfo &pi )
|
||||||
return pi.status;
|
return pi.status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(pi.fdn>0){
|
if(pi.FaceDescriptorVec.size()>0){
|
||||||
size_t totsz=0;
|
size_t totsz=0;
|
||||||
for(int i=0;i<pi.fdn;i++){
|
for(size_t i=0;i<pi.FaceDescriptorVec.size();i++){
|
||||||
FPV[i] = pi.FaceData[i];
|
FPV[i] = pi.FaceDescriptorVec[i];
|
||||||
FPV[i].offset1=offsetof(LoadPly_FaceAux,data)+totsz;
|
FPV[i].offset1=offsetof(LoadPly_FaceAux,data)+totsz;
|
||||||
totsz+=pi.FaceData[i].memtypesize();
|
totsz+=pi.FaceDescriptorVec[i].memtypesize();
|
||||||
if( pf.AddToRead(FPV[i])==-1 ) { pi.status = pf.GetError(); return pi.status; }
|
if( pf.AddToRead(FPV[i])==-1 ) { pi.status = pf.GetError(); return pi.status; }
|
||||||
}
|
}
|
||||||
if(totsz > MAX_USER_DATA)
|
if(totsz > MAX_USER_DATA)
|
||||||
|
@ -583,7 +583,7 @@ static int Open( OpenMeshType &m, const char * filename, PlyInfo &pi )
|
||||||
/* Main Reading Loop */
|
/* Main Reading Loop */
|
||||||
/**************************************************************/
|
/**************************************************************/
|
||||||
m.Clear();
|
m.Clear();
|
||||||
for(int i=0;i<int(pf.elements.size());i++)
|
for(size_t i=0;i<pf.elements.size();i++)
|
||||||
{
|
{
|
||||||
int n = pf.ElemNumber(i);
|
int n = pf.ElemNumber(i);
|
||||||
|
|
||||||
|
@ -695,8 +695,8 @@ static int Open( OpenMeshType &m, const char * filename, PlyInfo &pi )
|
||||||
(*vi).R() = va.radius;
|
(*vi).R() = va.radius;
|
||||||
|
|
||||||
|
|
||||||
for(int k=0;k<pi.vdn;k++)
|
for(size_t k=0;k<pi.VertDescriptorVec.size();k++)
|
||||||
memcpy((char *)(&*vi) + pi.VertexData[k].offset1,
|
memcpy((char *)(&*vi) + pi.VertDescriptorVec[k].offset1,
|
||||||
(char *)(&va) + VPV[k].offset1,
|
(char *)(&va) + VPV[k].offset1,
|
||||||
VPV[k].memtypesize());
|
VPV[k].memtypesize());
|
||||||
++vi;
|
++vi;
|
||||||
|
@ -756,7 +756,7 @@ static int Open( OpenMeshType &m, const char * filename, PlyInfo &pi )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(HasPolyInfo(m)) (*fi).Alloc(3);
|
if(HasPolyInfo(m)) (*fi).Alloc(fa.size);
|
||||||
|
|
||||||
if(HasPerFaceFlags(m) &&( pi.mask & Mask::IOM_FACEFLAGS) )
|
if(HasPerFaceFlags(m) &&( pi.mask & Mask::IOM_FACEFLAGS) )
|
||||||
{
|
{
|
||||||
|
@ -805,6 +805,22 @@ static int Open( OpenMeshType &m, const char * filename, PlyInfo &pi )
|
||||||
(*fi).C()[2] = (unsigned char)((fa.colors[0*3+2]*255+fa.colors[1*3+2]*255+fa.colors[2*3+2]*255)/3.0f);
|
(*fi).C()[2] = (unsigned char)((fa.colors[0*3+2]*255+fa.colors[1*3+2]*255+fa.colors[2*3+2]*255)/3.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (HasPolyInfo(m))
|
||||||
|
{
|
||||||
|
for(k=0; k<fa.size; ++k)
|
||||||
|
{
|
||||||
|
if( fa.v[k]<0 || fa.v[k]>=m.vn )
|
||||||
|
{
|
||||||
|
pi.status = PlyInfo::E_BAD_VERT_INDEX;
|
||||||
|
return pi.status;
|
||||||
|
}
|
||||||
|
(*fi).V(k) = index[ fa.v[k] ];
|
||||||
|
}
|
||||||
|
fi++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/// Now the temporary struct 'fa' is ready to be copied into the real face '*fi'
|
/// Now the temporary struct 'fa' is ready to be copied into the real face '*fi'
|
||||||
/// This loop
|
/// This loop
|
||||||
for(k=0;k<3;++k)
|
for(k=0;k<3;++k)
|
||||||
|
@ -820,8 +836,8 @@ static int Open( OpenMeshType &m, const char * filename, PlyInfo &pi )
|
||||||
// tag faux vertices of first face
|
// tag faux vertices of first face
|
||||||
if (fa.size>3) fi->SetF(2);
|
if (fa.size>3) fi->SetF(2);
|
||||||
|
|
||||||
for(k=0;k<pi.fdn;k++)
|
for(size_t k=0;k<pi.FaceDescriptorVec.size();k++)
|
||||||
memcpy((char *)(&(*fi)) + pi.FaceData[k].offset1,
|
memcpy((char *)(&(*fi)) + pi.FaceDescriptorVec[k].offset1,
|
||||||
(char *)(&fa) + FPV[k].offset1,
|
(char *)(&fa) + FPV[k].offset1,
|
||||||
FPV[k].memtypesize());
|
FPV[k].memtypesize());
|
||||||
|
|
||||||
|
@ -861,8 +877,8 @@ static int Open( OpenMeshType &m, const char * filename, PlyInfo &pi )
|
||||||
fi->SetF(0);
|
fi->SetF(0);
|
||||||
if(qq<(fa.size-4)) fi->SetF(2);
|
if(qq<(fa.size-4)) fi->SetF(2);
|
||||||
|
|
||||||
for(k=0;k<pi.fdn;k++)
|
for(size_t k=0;k<pi.FaceDescriptorVec.size();k++)
|
||||||
memcpy((char *)(&(*fi)) + pi.FaceData[k].offset1,
|
memcpy((char *)(&(*fi)) + pi.FaceDescriptorVec[k].offset1,
|
||||||
(char *)(&fa) + FPV[k].offset1, FPV[k].memtypesize());
|
(char *)(&fa) + FPV[k].offset1, FPV[k].memtypesize());
|
||||||
++fi;
|
++fi;
|
||||||
}
|
}
|
||||||
|
@ -911,7 +927,7 @@ static int Open( OpenMeshType &m, const char * filename, PlyInfo &pi )
|
||||||
//qDebug("Starting Reading of Range Grid");
|
//qDebug("Starting Reading of Range Grid");
|
||||||
if(RangeGridCols==0) // not initialized.
|
if(RangeGridCols==0) // not initialized.
|
||||||
{
|
{
|
||||||
for(int co=0;co<int(pf.comments.size());++co)
|
for(size_t co=0;co< pf.comments.size();++co)
|
||||||
{
|
{
|
||||||
std::string num_cols = "num_cols";
|
std::string num_cols = "num_cols";
|
||||||
std::string num_rows = "num_rows";
|
std::string num_rows = "num_rows";
|
||||||
|
@ -974,20 +990,20 @@ static int Open( OpenMeshType &m, const char * filename, PlyInfo &pi )
|
||||||
m.textures.clear();
|
m.textures.clear();
|
||||||
m.normalmaps.clear();
|
m.normalmaps.clear();
|
||||||
|
|
||||||
for(int co=0;co<int(pf.comments.size());++co)
|
for(size_t co=0;co<pf.comments.size();++co)
|
||||||
{
|
{
|
||||||
std::string TFILE = "TextureFile";
|
std::string TFILE = "TextureFile";
|
||||||
std::string NFILE = "TextureNormalFile";
|
std::string NFILE = "TextureNormalFile";
|
||||||
std::string &c = pf.comments[co];
|
std::string &c = pf.comments[co];
|
||||||
// char buf[256];
|
// char buf[256];
|
||||||
std::string bufstr,bufclean;
|
std::string bufstr,bufclean;
|
||||||
int i,n;
|
int n;
|
||||||
|
|
||||||
if( TFILE == c.substr(0,TFILE.length()) )
|
if( TFILE == c.substr(0,TFILE.length()) )
|
||||||
{
|
{
|
||||||
bufstr = c.substr(TFILE.length()+1);
|
bufstr = c.substr(TFILE.length()+1);
|
||||||
n = static_cast<int>(bufstr.length());
|
n = static_cast<int>(bufstr.length());
|
||||||
for(i=0;i<n;i++)
|
for(int i=0;i<n;i++)
|
||||||
if( bufstr[i]!=' ' && bufstr[i]!='\t' && bufstr[i]>32 && bufstr[i]<125 ) bufclean.push_back(bufstr[i]);
|
if( bufstr[i]!=' ' && bufstr[i]!='\t' && bufstr[i]>32 && bufstr[i]<125 ) bufclean.push_back(bufstr[i]);
|
||||||
|
|
||||||
char buf2[255];
|
char buf2[255];
|
||||||
|
@ -1036,8 +1052,7 @@ int LoadCamera(const char * filename)
|
||||||
|
|
||||||
|
|
||||||
bool found = true;
|
bool found = true;
|
||||||
int i;
|
for(int i=0;i<23;++i)
|
||||||
for(i=0;i<23;++i)
|
|
||||||
{
|
{
|
||||||
if( pf.AddToRead(CameraDesc(i))==-1 )
|
if( pf.AddToRead(CameraDesc(i))==-1 )
|
||||||
{
|
{
|
||||||
|
@ -1049,7 +1064,7 @@ int LoadCamera(const char * filename)
|
||||||
if(!found)
|
if(!found)
|
||||||
return this->pi.status;
|
return this->pi.status;
|
||||||
|
|
||||||
for(i=0;i<int(pf.elements.size());i++)
|
for(size_t i=0;i<pf.elements.size();i++)
|
||||||
{
|
{
|
||||||
int n = pf.ElemNumber(i);
|
int n = pf.ElemNumber(i);
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#ifndef __VCGLIB_IMPORT_STL
|
#ifndef __VCGLIB_IMPORT_STL
|
||||||
#define __VCGLIB_IMPORT_STL
|
#define __VCGLIB_IMPORT_STL
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include<algorithm>
|
||||||
#include <wrap/io_trimesh/io_mask.h>
|
#include <wrap/io_trimesh/io_mask.h>
|
||||||
|
|
||||||
namespace vcg {
|
namespace vcg {
|
||||||
|
@ -60,10 +61,11 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
enum STLError {
|
enum STLError {
|
||||||
E_NOERROR, // 0
|
E_NOERROR, // 0
|
||||||
// Errori di open
|
E_CANTOPEN, // 1
|
||||||
E_CANTOPEN, // 1
|
E_UNESPECTEDEOF, // 2
|
||||||
E_UNESPECTEDEOF // 2
|
E_MALFORMED, // 3
|
||||||
|
E_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *ErrorMsg(int error)
|
static const char *ErrorMsg(int error)
|
||||||
|
@ -72,20 +74,23 @@ static const char *ErrorMsg(int error)
|
||||||
{
|
{
|
||||||
"No errors",
|
"No errors",
|
||||||
"Can't open file",
|
"Can't open file",
|
||||||
"Premature End of file",
|
"Premature end of file",
|
||||||
|
"Malformed file",
|
||||||
};
|
};
|
||||||
|
|
||||||
if(error>2 || error<0) return "Unknown error";
|
if(error>=E_LAST || error<0) return "Unknown error";
|
||||||
else return stl_error_msg[error];
|
else return stl_error_msg[error];
|
||||||
};
|
}
|
||||||
|
|
||||||
static bool LoadMask(const char * filename, int &mask)
|
static bool LoadMask(const char * filename, int &mask)
|
||||||
{
|
{
|
||||||
bool magicMode;
|
bool magicMode,colored;
|
||||||
mask = Mask::IOM_VERTCOORD | Mask::IOM_FACEINDEX;
|
mask = Mask::IOM_VERTCOORD | Mask::IOM_FACEINDEX;
|
||||||
if(IsSTLColored(filename,magicMode))
|
if(!IsSTLColored(filename, colored, magicMode))
|
||||||
mask |= Mask::IOM_FACECOLOR;
|
return false;
|
||||||
return true;
|
|
||||||
|
if(colored) mask |= Mask::IOM_FACECOLOR;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to guess if a stl has color
|
/* Try to guess if a stl has color
|
||||||
|
@ -94,11 +99,19 @@ static bool LoadMask(const char * filename, int &mask)
|
||||||
* - It has to be binary
|
* - It has to be binary
|
||||||
* - The per face attribute should be not zero
|
* - The per face attribute should be not zero
|
||||||
*
|
*
|
||||||
|
* return false in case of malformed files
|
||||||
*/
|
*/
|
||||||
static bool IsSTLColored(const char * filename, bool &magicsMode)
|
static bool IsSTLColored(const char * filename, bool &coloredFlag, bool &magicsMode)
|
||||||
{
|
{
|
||||||
if(IsSTLBinary(filename)==false)
|
coloredFlag=false;
|
||||||
|
magicsMode=false;
|
||||||
|
bool binaryFlag;
|
||||||
|
if(IsSTLBinary(filename,binaryFlag)==false)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if(binaryFlag==false)
|
||||||
|
return true;
|
||||||
|
|
||||||
FILE *fp = fopen(filename, "rb");
|
FILE *fp = fopen(filename, "rb");
|
||||||
char buf[STL_LABEL_SIZE+1];
|
char buf[STL_LABEL_SIZE+1];
|
||||||
fread(buf,sizeof(char),STL_LABEL_SIZE,fp);
|
fread(buf,sizeof(char),STL_LABEL_SIZE,fp);
|
||||||
|
@ -123,39 +136,54 @@ static bool IsSTLColored(const char * filename, bool &magicsMode)
|
||||||
if(attr!=0)
|
if(attr!=0)
|
||||||
{
|
{
|
||||||
if(Color4b::FromUnsignedR5G5B5(attr) != Color4b(Color4b::White))
|
if(Color4b::FromUnsignedR5G5B5(attr) != Color4b(Color4b::White))
|
||||||
return true;
|
coloredFlag=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsSTLBinary(const char * filename)
|
/* Try to guess if a stl is in binary format
|
||||||
|
*
|
||||||
|
* return false in case of malformed files
|
||||||
|
*/
|
||||||
|
static bool IsSTLBinary(const char * filename, bool &binaryFlag)
|
||||||
{
|
{
|
||||||
bool binary=false;
|
binaryFlag=false;
|
||||||
FILE *fp = fopen(filename, "r");
|
FILE *fp = fopen(filename, "r");
|
||||||
/* Find size of file */
|
/* Find size of file */
|
||||||
fseek(fp, 0, SEEK_END);
|
fseek(fp, 0, SEEK_END);
|
||||||
int file_size = ftell(fp);
|
long file_size = ftell(fp);
|
||||||
int facenum;
|
unsigned int facenum;
|
||||||
/* Check for binary or ASCII file */
|
/* Check for binary or ASCII file */
|
||||||
fseek(fp, STL_LABEL_SIZE, SEEK_SET);
|
fseek(fp, STL_LABEL_SIZE, SEEK_SET);
|
||||||
fread(&facenum, sizeof(int), 1, fp);
|
fread(&facenum, sizeof(unsigned int), 1, fp);
|
||||||
|
|
||||||
int expected_file_size=STL_LABEL_SIZE + 4 + (sizeof(short)+sizeof(STLFacet) )*facenum ;
|
int expected_file_size=STL_LABEL_SIZE + 4 + (sizeof(short)+sizeof(STLFacet) )*facenum ;
|
||||||
if(file_size == expected_file_size) binary = true;
|
if(file_size == expected_file_size)
|
||||||
unsigned char tmpbuf[128];
|
{
|
||||||
fread(tmpbuf,sizeof(tmpbuf),1,fp);
|
binaryFlag = true;
|
||||||
for(unsigned int i = 0; i < sizeof(tmpbuf); i++)
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// second check, sometimes the size is a bit wrong,
|
||||||
|
// lets'make a test to check that we find only ascii stuff before assuming it is ascii
|
||||||
|
unsigned char tmpbuf[1000];
|
||||||
|
int byte_to_read = std::min(int(sizeof(tmpbuf)), int(file_size - 80));
|
||||||
|
fread(tmpbuf, byte_to_read,1,fp);
|
||||||
|
fclose(fp);
|
||||||
|
for(int i = 0; i < byte_to_read; i++)
|
||||||
{
|
{
|
||||||
if(tmpbuf[i] > 127)
|
if(tmpbuf[i] > 127)
|
||||||
{
|
{
|
||||||
binary=true;
|
binaryFlag=true;
|
||||||
|
if(abs(file_size-expected_file_size) > file_size/20 )
|
||||||
|
return false; //
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Now we know if the stl file is ascii or binary.
|
// Now we know if the stl file is ascii or binary.
|
||||||
fclose(fp);
|
return true;
|
||||||
return binary;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Open( OpenMeshType &m, const char * filename, int &loadMask, CallBackPos *cb=0)
|
static int Open( OpenMeshType &m, const char * filename, int &loadMask, CallBackPos *cb=0)
|
||||||
|
@ -165,8 +193,11 @@ static int Open( OpenMeshType &m, const char * filename, int &loadMask, CallBack
|
||||||
return E_CANTOPEN;
|
return E_CANTOPEN;
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
loadMask |= Mask::IOM_VERTCOORD | Mask::IOM_FACEINDEX;
|
loadMask |= Mask::IOM_VERTCOORD | Mask::IOM_FACEINDEX;
|
||||||
|
bool binaryFlag;
|
||||||
if(IsSTLBinary(filename)) return OpenBinary(m,filename,loadMask,cb);
|
if(!IsSTLBinary(filename,binaryFlag))
|
||||||
|
return E_MALFORMED;
|
||||||
|
|
||||||
|
if(binaryFlag) return OpenBinary(m,filename,loadMask,cb);
|
||||||
else return OpenAscii(m,filename,cb);
|
else return OpenAscii(m,filename,cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,8 +210,10 @@ static int OpenBinary( OpenMeshType &m, const char * filename, int &loadMask, Ca
|
||||||
return E_CANTOPEN;
|
return E_CANTOPEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool magicsMode;
|
bool magicsMode,coloredFlag;
|
||||||
if(!IsSTLColored(filename,magicsMode))
|
if(!IsSTLColored(filename,coloredFlag, magicsMode))
|
||||||
|
return E_MALFORMED;
|
||||||
|
if(!coloredFlag)
|
||||||
loadMask = loadMask & (~Mask::IOM_FACECOLOR);
|
loadMask = loadMask & (~Mask::IOM_FACECOLOR);
|
||||||
|
|
||||||
int facenum;
|
int facenum;
|
||||||
|
|
|
@ -52,6 +52,8 @@ namespace vcg {
|
||||||
namespace tri {
|
namespace tri {
|
||||||
namespace io {
|
namespace io {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Additional data needed or useful for parsing a ply mesh.
|
/** Additional data needed or useful for parsing a ply mesh.
|
||||||
This class can be passed to the ImporterPLY::Open() function for
|
This class can be passed to the ImporterPLY::Open() function for
|
||||||
|
@ -63,14 +65,66 @@ class PlyInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef ::vcg::ply::PropDescriptor PropDescriptor ;
|
typedef ::vcg::ply::PropDescriptor PropDescriptor ;
|
||||||
|
|
||||||
|
void AddPerElemFloatAttribute(int elemType, const char *attrName, const char * propName=0)
|
||||||
|
{
|
||||||
|
static const char *elemStr[2]={"vertex","face"};
|
||||||
|
static std::vector<PropDescriptor> *elemDescVec[2]={&(this->VertDescriptorVec), &(this->FaceDescriptorVec)};
|
||||||
|
static std::vector<std::string > *elemNameVec[2]={&(this->VertAttrNameVec), &(this->FaceAttrNameVec)};
|
||||||
|
|
||||||
|
if(propName==0) propName=attrName;
|
||||||
|
elemDescVec[elemType]->push_back(PropDescriptor());
|
||||||
|
elemNameVec[elemType]->push_back(attrName);
|
||||||
|
elemDescVec[elemType]->back().elemname=elemStr[elemType];
|
||||||
|
elemDescVec[elemType]->back().propname=strdup(propName);
|
||||||
|
elemDescVec[elemType]->back().stotype1 = vcg::ply::T_FLOAT;
|
||||||
|
elemDescVec[elemType]->back().memtype1 = vcg::ply::T_FLOAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddPerVertexFloatAttribute(const char *attrName, const char *propName=0) {
|
||||||
|
AddPerElemFloatAttribute(0,attrName,propName);
|
||||||
|
}
|
||||||
|
void AddPerFaceFloatAttribute(const char *attrName, const char *propName=0) {
|
||||||
|
AddPerElemFloatAttribute(1,attrName,propName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Note that saving a per vertex point3 attribute is a mess.
|
||||||
|
* Actually require to allocate 3 float attribute and save them. And they are never deallocated... */
|
||||||
|
template<class MeshType>
|
||||||
|
void AddPerVertexPoint3fAttribute(MeshType &m, const char *attrName, const char *propName="")
|
||||||
|
{
|
||||||
|
if(propName==0) propName=attrName;
|
||||||
|
|
||||||
|
const char *attrxyz[3] = {
|
||||||
|
strdup((std::string(attrName)+std::string("_x")).c_str()),
|
||||||
|
strdup((std::string(attrName)+std::string("_y")).c_str()),
|
||||||
|
strdup((std::string(attrName)+std::string("_z")).c_str()),
|
||||||
|
};
|
||||||
|
typename MeshType::template PerVertexAttributeHandle <vcg::Point3f>
|
||||||
|
ht = vcg::tri::Allocator<MeshType>:: template GetPerVertexAttribute <vcg::Point3f> (m,attrName);
|
||||||
|
|
||||||
|
typename MeshType::template PerVertexAttributeHandle <float> htt[3];
|
||||||
|
|
||||||
|
for(int i=0;i<3;++i)
|
||||||
|
{
|
||||||
|
htt[i] = vcg::tri::Allocator<MeshType>:: template GetPerVertexAttribute<float> (m,std::string(attrxyz[i]));
|
||||||
|
// ForEachVertex (m, [&](typename MeshType::VertexType &v) {
|
||||||
|
// htt[i][v] = ht[v][i];
|
||||||
|
// });
|
||||||
|
for(auto vi=m.vert.begin();vi!=m.vert.end();++vi)
|
||||||
|
if(!vi->IsD())
|
||||||
|
htt[i][vi] = ht[vi][i];
|
||||||
|
AddPerVertexFloatAttribute(attrxyz[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PlyInfo()
|
PlyInfo()
|
||||||
{
|
{
|
||||||
status=0;
|
status=0;
|
||||||
mask=0;
|
mask=0;
|
||||||
cb=0;
|
cb=0;
|
||||||
vdn=fdn=0;
|
|
||||||
VertexData=FaceData=0;
|
|
||||||
}
|
}
|
||||||
/// Store the error codes enconutered when parsing a ply
|
/// Store the error codes enconutered when parsing a ply
|
||||||
int status;
|
int status;
|
||||||
|
@ -81,15 +135,16 @@ public:
|
||||||
// it returns the current position, and formats a string with a description of what th efunction is doing (loading vertexes, faces...)
|
// it returns the current position, and formats a string with a description of what th efunction is doing (loading vertexes, faces...)
|
||||||
CallBackPos *cb;
|
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
|
/// The additional vertex descriptor that a user can specify to load additional per-vertex non-standard data stored in a ply
|
||||||
PropDescriptor *VertexData;
|
std::vector<PropDescriptor> VertDescriptorVec;
|
||||||
/// the number of per-face descriptor (usually 0)
|
/// AttributeName is an array, externally allocated, containing the names of the attributes to be saved (loaded).
|
||||||
int fdn;
|
/// We assume that AttributeName[], if not empty, is exactly of the same size of VertexdData[]
|
||||||
|
/// If AttributeName[i] is not empty we use it to retrieve/store the info instead of the offsetted space in the current vertex
|
||||||
|
std::vector<std::string> VertAttrNameVec;
|
||||||
|
|
||||||
/// The additional vertex descriptor that a user can specify to load additional per-face non-standard data stored in a ply
|
/// The additional vertex descriptor that a user can specify to load additional per-face non-standard data stored in a ply
|
||||||
PropDescriptor *FaceData;
|
std::vector<PropDescriptor> FaceDescriptorVec;
|
||||||
|
std::vector<std::string> FaceAttrNameVec;
|
||||||
|
|
||||||
/// a string containing the current ply header. Useful for showing it to the user.
|
/// a string containing the current ply header. Useful for showing it to the user.
|
||||||
std::string header;
|
std::string header;
|
||||||
|
|
Loading…
Reference in New Issue