Merge branch 'devel' of https://github.com/cnr-isti-vclab/vcglib into devel
This commit is contained in:
commit
1b50c7af37
|
@ -471,6 +471,41 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class TriMeshType>
|
||||||
|
static void ReprojectBorder(PolyMeshType &poly_m,
|
||||||
|
TriMeshType &tri_mesh,
|
||||||
|
bool FixS=true)
|
||||||
|
{
|
||||||
|
//then reproject on border
|
||||||
|
for (size_t i=0;i<poly_m.vert.size();i++)
|
||||||
|
{
|
||||||
|
if (!poly_m.vert[i].IsB())continue;
|
||||||
|
if (FixS && poly_m.vert[i].IsS())continue;
|
||||||
|
|
||||||
|
CoordType testPos=poly_m.vert[i].P();
|
||||||
|
ScalarType minD=std::numeric_limits<ScalarType>::max();
|
||||||
|
CoordType closPos;
|
||||||
|
for (size_t j=0;j<tri_mesh.face.size();j++)
|
||||||
|
for (size_t k=0;k<3;k++)
|
||||||
|
{
|
||||||
|
//check if border edge
|
||||||
|
if (tri_mesh.face[j].FFp(k)!=(&tri_mesh.face[j]))continue;
|
||||||
|
|
||||||
|
CoordType P0,P1;
|
||||||
|
P0.Import(tri_mesh.face[j].cP0(k));
|
||||||
|
P1.Import(tri_mesh.face[j].cP1(k));
|
||||||
|
vcg::Segment3<ScalarType> Seg(P0,P1);
|
||||||
|
ScalarType testD;
|
||||||
|
CoordType closTest;
|
||||||
|
vcg::SegmentPointDistance(Seg,testPos,closTest,testD);
|
||||||
|
if (testD>minD)continue;
|
||||||
|
minD=testD;
|
||||||
|
closPos=closTest;
|
||||||
|
}
|
||||||
|
poly_m.vert[i].P()=closPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*! \brief This function smooth the borders of the polygonal mesh and reproject back to the triangolar one
|
/*! \brief This function smooth the borders of the polygonal mesh and reproject back to the triangolar one
|
||||||
* except the vertices that are considered as corner wrt the angleDeg threshold
|
* except the vertices that are considered as corner wrt the angleDeg threshold
|
||||||
*/
|
*/
|
||||||
|
@ -507,33 +542,34 @@ public:
|
||||||
AvVert[i]*(1-Damp);
|
AvVert[i]*(1-Damp);
|
||||||
}
|
}
|
||||||
|
|
||||||
//then reproject on border
|
// //then reproject on border
|
||||||
for (size_t i=0;i<poly_m.vert.size();i++)
|
// for (size_t i=0;i<poly_m.vert.size();i++)
|
||||||
{
|
// {
|
||||||
if (!poly_m.vert[i].IsB())continue;
|
// if (!poly_m.vert[i].IsB())continue;
|
||||||
if (poly_m.vert[i].IsS())continue;
|
// if (poly_m.vert[i].IsS())continue;
|
||||||
|
|
||||||
CoordType testPos=poly_m.vert[i].P();
|
// CoordType testPos=poly_m.vert[i].P();
|
||||||
ScalarType minD=std::numeric_limits<ScalarType>::max();
|
// ScalarType minD=std::numeric_limits<ScalarType>::max();
|
||||||
CoordType closPos;
|
// CoordType closPos;
|
||||||
for (size_t j=0;j<tri_mesh.face.size();j++)
|
// for (size_t j=0;j<tri_mesh.face.size();j++)
|
||||||
for (size_t k=0;k<3;k++)
|
// for (size_t k=0;k<3;k++)
|
||||||
{
|
// {
|
||||||
if (tri_mesh.face[j].FFp(k)!=(&tri_mesh.face[j]))continue;
|
// if (tri_mesh.face[j].FFp(k)!=(&tri_mesh.face[j]))continue;
|
||||||
|
|
||||||
CoordType P0,P1;
|
// CoordType P0,P1;
|
||||||
P0.Import(tri_mesh.face[j].cP0(k));
|
// P0.Import(tri_mesh.face[j].cP0(k));
|
||||||
P1.Import(tri_mesh.face[j].cP1(k));
|
// P1.Import(tri_mesh.face[j].cP1(k));
|
||||||
vcg::Segment3<ScalarType> Seg(P0,P1);
|
// vcg::Segment3<ScalarType> Seg(P0,P1);
|
||||||
ScalarType testD;
|
// ScalarType testD;
|
||||||
CoordType closTest;
|
// CoordType closTest;
|
||||||
vcg::SegmentPointDistance(Seg,testPos,closTest,testD);
|
// vcg::SegmentPointDistance(Seg,testPos,closTest,testD);
|
||||||
if (testD>minD)continue;
|
// if (testD>minD)continue;
|
||||||
minD=testD;
|
// minD=testD;
|
||||||
closPos=closTest;
|
// closPos=closTest;
|
||||||
}
|
// }
|
||||||
poly_m.vert[i].P()=closPos;
|
// poly_m.vert[i].P()=closPos;
|
||||||
}
|
// }
|
||||||
|
ReprojectBorder(poly_m,tri_mesh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -797,6 +833,47 @@ public:
|
||||||
vcg::PolygonalAlgorithm<PolyMeshType>::SmoothReprojectPCA<TempMesh>(poly_m,GuideSurf,relaxStep,fixIrr,Damp,SharpDeg,WeightByQuality);
|
vcg::PolygonalAlgorithm<PolyMeshType>::SmoothReprojectPCA<TempMesh>(poly_m,GuideSurf,relaxStep,fixIrr,Damp,SharpDeg,WeightByQuality);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void Reproject(PolyMeshType &poly_m,
|
||||||
|
PolyMeshType &target)
|
||||||
|
{
|
||||||
|
vcg::tri::UpdateTopology<PolyMeshType>::FaceFace(poly_m);
|
||||||
|
vcg::tri::UpdateFlags<PolyMeshType>::VertexBorderFromFaceAdj(poly_m);
|
||||||
|
|
||||||
|
//transform into triangular
|
||||||
|
TempMesh GuideSurf;
|
||||||
|
//vcg::tri::PolygonSupport<TempMesh,PolyMeshType>:(GuideSurf,poly_m);
|
||||||
|
TriangulateToTriMesh<TempMesh>(target,GuideSurf);
|
||||||
|
vcg::tri::UpdateBounding<TempMesh>::Box(GuideSurf);
|
||||||
|
vcg::tri::UpdateNormal<TempMesh>::PerVertexNormalizedPerFace(GuideSurf);
|
||||||
|
vcg::tri::UpdateTopology<TempMesh>::FaceFace(GuideSurf);
|
||||||
|
vcg::tri::UpdateFlags<TempMesh>::FaceBorderFromFF(GuideSurf);
|
||||||
|
|
||||||
|
//initialize the grid
|
||||||
|
typedef typename TempMesh::FaceType FaceType;
|
||||||
|
typedef vcg::GridStaticPtr<FaceType, typename TempMesh::ScalarType> TriMeshGrid;
|
||||||
|
TriMeshGrid grid;
|
||||||
|
grid.Set(GuideSurf.face.begin(),GuideSurf.face.end());
|
||||||
|
|
||||||
|
ScalarType MaxD=GuideSurf.bbox.Diag();
|
||||||
|
|
||||||
|
for (size_t i=0;i<poly_m.vert.size();i++)
|
||||||
|
{
|
||||||
|
//reproject on border later
|
||||||
|
if (poly_m.vert[i].IsB())continue;
|
||||||
|
typename TempMesh::CoordType testPos;
|
||||||
|
testPos.Import(poly_m.vert[i].P());
|
||||||
|
typename TempMesh::CoordType closestPt;
|
||||||
|
typename TempMesh::ScalarType minDist;
|
||||||
|
typename TempMesh::FaceType *f=NULL;
|
||||||
|
typename TempMesh::CoordType norm,ip;
|
||||||
|
f=vcg::tri::GetClosestFaceBase(GuideSurf,grid,testPos,MaxD,minDist,closestPt,norm,ip);
|
||||||
|
poly_m.vert[i].P()=closestPt;
|
||||||
|
}
|
||||||
|
//then reprojec the border
|
||||||
|
ReprojectBorder(poly_m,GuideSurf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! \brief This function return average edge size
|
/*! \brief This function return average edge size
|
||||||
*/
|
*/
|
||||||
static ScalarType AverageEdge(const PolyMeshType &poly_m)
|
static ScalarType AverageEdge(const PolyMeshType &poly_m)
|
||||||
|
@ -928,18 +1005,20 @@ public:
|
||||||
* this is sometimes useful to remove small edges coming out from a quadrangulation which is not
|
* this is sometimes useful to remove small edges coming out from a quadrangulation which is not
|
||||||
* aligned to boundaries
|
* aligned to boundaries
|
||||||
*/
|
*/
|
||||||
static void CollapseBorderSmallEdges(PolyMeshType &poly_m,const ScalarType perc_average=0.3)
|
static bool CollapseBorderSmallEdges(PolyMeshType &poly_m,
|
||||||
|
const ScalarType perc_average=0.3)
|
||||||
{
|
{
|
||||||
//compute the average edge
|
//compute the average edge
|
||||||
ScalarType AvEdge=AverageEdge(poly_m);
|
ScalarType AvEdge=AverageEdge(poly_m);
|
||||||
ScalarType minLimit=AvEdge*perc_average;
|
ScalarType minLimit=AvEdge*perc_average;
|
||||||
|
bool collapsed=false;
|
||||||
while(CollapseBorderSmallEdgesStep(poly_m,minLimit)){};
|
while(CollapseBorderSmallEdgesStep(poly_m,minLimit)){collapsed=true;};
|
||||||
|
|
||||||
RemoveValence2Faces(poly_m);
|
RemoveValence2Faces(poly_m);
|
||||||
|
|
||||||
//RemoveValence2BorderVertices(poly_m);
|
//RemoveValence2BorderVertices(poly_m);
|
||||||
RemoveValence2Vertices(poly_m);
|
RemoveValence2Vertices(poly_m);
|
||||||
|
return collapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief This function use a local global approach to flatten polygonal faces
|
/*! \brief This function use a local global approach to flatten polygonal faces
|
||||||
|
@ -1133,6 +1212,89 @@ public:
|
||||||
ToUpdateF.push_back(IndexF);
|
ToUpdateF.push_back(IndexF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ReorderFaceVert(FaceType &f,const size_t &StartI)
|
||||||
|
{
|
||||||
|
if (StartI==0)return;
|
||||||
|
size_t sizeN=f.VN();
|
||||||
|
assert(StartI>=0);
|
||||||
|
assert(StartI<sizeN);
|
||||||
|
std::vector<VertexType*> NewV;
|
||||||
|
for (size_t i=0;i<sizeN;i++)
|
||||||
|
{
|
||||||
|
int IndexV=(i+StartI)%sizeN;
|
||||||
|
NewV.push_back(f.V(IndexV));
|
||||||
|
}
|
||||||
|
//then reset all vertices
|
||||||
|
for (size_t i=0;i<sizeN;i++)
|
||||||
|
f.V(i)=NewV[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MergeAlongEdge(PolyMeshType &poly_m,
|
||||||
|
FaceType &f,
|
||||||
|
const size_t &EdgeI)
|
||||||
|
{
|
||||||
|
//cannot be a border
|
||||||
|
assert(f.FFp(EdgeI)!=&f);
|
||||||
|
FaceType *f1=f.FFp(EdgeI);
|
||||||
|
int EdgeI1=f.FFi(EdgeI);
|
||||||
|
|
||||||
|
//sort first face
|
||||||
|
int FirstV0=(EdgeI+1) % f.VN();
|
||||||
|
ReorderFaceVert(f,FirstV0);
|
||||||
|
int FirstV1=(EdgeI1+1)%f1->VN();
|
||||||
|
ReorderFaceVert(*f1,FirstV1);
|
||||||
|
|
||||||
|
std::vector<VertexType*> NewV;
|
||||||
|
for (size_t i=0;i<(f.VN()-1);i++)
|
||||||
|
NewV.push_back(f.V(i));
|
||||||
|
|
||||||
|
for (size_t i=0;i<(f1->VN()-1);i++)
|
||||||
|
NewV.push_back(f1->V(i));
|
||||||
|
|
||||||
|
f.Dealloc();
|
||||||
|
f.Alloc(NewV.size());
|
||||||
|
for (size_t i=0;i<NewV.size();i++)
|
||||||
|
f.V(i)=NewV[i];
|
||||||
|
|
||||||
|
vcg::tri::Allocator<PolyMeshType>::DeleteFace(poly_m,*f1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MergeAlongEdges(PolyMeshType &poly_m,
|
||||||
|
const std::vector<FaceType*> &PolyF,
|
||||||
|
const std::vector<size_t> &EdgeI)
|
||||||
|
{
|
||||||
|
//create a table with all edges that have to be merged
|
||||||
|
std::set<std::pair<CoordType,CoordType> > NeedMerge;
|
||||||
|
for (size_t i=0;i<PolyF.size();i++)
|
||||||
|
{
|
||||||
|
CoordType P0=PolyF[i]->P0(EdgeI[i]);
|
||||||
|
CoordType P1=PolyF[i]->P1(EdgeI[i]);
|
||||||
|
std::pair<CoordType,CoordType> key(std::min(P0,P1),std::max(P0,P1));
|
||||||
|
NeedMerge.insert(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
//then cycle and collapse
|
||||||
|
do{
|
||||||
|
for (size_t i=0;i<poly_m.face.size();i++)
|
||||||
|
{
|
||||||
|
if (poly_m.face[i].IsD())continue;
|
||||||
|
for (size_t j=0;j<poly_m.face[i].VN();j++)
|
||||||
|
{
|
||||||
|
CoordType P0=poly_m.face[i].P0(j);
|
||||||
|
CoordType P1=poly_m.face[i].P1(j);
|
||||||
|
std::pair<CoordType,CoordType> key(std::min(P0,P1),std::max(P0,P1));
|
||||||
|
if (NeedMerge.count(key)==0)continue;
|
||||||
|
|
||||||
|
//do the merge
|
||||||
|
MergeAlongEdge(poly_m,poly_m.face[i],j);
|
||||||
|
//remove it
|
||||||
|
NeedMerge.erase(key);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vcg::tri::Allocator<PolyMeshType>::CompactEveryVector(poly_m);
|
||||||
|
}while (!NeedMerge.empty());
|
||||||
|
}
|
||||||
|
|
||||||
static void Triangulate(PolyMeshType &poly_m)
|
static void Triangulate(PolyMeshType &poly_m)
|
||||||
{
|
{
|
||||||
|
|
|
@ -41,17 +41,18 @@
|
||||||
|
|
||||||
|
|
||||||
namespace vcg {
|
namespace vcg {
|
||||||
namespace tri {
|
namespace tri {
|
||||||
namespace io {
|
namespace io {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This class encapsulate a filter for importing obj (Alias Wavefront) meshes.
|
This class encapsulate a filter for importing obj (Alias Wavefront) meshes.
|
||||||
Warning: this code assume little endian (PC) architecture!!!
|
Warning: this code assume little endian (PC) architecture!!!
|
||||||
*/
|
*/
|
||||||
template <class OpenMeshType>
|
|
||||||
class ImporterOBJ
|
template <class OpenMeshType>
|
||||||
{
|
class ImporterOBJ
|
||||||
public:
|
{
|
||||||
|
public:
|
||||||
static int &MRGBLineCount(){static int _MRGBLineCount=0; return _MRGBLineCount;}
|
static int &MRGBLineCount(){static int _MRGBLineCount=0; return _MRGBLineCount;}
|
||||||
|
|
||||||
typedef typename OpenMeshType::VertexPointer VertexPointer;
|
typedef typename OpenMeshType::VertexPointer VertexPointer;
|
||||||
|
@ -67,43 +68,23 @@ namespace vcg {
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Info()
|
Info() {}
|
||||||
{
|
|
||||||
mask = 0;
|
|
||||||
cb = 0;
|
|
||||||
numTexCoords=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// It returns a bit mask describing the field preesnt in the ply file
|
/// It returns a bit mask describing the field present in the obj file
|
||||||
int mask;
|
int mask=0;
|
||||||
|
|
||||||
/// a Simple callback that can be used for long obj parsing.
|
/// a Simple callback that can be used for long obj parsing.
|
||||||
// it returns the current position, and formats a string with a description of what th efunction is doing (loading vertexes, faces...)
|
CallBackPos *cb=nullptr;
|
||||||
CallBackPos *cb;
|
|
||||||
|
|
||||||
/// number of vertices
|
|
||||||
int numVertices;
|
int numVertices;
|
||||||
/// number of edges
|
|
||||||
int numEdges;
|
int numEdges;
|
||||||
/// number of faces (the number of triangles could be
|
int numFaces; // Note that numFaces can be different from the final number of triangles
|
||||||
/// larger in presence of polygonal faces
|
int numTexCoords=0;
|
||||||
int numFaces;
|
|
||||||
/// number of texture coords indexes
|
|
||||||
int numTexCoords;
|
|
||||||
/// number of normals
|
|
||||||
int numNormals;
|
int numNormals;
|
||||||
|
|
||||||
}; // end class
|
}; // end class
|
||||||
|
|
||||||
|
|
||||||
//struct OBJFacet
|
|
||||||
//{
|
|
||||||
// CoordType n;
|
|
||||||
// CoordType t;
|
|
||||||
// CoordType v[3];
|
|
||||||
//
|
|
||||||
// short attr; // material index
|
|
||||||
//};
|
|
||||||
struct ObjIndexedFace
|
struct ObjIndexedFace
|
||||||
{
|
{
|
||||||
void set(const int & num){v.resize(num);n.resize(num); t.resize(num);}
|
void set(const int & num){v.resize(num);n.resize(num); t.resize(num);}
|
||||||
|
@ -244,11 +225,6 @@ namespace vcg {
|
||||||
if (oi.numVertices == 0)
|
if (oi.numVertices == 0)
|
||||||
return E_NO_VERTEX;
|
return E_NO_VERTEX;
|
||||||
|
|
||||||
// Commented out this test. You should be allowed to load point clouds.
|
|
||||||
//if (oi.numFaces == 0)
|
|
||||||
// return E_NO_FACE;
|
|
||||||
|
|
||||||
|
|
||||||
std::ifstream stream(filename);
|
std::ifstream stream(filename);
|
||||||
if (stream.fail())
|
if (stream.fail())
|
||||||
{
|
{
|
||||||
|
@ -420,7 +396,7 @@ namespace vcg {
|
||||||
|
|
||||||
if( (vertexesPerFace>3) && OpenMeshType::FaceType::HasPolyInfo() )
|
if( (vertexesPerFace>3) && OpenMeshType::FaceType::HasPolyInfo() )
|
||||||
{
|
{
|
||||||
//_BEGIN___ if you are loading a GENERIC POLYGON mesh
|
//_BEGIN___ if you are filling a vcg mesh with GENERIC POLYGON
|
||||||
ff.set(vertexesPerFace);
|
ff.set(vertexesPerFace);
|
||||||
for(int i=0;i<vertexesPerFace;++i) { // remember index starts from 1 instead of 0
|
for(int i=0;i<vertexesPerFace;++i) { // remember index starts from 1 instead of 0
|
||||||
SplitToken(tokens[i+1], ff.v[i], ff.n[i], ff.t[i], inputMask);
|
SplitToken(tokens[i+1], ff.v[i], ff.n[i], ff.t[i], inputMask);
|
||||||
|
@ -474,11 +450,11 @@ namespace vcg {
|
||||||
++numTriangles;
|
++numTriangles;
|
||||||
indexedFaces.push_back(ff);
|
indexedFaces.push_back(ff);
|
||||||
|
|
||||||
//_END ___ if you are loading a GENERIC POLYGON mesh
|
//_END ___ if you are filling a vcg mesh with GENERIC POLYGON
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//_BEGIN___ if you are loading a TRIMESH mesh
|
//_BEGIN___ if you are filling a vcg mesh with TRIANGLES
|
||||||
std::vector<std::vector<vcg::Point3f> > polygonVect(1); // it is a vector of polygon loops
|
std::vector<std::vector<vcg::Point3f> > polygonVect(1); // it is a vector of polygon loops
|
||||||
polygonVect[0].resize(vertexesPerFace);
|
polygonVect[0].resize(vertexesPerFace);
|
||||||
std::vector<int> indexVVect(vertexesPerFace);
|
std::vector<int> indexVVect(vertexesPerFace);
|
||||||
|
@ -599,7 +575,7 @@ namespace vcg {
|
||||||
indexedFaces.push_back(ff);
|
indexedFaces.push_back(ff);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} //_END ___ if you are filling a vcg mesh with TRIANGLES
|
||||||
}
|
}
|
||||||
else if ((header.compare("mtllib")==0) && (tokens.size() > 1)) // material library
|
else if ((header.compare("mtllib")==0) && (tokens.size() > 1)) // material library
|
||||||
{
|
{
|
||||||
|
@ -615,7 +591,7 @@ 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
|
// emergency check. If there are no materials, the material 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
|
// 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
|
// "mtllib" definition in the header. So, we can try to see if this is the case
|
||||||
if ((materials.size() == 1)&&(materials[0].materialName == "")){
|
if ((materials.size() == 1)&&(materials[0].materialName == "")){
|
||||||
|
@ -860,7 +836,16 @@ namespace vcg {
|
||||||
if (hasNormal)
|
if (hasNormal)
|
||||||
nId = atoi(token.substr(secondSep + 1).c_str()) - 1;
|
nId = atoi(token.substr(secondSep + 1).c_str()) - 1;
|
||||||
}
|
}
|
||||||
|
/** returns a Point3f done from (tokens[pos],tokens[pos+1],tokens[pos+2])
|
||||||
|
|
||||||
|
*/
|
||||||
|
static Point3f Point3fFrom3Tokens(std::vector< std::string > &tokens, int pos)
|
||||||
|
{
|
||||||
|
float r = (float) atof(tokens[pos+0].c_str());
|
||||||
|
float g = (float) atof(tokens[pos+1].c_str());
|
||||||
|
float b = (float) atof(tokens[pos+2].c_str());
|
||||||
|
return Point3f(r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Retrieves infos about kind of data stored into the file and fills a mask appropriately
|
* Retrieves infos about kind of data stored into the file and fills a mask appropriately
|
||||||
|
@ -1028,54 +1013,34 @@ namespace vcg {
|
||||||
}
|
}
|
||||||
else if (header.compare("Ka")==0)
|
else if (header.compare("Ka")==0)
|
||||||
{
|
{
|
||||||
if (tokens.size() < 4)
|
if (tokens.size() < 4) return false;
|
||||||
return false;
|
currentMaterial.Ka = Point3fFrom3Tokens(tokens,1);
|
||||||
float r = (float) atof(tokens[1].c_str());
|
|
||||||
float g = (float) atof(tokens[2].c_str());
|
|
||||||
float b = (float) atof(tokens[3].c_str());
|
|
||||||
|
|
||||||
currentMaterial.Ka = Point3f(r, g, b);
|
|
||||||
}
|
}
|
||||||
else if (header.compare("Kd")==0)
|
else if (header.compare("Kd")==0)
|
||||||
{
|
{
|
||||||
if (tokens.size() < 4)
|
if (tokens.size() < 4) return false;
|
||||||
return false;
|
currentMaterial.Kd = Point3fFrom3Tokens(tokens,1);
|
||||||
float r = (float) atof(tokens[1].c_str());
|
|
||||||
float g = (float) atof(tokens[2].c_str());
|
|
||||||
float b = (float) atof(tokens[3].c_str());
|
|
||||||
|
|
||||||
currentMaterial.Kd = Point3f(r, g, b);
|
|
||||||
}
|
}
|
||||||
else if (header.compare("Ks")==0)
|
else if (header.compare("Ks")==0)
|
||||||
{
|
{
|
||||||
if (tokens.size() < 4)
|
if (tokens.size() < 4) return false;
|
||||||
return false;
|
currentMaterial.Ks = Point3fFrom3Tokens(tokens,1);
|
||||||
float r = (float) atof(tokens[1].c_str());
|
|
||||||
float g = (float) atof(tokens[2].c_str());
|
|
||||||
float b = (float) atof(tokens[3].c_str());
|
|
||||||
|
|
||||||
currentMaterial.Ks = Point3f(r, g, b);
|
|
||||||
}
|
}
|
||||||
else if ( (header.compare("d")==0) ||
|
else if ( (header.compare("d")==0) ||
|
||||||
(header.compare("Tr")==0) ) // alpha
|
(header.compare("Tr")==0) ) // alpha
|
||||||
{
|
{
|
||||||
if (tokens.size() < 2)
|
if (tokens.size() < 2) return false;
|
||||||
return false;
|
|
||||||
currentMaterial.Tr = (float) atof(tokens[1].c_str());
|
currentMaterial.Tr = (float) atof(tokens[1].c_str());
|
||||||
}
|
}
|
||||||
else if (header.compare("Ns")==0) // shininess
|
else if (header.compare("Ns")==0) // shininess
|
||||||
{
|
{
|
||||||
if (tokens.size() < 2)
|
if (tokens.size() < 2) return false;
|
||||||
return false;
|
|
||||||
currentMaterial.Ns = float(atoi(tokens[1].c_str()));
|
currentMaterial.Ns = float(atoi(tokens[1].c_str()));
|
||||||
}
|
}
|
||||||
else if (header.compare("illum")==0) // specular illumination on/off
|
else if (header.compare("illum")==0) // specular illumination on/off
|
||||||
{
|
{
|
||||||
if (tokens.size() < 2)
|
if (tokens.size() < 2) return false;
|
||||||
return false;
|
currentMaterial.illum = atoi(tokens[1].c_str());;
|
||||||
int illumination = atoi(tokens[1].c_str());
|
|
||||||
//currentMaterial.bSpecular = (illumination == 2);
|
|
||||||
currentMaterial.illum = illumination;
|
|
||||||
}
|
}
|
||||||
else if(header.compare("map_Kd")==0) // texture name
|
else if(header.compare("map_Kd")==0) // texture name
|
||||||
{
|
{
|
||||||
|
@ -1091,22 +1056,12 @@ namespace vcg {
|
||||||
|
|
||||||
// adding texture name into textures vector (if not already present)
|
// adding texture name into textures vector (if not already present)
|
||||||
// avoid adding the same name twice
|
// avoid adding the same name twice
|
||||||
bool found = false;
|
auto it = std::find(textures.begin(), textures.end(), textureName);
|
||||||
unsigned int size = static_cast<unsigned int>(textures.size());
|
if(it==textures.end()) {
|
||||||
unsigned j = 0;
|
currentMaterial.index = textures.size();
|
||||||
while (!found && (j < size))
|
|
||||||
{
|
|
||||||
if (textureName.compare(textures[j])==0)
|
|
||||||
{
|
|
||||||
currentMaterial.index = (int)j;
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
++j;
|
|
||||||
}
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
textures.push_back(textureName);
|
textures.push_back(textureName);
|
||||||
currentMaterial.index = (int)size;
|
} else {
|
||||||
|
currentMaterial.index = std::distance(textures.begin(),it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// we simply ignore other situations
|
// we simply ignore other situations
|
||||||
|
@ -1115,13 +1070,27 @@ namespace vcg {
|
||||||
materials.push_back(currentMaterial); // add last read material
|
materials.push_back(currentMaterial); // add last read material
|
||||||
|
|
||||||
stream.close();
|
stream.close();
|
||||||
|
// Sometimes some materials have texture and no texture
|
||||||
|
// in this case for sake of uniformity we just use the first texture.
|
||||||
|
if(!textures.empty())
|
||||||
|
{
|
||||||
|
for(size_t i=0;i<materials.size();++i)
|
||||||
|
{
|
||||||
|
if(materials[i].map_Kd.empty())
|
||||||
|
{
|
||||||
|
materials[i].map_Kd=textures[0];
|
||||||
|
materials[i].index=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // end class
|
}; // end class
|
||||||
} // end Namespace tri
|
} // end Namespace tri
|
||||||
} // end Namespace io
|
} // end Namespace io
|
||||||
} // end Namespace vcg
|
} // end Namespace vcg
|
||||||
|
|
||||||
#endif // ndef __VCGLIB_IMPORT_OBJ
|
#endif // ndef __VCGLIB_IMPORT_OBJ
|
||||||
|
|
|
@ -221,10 +221,10 @@ static const PropDescriptor &FaceDesc(int i)
|
||||||
/* 15 */ {"face", "vertex_indices", ply::T_UINT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_UCHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
/* 15 */ {"face", "vertex_indices", ply::T_UINT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_UCHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
||||||
/* 16 */ {"face", "vertex_indices", ply::T_UINT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_CHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
/* 16 */ {"face", "vertex_indices", ply::T_UINT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_CHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
||||||
/* 17 */ {"face", "vertex_indices", ply::T_UINT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_INT, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
/* 17 */ {"face", "vertex_indices", ply::T_UINT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_INT, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
||||||
/* 18 */ {"face", "vertex_indices", ply::T_SHORT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_CHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
/* 18 */ {"face", "vertex_indices", ply::T_UINT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_USHORT,ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
||||||
/* 19 */ {"face", "vertex_indices", ply::T_SHORT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_UCHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
/* 19 */ {"face", "vertex_indices", ply::T_SHORT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_CHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
||||||
/* 20 */ {"face", "vertex_indices", ply::T_SHORT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_INT, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
/* 20 */ {"face", "vertex_indices", ply::T_SHORT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_UCHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
||||||
/* 21 */ {"face", "vertex_indices", ply::T_CHAR, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_UCHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0}
|
/* 21 */ {"face", "vertex_indices", ply::T_SHORT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_INT, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0},
|
||||||
};
|
};
|
||||||
return qf[i];
|
return qf[i];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue