From Doug McCorkle, "Attached is patch that corrects/improves the following issues with the OBJ loader:

1. Added options to control wether the osgUtil::Tessellator or osgUtil::TriStripVisitor are run. By default they still run just as before.
2. Added support for the Emissive material. The data was being read from the mtl file but was never being applied to the model.
3. This is the main bug addressed, when a model is read in with an alpha value specified like:

newmtl Material__8
       Ns 24
       d 0.33
       illum 2
       Kd 0.204 0.204 0.204
       Ks 0 0 0
       Ka 0.153 0.153 0.153

where the alpha value is d. The loader would then overwrite the alpha value when reading the diffuse, specular, and ambient colors. I have changed all the material color readers to only set the values they read and to use the default colors specified in the constructor of the obj class. With these changes, the obj reader now handles opacity correctly if the alpha value is specified before the material colo"
This commit is contained in:
Robert Osfield 2008-07-12 12:00:58 +00:00
parent ccb50019e4
commit 4ca61c38f0
2 changed files with 184 additions and 42 deletions

View File

@ -122,7 +122,8 @@ protected:
osg::Geometry* convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList, bool& rotate) const; osg::Geometry* convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList, bool& rotate) const;
osg::Node* convertModelToSceneGraph(obj::Model& model, bool& rotate) const; osg::Node* convertModelToSceneGraph(obj::Model& model, bool& rotate,
bool& noTesselateLargePolygons, bool& noTriStripPolygons) const;
inline osg::Vec3 transformVertex(const osg::Vec3& vec, const bool rotate) const ; inline osg::Vec3 transformVertex(const osg::Vec3& vec, const bool rotate) const ;
inline osg::Vec3 transformNormal(const osg::Vec3& vec, const bool rotate) const ; inline osg::Vec3 transformNormal(const osg::Vec3& vec, const bool rotate) const ;
@ -267,6 +268,8 @@ void ReaderWriterOBJ::buildMaterialToStateSetMap(obj::Model& model, MaterialToSt
osg_material->setAmbient(osg::Material::FRONT_AND_BACK,material.ambient); osg_material->setAmbient(osg::Material::FRONT_AND_BACK,material.ambient);
osg_material->setDiffuse(osg::Material::FRONT_AND_BACK,material.diffuse); osg_material->setDiffuse(osg::Material::FRONT_AND_BACK,material.diffuse);
osg_material->setEmission(osg::Material::FRONT_AND_BACK,material.emissive);
if (material.illum == 2) { if (material.illum == 2) {
osg_material->setSpecular(osg::Material::FRONT_AND_BACK,material.specular); osg_material->setSpecular(osg::Material::FRONT_AND_BACK,material.specular);
} else { } else {
@ -276,7 +279,8 @@ void ReaderWriterOBJ::buildMaterialToStateSetMap(obj::Model& model, MaterialToSt
if (material.ambient[3]!=1.0 || if (material.ambient[3]!=1.0 ||
material.diffuse[3]!=1.0 || material.diffuse[3]!=1.0 ||
material.specular[3]!=1.0) material.specular[3]!=1.0||
material.emissive[3]!=1.0)
{ {
osg::notify(osg::INFO)<<"Found transparent material"<<std::endl; osg::notify(osg::INFO)<<"Found transparent material"<<std::endl;
isTransparent = true; isTransparent = true;
@ -292,8 +296,13 @@ void ReaderWriterOBJ::buildMaterialToStateSetMap(obj::Model& model, MaterialToSt
load_material_texture( model, material, stateset.get(), material.map_Kd, TEXTURE_UNIT_KD ); load_material_texture( model, material, stateset.get(), material.map_Kd, TEXTURE_UNIT_KD );
load_material_texture( model, material, stateset.get(), material.map_opacity, TEXTURE_UNIT_OPACITY ); load_material_texture( model, material, stateset.get(), material.map_opacity, TEXTURE_UNIT_OPACITY );
if (isTransparent)
{
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
}
materialToStateSetMap[material.name] = stateset.get(); materialToStateSetMap[material.name] = stateset.get();
} }
} }
@ -550,7 +559,8 @@ osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model,
return geometry; return geometry;
} }
osg::Node* ReaderWriterOBJ::convertModelToSceneGraph(obj::Model& model, bool& rotate) const osg::Node* ReaderWriterOBJ::convertModelToSceneGraph(obj::Model& model,
bool& rotate, bool& noTesselateLargePolygons, bool& noTriStripPolygons) const
{ {
if (model.elementStateMap.empty()) return 0; if (model.elementStateMap.empty()) return 0;
@ -579,18 +589,24 @@ osg::Node* ReaderWriterOBJ::convertModelToSceneGraph(obj::Model& model, bool& ro
geometry->setStateSet(stateset); geometry->setStateSet(stateset);
// tesseleate any large polygons // tesseleate any large polygons
osgUtil::Tessellator tessellator; if (!noTesselateLargePolygons)
tessellator.retessellatePolygons(*geometry); {
osgUtil::Tessellator tessellator;
tessellator.retessellatePolygons(*geometry);
}
// tri strip polygons to improve graphics peformance // tri strip polygons to improve graphics peformance
osgUtil::TriStripVisitor tsv; if (!noTriStripPolygons)
tsv.stripify(*geometry); {
osgUtil::TriStripVisitor tsv;
tsv.stripify(*geometry);
}
// if no normals present add them. // if no normals present add them.
if (!geometry->getNormalArray() || geometry->getNormalArray()->getNumElements()==0) if (!geometry->getNormalArray() || geometry->getNormalArray()->getNumElements()==0)
{ {
osgUtil::SmoothingVisitor tsv; osgUtil::SmoothingVisitor sv;
tsv.smooth(*geometry); sv.smooth(*geometry);
} }
@ -641,14 +657,32 @@ osgDB::ReaderWriter::ReadResult ReaderWriterOBJ::readNode(const std::string& fil
model.setDatabasePath(osgDB::getFilePath(fileName.c_str())); model.setDatabasePath(osgDB::getFilePath(fileName.c_str()));
model.readOBJ(fin, local_opt.get()); model.readOBJ(fin, local_opt.get());
// code for checking the noRotation // code for checking the nonRotation, noTesselateLargePolygons,
// and noTriStripPolygons
bool rotate = true; bool rotate = true;
if ((options!=NULL) && (options->getOptionString() == "noRotation")) bool noTesselateLargePolygons = false;
bool noTriStripPolygons = false;
if (options!=NULL)
{ {
rotate = false; if (options->getOptionString() == "noRotation")
{
rotate = false;
}
if (options->getOptionString() == "noTesselateLargePolygons")
{
noTesselateLargePolygons = true;
}
if (options->getOptionString() == "noTriStripPolygons")
{
noTesselateLargePolygons = true;
}
} }
osg::Node* node = convertModelToSceneGraph(model,rotate); osg::Node* node = convertModelToSceneGraph(model,rotate,
noTesselateLargePolygons,noTriStripPolygons);
return node; return node;
} }
@ -662,14 +696,32 @@ osgDB::ReaderWriter::ReadResult ReaderWriterOBJ::readNode(std::istream& fin, con
obj::Model model; obj::Model model;
model.readOBJ(fin, options); model.readOBJ(fin, options);
// code for checking the nonRotation // code for checking the nonRotation, noTesselateLargePolygons,
// and noTriStripPolygons
bool rotate = true; bool rotate = true;
if ((options!=NULL) && (options->getOptionString() == "noRotation")) bool noTesselateLargePolygons = false;
bool noTriStripPolygons = false;
if (options!=NULL)
{ {
rotate = false; if (options->getOptionString() == "noRotation")
{
rotate = false;
}
if (options->getOptionString() == "noTesselateLargePolygons")
{
noTesselateLargePolygons = true;
}
if (options->getOptionString() == "noTriStripPolygons")
{
noTesselateLargePolygons = true;
}
} }
osg::Node* node = convertModelToSceneGraph(model,rotate); osg::Node* node = convertModelToSceneGraph(model,rotate,
noTesselateLargePolygons,noTriStripPolygons);
return node; return node;
} }

View File

@ -155,46 +155,136 @@ bool Model::readMTL(std::istream& fin)
{ {
unsigned int fieldsRead = sscanf(line+3,"%f %f %f %f", &r, &g, &b, &a); unsigned int fieldsRead = sscanf(line+3,"%f %f %f %f", &r, &g, &b, &a);
if (fieldsRead==1) material->ambient.set(r,0.0f,0.0f,1.0f); if (fieldsRead==1)
else if (fieldsRead==2) material->ambient.set(r,g,0.0f,1.0f); {
else if (fieldsRead==3) material->ambient.set(r,g,b,1.0f); material->ambient[ 0 ] = r;
else if (fieldsRead==4) material->ambient.set(r,g,b,a); }
else if (fieldsRead==2)
{
material->ambient[ 0 ] = r;
material->ambient[ 1 ] = g;
}
else if (fieldsRead==3)
{
material->ambient[ 0 ] = r;
material->ambient[ 1 ] = g;
material->ambient[ 2 ] = b;
}
else if (fieldsRead==4)
{
material->ambient[ 0 ] = r;
material->ambient[ 1 ] = g;
material->ambient[ 2 ] = b;
material->ambient[ 3 ] = a;
}
} }
else if (strncmp(line,"Kd ",3)==0) else if (strncmp(line,"Kd ",3)==0)
{ {
unsigned int fieldsRead = sscanf(line+3,"%f %f %f %f", &r, &g, &b, &a); unsigned int fieldsRead = sscanf(line+3,"%f %f %f %f", &r, &g, &b, &a);
if (fieldsRead==1) material->diffuse.set(r,0.0f,0.0f,1.0f); if (fieldsRead==1)
else if (fieldsRead==2) material->diffuse.set(r,g,0.0f,1.0f); {
else if (fieldsRead==3) material->diffuse.set(r,g,b,1.0f); material->diffuse[ 0 ] = r;
else if (fieldsRead==4) material->diffuse.set(r,g,b,a); }
else if (fieldsRead==2)
{
material->diffuse[ 0 ] = r;
material->diffuse[ 1 ] = g;
}
else if (fieldsRead==3)
{
material->diffuse[ 0 ] = r;
material->diffuse[ 1 ] = g;
material->diffuse[ 2 ] = b;
}
else if (fieldsRead==4)
{
material->diffuse[ 0 ] = r;
material->diffuse[ 1 ] = g;
material->diffuse[ 2 ] = b;
material->diffuse[ 3 ] = a;
}
} }
else if (strncmp(line,"Ks ",3)==0) else if (strncmp(line,"Ks ",3)==0)
{ {
unsigned int fieldsRead = sscanf(line+3,"%f %f %f %f", &r, &g, &b, &a); unsigned int fieldsRead = sscanf(line+3,"%f %f %f %f", &r, &g, &b, &a);
if (fieldsRead==1) material->specular.set(r,0.0f,0.0f,1.0f); if (fieldsRead==1)
else if (fieldsRead==2) material->specular.set(r,g,0.0f,1.0f); {
else if (fieldsRead==3) material->specular.set(r,g,b,1.0f); material->specular[ 0 ] = r;
else if (fieldsRead==4) material->specular.set(r,g,b,a); }
else if (fieldsRead==2)
{
material->specular[ 0 ] = r;
material->specular[ 1 ] = g;
}
else if (fieldsRead==3)
{
material->specular[ 0 ] = r;
material->specular[ 1 ] = g;
material->specular[ 2 ] = b;
}
else if (fieldsRead==4)
{
material->specular[ 0 ] = r;
material->specular[ 1 ] = g;
material->specular[ 2 ] = b;
material->specular[ 3 ] = a;
}
} }
else if (strncmp(line,"Ke ",3)==0) else if (strncmp(line,"Ke ",3)==0)
{ {
unsigned int fieldsRead = sscanf(line+3,"%f %f %f %f", &r, &g, &b, &a); unsigned int fieldsRead = sscanf(line+3,"%f %f %f %f", &r, &g, &b, &a);
if (fieldsRead==1) material->emissive.set(r,0.0f,0.0f,1.0f); if (fieldsRead==1)
else if (fieldsRead==2) material->emissive.set(r,g,0.0f,1.0f); {
else if (fieldsRead==3) material->emissive.set(r,g,b,1.0f); material->emissive[ 0 ] = r;
else if (fieldsRead==4) material->emissive.set(r,g,b,a); }
else if (fieldsRead==2)
{
material->emissive[ 0 ] = r;
material->emissive[ 1 ] = g;
}
else if (fieldsRead==3)
{
material->emissive[ 0 ] = r;
material->emissive[ 1 ] = g;
material->emissive[ 2 ] = b;
}
else if (fieldsRead==4)
{
material->emissive[ 0 ] = r;
material->emissive[ 1 ] = g;
material->emissive[ 2 ] = b;
material->emissive[ 3 ] = a;
}
} }
else if (strncmp(line,"Tf ",3)==0) else if (strncmp(line,"Tf ",3)==0)
{ {
unsigned int fieldsRead = sscanf(line+3,"%f %f %f %f", &r, &g, &b, &a); unsigned int fieldsRead = sscanf(line+3,"%f %f %f %f", &r, &g, &b, &a);
if (fieldsRead==1) material->Tf.set(r,0.0f,0.0f,1.0f); if (fieldsRead==1)
else if (fieldsRead==2) material->Tf.set(r,g,0.0f,1.0f); {
else if (fieldsRead==3) material->Tf.set(r,g,b,1.0f); material->Tf[ 0 ] = r;
else if (fieldsRead==4) material->Tf.set(r,g,b,a); }
else if (fieldsRead==2)
{
material->Tf[ 0 ] = r;
material->Tf[ 1 ] = g;
}
else if (fieldsRead==3)
{
material->Tf[ 0 ] = r;
material->Tf[ 1 ] = g;
material->Tf[ 2 ] = b;
}
else if (fieldsRead==4)
{
material->Tf[ 0 ] = r;
material->Tf[ 1 ] = g;
material->Tf[ 2 ] = b;
material->Tf[ 3 ] = a;
}
} }
else if (strncmp(line,"sharpness ",10)==0) else if (strncmp(line,"sharpness ",10)==0)
{ {