From Lee Butler, "The attached ZIP file contains a modified OBJ file format reader which

makes smoothing optional for verticies which do not have a normal
associated with them in the OBJ input file.  The previous behavior was
to always smooth at all verticies which did not have surface normals.
In this new implementation smoothing is on by default to be compatible
with previous behavior.  The user can now specify the "generateFacetNormals"
option to the reader to use facet normals for verticies where the OBJ
file does not specify a normal."

Note from Robert Osfield, changed "noSmoothing" naming used by Lee to "generateFacetNormals".
This commit is contained in:
Robert Osfield 2009-11-18 14:08:46 +00:00
parent 2a0497e2c1
commit a3f141d4b5

View File

@ -27,6 +27,7 @@
#include <osg/Node>
#include <osg/MatrixTransform>
#include <osg/Geode>
#include <osg/Vec3f>
#include <osg/Geometry>
#include <osg/StateSet>
@ -59,6 +60,7 @@ public:
supportsOption("noRotation","Do not do the default rotate about X axis");
supportsOption("noTesselateLargePolygons","Do not do the default tesselation of large polygons");
supportsOption("noTriStripPolygons","Do not do the default tri stripping of polygons");
supportsOption("generateFacetNormals","generate facet normals for verticies without normals");
supportsOption("DIFFUSE=<unit>", "Set texture unit for diffuse texture");
supportsOption("AMBIENT=<unit>", "Set texture unit for ambient texture");
@ -134,6 +136,7 @@ protected:
bool rotate;
bool noTesselateLargePolygons;
bool noTriStripPolygons;
bool generateFacetNormals;
bool fixBlackMaterials;
// This is the order in which the materials will be assigned to texture maps, unless
// otherwise overriden
@ -145,7 +148,7 @@ protected:
void buildMaterialToStateSetMap(obj::Model& model, MaterialToStateSetMap& materialToSetSetMapObj, ObjOptionsStruct& localOptions) const;
osg::Geometry* convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList, bool& rotate) const;
osg::Geometry* convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList, ObjOptionsStruct& localOptions) const;
osg::Node* convertModelToSceneGraph(obj::Model& model, ObjOptionsStruct& localOptions) const;
@ -402,7 +405,7 @@ void ReaderWriterOBJ::buildMaterialToStateSetMap(obj::Model& model, MaterialToSt
}
}
osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList, bool& rotate) const
osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList, ObjOptionsStruct& localOptions) const
{
unsigned int numVertexIndices = 0;
@ -414,6 +417,41 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
unsigned int numPolygonElements = 0;
obj::Model::ElementList::iterator itr;
if (localOptions.generateFacetNormals == true) {
for(itr=elementList.begin();
itr!=elementList.end();
++itr)
{
obj::Element& element = *(*itr);
if (element.dataType==obj::Element::POINTS || element.dataType==obj::Element::POLYLINE)
continue;
if (element.normalIndices.size() == 0) {
// fill in the normals
int a = element.vertexIndices[0];
int b = element.vertexIndices[1];
int c = element.vertexIndices[2];
osg::Vec3f ab(model.vertices[b]);
osg::Vec3f ac(model.vertices[c]);
ab -= model.vertices[a];
ac -= model.vertices[a];
osg::Vec3f Norm( ab ^ ac );
Norm.normalize();
int normal_idx = model.normals.size();
model.normals.push_back(Norm);
for (unsigned i=0 ; i < element.vertexIndices.size() ; i++)
element.normalIndices.push_back(normal_idx);
}
}
}
for(itr=elementList.begin();
itr!=elementList.end();
++itr)
@ -480,7 +518,7 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
index_itr != element.vertexIndices.end();
++index_itr)
{
vertices->push_back(transformVertex(model.vertices[*index_itr],rotate));
vertices->push_back(transformVertex(model.vertices[*index_itr],localOptions.rotate));
++numPoints;
}
if (numNormalIndices)
@ -489,7 +527,7 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
index_itr != element.normalIndices.end();
++index_itr)
{
normals->push_back(transformNormal(model.normals[*index_itr],rotate));
normals->push_back(transformNormal(model.normals[*index_itr],localOptions.rotate));
}
}
if (numTexCoordIndices)
@ -526,7 +564,7 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
index_itr != element.vertexIndices.end();
++index_itr)
{
vertices->push_back(transformVertex(model.vertices[*index_itr],rotate));
vertices->push_back(transformVertex(model.vertices[*index_itr],localOptions.rotate));
}
if (numNormalIndices)
{
@ -534,7 +572,7 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
index_itr != element.normalIndices.end();
++index_itr)
{
normals->push_back(transformNormal(model.normals[*index_itr],rotate));
normals->push_back(transformNormal(model.normals[*index_itr],localOptions.rotate));
}
}
if (numTexCoordIndices)
@ -572,6 +610,11 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
if (element.dataType==obj::Element::POLYGON)
{
#ifdef USE_DRAWARRAYLENGTHS
drawArrayLengths->push_back(element.vertexIndices.size());
#else
@ -597,7 +640,7 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
index_itr != element.vertexIndices.rend();
++index_itr)
{
vertices->push_back(transformVertex(model.vertices[*index_itr],rotate));
vertices->push_back(transformVertex(model.vertices[*index_itr],localOptions.rotate));
}
if (numNormalIndices)
{
@ -605,9 +648,11 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
index_itr != element.normalIndices.rend();
++index_itr)
{
normals->push_back(transformNormal(model.normals[*index_itr],rotate));
normals->push_back(transformNormal(model.normals[*index_itr],localOptions.rotate));
}
}
if (numTexCoordIndices)
{
for(obj::Element::IndexList::reverse_iterator index_itr = element.texCoordIndices.rbegin();
@ -625,7 +670,7 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
index_itr != element.vertexIndices.end();
++index_itr)
{
vertices->push_back(transformVertex(model.vertices[*index_itr],rotate));
vertices->push_back(transformVertex(model.vertices[*index_itr],localOptions.rotate));
}
if (numNormalIndices)
{
@ -633,7 +678,7 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
index_itr != element.normalIndices.end();
++index_itr)
{
normals->push_back(transformNormal(model.normals[*index_itr],rotate));
normals->push_back(transformNormal(model.normals[*index_itr],localOptions.rotate));
}
}
if (numTexCoordIndices)
@ -675,7 +720,7 @@ osg::Node* ReaderWriterOBJ::convertModelToSceneGraph(obj::Model& model, ObjOptio
const obj::ElementState& es = itr->first;
obj::Model::ElementList& el = itr->second;
osg::Geometry* geometry = convertElementListToGeometry(model,el,localOptions.rotate);
osg::Geometry* geometry = convertElementListToGeometry(model,el,localOptions);
if (geometry)
{
@ -698,7 +743,7 @@ osg::Node* ReaderWriterOBJ::convertModelToSceneGraph(obj::Model& model, ObjOptio
}
// if no normals present add them.
if (!geometry->getNormalArray() || geometry->getNormalArray()->getNumElements()==0)
if (localOptions.generateFacetNormals==false && (!geometry->getNormalArray() || geometry->getNormalArray()->getNumElements()==0))
{
osgUtil::SmoothingVisitor sv;
sv.smooth(*geometry);
@ -735,6 +780,7 @@ ReaderWriterOBJ::ObjOptionsStruct ReaderWriterOBJ::parseOptions(const osgDB::Rea
localOptions.rotate = true;
localOptions.noTesselateLargePolygons = false;
localOptions.noTriStripPolygons = false;
localOptions.generateFacetNormals = false;
localOptions.fixBlackMaterials = true;
if (options!=NULL)
@ -770,6 +816,10 @@ ReaderWriterOBJ::ObjOptionsStruct ReaderWriterOBJ::parseOptions(const osgDB::Rea
{
localOptions.noTriStripPolygons = true;
}
else if (pre_equals == "generateFacetNormals")
{
localOptions.generateFacetNormals = true;
}
else if (post_equals.length()>0)
{
obj::Material::Map::TextureMapType type = obj::Material::Map::UNKNOWN;