From Sukender: Fixed FBX writer: now handles double precision arrays (vertices, normals, texcoords)
This commit is contained in:
@@ -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
|
||||
)
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
150
src/osgPlugins/fbx/WriterCompareTriangle.cpp
Normal file
150
src/osgPlugins/fbx/WriterCompareTriangle.cpp
Normal 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";
|
||||
}
|
||||
51
src/osgPlugins/fbx/WriterCompareTriangle.h
Normal file
51
src/osgPlugins/fbx/WriterCompareTriangle.h
Normal 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__
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user