From Sukender: Fixed FBX writer: now handles double precision arrays (vertices, normals, texcoords)

This commit is contained in:
Michael PLATINGS
2010-04-12 15:04:25 +00:00
parent fccda08491
commit 5d64318597
6 changed files with 368 additions and 92 deletions

View File

@@ -7,6 +7,7 @@ SET(TARGET_SRC
fbxRMesh.cpp
fbxRNode.cpp
ReaderWriterFBX.cpp
WriterCompareTriangle.cpp
WriterNodeVisitor.cpp
fbxMaterialToOsgStateSet.cpp
)
@@ -18,6 +19,7 @@ SET(TARGET_H
fbxRMesh.h
fbxRNode.h
ReaderWriterFBX.h
WriterCompareTriangle.h
WriterNodeVisitor.h
fbxMaterialToOsgStateSet.h
)

View File

@@ -13,7 +13,7 @@ public:
ReaderWriterFBX()
{
supportsExtension("fbx", "FBX format");
supportsOption("Embedded", "Embed textures in FBX file when writing");
supportsOption("Embedded", "(Write option) Embed textures in FBX file");
supportsOption("UseFbxRoot", "(Read/write option) If the source OSG root node is a simple group with no stateset, the writer will put its children directly under the FBX root, and vice-versa for reading");
}

View File

@@ -0,0 +1,150 @@
#include "WriterCompareTriangle.h"
WriterCompareTriangle::WriterCompareTriangle(const osg::Geode & geode,
unsigned int nbVertices)
: geode(geode)
{
cutscene(nbVertices, geode.getDrawable ( 0 )->asGeometry()->getBound());
}
bool
WriterCompareTriangle::operator()(const std::pair<Triangle, int> & t1,
const std::pair<Triangle, int> & t2) const
{
const osg::Geometry *g = geode.getDrawable( t1.second )->asGeometry();
const osg::Vec3Array * vecs= static_cast<const osg::Vec3Array *>(g->getVertexArray());
const osg::Vec3::value_type x1 = (*vecs)[t1.first.t1].x();
const osg::Vec3::value_type y1 = (*vecs)[t1.first.t1].y();
const osg::Vec3::value_type z1 = (*vecs)[t1.first.t1].z();
if (t1.second != t2.second)
{
const osg::Geometry *g = geode.getDrawable( t2.second )->asGeometry();
vecs = static_cast<const osg::Vec3Array *>(g->getVertexArray());
};
const osg::Vec3::value_type x2 = (*vecs)[t2.first.t1].x();
const osg::Vec3::value_type y2 = (*vecs)[t2.first.t1].y();
const osg::Vec3::value_type z2 = (*vecs)[t2.first.t1].z();
int val1 = inWhichBox(x1,y1,z1);
int val2 = inWhichBox(x2,y2,z2);
return (val1 < val2);
};
void
WriterCompareTriangle::setMaxMin(unsigned int & nbVerticesX,
unsigned int & nbVerticesY,
unsigned int & nbVerticesZ) const
{
static const unsigned int min = 1;
if (nbVerticesX < min)
nbVerticesX = min;
if (nbVerticesY < min)
nbVerticesY = min;
if (nbVerticesZ < min)
nbVerticesZ = min;
static const unsigned int max = 20;
if (nbVerticesX > max)
nbVerticesX = max;
if (nbVerticesY > max)
nbVerticesY = max;
if (nbVerticesZ > max)
nbVerticesZ = max;
}
void
WriterCompareTriangle::cutscene(int nbVertices,
const osg::BoundingBox & sceneBox)
{
osg::BoundingBox::vec_type length = sceneBox._max - sceneBox._min;
static const unsigned int k = 4;
unsigned int nbVerticesX = (nbVertices * k) / (length.z() * length.y());
unsigned int nbVerticesY = (nbVertices * k) / (length.z() * length.x());
unsigned int nbVerticesZ = (nbVertices * k) / (length.x() * length.y());
setMaxMin (nbVerticesX, nbVerticesY, nbVerticesZ); // This function prevent from cut scene in too many blocs
osg::notify(osg::DEBUG_INFO) << "Cutting x by " << nbVerticesX << std::endl
<< "Cutting y by " << nbVerticesY << std::endl
<< "Cutting z by " << nbVerticesZ << std::endl;
osg::BoundingBox::value_type blocX = length.x() / nbVerticesX; //This 3 lines set the size of a bloc in x, y and z
osg::BoundingBox::value_type blocY = length.y() / nbVerticesY;
osg::BoundingBox::value_type blocZ = length.z() / nbVerticesZ;
boxList.reserve(nbVerticesX * nbVerticesY * nbVerticesZ);
short yinc = 1;
short xinc = 1;
unsigned int y = 0;
unsigned int x = 0;
for (unsigned int z = 0; z < nbVerticesZ; ++z)
{
while (x < nbVerticesX && x >= 0)
{
while (y < nbVerticesY && y >= 0)
{
osg::BoundingBox::value_type xMin = sceneBox.xMin() + x * blocX;
if (x == 0) //to prevent from mesh with no case
xMin -= 10;
osg::BoundingBox::value_type yMin = sceneBox.yMin() + y * blocY;
if (y == 0) //to prevent from mesh with no case
yMin -= 10;
osg::BoundingBox::value_type zMin = sceneBox.zMin() + z * blocZ;
if (z == 0) //to prevent from mesh with no case
zMin -= 10;
osg::BoundingBox::value_type xMax = sceneBox.xMin() + (x + 1) * blocX;
if (x == nbVerticesX - 1) //to prevent from mesh with no case
xMax += 10;
osg::BoundingBox::value_type yMax = sceneBox.yMin() + (y + 1) * blocY;
if (y == nbVerticesY - 1) //to prevent from mesh with no case
yMax += 10;
osg::BoundingBox::value_type zMax = sceneBox.zMin() + (z + 1) * blocZ;
if (z == nbVerticesZ - 1) //to prevent from mesh with no case
zMax += 10;
boxList.push_back(osg::BoundingBox(xMin, // Add a bloc to the list
yMin,
zMin,
xMax,
yMax,
zMax));
y += yinc;
}
yinc = -yinc;
y += yinc;
x += xinc;
}
xinc = -xinc;
x += xinc;
}
}
int
WriterCompareTriangle::inWhichBox(const osg::Vec3::value_type x,
const osg::Vec3::value_type y,
const osg::Vec3::value_type z) const
{
for (unsigned int i = 0; i < boxList.size(); ++i)
{
if (x >= boxList[i].xMin() &&
x < boxList[i].xMax() &&
y >= boxList[i].yMin() &&
y < boxList[i].yMax() &&
z >= boxList[i].zMin() &&
z < boxList[i].zMax())
{
return i;
}
}
throw "Point is not in any blocs";
}

View File

@@ -0,0 +1,51 @@
#ifndef _3DS_WRITER_COMPARE_TRIANGLE_HEADER__
#define _3DS_WRITER_COMPARE_TRIANGLE_HEADER__
#include <osg/Geode>
#include <osg/Geometry>
#include <iostream>
struct Triangle
{
unsigned int t1;
unsigned int t2;
unsigned int t3;
unsigned int material;
};
class WriterCompareTriangle {
public:
WriterCompareTriangle(const osg::Geode & geode,
unsigned int nbVertices);
bool operator()(const std::pair<Triangle, int> & t1,
const std::pair<Triangle, int> & t2) const;
private:
void // This function prevent from cut scene in too many blocs
setMaxMin(unsigned int & nbVerticesX,
unsigned int & nbVerticesY,
unsigned int & nbVerticesZ) const;
/**
* Cut the scene in different bloc to sort.
* \param nbVertices is the number of vertice in mesh.
* \param sceneBox contain the size of the scene.
*/
void
cutscene(int nbVertices,
const osg::BoundingBox & sceneBox);
/**
* Find in which box those points are.
* \return the place of the box in the vector.
* \sa See cutScene() about the definition of the boxes for faces sorting.
*/
int inWhichBox(const osg::Vec3::value_type x,
const osg::Vec3::value_type y,
const osg::Vec3::value_type z) const;
const osg::Geode & geode;
std::vector<osg::BoundingBox> boxList;
};
#endif // _3DS_WRITER_COMPARE_TRIANGLE_HEADER__

View File

@@ -39,10 +39,20 @@ public:
_lastFaceIndex(0),
_listTriangles(listTriangles),
_drawable_n(drawable_n),
_material(material)
_material(material),
//_iPrimitiveSet(iPrimitiveSet),
_curNormalIndex(0),
_normalBinding(geo->getNormalBinding())
{
if (!geo->getNormalArray() || geo->getNormalArray()->getNumElements()==0)
{
_normalBinding = osg::Geometry::BIND_OFF; // Turn off binding if there is no normal data
}
reset();
}
void reset() { _curNormalIndex = 0; }
unsigned int getNextFaceIndex() { return _lastFaceIndex; }
virtual void setVertexArray(unsigned int, const osg::Vec2*) {}
@@ -64,6 +74,7 @@ public:
triangle.t1 = i1;
triangle.t2 = i2;
triangle.t3 = i3;
triangle.normalIndex = _curNormalIndex;
triangle.material = _material;
_listTriangles.push_back(std::make_pair(triangle, _drawable_n));
}
@@ -117,8 +128,10 @@ protected:
{
IndexPointer ilast = indices + count;
for (IndexPointer iptr = indices; iptr < ilast; iptr+=3)
{
writeTriangle(iptr[0], iptr[1], iptr[2]);
if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
}
break;
}
case GL_TRIANGLE_STRIP:
@@ -129,6 +142,7 @@ protected:
if (i & 1) writeTriangle(iptr[0], iptr[2], iptr[1]);
else writeTriangle(iptr[0], iptr[1], iptr[2]);
}
if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
break;
}
case GL_QUADS:
@@ -138,6 +152,7 @@ protected:
{
writeTriangle(iptr[0], iptr[1], iptr[2]);
writeTriangle(iptr[0], iptr[2], iptr[3]);
if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
}
break;
}
@@ -149,6 +164,7 @@ protected:
writeTriangle(iptr[0], iptr[1], iptr[2]);
writeTriangle(iptr[1], iptr[3], iptr[2]);
}
if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
break;
}
case GL_POLYGON: // treat polygons as GL_TRIANGLE_FAN
@@ -161,6 +177,7 @@ protected:
{
writeTriangle(first, iptr[0], iptr[1]);
}
if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
break;
}
case GL_POINTS:
@@ -173,10 +190,11 @@ protected:
// uhm should never come to this point :)
break;
}
if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE_SET) ++_curNormalIndex;
}
private:
PrimitiveIndexWriter& operator = (const PrimitiveIndexWriter&) { return *this; }
PrimitiveIndexWriter& operator = (const PrimitiveIndexWriter&); // { return *this; }
unsigned int _drawable_n;
ListTriangle& _listTriangles;
@@ -186,6 +204,8 @@ private:
const osg::Geometry* _geo;
unsigned int _lastFaceIndex;
int _material;
unsigned int _curNormalIndex;
osg::Geometry::AttributeBinding _normalBinding;
KFbxMesh* _mesh;
};
@@ -198,6 +218,7 @@ void PrimitiveIndexWriter::drawArrays(GLenum mode,GLint first,GLsizei count)
for (GLsizei i = 2; i < count; i += 3, pos += 3)
{
writeTriangle(pos, pos + 1, pos + 2);
if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
}
break;
case GL_TRIANGLE_STRIP:
@@ -206,12 +227,14 @@ void PrimitiveIndexWriter::drawArrays(GLenum mode,GLint first,GLsizei count)
if (i & 1) writeTriangle(pos, pos + 2, pos + 1);
else writeTriangle(pos, pos + 1, pos + 2);
}
if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
break;
case GL_QUADS:
for (GLsizei i = 3; i < count; i += 4, pos += 4)
{
writeTriangle(pos, pos + 1, pos + 2);
writeTriangle(pos, pos + 2, pos + 3);
if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
}
break;
case GL_QUAD_STRIP:
@@ -220,6 +243,7 @@ void PrimitiveIndexWriter::drawArrays(GLenum mode,GLint first,GLsizei count)
writeTriangle(pos, pos + 1, pos + 2);
writeTriangle(pos + 1, pos + 3, pos + 2);
}
if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
break;
case GL_POLYGON: // treat polygons as GL_TRIANGLE_FAN
case GL_TRIANGLE_FAN:
@@ -228,6 +252,7 @@ void PrimitiveIndexWriter::drawArrays(GLenum mode,GLint first,GLsizei count)
{
writeTriangle(first, pos, pos+1);
}
if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
break;
case GL_POINTS:
case GL_LINES:
@@ -237,6 +262,7 @@ void PrimitiveIndexWriter::drawArrays(GLenum mode,GLint first,GLsizei count)
osg::notify(osg::WARN) << "WriterNodeVisitor :: can't handle mode " << mode << std::endl;
break;
}
if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE_SET) ++_curNormalIndex;
}
// If 'to' is in a subdirectory of 'from' then this function returns the
@@ -398,6 +424,10 @@ WriterNodeVisitor::Material::Material(WriterNodeVisitor& writerNodeVisitor,
destPath = osgDB::getRealPath(osgDB::convertFileNameToNativeStyle( osgDB::concatPaths(_directory, relativePath) ));
if (destPath != canonicalPath)
{
if (!osgDB::makeDirectoryForFile(destPath))
{
osg::notify(osg::NOTICE) << "Can't create directory for file '" << destPath << "'. May fail creating the image file." << std::endl;
}
osgDB::writeImageFile(*_osgImage, destPath);
}
}
@@ -438,28 +468,27 @@ int WriterNodeVisitor::processStateSet(const osg::StateSet* ss)
return -1;
}
/**
* Add a vertex to the index and link him with the Triangle index and the drawable.
* \param index_vert is the map where the vertices are stored.
* \param index is the index of the vertices position in the vec3.
* \param drawable_n is the number of the drawable.
* \return the position of the vertex in the final mesh.
*/
unsigned int
WriterNodeVisitor::getMeshIndexForGeometryIndex(MapIndices& index_vert,
unsigned int index,
unsigned int drawable_n)
unsigned int addPolygon(MapIndices & index_vert, unsigned int vertIndex, unsigned int normIndex, unsigned int drawableNum)
{
MapIndices::iterator itIndex = index_vert.find(std::make_pair(index, drawable_n));
VertexIndex vert(vertIndex, drawableNum, normIndex);
MapIndices::iterator itIndex = index_vert.find(vert);
if (itIndex == index_vert.end())
{
unsigned int indexMesh = index_vert.size();
index_vert.insert(std::make_pair(std::make_pair(index, drawable_n), indexMesh));
index_vert.insert(std::make_pair(vert, indexMesh));
return indexMesh;
}
return itIndex->second;
}
void addPolygon(KFbxMesh * mesh, MapIndices & index_vert, const Triangle & tri, unsigned int drawableNum)
{
mesh->AddPolygon(addPolygon(index_vert, tri.t1, tri.normalIndex, drawableNum));
mesh->AddPolygon(addPolygon(index_vert, tri.t2, tri.normalIndex, drawableNum));
mesh->AddPolygon(addPolygon(index_vert, tri.t3, tri.normalIndex, drawableNum));
}
void
WriterNodeVisitor::setLayerTextureAndMaterial(KFbxMesh* mesh)
{
@@ -495,6 +524,7 @@ WriterNodeVisitor::setControlPointAndNormalsAndUV(const osg::Geode& geo,
{
mesh->InitControlPoints(index_vert.size());
KFbxLayerElementNormal* lLayerElementNormal= KFbxLayerElementNormal::Create(mesh, "");
// For now, FBX writer only supports normals bound per vertices
lLayerElementNormal->SetMappingMode(KFbxLayerElement::eBY_CONTROL_POINT);
lLayerElementNormal->SetReferenceMode(KFbxLayerElement::eDIRECT);
lLayerElementNormal->GetDirectArray().SetCount(index_vert.size());
@@ -511,53 +541,100 @@ WriterNodeVisitor::setControlPointAndNormalsAndUV(const osg::Geode& geo,
for (MapIndices::iterator it = index_vert.begin(); it != index_vert.end(); ++it)
{
const osg::Geometry* pGeometry = geo.getDrawable(it->first.second)->asGeometry();
assert(pGeometry->getVertexArray());
const osg::Geometry* pGeometry = geo.getDrawable(it->first.drawableIndex)->asGeometry();
unsigned int vertexIndex = it->first.vertexIndex;
unsigned int normalIndex = it->first.normalIndex;
if (pGeometry->getVertexArray()->getType() != osg::Array::Vec3ArrayType)
const osg::Array * basevecs = pGeometry->getVertexArray();
assert(basevecs);
if (!basevecs || basevecs->getNumElements()==0)
{
throw "Vertex array is not Vec3. Not implemented"; // TODO
//OSG_NOTIFY()
continue;
}
const osg::Vec3Array* vecs= static_cast<const osg::Vec3Array*>(pGeometry->getVertexArray());
if (vecs)
KFbxVector4 vertex;
if (basevecs->getType() == osg::Array::Vec3ArrayType)
{
mesh->SetControlPointAt(*new KFbxVector4(
(*vecs)[it->first.first].x(),
(*vecs)[it->first.first].y(),
(*vecs)[it->first.first].z()), it->second);
const osg::Vec3 & vec = (*static_cast<const osg::Vec3Array *>(basevecs))[vertexIndex];
// Sukender: "*new KFbxVector4"? Shouldn't it be "KFbxVector4" alone?
//mesh->SetControlPointAt(*new KFbxVector4(vec.x(), vec.y(), vec.z()), it->second);
vertex.Set(vec.x(), vec.y(), vec.z());
}
const osg::Vec3Array* pNormals = static_cast<const osg::Vec3Array*>(pGeometry->getNormalArray());
if (pNormals)
else if (basevecs->getType() == osg::Array::Vec3dArrayType)
{
switch (pGeometry->getNormalBinding())
const osg::Vec3d & vec = (*static_cast<const osg::Vec3dArray *>(basevecs))[vertexIndex];
// Sukender: "*new KFbxVector4"? Shouldn't it be "KFbxVector4" alone?
//mesh->SetControlPointAt(*new KFbxVector4(vec.x(), vec.y(), vec.z()), it->second);
vertex.Set(vec.x(), vec.y(), vec.z());
}
else
{
OSG_NOTIFY(osg::FATAL) << "Vertex array is not Vec3 or Vec3d. Not implemented" << std::endl;
throw "Vertex array is not Vec3 or Vec3d. Not implemented";
//_succeeded = false;
//return;
}
mesh->SetControlPointAt(vertex, it->second);
const osg::Array * basenormals = pGeometry->getNormalArray();
if (basenormals && basenormals->getNumElements()>0)
{
KFbxVector4 normal;
if (basenormals->getType() == osg::Array::Vec3ArrayType)
{
case osg::Geometry::BIND_PER_PRIMITIVE_SET:
case osg::Geometry::BIND_PER_PRIMITIVE:
lLayerElementNormal->GetDirectArray().SetAt(it->second,
KFbxVector4(
(*pNormals)[0].x(),
(*pNormals)[0].y(),
(*pNormals)[0].z(), 0));
break;
const osg::Vec3 & vec = (*static_cast<const osg::Vec3Array *>(basenormals))[normalIndex];
normal.Set(vec.x(), vec.y(), vec.z(), 0);
}
else if (basenormals->getType() == osg::Array::Vec3dArrayType)
{
const osg::Vec3d & vec = (*static_cast<const osg::Vec3dArray *>(basenormals))[normalIndex];
normal.Set(vec.x(), vec.y(), vec.z(), 0);
}
else
{
OSG_NOTIFY(osg::FATAL) << "Normal array is not Vec3 or Vec3d. Not implemented" << std::endl;
throw "Normal array is not Vec3 or Vec3d. Not implemented";
//_succeeded = false;
//return;
}
case osg::Geometry::BIND_PER_VERTEX:
lLayerElementNormal->GetDirectArray().SetAt(it->second,
KFbxVector4(
(*pNormals)[it->first.first].x(),
(*pNormals)[it->first.first].y(),
(*pNormals)[it->first.first].z(), 0));
break;
}
//switch (pGeometry->getNormalBinding())
//{
//case osg::Geometry::BIND_PER_PRIMITIVE_SET:
//case osg::Geometry::BIND_PER_PRIMITIVE:
//case osg::Geometry::BIND_PER_VERTEX:
// break;
//}
lLayerElementNormal->GetDirectArray().SetAt(it->second, normal);
}
if (texcoords)
{
const osg::Vec2Array* vec2= static_cast<const osg::Vec2Array*>(pGeometry->getTexCoordArray(0));
if (vec2)
lUVDiffuseLayer->GetDirectArray().SetAt(it->second, KFbxVector2((*vec2)[it->first.first].x(), (*vec2)[it->first.first].y()));
const osg::Array * basetexcoords = pGeometry->getTexCoordArray(0);
if (basetexcoords && basetexcoords->getNumElements()>0)
{
KFbxVector2 texcoord;
if (basetexcoords->getType() == osg::Array::Vec2ArrayType)
{
const osg::Vec2 & vec = (*static_cast<const osg::Vec2Array *>(basetexcoords))[vertexIndex];
texcoord.Set(vec.x(), vec.y());
}
else if (basetexcoords->getType() == osg::Array::Vec2dArrayType)
{
const osg::Vec2d & vec = (*static_cast<const osg::Vec2dArray *>(basetexcoords))[vertexIndex];
texcoord.Set(vec.x(), vec.y());
}
else
{
OSG_NOTIFY(osg::FATAL) << "Texture coords array is not Vec2 or Vec2d. Not implemented" << std::endl;
throw "Texture coords array is not Vec2 or Vec2d. Not implemented";
//_succeeded = false;
//return;
}
lUVDiffuseLayer->GetDirectArray().SetAt(it->second, texcoord);
}
}
}
}
@@ -593,9 +670,7 @@ void WriterNodeVisitor::buildFaces(const osg::Geode& geo,
lLayer->GetDiffuseTextures()->GetIndexArray().SetAt(i, it->first.material);
lLayer->GetMaterials()->GetIndexArray().SetAt(i, it->first.material);
}
mesh->AddPolygon(getMeshIndexForGeometryIndex(index_vert, it->first.t1, it->second));
mesh->AddPolygon(getMeshIndexForGeometryIndex(index_vert, it->first.t2, it->second));
mesh->AddPolygon(getMeshIndexForGeometryIndex(index_vert, it->first.t3, it->second));
addPolygon(mesh, index_vert, it->first, it->second);
mesh->EndPolygon();
}
setControlPointAndNormalsAndUV(geo, index_vert, texcoords, mesh);
@@ -607,33 +682,23 @@ void WriterNodeVisitor::createListTriangle(const osg::Geometry* geo,
unsigned int& drawable_n)
{
unsigned int nbVertices = 0;
texcoords = false;
{
if (geo->getVertexArray() && geo->getVertexArray()->getType() != osg::Array::Vec3ArrayType)
{
throw "Vertex array is not Vec3. Not implemented"; // TODO
}
const osg::Vec3Array* vecs = static_cast<const osg::Vec3Array*>(geo->getVertexArray());
const osg::Array * vecs = geo->getVertexArray();
if (vecs)
{
nbVertices = geo->getVertexArray()->getNumElements();
nbVertices = vecs->getNumElements();
// Texture coords
if (geo->getTexCoordArray(0) && geo->getTexCoordArray(0)->getType() != osg::Array::Vec2ArrayType)
const osg::Array * texvec = geo->getTexCoordArray(0);
if (texvec)
{
throw "Texture coords array is not Vec2. Not implemented"; // TODO
}
const osg::Vec2Array* texvecs = static_cast<const osg::Vec2Array*>(geo->getTexCoordArray(0));
if (texvecs)
{
unsigned int nb = geo->getTexCoordArray(0)->getNumElements();
if (nb != geo->getVertexArray()->getNumElements())
unsigned int nb = texvec->getNumElements();
if (nb == nbVertices) texcoords = true;
else
{
throw "There are more/less texture coords than vertices!";
OSG_NOTIFY(osg::WARN) << "There are more/less texture coords than vertices! Ignoring texture coords.";
}
texcoords = true;
}
}
}
@@ -642,10 +707,10 @@ void WriterNodeVisitor::createListTriangle(const osg::Geometry* geo,
int material = processStateSet(_currentStateSet.get());
for (unsigned int i = 0; i < geo->getNumPrimitiveSets(); ++i) //Fill the Triangle List
PrimitiveIndexWriter pif(geo, listTriangles, drawable_n, material);
for (unsigned int iPrimSet = 0; iPrimSet < geo->getNumPrimitiveSets(); ++iPrimSet) //Fill the Triangle List
{
const osg::PrimitiveSet* ps = geo->getPrimitiveSet(i);
PrimitiveIndexWriter pif(geo, listTriangles, drawable_n, material);
const osg::PrimitiveSet* ps = geo->getPrimitiveSet(iPrimSet);
const_cast<osg::PrimitiveSet*>(ps)->accept(pif);
}
}

View File

@@ -35,13 +35,32 @@ struct Triangle
unsigned int t1;
unsigned int t2;
unsigned int t3;
unsigned int normalIndex; ///< Normal index for all bindings except BIND_PER_VERTEX and BIND_OFF.
int material;
};
typedef std::map<std::pair<unsigned int, unsigned int>, unsigned int> MapIndices;
typedef std::vector<std::pair<Triangle, int> > ListTriangle; //the int is the drawable of the triangle
struct VertexIndex
{
VertexIndex(unsigned int vertexIndex, unsigned int drawableIndex, unsigned int normalIndex)
: vertexIndex(vertexIndex), drawableIndex(drawableIndex), normalIndex(normalIndex)
{}
VertexIndex(const VertexIndex & v) : vertexIndex(v.vertexIndex), drawableIndex(v.drawableIndex), normalIndex(v.normalIndex) {}
///\author Capo (Thibault Caporal)
unsigned int vertexIndex; ///< Index of the vertice position in the vec3 array
unsigned int drawableIndex;
unsigned int normalIndex; ///< Normal index for all bindings except BIND_PER_VERTEX and BIND_OFF.
bool operator<(const VertexIndex & v) const {
if (drawableIndex!=v.drawableIndex) return drawableIndex<v.drawableIndex;
return vertexIndex<v.vertexIndex;
}
};
typedef std::vector<std::pair<Triangle, int> > ListTriangle; //the int is the drawable of the triangle
typedef std::map<VertexIndex, unsigned int> MapIndices; ///< Map OSG indices to FBX mesh indices
///\author Capo (Thibault Caporal), Sukender (Benoit Neil)
class WriterNodeVisitor: public osg::NodeVisitor
{
public:
@@ -192,17 +211,6 @@ class WriterNodeVisitor: public osg::NodeVisitor
bool texcoords,
KFbxMesh* fbxMesh);
/**
* Add a vertex to the index and link him with the Triangle index and the drawable.
* \param index_vert is the map where the vertices are stored.
* \param index is the indices of the vertices position in the vec3.
* \param drawable_n is the number of the drawable.
* \return the position of the vertices in the final mesh.
*/
unsigned int getMeshIndexForGeometryIndex(MapIndices& index_vert,
unsigned int index,
unsigned int drawable_n);
/**
* Create the list of faces from the geode.
* \param geo is the geode to study.