Rewrite of OBJ parser + converter to OSG
This commit is contained in:
@@ -96,7 +96,7 @@ LINK32=link.exe
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\obj\glm.cpp
|
||||
SOURCE=..\..\..\src\osgPlugins\obj\obj.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
@@ -108,7 +108,7 @@ SOURCE=..\..\..\src\osgPlugins\obj\ReaderWriterOBJ.cpp
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\osgPlugins\obj\glm.h
|
||||
SOURCE=..\..\..\Src\osgPlugins\obj\obj.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
@@ -2,7 +2,7 @@ TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
glm.cpp\
|
||||
obj.cpp\
|
||||
ReaderWriterOBJ.cpp\
|
||||
|
||||
|
||||
|
||||
@@ -38,19 +38,13 @@
|
||||
|
||||
#include <osgUtil/TriStripVisitor>
|
||||
#include <osgUtil/SmoothingVisitor>
|
||||
#include <osgUtil/Tesselator>
|
||||
|
||||
#include "glm.h"
|
||||
#include "obj.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
template <class T>
|
||||
struct DerefLess
|
||||
{
|
||||
bool operator ()(T lhs,T rhs) const { return *lhs < *rhs; }
|
||||
};
|
||||
|
||||
|
||||
class ReaderWriterOBJ : public osgDB::ReaderWriter
|
||||
{
|
||||
public:
|
||||
@@ -63,93 +57,351 @@ public:
|
||||
|
||||
virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options*);
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
enum DrawableMode
|
||||
{
|
||||
DUPLICATE_COORDS,
|
||||
USE_SEPERATE_INDICES,
|
||||
};
|
||||
|
||||
osg::Drawable* makeDrawable(DrawableMode drawableMode, GLMmodel* obj, GLMgroup* grp);
|
||||
osg::Drawable* makeDrawable_duplicateCoords(GLMmodel* obj, GLMgroup* grp);
|
||||
osg::Drawable* makeDrawable_useSeperateIndices(GLMmodel* obj, GLMgroup* grp);
|
||||
typedef std::map< std::string, osg::ref_ptr<osg::StateSet> > MaterialToStateSetMap;
|
||||
|
||||
typedef std::map< std::string, osg::ref_ptr<osg::Texture2D> > TextureMap;
|
||||
typedef std::set< osg::ref_ptr<osg::Material>, DerefLess< osg::ref_ptr<osg::Material> > > MaterialSet;
|
||||
typedef std::set< osg::ref_ptr<osg::StateSet>, DerefLess< osg::ref_ptr<osg::StateSet> > > StateSetSet;
|
||||
typedef std::vector< osg::ref_ptr<osg::StateSet> > ObjMatierialOsgStateSetArray;
|
||||
void buildMaterialToStateSetMap(obj::Model& model, MaterialToStateSetMap& materialToSetSetMap);
|
||||
|
||||
class IndexMap
|
||||
{
|
||||
public:
|
||||
|
||||
IndexMap():
|
||||
_maximumIn(-1),
|
||||
_maximumOut(-1) {}
|
||||
|
||||
inline void updateMaximum(int index)
|
||||
{
|
||||
if (index>_maximumIn) _maximumIn=index;
|
||||
}
|
||||
|
||||
inline void initialize()
|
||||
{
|
||||
_indices.assign(_maximumIn+1,-1);
|
||||
}
|
||||
|
||||
inline void insertIndex(int index)
|
||||
{
|
||||
if (_indices[index]<0) _indices[index]=++_maximumOut;
|
||||
}
|
||||
|
||||
inline int index(int i) const { return _indices[i]; }
|
||||
|
||||
osg::Vec3Array* createVec3Array(const float* array)
|
||||
{
|
||||
osg::Vec3Array* vec3array = new osg::Vec3Array(_maximumOut+1);
|
||||
for(unsigned int i=0;i<_indices.size();++i)
|
||||
{
|
||||
if (_indices[i]>=0) (*vec3array)[_indices[i]].set(array[i*3],-array[i*3+2],array[i*3+1]);
|
||||
}
|
||||
return vec3array;
|
||||
}
|
||||
|
||||
osg::Vec2Array* createVec2Array(const float* array)
|
||||
{
|
||||
osg::Vec2Array* vec2array = new osg::Vec2Array(_maximumOut+1);
|
||||
for(unsigned int i=0;i<_indices.size();++i)
|
||||
{
|
||||
if (_indices[i]>=0) (*vec2array)[_indices[i]].set(array[i*2],array[i*2+1]);
|
||||
}
|
||||
return vec2array;
|
||||
}
|
||||
|
||||
osg::UByte4Array* createUByte4Array(const osg::UByte4* array)
|
||||
{
|
||||
osg::UByte4Array* ubyte4array = new osg::UByte4Array(_maximumOut+1);
|
||||
for(unsigned int i=0;i<_indices.size();++i)
|
||||
{
|
||||
if (_indices[i]>=0) (*ubyte4array)[_indices[i]] = array[i];
|
||||
}
|
||||
return ubyte4array;
|
||||
}
|
||||
|
||||
typedef std::vector<int> Indices;
|
||||
|
||||
int _maximumIn;
|
||||
int _maximumOut;
|
||||
Indices _indices;
|
||||
|
||||
};
|
||||
|
||||
osg::Geometry* convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList);
|
||||
|
||||
osg::Node* convertModelToSceneGraph(obj::Model& model);
|
||||
|
||||
inline osg::Vec3 transformVertex(const osg::Vec3& vec) { return osg::Vec3(vec.x(),-vec.z(),vec.y()); }
|
||||
inline osg::Vec3 transformNormal(const osg::Vec3& vec) { return osg::Vec3(vec.x(),-vec.z(),vec.y()); }
|
||||
|
||||
};
|
||||
|
||||
|
||||
// register with Registry to instantiate the above reader/writer.
|
||||
osgDB::RegisterReaderWriterProxy<ReaderWriterOBJ> g_objReaderWriterProxy;
|
||||
|
||||
void ReaderWriterOBJ::buildMaterialToStateSetMap(obj::Model& model, MaterialToStateSetMap& materialToStateSetMap)
|
||||
{
|
||||
for(obj::Model::MaterialMap::iterator itr = model.materialMap.begin();
|
||||
itr != model.materialMap.end();
|
||||
++itr)
|
||||
{
|
||||
obj::Material& material = itr->second;
|
||||
|
||||
osg::StateSet* stateset = new osg::StateSet;
|
||||
|
||||
// handle material colors
|
||||
{
|
||||
osg::Material* osg_material = new osg::Material;
|
||||
stateset->setAttribute(osg_material);
|
||||
|
||||
osg_material->setAmbient(osg::Material::FRONT_AND_BACK,material.ambient);
|
||||
osg_material->setDiffuse(osg::Material::FRONT_AND_BACK,material.diffuse);
|
||||
osg_material->setSpecular(osg::Material::FRONT_AND_BACK,material.specular);
|
||||
osg_material->setShininess(osg::Material::FRONT_AND_BACK,(material.shininess/1000.0f)*128.0f ); // note OBJ shiniess is 0..1000.
|
||||
}
|
||||
|
||||
// handle textures
|
||||
if (!material.map_Kd.empty())
|
||||
{
|
||||
std::string filename = material.map_Kd;
|
||||
osg::Image* image = osgDB::readImageFile(filename);
|
||||
if (image)
|
||||
{
|
||||
osg::Texture2D* texture = new osg::Texture2D(image);
|
||||
stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
materialToStateSetMap[material.name] = stateset;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList)
|
||||
{
|
||||
|
||||
unsigned int numVertexIndices = 0;
|
||||
unsigned int numNormalIndices = 0;
|
||||
unsigned int numTexCoordIndices = 0;
|
||||
|
||||
unsigned int numPointElements = 0;
|
||||
unsigned int numPolylineElements = 0;
|
||||
unsigned int numPolygonElements = 0;
|
||||
|
||||
obj::Model::ElementList::iterator itr;
|
||||
for(itr=elementList.begin();
|
||||
itr!=elementList.end();
|
||||
++itr)
|
||||
{
|
||||
obj::Element& element = *(*itr);
|
||||
|
||||
numVertexIndices += element.vertexIndices.size();
|
||||
numNormalIndices += element.normalIndices.size();
|
||||
numTexCoordIndices += element.texCoordIndices.size();
|
||||
|
||||
numPointElements += (element.dataType==obj::Element::POINTS) ? 1 : 0;
|
||||
numPolylineElements += (element.dataType==obj::Element::POLYLINE) ? 1 : 0;
|
||||
numPolygonElements += (element.dataType==obj::Element::POLYGON) ? 1 : 0;
|
||||
|
||||
}
|
||||
|
||||
if (numVertexIndices==0) return 0;
|
||||
|
||||
if (numNormalIndices!=0 && numNormalIndices!=numVertexIndices)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Incorrect number of normals, ignore them"<<std::endl;
|
||||
numNormalIndices = 0;
|
||||
}
|
||||
|
||||
if (numTexCoordIndices!=0 && numTexCoordIndices!=numVertexIndices)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Incorrect number of normals, ignore them"<<std::endl;
|
||||
numTexCoordIndices = 0;
|
||||
}
|
||||
|
||||
osg::Vec3Array* vertices = numVertexIndices ? new osg::Vec3Array : 0;
|
||||
osg::Vec3Array* normals = numNormalIndices ? new osg::Vec3Array : 0;
|
||||
osg::Vec2Array* texcoords = numTexCoordIndices ? new osg::Vec2Array : 0;
|
||||
|
||||
if (vertices) vertices->reserve(numVertexIndices);
|
||||
if (normals) normals->reserve(numNormalIndices);
|
||||
if (texcoords) texcoords->reserve(numTexCoordIndices);
|
||||
|
||||
osg::Geometry* geometry = new osg::Geometry;
|
||||
if (vertices) geometry->setVertexArray(vertices);
|
||||
if (normals)
|
||||
{
|
||||
geometry->setNormalArray(normals);
|
||||
geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
}
|
||||
if (texcoords)
|
||||
{
|
||||
geometry->setTexCoordArray(0,texcoords);
|
||||
}
|
||||
|
||||
|
||||
if (numPointElements>0)
|
||||
{
|
||||
unsigned int startPos = vertices->size();
|
||||
unsigned int numPoints = 0;
|
||||
for(itr=elementList.begin();
|
||||
itr!=elementList.end();
|
||||
++itr)
|
||||
{
|
||||
obj::Element& element = *(*itr);
|
||||
if (element.dataType==obj::Element::POINTS)
|
||||
{
|
||||
for(obj::Element::IndexList::iterator index_itr = element.vertexIndices.begin();
|
||||
index_itr != element.vertexIndices.end();
|
||||
++index_itr)
|
||||
{
|
||||
vertices->push_back(transformVertex(model.vertices[*index_itr]));
|
||||
++numPoints;
|
||||
}
|
||||
if (numNormalIndices)
|
||||
{
|
||||
for(obj::Element::IndexList::iterator index_itr = element.normalIndices.begin();
|
||||
index_itr != element.normalIndices.end();
|
||||
++index_itr)
|
||||
{
|
||||
normals->push_back(transformNormal(model.normals[*index_itr]));
|
||||
}
|
||||
}
|
||||
if (numTexCoordIndices)
|
||||
{
|
||||
for(obj::Element::IndexList::iterator index_itr = element.texCoordIndices.begin();
|
||||
index_itr != element.texCoordIndices.end();
|
||||
++index_itr)
|
||||
{
|
||||
texcoords->push_back(model.texcoords[*index_itr]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
osg::DrawArrays* drawArrays = new osg::DrawArrays(GL_POINTS,startPos,numPoints);
|
||||
geometry->addPrimitiveSet(drawArrays);
|
||||
}
|
||||
|
||||
if (numPolylineElements>0)
|
||||
{
|
||||
unsigned int startPos = vertices->size();
|
||||
osg::DrawArrayLengths* drawArrayLengths = new osg::DrawArrayLengths(GL_LINES,startPos);
|
||||
|
||||
for(itr=elementList.begin();
|
||||
itr!=elementList.end();
|
||||
++itr)
|
||||
{
|
||||
obj::Element& element = *(*itr);
|
||||
if (element.dataType==obj::Element::POLYLINE)
|
||||
{
|
||||
drawArrayLengths->push_back(element.vertexIndices.size());
|
||||
|
||||
for(obj::Element::IndexList::iterator index_itr = element.vertexIndices.begin();
|
||||
index_itr != element.vertexIndices.end();
|
||||
++index_itr)
|
||||
{
|
||||
vertices->push_back(transformVertex(model.vertices[*index_itr]));
|
||||
}
|
||||
if (numNormalIndices)
|
||||
{
|
||||
for(obj::Element::IndexList::iterator index_itr = element.normalIndices.begin();
|
||||
index_itr != element.normalIndices.end();
|
||||
++index_itr)
|
||||
{
|
||||
normals->push_back(transformNormal(model.normals[*index_itr]));
|
||||
}
|
||||
}
|
||||
if (numTexCoordIndices)
|
||||
{
|
||||
for(obj::Element::IndexList::iterator index_itr = element.texCoordIndices.begin();
|
||||
index_itr != element.texCoordIndices.end();
|
||||
++index_itr)
|
||||
{
|
||||
texcoords->push_back(model.texcoords[*index_itr]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
geometry->addPrimitiveSet(drawArrayLengths);
|
||||
|
||||
}
|
||||
|
||||
bool reverseWinding = true;
|
||||
|
||||
if (numPolygonElements>0)
|
||||
{
|
||||
unsigned int startPos = vertices->size();
|
||||
osg::DrawArrayLengths* drawArrayLengths = new osg::DrawArrayLengths(GL_POLYGON,startPos);
|
||||
|
||||
for(itr=elementList.begin();
|
||||
itr!=elementList.end();
|
||||
++itr)
|
||||
{
|
||||
obj::Element& element = *(*itr);
|
||||
if (element.dataType==obj::Element::POLYGON)
|
||||
{
|
||||
drawArrayLengths->push_back(element.vertexIndices.size());
|
||||
|
||||
if (reverseWinding)
|
||||
{
|
||||
// need to reverse so add to OSG arrays in same order as in OBJ, as OSG assume anticlockwise ordering.
|
||||
for(obj::Element::IndexList::reverse_iterator index_itr = element.vertexIndices.rbegin();
|
||||
index_itr != element.vertexIndices.rend();
|
||||
++index_itr)
|
||||
{
|
||||
vertices->push_back(transformVertex(model.vertices[*index_itr]));
|
||||
}
|
||||
if (numNormalIndices)
|
||||
{
|
||||
for(obj::Element::IndexList::reverse_iterator index_itr = element.normalIndices.rbegin();
|
||||
index_itr != element.normalIndices.rend();
|
||||
++index_itr)
|
||||
{
|
||||
normals->push_back(transformNormal(model.normals[*index_itr]));
|
||||
}
|
||||
}
|
||||
if (numTexCoordIndices)
|
||||
{
|
||||
for(obj::Element::IndexList::reverse_iterator index_itr = element.texCoordIndices.rbegin();
|
||||
index_itr != element.texCoordIndices.rend();
|
||||
++index_itr)
|
||||
{
|
||||
texcoords->push_back(model.texcoords[*index_itr]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no need to reverse so add to OSG arrays in same order as in OBJ.
|
||||
for(obj::Element::IndexList::iterator index_itr = element.vertexIndices.begin();
|
||||
index_itr != element.vertexIndices.end();
|
||||
++index_itr)
|
||||
{
|
||||
vertices->push_back(model.vertices[*index_itr]);
|
||||
}
|
||||
if (numNormalIndices)
|
||||
{
|
||||
for(obj::Element::IndexList::iterator index_itr = element.normalIndices.begin();
|
||||
index_itr != element.normalIndices.end();
|
||||
++index_itr)
|
||||
{
|
||||
normals->push_back(model.normals[*index_itr]);
|
||||
}
|
||||
}
|
||||
if (numTexCoordIndices)
|
||||
{
|
||||
for(obj::Element::IndexList::iterator index_itr = element.texCoordIndices.begin();
|
||||
index_itr != element.texCoordIndices.end();
|
||||
++index_itr)
|
||||
{
|
||||
texcoords->push_back(model.texcoords[*index_itr]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
geometry->addPrimitiveSet(drawArrayLengths);
|
||||
|
||||
}
|
||||
|
||||
return geometry;
|
||||
}
|
||||
|
||||
osg::Node* ReaderWriterOBJ::convertModelToSceneGraph(obj::Model& model)
|
||||
{
|
||||
|
||||
if (model.elementStateMap.empty()) return 0;
|
||||
|
||||
osg::Group* group = new osg::Group;
|
||||
|
||||
// set up the materials
|
||||
MaterialToStateSetMap materialToSetSetMap;
|
||||
buildMaterialToStateSetMap(model, materialToSetSetMap);
|
||||
|
||||
// go through the groups of related elements and build geometry from them.
|
||||
for(obj::Model::ElementStateMap::iterator itr=model.elementStateMap.begin();
|
||||
itr!=model.elementStateMap.end();
|
||||
++itr)
|
||||
{
|
||||
|
||||
const obj::ElementState& es = itr->first;
|
||||
obj::Model::ElementList& el = itr->second;
|
||||
|
||||
osg::Geometry* geometry = convertElementListToGeometry(model,el);
|
||||
|
||||
if (geometry)
|
||||
{
|
||||
|
||||
osg::StateSet* stateset = materialToSetSetMap[es.materialName].get();
|
||||
geometry->setStateSet(stateset);
|
||||
|
||||
// osgUtil::Tesselator tesselator;
|
||||
// tesselator.retesselatePolygons(*geometry);
|
||||
|
||||
osgUtil::TriStripVisitor tsv;
|
||||
tsv.stripify(*geometry);
|
||||
|
||||
if (!geometry->getNormalArray() || geometry->getNormalArray()->getNumElements()==0)
|
||||
{
|
||||
osgUtil::SmoothingVisitor tsv;
|
||||
tsv.smooth(*geometry);
|
||||
}
|
||||
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
geode->addDrawable(geometry);
|
||||
geode->setName(es.objectName);
|
||||
|
||||
group->addChild(geode);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
|
||||
// read file and convert to OSG.
|
||||
osgDB::ReaderWriter::ReadResult ReaderWriterOBJ::readNode(const std::string& file, const osgDB::ReaderWriter::Options*)
|
||||
@@ -159,469 +411,18 @@ osgDB::ReaderWriter::ReadResult ReaderWriterOBJ::readNode(const std::string& fil
|
||||
|
||||
std::string fileName = osgDB::findDataFile( file );
|
||||
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
|
||||
|
||||
GLMmodel* obj = glmReadOBJ((char*) fileName.c_str());
|
||||
if (!obj)
|
||||
return ReadResult::FILE_NOT_HANDLED;
|
||||
|
||||
std::string directory = osgDB::getFilePath(fileName);
|
||||
|
||||
|
||||
osg::notify(osg::INFO) << "vertices " << obj->numvertices << std::endl;
|
||||
osg::notify(osg::INFO) << "normals " << obj->numnormals << std::endl;
|
||||
osg::notify(osg::INFO) << "texcoords " << obj->numtexcoords << std::endl;
|
||||
osg::notify(osg::INFO) << "face normals " << obj->numfacetnorms << std::endl;
|
||||
osg::notify(osg::INFO) << "tris " << obj->numtriangles << std::endl;
|
||||
osg::notify(osg::INFO) << "materials " << obj->nummaterials << std::endl;
|
||||
osg::notify(osg::INFO) << "groups " << obj->numgroups << std::endl;
|
||||
|
||||
|
||||
// if (obj->numnormals==0)
|
||||
// {
|
||||
// osg::notify(osg::NOTICE) << "No normals in .obj file, automatically calculating normals..."<< std::endl;
|
||||
// glmFacetNormals(obj);
|
||||
// glmVertexNormals(obj,90.0f);
|
||||
// }
|
||||
|
||||
|
||||
unsigned int i;
|
||||
|
||||
|
||||
TextureMap textureMap;
|
||||
MaterialSet materialSet;
|
||||
StateSetSet statesetSet;
|
||||
|
||||
// create a sphere mapped texgen just in case we need it.
|
||||
osg::ref_ptr<osg::TexGen> osg_texgen = new osg::TexGen;
|
||||
osg_texgen->setMode(osg::TexGen::SPHERE_MAP);
|
||||
|
||||
ObjMatierialOsgStateSetArray osg_mtl(obj->nummaterials);
|
||||
|
||||
for (i = 0; i < obj->nummaterials; i++)
|
||||
std::ifstream fin(fileName.c_str());
|
||||
if (fin)
|
||||
{
|
||||
GLMmaterial* omtl = &(obj->materials[i]);
|
||||
osg::notify(osg::DEBUG_INFO) << "mtl: " << omtl->name << std::endl;
|
||||
|
||||
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
|
||||
|
||||
osg::ref_ptr<osg::Material> mtl = new osg::Material;
|
||||
mtl->setAmbient(osg::Material::FRONT_AND_BACK,
|
||||
osg::Vec4(omtl->ambient[0], omtl->ambient[1],
|
||||
omtl->ambient[2], omtl->ambient[3]));
|
||||
mtl->setDiffuse(osg::Material::FRONT_AND_BACK,
|
||||
osg::Vec4(omtl->diffuse[0], omtl->diffuse[1],
|
||||
omtl->diffuse[2], omtl->diffuse[3]));
|
||||
mtl->setSpecular(osg::Material::FRONT_AND_BACK,
|
||||
osg::Vec4(omtl->specular[0], omtl->specular[1],
|
||||
omtl->specular[2], omtl->specular[3]));
|
||||
mtl->setEmission(osg::Material::FRONT_AND_BACK,
|
||||
osg::Vec4(omtl->emmissive[0], omtl->emmissive[1],
|
||||
omtl->emmissive[2], omtl->emmissive[3]));
|
||||
|
||||
// note, osg shininess scales between 0.0 and 1.0.
|
||||
mtl->setShininess(osg::Material::FRONT_AND_BACK, omtl->shininess);
|
||||
mtl->setAlpha(osg::Material::FRONT_AND_BACK, omtl->alpha);
|
||||
|
||||
MaterialSet::iterator mitr = materialSet.find(mtl);
|
||||
if (mitr==materialSet.end())
|
||||
{
|
||||
materialSet.insert(mtl);
|
||||
}
|
||||
else
|
||||
{
|
||||
mtl = *mitr;
|
||||
}
|
||||
|
||||
stateset->setAttribute(mtl.get());
|
||||
|
||||
if (omtl->alpha<1.0f) {
|
||||
stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
|
||||
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||
}
|
||||
|
||||
if (omtl->textureName)
|
||||
{
|
||||
TextureMap::iterator titr = textureMap.find(omtl->textureName);
|
||||
|
||||
osg::notify(osg::DEBUG_INFO) << "textureName: " << omtl->textureName << std::endl;
|
||||
|
||||
if (titr==textureMap.end())
|
||||
{
|
||||
|
||||
std::string fileName = osgDB::findFileInDirectory(omtl->textureName,directory,osgDB::CASE_INSENSITIVE);
|
||||
if (fileName.empty()) fileName = osgDB::findDataFile(omtl->textureName,osgDB::CASE_INSENSITIVE);
|
||||
|
||||
if (!fileName.empty())
|
||||
{
|
||||
|
||||
osg::notify(osg::DEBUG_INFO) << "filename: " << fileName << std::endl;
|
||||
|
||||
osg::Image* osg_image = osgDB::readImageFile(fileName.c_str());
|
||||
if (osg_image)
|
||||
{
|
||||
|
||||
osg::notify(osg::DEBUG_INFO) << "imageRead: " << omtl->textureName << std::endl;
|
||||
|
||||
|
||||
osg::Texture2D* osg_texture = new osg::Texture2D;
|
||||
osg_texture->setImage(osg_image);
|
||||
stateset->setTextureAttributeAndModes(0,osg_texture,osg::StateAttribute::ON);
|
||||
|
||||
textureMap[omtl->textureName] = osg_texture;
|
||||
|
||||
// Adjust the texture matrix if necessary
|
||||
bool needsUVScaling = (1.0 != omtl->textureUScale) || (1.0 != omtl->textureVScale);
|
||||
bool needsUVOffsetting = (0.0 != omtl->textureUOffset) || (0.0 != omtl->textureVOffset);
|
||||
|
||||
if (needsUVScaling || needsUVOffsetting)
|
||||
{
|
||||
osg::TexMat* osg_texmat = new osg::TexMat;
|
||||
|
||||
osg::Matrix scale;
|
||||
osg::Matrix translate;
|
||||
scale.makeIdentity();
|
||||
translate.makeIdentity();
|
||||
|
||||
if (needsUVScaling)
|
||||
{
|
||||
scale.makeScale(omtl->textureUScale, omtl->textureVScale, 1.0f);
|
||||
}
|
||||
|
||||
if (needsUVOffsetting)
|
||||
{
|
||||
translate.makeTranslate(omtl->textureUOffset, omtl->textureVOffset, 0.0f);
|
||||
}
|
||||
|
||||
osg_texmat->setMatrix(scale * translate);
|
||||
stateset->setTextureAttributeAndModes(0,osg_texmat,osg::StateAttribute::ON);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::NOTICE) << "Warning: Cannot create texture "<<omtl->textureName<< std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "texture '"<<omtl->textureName<<"' not found"<< std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
stateset->setTextureAttributeAndModes(0,titr->second.get(),osg::StateAttribute::ON);
|
||||
}
|
||||
}
|
||||
obj::Model model;
|
||||
model.readOBJ(fin);
|
||||
|
||||
if (omtl->textureReflection)
|
||||
{
|
||||
stateset->setTextureAttributeAndModes(0,osg_texgen.get(),osg::StateAttribute::ON);
|
||||
}
|
||||
|
||||
StateSetSet::iterator sitr = statesetSet.find(stateset);
|
||||
if (sitr==statesetSet.end())
|
||||
{
|
||||
osg_mtl[i] = stateset;
|
||||
statesetSet.insert(stateset);
|
||||
}
|
||||
else
|
||||
{
|
||||
osg_mtl[i] = *sitr;
|
||||
}
|
||||
osg::Node* node = convertModelToSceneGraph(model);
|
||||
return node;
|
||||
}
|
||||
|
||||
// toplevel group or transform
|
||||
osg::Group* osg_top = NULL;
|
||||
if (obj->position[0] != 0.0f || obj->position[1] != 0.0f || obj->position[2] != 0.0f) {
|
||||
osg::MatrixTransform* xform = new osg::MatrixTransform;
|
||||
// note obj_x -> osg_x,
|
||||
// obj_y -> osg_z,
|
||||
// obj_z -> osg_y,
|
||||
xform->setMatrix(osg::Matrix::translate(obj->position[0], -obj->position[2], obj->position[1]));
|
||||
osg_top = xform;
|
||||
}
|
||||
else
|
||||
osg_top = new osg::Group;
|
||||
|
||||
osg_top->setName(obj->pathname);
|
||||
|
||||
DrawableMode drawableMode = USE_SEPERATE_INDICES;
|
||||
// DrawableMode drawableMode = DUPLICATE_COORDS;
|
||||
|
||||
// subgroups
|
||||
// XXX one Geode per group is probably not necessary...
|
||||
GLMgroup* ogrp = obj->groups;
|
||||
while (ogrp) {
|
||||
if (ogrp->numtriangles > 0) {
|
||||
|
||||
osg::Geode* osg_geo = new osg::Geode;
|
||||
osg_geo->setName(ogrp->name);
|
||||
osg::Drawable* drawable = makeDrawable(drawableMode,obj,ogrp);
|
||||
|
||||
// state and material (if any)
|
||||
if (!osg_mtl.empty()) {
|
||||
|
||||
osg::notify(osg::NOTICE)<<"ogrp->material="<<ogrp->material<<std::endl;
|
||||
|
||||
drawable->setStateSet(osg_mtl[ogrp->material].get());
|
||||
}
|
||||
|
||||
osg_geo->addDrawable(drawable);
|
||||
osg_top->addChild(osg_geo);
|
||||
}
|
||||
ogrp = ogrp->next;
|
||||
}
|
||||
|
||||
// free
|
||||
glmDelete(obj);
|
||||
|
||||
return osg_top;
|
||||
|
||||
return ReadResult::FILE_NOT_HANDLED;
|
||||
}
|
||||
|
||||
osg::Drawable* ReaderWriterOBJ::makeDrawable(DrawableMode drawableMode, GLMmodel* obj, GLMgroup* grp)
|
||||
{
|
||||
switch(drawableMode)
|
||||
{
|
||||
case(DUPLICATE_COORDS): return makeDrawable_duplicateCoords(obj,grp);
|
||||
case(USE_SEPERATE_INDICES): return makeDrawable_useSeperateIndices(obj,grp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// make drawable from OBJ group
|
||||
osg::Drawable* ReaderWriterOBJ::makeDrawable_duplicateCoords(GLMmodel* obj, GLMgroup* grp)
|
||||
{
|
||||
|
||||
GLMtriangle* tris = obj->triangles;
|
||||
|
||||
unsigned int ntris = grp->numtriangles;
|
||||
unsigned int i = 0;
|
||||
|
||||
// geometry
|
||||
osg::Geometry* geom = new osg::Geometry;
|
||||
|
||||
geom->setUseDisplayList(false);
|
||||
// geom->setUseVertexBufferObjects(true);
|
||||
|
||||
// primitives are only triangles
|
||||
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,ntris*3));
|
||||
|
||||
// the following code for mapping the coords, normals and texcoords
|
||||
// is complicated greatly by the need to create separate out the
|
||||
// sets of coords etc for each drawable.
|
||||
|
||||
bool needColors = obj->useColors && obj->colors;
|
||||
bool needNormals = obj->normals && obj->normals;
|
||||
bool needTexcoords = obj->texcoords && obj->numtexcoords>0 && grp->hastexcoords;
|
||||
|
||||
|
||||
osg::Vec3Array* coordArray = new osg::Vec3Array(3*ntris);
|
||||
|
||||
osg::Vec3Array::iterator coords = coordArray->begin();
|
||||
geom->setVertexArray(coordArray);
|
||||
|
||||
osg::UByte4Array::iterator colors = osg::UByte4Array::iterator();// dummy assignment to get round stupid compiler warnings.
|
||||
if (needColors)
|
||||
{
|
||||
osg::UByte4Array* colorArray = new osg::UByte4Array(3*ntris);
|
||||
geom->setColorArray(colorArray);
|
||||
geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
colors = colorArray->begin();
|
||||
}
|
||||
|
||||
|
||||
osg::Vec3Array::iterator normals = osg::Vec3Array::iterator();// dummy assignment to get round stupid compiler warnings.
|
||||
if (needNormals)
|
||||
{
|
||||
osg::Vec3Array* normalArray = new osg::Vec3Array(3*ntris);
|
||||
geom->setNormalArray(normalArray);
|
||||
geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
normals = normalArray->begin();
|
||||
}
|
||||
|
||||
osg::Vec2Array::iterator texcoords = osg::Vec2Array::iterator(); // dummy assignment to get round stupid compiler warnings.
|
||||
if (needTexcoords)
|
||||
{
|
||||
osg::Vec2Array* texCoordArray = new osg::Vec2Array(3*ntris);
|
||||
geom->setTexCoordArray(0,texCoordArray);
|
||||
|
||||
texcoords = texCoordArray->begin();
|
||||
}
|
||||
|
||||
// first count the number of vertices used in this group.
|
||||
for (i = 0; i < ntris; i++)
|
||||
{
|
||||
GLMtriangle* tri = &(tris[grp->triangles[i]]);
|
||||
|
||||
for(int corner=0;corner<3;++corner)
|
||||
{
|
||||
int ci = tri->vindices[corner]*3;
|
||||
|
||||
// note rotate about the x axis to place the OBJ y up to OSG z up.
|
||||
coords->set(obj->vertices[ci],-obj->vertices[ci+2],obj->vertices[ci+1]);
|
||||
++coords;
|
||||
|
||||
if (needColors)
|
||||
{
|
||||
(*colors) = obj->colors[tri->vindices[corner]];
|
||||
++colors;
|
||||
}
|
||||
|
||||
if (needNormals)
|
||||
{
|
||||
int ni = tri->nindices[corner]*3;
|
||||
|
||||
// note rotate about the x axis to place the OBJ y up to OSG z up.
|
||||
normals->set(obj->normals[ni],-obj->normals[ni+2],obj->normals[ni+1]);
|
||||
++normals;
|
||||
}
|
||||
|
||||
if (needTexcoords)
|
||||
{
|
||||
int ti = tri->tindices[corner]*2;
|
||||
texcoords->set(obj->texcoords[ti+0], obj->texcoords[ti+1]);
|
||||
++texcoords;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return geom;
|
||||
}
|
||||
|
||||
osg::Drawable* ReaderWriterOBJ::makeDrawable_useSeperateIndices(GLMmodel* obj, GLMgroup* grp)
|
||||
{
|
||||
|
||||
GLMtriangle* tris = obj->triangles;
|
||||
|
||||
unsigned int ntris = grp->numtriangles;
|
||||
unsigned int i = 0;
|
||||
|
||||
// geometry
|
||||
osg::Geometry* geom = new osg::Geometry;
|
||||
|
||||
// geom->setUseDisplayList(false);
|
||||
// geom->setUseVertexBufferObjects(true);
|
||||
|
||||
// the following code for mapping the coords, normals and texcoords
|
||||
// is complicated greatly by the need to create separate out the
|
||||
// sets of coords etc for each drawable.
|
||||
|
||||
bool needColors = obj->useColors && obj->colors;
|
||||
bool needNormals = obj->normals && obj->normals;
|
||||
bool needTexcoords = obj->texcoords && obj->numtexcoords>0 && grp->hastexcoords;
|
||||
|
||||
|
||||
// needNormals = false;
|
||||
|
||||
IndexMap vertexIndexMap;
|
||||
IndexMap normalIndexMap;
|
||||
IndexMap texcoordIndexMap;
|
||||
|
||||
// find maxium value.
|
||||
for (i = 0; i < ntris; i++)
|
||||
{
|
||||
GLMtriangle& tri = tris[grp->triangles[i]];
|
||||
for(int corner=0;corner<3;++corner)
|
||||
{
|
||||
vertexIndexMap.updateMaximum(tri.vindices[corner]);
|
||||
if (needNormals) normalIndexMap.updateMaximum(tri.nindices[corner]);
|
||||
if (needTexcoords) texcoordIndexMap.updateMaximum(tri.tindices[corner]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// intialialize map.
|
||||
vertexIndexMap.initialize();
|
||||
if (needNormals) normalIndexMap.initialize();
|
||||
if (needTexcoords) texcoordIndexMap.initialize();
|
||||
|
||||
// populate map.
|
||||
for (i = 0; i < ntris; i++)
|
||||
{
|
||||
GLMtriangle& tri = tris[grp->triangles[i]];
|
||||
for(int corner=0;corner<3;++corner)
|
||||
{
|
||||
vertexIndexMap.insertIndex(tri.vindices[corner]);
|
||||
if (needNormals) normalIndexMap.insertIndex(tri.nindices[corner]);
|
||||
if (needTexcoords) texcoordIndexMap.insertIndex(tri.tindices[corner]);
|
||||
}
|
||||
}
|
||||
|
||||
// copy data across to geometry.
|
||||
geom->setVertexArray(vertexIndexMap.createVec3Array(obj->vertices));
|
||||
|
||||
if (needColors)
|
||||
{
|
||||
geom->setColorArray(vertexIndexMap.createUByte4Array(obj->colors));
|
||||
geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
}
|
||||
|
||||
if (needNormals)
|
||||
{
|
||||
geom->setNormalArray(normalIndexMap.createVec3Array(obj->normals));
|
||||
geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
}
|
||||
|
||||
if (needTexcoords)
|
||||
{
|
||||
geom->setTexCoordArray(0,texcoordIndexMap.createVec2Array(obj->texcoords));
|
||||
}
|
||||
|
||||
|
||||
osg::ref_ptr<osg::UIntArray> vertexIndices = new osg::UIntArray(ntris*3);
|
||||
osg::ref_ptr<osg::UIntArray> normalIndices = needNormals ? new osg::UIntArray(ntris*3) : 0;
|
||||
osg::ref_ptr<osg::UIntArray> texcoordIndices = needTexcoords ? new osg::UIntArray(ntris*3) : 0;
|
||||
|
||||
int vi=0;
|
||||
for (i = 0; i < ntris; i++)
|
||||
{
|
||||
GLMtriangle& tri = (tris[grp->triangles[i]]);
|
||||
|
||||
for(int corner=0;corner<3;++corner,++vi)
|
||||
{
|
||||
(*vertexIndices)[vi] = vertexIndexMap.index(tri.vindices[corner]);
|
||||
|
||||
if (needNormals)
|
||||
{
|
||||
(*normalIndices)[vi] = normalIndexMap.index(tri.nindices[corner]);
|
||||
}
|
||||
|
||||
if (needTexcoords)
|
||||
{
|
||||
(*texcoordIndices)[vi] = texcoordIndexMap.index(tri.tindices[corner]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool indexArraysEqual=true;
|
||||
if (needNormals) indexArraysEqual=(*vertexIndices==*normalIndices);
|
||||
if (indexArraysEqual && needTexcoords) indexArraysEqual=(*vertexIndices==*texcoordIndices);
|
||||
|
||||
if (indexArraysEqual)
|
||||
{
|
||||
geom->addPrimitiveSet(new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES,vertexIndices->begin(),vertexIndices->end()));
|
||||
}
|
||||
else
|
||||
{
|
||||
geom->setVertexIndices(vertexIndices.get());
|
||||
if (needColors) geom->setColorIndices(vertexIndices.get());
|
||||
if (needNormals) geom->setNormalIndices(normalIndices.get());
|
||||
if (needTexcoords) geom->setTexCoordIndices(0,texcoordIndices.get());
|
||||
|
||||
// primitives are only triangles
|
||||
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,ntris*3));
|
||||
|
||||
}
|
||||
#if 0
|
||||
osgUtil::TriStripVisitor tsv;
|
||||
tsv.stripify(*geom);
|
||||
#endif
|
||||
|
||||
if (obj->numnormals==0)
|
||||
{
|
||||
osgUtil::SmoothingVisitor tsv;
|
||||
tsv.smooth(*geom);
|
||||
}
|
||||
return geom;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,306 +0,0 @@
|
||||
/*
|
||||
* Wavefront .obj file format reader.
|
||||
*
|
||||
* author: Nate Robins
|
||||
* email: ndr@pobox.com
|
||||
* www: http://www.pobox.com/~ndr
|
||||
*/
|
||||
|
||||
|
||||
/* includes */
|
||||
/* #include "glut.h" */
|
||||
//#include <GL/glu.h>
|
||||
//#include<GL/glut.h>
|
||||
|
||||
// Replace about glu/glut calls with the more x-platform friendly osg version,
|
||||
// also neither glu or glut were requied?! Only gl.h... even this I think
|
||||
// should be removed since all the GLfloat etc could just as easily be floats.
|
||||
// Will leave for now as it works... Robert Osfield, June 5th 2001.
|
||||
#include <osg/GL>
|
||||
#include <osg/UByte4>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265
|
||||
#endif
|
||||
|
||||
|
||||
/* defines */
|
||||
#define GLM_NONE (0) /* render with only vertices */
|
||||
#define GLM_FLAT (1 << 0) /* render with facet normals */
|
||||
#define GLM_SMOOTH (1 << 1) /* render with vertex normals */
|
||||
#define GLM_TEXTURE (1 << 2) /* render with texture coords */
|
||||
#define GLM_COLOR (1 << 3) /* render with colors */
|
||||
#define GLM_MATERIAL (1 << 4) /* render with materials */
|
||||
|
||||
|
||||
/* structs */
|
||||
|
||||
/* GLMmaterial: Structure that defines a material in a model.
|
||||
*/
|
||||
struct GLMmaterial
|
||||
{
|
||||
char* name; /* name of material */
|
||||
GLfloat diffuse[4]; /* diffuse component */
|
||||
GLfloat ambient[4]; /* ambient component */
|
||||
GLfloat specular[4]; /* specular component */
|
||||
GLfloat emmissive[4]; /* emmissive component */
|
||||
GLfloat shininess; /* specular exponent */
|
||||
char* textureName; /* name of any attached texture, add by RO */
|
||||
bool textureReflection; /* true if texture is a reflection map */
|
||||
float alpha; /* alpha */
|
||||
float textureUScale; /* Scaling along U */
|
||||
float textureVScale; /* Scaling along V */
|
||||
float textureUOffset; /* Offset along U */
|
||||
float textureVOffset; /* Offset along V */
|
||||
|
||||
void init()
|
||||
{
|
||||
name = NULL;
|
||||
diffuse[0] = diffuse[1] = diffuse[2] = 0.8f; diffuse[3] = 1.0f;
|
||||
ambient[0] = ambient[1] = ambient[2] = 0.2f; ambient[3] = 1.0f;
|
||||
specular[0] = specular[1] = specular[2] = 0.0f; specular[3] = 1.0f;
|
||||
emmissive[0] = emmissive[1] = emmissive[2] = 0.0f; emmissive[3] = 1.0f;
|
||||
shininess = 0.0f;
|
||||
textureName = NULL;
|
||||
textureReflection = false;
|
||||
alpha = 1.0f;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/* GLMtriangle: Structure that defines a triangle in a model.
|
||||
*/
|
||||
struct GLMtriangle {
|
||||
unsigned int vindices[3]; /* array of triangle vertex indices */
|
||||
unsigned int nindices[3]; /* array of triangle normal indices */
|
||||
unsigned int tindices[3]; /* array of triangle texcoord indices*/
|
||||
unsigned int findex; /* index of triangle facet normal */
|
||||
void init()
|
||||
{
|
||||
vindices[0] = vindices[2] = vindices[2] = 0 ;
|
||||
nindices[0] = nindices[2] = nindices[2] = 0 ;
|
||||
tindices[0] = tindices[2] = tindices[2] = 0 ;
|
||||
findex=0;
|
||||
}
|
||||
};
|
||||
|
||||
/* GLMgroup: Structure that defines a group in a model.
|
||||
*/
|
||||
struct GLMgroup {
|
||||
char* name; /* name of this group */
|
||||
unsigned int numtriangles; /* number of triangles in this group */
|
||||
unsigned int* triangles; /* array of triangle indices */
|
||||
unsigned int material; /* index to material for group */
|
||||
bool hastexcoords; /* set to true if triangles have texture coords */
|
||||
struct GLMgroup* next; /* pointer to next group in model */
|
||||
|
||||
void init()
|
||||
{
|
||||
name = NULL;
|
||||
numtriangles = 0;
|
||||
triangles = NULL;
|
||||
material = 0;
|
||||
hastexcoords = false;
|
||||
next = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
/* GLMmodel: Structure that defines a model.
|
||||
*/
|
||||
struct GLMmodel {
|
||||
char* pathname; /* path to this model */
|
||||
char* mtllibname; /* name of the material library */
|
||||
|
||||
unsigned int numvertices; /* number of vertices in model */
|
||||
GLfloat* vertices; /* array of vertices */
|
||||
|
||||
bool useColors; /* true if per vertex colors are present.*/
|
||||
osg::UByte4* colors; /* array of per vertex colors */
|
||||
|
||||
unsigned int numnormals; /* number of normals in model */
|
||||
GLfloat* normals; /* array of normals */
|
||||
|
||||
unsigned int numtexcoords; /* number of texcoords in model */
|
||||
GLfloat* texcoords; /* array of texture coordinates */
|
||||
|
||||
unsigned int numfacetnorms; /* number of facetnorms in model */
|
||||
GLfloat* facetnorms; /* array of facetnorms */
|
||||
|
||||
unsigned int numtriangles; /* number of triangles in model */
|
||||
GLMtriangle* triangles; /* array of triangles */
|
||||
|
||||
unsigned int nummaterials; /* number of materials in model */
|
||||
GLMmaterial* materials; /* array of materials */
|
||||
|
||||
unsigned int numgroups; /* number of groups in model */
|
||||
GLMgroup* groups; /* linked list of groups */
|
||||
|
||||
GLfloat position[3]; /* position of the model */
|
||||
|
||||
|
||||
void init()
|
||||
{
|
||||
pathname = NULL;
|
||||
mtllibname = NULL;
|
||||
|
||||
numvertices = 0;
|
||||
vertices = NULL;
|
||||
|
||||
useColors = false;
|
||||
colors = NULL;
|
||||
|
||||
numnormals = 0;
|
||||
normals = NULL;
|
||||
|
||||
numtexcoords = 0;
|
||||
texcoords = NULL;
|
||||
|
||||
numfacetnorms = 0;
|
||||
facetnorms = NULL;
|
||||
|
||||
numtriangles = 0;
|
||||
triangles = NULL;
|
||||
|
||||
nummaterials = 0;
|
||||
materials = NULL;
|
||||
|
||||
numgroups = 0;
|
||||
groups = NULL;
|
||||
|
||||
position[0] = position[1] = position[2] = 0.0f;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
/* glmUnitize: "unitize" a model by translating it to the origin and
|
||||
* scaling it to fit in a unit cube around the origin. Returns the
|
||||
* scalefactor used.
|
||||
*
|
||||
* model - properly initialized GLMmodel structure
|
||||
*/
|
||||
GLfloat
|
||||
glmUnitize(GLMmodel* model);
|
||||
|
||||
/* glmDimensions: Calculates the dimensions (width, height, depth) of
|
||||
* a model.
|
||||
*
|
||||
* model - initialized GLMmodel structure
|
||||
* dimensions - array of 3 GLfloats (GLfloat dimensions[3])
|
||||
*/
|
||||
GLvoid
|
||||
glmDimensions(GLMmodel* model, GLfloat* dimensions);
|
||||
|
||||
/* glmScale: Scales a model by a given amount.
|
||||
*
|
||||
* model - properly initialized GLMmodel structure
|
||||
* scale - scalefactor (0.5 = half as large, 2.0 = twice as large)
|
||||
*/
|
||||
GLvoid
|
||||
glmScale(GLMmodel* model, GLfloat scale);
|
||||
|
||||
/* glmReverseWinding: Reverse the polygon winding for all polygons in
|
||||
* this model. Default winding is counter-clockwise. Also changes
|
||||
* the direction of the normals.
|
||||
*
|
||||
* model - properly initialized GLMmodel structure
|
||||
*/
|
||||
GLvoid
|
||||
glmReverseWinding(GLMmodel* model);
|
||||
|
||||
/* glmFacetNormals: Generates facet normals for a model (by taking the
|
||||
* cross product of the two vectors derived from the sides of each
|
||||
* triangle). Assumes a counter-clockwise winding.
|
||||
*
|
||||
* model - initialized GLMmodel structure
|
||||
*/
|
||||
GLvoid
|
||||
glmFacetNormals(GLMmodel* model);
|
||||
|
||||
/* glmVertexNormals: Generates smooth vertex normals for a model.
|
||||
* First builds a list of all the triangles each vertex is in. Then
|
||||
* loops through each vertex in the the list averaging all the facet
|
||||
* normals of the triangles each vertex is in. Finally, sets the
|
||||
* normal index in the triangle for the vertex to the generated smooth
|
||||
* normal. If the dot product of a facet normal and the facet normal
|
||||
* associated with the first triangle in the list of triangles the
|
||||
* current vertex is in is greater than the cosine of the angle
|
||||
* parameter to the function, that facet normal is not added into the
|
||||
* average normal calculation and the corresponding vertex is given
|
||||
* the facet normal. This tends to preserve hard edges. The angle to
|
||||
* use depends on the model, but 90 degrees is usually a good start.
|
||||
*
|
||||
* model - initialized GLMmodel structure
|
||||
* angle - maximum angle (in degrees) to smooth across
|
||||
*/
|
||||
GLvoid
|
||||
glmVertexNormals(GLMmodel* model, GLfloat angle);
|
||||
|
||||
/* glmLinearTexture: Generates texture coordinates according to a
|
||||
* linear projection of the texture map. It generates these by
|
||||
* linearly mapping the vertices onto a square.
|
||||
*
|
||||
* model - pointer to initialized GLMmodel structure
|
||||
*/
|
||||
GLvoid
|
||||
glmLinearTexture(GLMmodel* model);
|
||||
|
||||
/* glmSpheremapTexture: Generates texture coordinates according to a
|
||||
* spherical projection of the texture map. Sometimes referred to as
|
||||
* spheremap, or reflection map texture coordinates. It generates
|
||||
* these by using the normal to calculate where that vertex would map
|
||||
* onto a sphere. Since it is impossible to map something flat
|
||||
* perfectly onto something spherical, there is distortion at the
|
||||
* poles. This particular implementation causes the poles along the X
|
||||
* axis to be distorted.
|
||||
*
|
||||
* model - pointer to initialized GLMmodel structure
|
||||
*/
|
||||
GLvoid
|
||||
glmSpheremapTexture(GLMmodel* model);
|
||||
|
||||
/* glmDelete: Deletes a GLMmodel structure.
|
||||
*
|
||||
* model - initialized GLMmodel structure
|
||||
*/
|
||||
GLvoid
|
||||
glmDelete(GLMmodel* model);
|
||||
|
||||
/* glmReadOBJ: Reads a model description from a Wavefront .OBJ file.
|
||||
* Returns a pointer to the created object which should be free'd with
|
||||
* glmDelete().
|
||||
*
|
||||
* filename - name of the file containing the Wavefront .OBJ format data.
|
||||
*/
|
||||
GLMmodel*
|
||||
glmReadOBJ(char* filename);
|
||||
|
||||
/* glmWriteOBJ: Writes a model description in Wavefront .OBJ format to
|
||||
* a file.
|
||||
*
|
||||
* model - initialized GLMmodel structure
|
||||
* filename - name of the file to write the Wavefront .OBJ format data to
|
||||
* mode - a bitwise or of values describing what is written to the file
|
||||
* GLM_NONE - write only vertices
|
||||
* GLM_FLAT - write facet normals
|
||||
* GLM_SMOOTH - write vertex normals
|
||||
* GLM_TEXTURE - write texture coords
|
||||
* GLM_FLAT and GLM_SMOOTH should not both be specified.
|
||||
*/
|
||||
GLvoid
|
||||
glmWriteOBJ(GLMmodel* model, char* filename, unsigned int mode);
|
||||
|
||||
|
||||
/* glmWeld: eliminate (weld) vectors that are within an epsilon of
|
||||
* each other.
|
||||
*
|
||||
* model - initialized GLMmodel structure
|
||||
* epsilon - maximum difference between vertices
|
||||
* ( 0.00001 is a good start for a unitized model)
|
||||
*
|
||||
*/
|
||||
GLvoid
|
||||
glmWeld(GLMmodel* model, GLfloat epsilon);
|
||||
458
src/osgPlugins/obj/obj.cpp
Normal file
458
src/osgPlugins/obj/obj.cpp
Normal file
@@ -0,0 +1,458 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2004 Robert Osfield
|
||||
*
|
||||
* This library is open source and may be redistributed and/or modified under
|
||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "obj.h"
|
||||
|
||||
#include <osg/Notify>
|
||||
|
||||
using namespace obj;
|
||||
|
||||
bool Model::readline(std::istream& fin, char* line, const int LINE_SIZE)
|
||||
{
|
||||
if (LINE_SIZE<1) return false;
|
||||
|
||||
bool eatWhiteSpaceAtStart = true;
|
||||
|
||||
char* ptr = line;
|
||||
char* end = line+LINE_SIZE-1;
|
||||
bool skipNewline = false;
|
||||
while (fin && ptr<end)
|
||||
{
|
||||
|
||||
int c=fin.get();
|
||||
int p=fin.peek();
|
||||
if (c=='\r')
|
||||
{
|
||||
if (p=='\n')
|
||||
{
|
||||
// we have a windows line endings.
|
||||
fin.get();
|
||||
// osg::notify(osg::NOTICE)<<"We have dos line ending"<<std::endl;
|
||||
if (skipNewline)
|
||||
{
|
||||
skipNewline = false;
|
||||
continue;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
// we have Mac line ending
|
||||
// osg::notify(osg::NOTICE)<<"We have mac line ending"<<std::endl;
|
||||
if (skipNewline)
|
||||
{
|
||||
skipNewline = false;
|
||||
continue;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
else if (c=='\n')
|
||||
{
|
||||
// we have unix line ending.
|
||||
// osg::notify(osg::NOTICE)<<"We have unix line ending"<<std::endl;
|
||||
if (skipNewline)
|
||||
{
|
||||
skipNewline = false;
|
||||
continue;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
else if (c=='\\' && (p=='\r' || p=='\n'))
|
||||
{
|
||||
// need to keep return;
|
||||
skipNewline = true;
|
||||
}
|
||||
else if (c!=std::ifstream::traits_type::eof()) // don't copy eof.
|
||||
{
|
||||
skipNewline = false;
|
||||
|
||||
if (!eatWhiteSpaceAtStart || (c!=' ' && c!='\t'))
|
||||
{
|
||||
eatWhiteSpaceAtStart = false;
|
||||
*ptr++ = c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
*ptr = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Model::readMTL(std::istream& fin)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Reading MTL file"<<std::endl;
|
||||
|
||||
const int LINE_SIZE = 4096;
|
||||
char line[LINE_SIZE];
|
||||
float r = 1.0f, g = 1.0f, b = 1.0f, a = 1.0f;
|
||||
|
||||
Material* material = &(materialMap[""]);
|
||||
|
||||
while (fin)
|
||||
{
|
||||
readline(fin,line,LINE_SIZE);
|
||||
if (line[0]=='#')
|
||||
{
|
||||
// comment line
|
||||
// osg::notify(osg::NOTICE) <<"Comment: "<<line<<std::endl;
|
||||
}
|
||||
else if (strlen(line)>0)
|
||||
{
|
||||
if (strncmp(line,"Ka ",3)==0)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
else if (fieldsRead==4) material->ambient.set(r,g,b,a);
|
||||
}
|
||||
else if (strncmp(line,"Kd ",3)==0)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
else if (fieldsRead==4) material->diffuse.set(r,g,b,a);
|
||||
}
|
||||
else if (strncmp(line,"Ks ",3)==0)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
else if (fieldsRead==4) material->specular.set(r,g,b,a);
|
||||
}
|
||||
else if (strncmp(line,"Ke ",3)==0)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
else if (fieldsRead==4) material->emissive.set(r,g,b,a);
|
||||
}
|
||||
else if (strncmp(line,"Tf ",3)==0)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
else if (fieldsRead==4) material->Tf.set(r,g,b,a);
|
||||
}
|
||||
else if (strncmp(line,"newmtl ",7)==0)
|
||||
{
|
||||
std::string materialName(line+7);
|
||||
if (material->name != materialName)
|
||||
{
|
||||
material = & materialMap[materialName];
|
||||
material->name = materialName;
|
||||
}
|
||||
}
|
||||
else if (strncmp(line,"sharpness ",10)==0)
|
||||
{
|
||||
float sharpness = 0.0f;
|
||||
unsigned int fieldsRead = sscanf(line+10,"%f", &sharpness);
|
||||
|
||||
if (fieldsRead==1) material->sharpness = sharpness;
|
||||
}
|
||||
else if (strncmp(line,"illum ",6)==0)
|
||||
{
|
||||
int illum = 0;
|
||||
unsigned int fieldsRead = sscanf(line+6,"%d", &illum);
|
||||
|
||||
if (fieldsRead==1) material->illum = illum;
|
||||
}
|
||||
else if (strncmp(line,"Ns ",3)==0)
|
||||
{
|
||||
int Ns = 0;
|
||||
unsigned int fieldsRead = sscanf(line+3,"%d", &Ns);
|
||||
|
||||
if (fieldsRead==1) material->Ns = Ns;
|
||||
}
|
||||
else if (strncmp(line,"Ni ",3)==0)
|
||||
{
|
||||
int Ni = 0;
|
||||
unsigned int fieldsRead = sscanf(line+3,"%d", &Ni);
|
||||
|
||||
if (fieldsRead==1) material->Ni = Ni;
|
||||
}
|
||||
else if (strncmp(line,"illum ",6)==0)
|
||||
{
|
||||
int illum = 0;
|
||||
unsigned int fieldsRead = sscanf(line+6,"%d", &illum);
|
||||
|
||||
if (fieldsRead==1) material->illum = illum;
|
||||
}
|
||||
else if (strncmp(line,"Tr ",3)==0)
|
||||
{
|
||||
float alpha=1.0f;
|
||||
unsigned int fieldsRead = sscanf(line+3,"%f", &alpha);
|
||||
|
||||
if (fieldsRead==1)
|
||||
{
|
||||
material->ambient[3] = alpha;
|
||||
material->diffuse[3] = alpha;
|
||||
material->specular[3] = alpha;
|
||||
material->emissive[3] = alpha;
|
||||
}
|
||||
}
|
||||
else if (strncmp(line,"d ",2)==0)
|
||||
{
|
||||
float alpha=1.0f;
|
||||
unsigned int fieldsRead = sscanf(line+2,"%f", &alpha);
|
||||
|
||||
if (fieldsRead==1)
|
||||
{
|
||||
material->ambient[3] = alpha;
|
||||
material->diffuse[3] = alpha;
|
||||
material->specular[3] = alpha;
|
||||
material->emissive[3] = alpha;
|
||||
}
|
||||
}
|
||||
else if (strncmp(line,"map_Ka ",7)==0)
|
||||
{
|
||||
std::string filename(line+7);
|
||||
material->map_Ka = filename;
|
||||
}
|
||||
else if (strncmp(line,"map_Kd ",7)==0)
|
||||
{
|
||||
std::string filename(line+7);
|
||||
material->map_Kd = filename;
|
||||
}
|
||||
else if (strncmp(line,"map_Ks ",7)==0)
|
||||
{
|
||||
std::string filename(line+7);
|
||||
material->map_Ks = filename;
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::NOTICE) <<"*** line not handled *** :"<<line<<std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Model::readOBJ(std::istream& fin)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Reading OBJ file"<<std::endl;
|
||||
|
||||
const int LINE_SIZE = 4096;
|
||||
char line[LINE_SIZE];
|
||||
float x = 0.0f, y = 0.0f, z = 0.0f, w = 0.0f;
|
||||
|
||||
while (fin)
|
||||
{
|
||||
readline(fin,line,LINE_SIZE);
|
||||
if (line[0]=='#')
|
||||
{
|
||||
// comment line
|
||||
// osg::notify(osg::NOTICE) <<"Comment: "<<line<<std::endl;
|
||||
}
|
||||
else if (strlen(line)>0)
|
||||
{
|
||||
if (strncmp(line,"v ",2)==0)
|
||||
{
|
||||
unsigned int fieldsRead = sscanf(line+2,"%f %f %f %f", &x, &y, &z, &w);
|
||||
|
||||
if (fieldsRead==1) vertices.push_back(osg::Vec3(x,0.0f,0.0f));
|
||||
else if (fieldsRead==2) vertices.push_back(osg::Vec3(x,y,0.0f));
|
||||
else if (fieldsRead==3) vertices.push_back(osg::Vec3(x,y,z));
|
||||
else if (fieldsRead>=4) vertices.push_back(osg::Vec3(x/w,y/w,z/w));
|
||||
}
|
||||
else if (strncmp(line,"vn ",3)==0)
|
||||
{
|
||||
unsigned int fieldsRead = sscanf(line+3,"%f %f %f", &x, &y, &z);
|
||||
|
||||
if (fieldsRead==1) normals.push_back(osg::Vec3(x,0.0f,0.0f));
|
||||
else if (fieldsRead==2) normals.push_back(osg::Vec3(x,y,0.0f));
|
||||
else if (fieldsRead==3) normals.push_back(osg::Vec3(x,y,z));
|
||||
}
|
||||
else if (strncmp(line,"vt ",3)==0)
|
||||
{
|
||||
unsigned int fieldsRead = sscanf(line+3,"%f %f %f", &x, &y, &z);
|
||||
|
||||
if (fieldsRead==1) texcoords.push_back(osg::Vec2(x,0.0f));
|
||||
else if (fieldsRead==2) texcoords.push_back(osg::Vec2(x,y));
|
||||
else if (fieldsRead==3) texcoords.push_back(osg::Vec2(x,y));
|
||||
}
|
||||
else if (strncmp(line,"l ",2)==0 ||
|
||||
strncmp(line,"p ",2)==0 ||
|
||||
strncmp(line,"f ",2)==0)
|
||||
{
|
||||
char* ptr = line+2;
|
||||
|
||||
Element* element = new Element( (line[0]=='p') ? Element::POINTS :
|
||||
(line[0]=='l') ? Element::POLYLINE :
|
||||
Element::POLYGON );
|
||||
|
||||
int vi=0, ti=0, ni=0;
|
||||
while(*ptr!=0)
|
||||
{
|
||||
// skip white space
|
||||
while(*ptr==' ') ++ptr;
|
||||
|
||||
if (sscanf(ptr, "%d/%d/%d", &vi, &ti, &ni) == 3)
|
||||
{
|
||||
element->vertexIndices.push_back(remapVertexIndex(vi));
|
||||
element->normalIndices.push_back(remapNormalIndex(ni));
|
||||
element->texCoordIndices.push_back(remapTexCoordIndex(ti));
|
||||
}
|
||||
else if (sscanf(ptr, "%d//%d", &vi, &ni) == 2)
|
||||
{
|
||||
element->vertexIndices.push_back(remapVertexIndex(vi));
|
||||
element->normalIndices.push_back(remapNormalIndex(ni));
|
||||
}
|
||||
else if (sscanf(ptr, "%d/%d", &vi, &ti) == 2)
|
||||
{
|
||||
element->vertexIndices.push_back(remapVertexIndex(vi));
|
||||
element->texCoordIndices.push_back(remapTexCoordIndex(ti));
|
||||
}
|
||||
else if (sscanf(ptr, "%d", &vi) == 1)
|
||||
{
|
||||
element->vertexIndices.push_back(remapVertexIndex(vi));
|
||||
}
|
||||
|
||||
// skip to white space or end of line
|
||||
while(*ptr!=' ' && *ptr!=0) ++ptr;
|
||||
|
||||
}
|
||||
|
||||
if (!element->normalIndices.empty() && element->normalIndices.size() != element->vertexIndices.size())
|
||||
{
|
||||
element->normalIndices.clear();
|
||||
}
|
||||
|
||||
if (!element->texCoordIndices.empty() && element->texCoordIndices.size() != element->vertexIndices.size())
|
||||
{
|
||||
element->texCoordIndices.clear();
|
||||
}
|
||||
|
||||
if (!element->vertexIndices.empty())
|
||||
{
|
||||
Element::CoordinateCombination coordateCombination = element->getCoordinateCombination();
|
||||
if (coordateCombination!=currentElementState.coordinateCombination)
|
||||
{
|
||||
currentElementState.coordinateCombination = coordateCombination;
|
||||
currentElementList = 0; // reset the element list to force a recompute of which ElementList to use
|
||||
}
|
||||
addElement(element);
|
||||
}
|
||||
else
|
||||
{
|
||||
// empty element, don't both adding, just unref to delete it.
|
||||
element->unref();
|
||||
}
|
||||
|
||||
}
|
||||
else if (strncmp(line,"usemtl ",7)==0)
|
||||
{
|
||||
std::string materialName(line+7);
|
||||
if (currentElementState.materialName != materialName)
|
||||
{
|
||||
currentElementState.materialName = materialName;
|
||||
currentElementList = 0; // reset the element list to force a recompute of which ElementList to use
|
||||
}
|
||||
}
|
||||
else if (strncmp(line,"mtllib ",7)==0)
|
||||
{
|
||||
std::ifstream mfin(line+7);
|
||||
if (mfin)
|
||||
{
|
||||
readMTL(mfin);
|
||||
}
|
||||
}
|
||||
else if (strncmp(line,"o ",2)==0)
|
||||
{
|
||||
std::string objectName(line+2);
|
||||
if (currentElementState.objectName != objectName)
|
||||
{
|
||||
currentElementState.objectName = objectName;
|
||||
currentElementList = 0; // reset the element list to force a recompute of which ElementList to use
|
||||
}
|
||||
}
|
||||
else if (strncmp(line,"g ",2)==0)
|
||||
{
|
||||
std::string groupName(line+2);
|
||||
if (currentElementState.groupName != groupName)
|
||||
{
|
||||
currentElementState.groupName = groupName;
|
||||
currentElementList = 0; // reset the element list to force a recompute of which ElementList to use
|
||||
}
|
||||
}
|
||||
else if (strncmp(line,"s ",2)==0)
|
||||
{
|
||||
int smoothingGroup=0;
|
||||
if (strncmp(line+2,"off",3)==0) smoothingGroup = 0;
|
||||
else sscanf(line+2,"%d",&smoothingGroup);
|
||||
|
||||
if (currentElementState.smoothingGroup != smoothingGroup)
|
||||
{
|
||||
currentElementState.smoothingGroup = smoothingGroup;
|
||||
currentElementList = 0; // reset the element list to force a recompute of which ElementList to use
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::NOTICE) <<"*** line not handled *** :"<<line<<std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
osg::notify(osg::NOTICE) <<"vertices :"<<vertices.size()<<std::endl;
|
||||
osg::notify(osg::NOTICE) <<"normals :"<<normals.size()<<std::endl;
|
||||
osg::notify(osg::NOTICE) <<"texcoords :"<<texcoords.size()<<std::endl;
|
||||
osg::notify(osg::NOTICE) <<"materials :"<<materialMap.size()<<std::endl;
|
||||
osg::notify(osg::NOTICE) <<"elementStates :"<<elementStateMap.size()<<std::endl;
|
||||
/*
|
||||
unsigned int pos=0;
|
||||
for(ElementStateMap::iterator itr=elementStateMap.begin();
|
||||
itr!=elementStateMap.end();
|
||||
++itr,++pos)
|
||||
{
|
||||
const ElementState& es = itr->first;
|
||||
ElementList& el = itr->second;
|
||||
osg::notify(osg::NOTICE)<<"ElementState "<<pos<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" es.objectName="<<es.objectName<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" es.groupName="<<es.groupName<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" es.materialName="<<es.materialName<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" es.smoothGroup="<<es.smoothingGroup<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" ElementList ="<<el.size()<<std::endl;
|
||||
|
||||
}
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Model::addElement(Element* element)
|
||||
{
|
||||
if (!currentElementList)
|
||||
{
|
||||
currentElementList = & (elementStateMap[currentElementState]);
|
||||
}
|
||||
currentElementList->push_back(element);
|
||||
|
||||
}
|
||||
191
src/osgPlugins/obj/obj.h
Normal file
191
src/osgPlugins/obj/obj.h
Normal file
@@ -0,0 +1,191 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2004 Robert Osfield
|
||||
*
|
||||
* This library is open source and may be redistributed and/or modified under
|
||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OBJ_H
|
||||
#define OBJ_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <istream>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Referenced>
|
||||
#include <osg/Vec2>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Vec4>
|
||||
|
||||
|
||||
namespace obj
|
||||
{
|
||||
|
||||
class Material
|
||||
{
|
||||
public:
|
||||
Material():
|
||||
ambient(0.2f,0.2f,0.2f,1.0f),
|
||||
diffuse(0.8f,0.8f,0.8f,1.0f),
|
||||
specular(0.0f,0.0f,0.0f,1.0f),
|
||||
emissive(0.0f,0.0f,0.0f,1.0f),
|
||||
shininess(0.0f),
|
||||
sharpness(0.0f),
|
||||
illum(0),
|
||||
Tf(0.0f,0.0f,0.0f,1.0f),
|
||||
textureReflection(false),
|
||||
alpha(1.0f),
|
||||
uScale(1.0f),
|
||||
vScale(1.0f),
|
||||
uOffset(1.0f),
|
||||
vOffset(1.0f) {}
|
||||
|
||||
std::string name;
|
||||
|
||||
osg::Vec4 ambient;
|
||||
osg::Vec4 diffuse;
|
||||
osg::Vec4 specular;
|
||||
osg::Vec4 emissive;
|
||||
float shininess;
|
||||
float sharpness;
|
||||
int illum;
|
||||
|
||||
osg::Vec4 Tf;
|
||||
int Ni;
|
||||
int Ns;
|
||||
|
||||
std::string map_Ka;
|
||||
std::string map_Kd;
|
||||
std::string map_Ks;
|
||||
bool textureReflection;
|
||||
float alpha;
|
||||
float uScale;
|
||||
float vScale;
|
||||
float uOffset;
|
||||
float vOffset;
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
class Element : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::vector<int> IndexList;
|
||||
|
||||
enum DataType
|
||||
{
|
||||
POINTS,
|
||||
POLYLINE,
|
||||
POLYGON
|
||||
};
|
||||
|
||||
Element(DataType type):
|
||||
dataType(type) {}
|
||||
|
||||
enum CoordinateCombination
|
||||
{
|
||||
VERTICES,
|
||||
VERTICES_NORMALS,
|
||||
VERTICES_TEXCOORDS,
|
||||
VERTICES_NORMALS_TEXCOORDS
|
||||
};
|
||||
|
||||
CoordinateCombination getCoordinateCombination() const
|
||||
{
|
||||
if (vertexIndices.size()==normalIndices.size())
|
||||
return (vertexIndices.size()==texCoordIndices.size()) ? VERTICES_NORMALS_TEXCOORDS : VERTICES_NORMALS;
|
||||
else
|
||||
return (vertexIndices.size()==texCoordIndices.size()) ? VERTICES_TEXCOORDS : VERTICES;
|
||||
}
|
||||
|
||||
DataType dataType;
|
||||
IndexList vertexIndices;
|
||||
IndexList normalIndices;
|
||||
IndexList texCoordIndices;
|
||||
};
|
||||
|
||||
class ElementState
|
||||
{
|
||||
public:
|
||||
|
||||
ElementState():
|
||||
coordinateCombination(Element::VERTICES),
|
||||
smoothingGroup(0) {}
|
||||
|
||||
bool operator < (const ElementState& rhs) const
|
||||
{
|
||||
if (materialName<rhs.materialName) return true;
|
||||
else if (rhs.materialName<materialName) return false;
|
||||
|
||||
if (objectName<rhs.objectName) return true;
|
||||
else if (rhs.objectName<objectName) return false;
|
||||
|
||||
if (groupName<rhs.groupName) return true;
|
||||
else if (rhs.groupName<groupName) return false;
|
||||
|
||||
if (coordinateCombination<rhs.coordinateCombination) return true;
|
||||
else if (rhs.coordinateCombination<coordinateCombination) return false;
|
||||
|
||||
return (smoothingGroup<rhs.smoothingGroup);
|
||||
}
|
||||
|
||||
|
||||
std::string objectName;
|
||||
std::string groupName;
|
||||
std::string materialName;
|
||||
Element::CoordinateCombination coordinateCombination;
|
||||
int smoothingGroup;
|
||||
};
|
||||
|
||||
class Model
|
||||
{
|
||||
public:
|
||||
Model():
|
||||
currentElementList(0) {}
|
||||
|
||||
bool readMTL(std::istream& fin);
|
||||
bool readOBJ(std::istream& fin);
|
||||
|
||||
bool readline(std::istream& fin, char* line, const int LINE_SIZE);
|
||||
void addElement(Element* element);
|
||||
|
||||
int remapVertexIndex(int vi) { return (vi<0) ? vertices.size()+vi : vi-1; }
|
||||
int remapNormalIndex(int vi) { return (vi<0) ? normals.size()+vi : vi-1; }
|
||||
int remapTexCoordIndex(int vi) { return (vi<0) ? texcoords.size()+vi : vi-1; }
|
||||
|
||||
typedef std::map<std::string,Material> MaterialMap;
|
||||
typedef std::vector< osg::Vec2 > Vec2Array;
|
||||
typedef std::vector< osg::Vec3 > Vec3Array;
|
||||
typedef std::vector< osg::ref_ptr<Element> > ElementList;
|
||||
typedef std::map< ElementState,ElementList > ElementStateMap;
|
||||
|
||||
MaterialMap materialMap;
|
||||
|
||||
Vec3Array vertices;
|
||||
Vec3Array normals;
|
||||
Vec2Array texcoords;
|
||||
|
||||
ElementState currentElementState;
|
||||
|
||||
ElementStateMap elementStateMap;
|
||||
ElementList* currentElementList;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user