diff --git a/VisualStudio/osgPlugins/obj/obj.dsp b/VisualStudio/osgPlugins/obj/obj.dsp index 10dc582d7..03d5c601c 100644 --- a/VisualStudio/osgPlugins/obj/obj.dsp +++ b/VisualStudio/osgPlugins/obj/obj.dsp @@ -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" diff --git a/src/osgPlugins/obj/GNUmakefile b/src/osgPlugins/obj/GNUmakefile index 23d5d9d07..4e1164f8f 100644 --- a/src/osgPlugins/obj/GNUmakefile +++ b/src/osgPlugins/obj/GNUmakefile @@ -2,7 +2,7 @@ TOPDIR = ../../.. include $(TOPDIR)/Make/makedefs CXXFILES =\ - glm.cpp\ + obj.cpp\ ReaderWriterOBJ.cpp\ diff --git a/src/osgPlugins/obj/ReaderWriterOBJ.cpp b/src/osgPlugins/obj/ReaderWriterOBJ.cpp index 855251fc5..b9e387499 100644 --- a/src/osgPlugins/obj/ReaderWriterOBJ.cpp +++ b/src/osgPlugins/obj/ReaderWriterOBJ.cpp @@ -38,19 +38,13 @@ #include #include +#include -#include "glm.h" +#include "obj.h" #include #include -template -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 > MaterialToStateSetMap; - typedef std::map< std::string, osg::ref_ptr > TextureMap; - typedef std::set< osg::ref_ptr, DerefLess< osg::ref_ptr > > MaterialSet; - typedef std::set< osg::ref_ptr, DerefLess< osg::ref_ptr > > StateSetSet; - typedef std::vector< osg::ref_ptr > 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 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 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"<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 = 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 stateset = new osg::StateSet; - - osg::ref_ptr 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 "<textureName<< std::endl; - } - } - else - { - osg::notify(osg::WARN) << "texture '"<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="<material<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 vertexIndices = new osg::UIntArray(ntris*3); - osg::ref_ptr normalIndices = needNormals ? new osg::UIntArray(ntris*3) : 0; - osg::ref_ptr 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; -} diff --git a/src/osgPlugins/obj/glm.cpp b/src/osgPlugins/obj/glm.cpp deleted file mode 100644 index 2bd57a4ea..000000000 --- a/src/osgPlugins/obj/glm.cpp +++ /dev/null @@ -1,1932 +0,0 @@ -/* - * Wavefront .obj file format reader. - * - * author: Nate Robins - * email: ndr@pobox.com - * www: http://www.pobox.com/~ndr - */ - - -/* includes */ -#include "glm.h" -#include -#include -#include -#include -#include -#include - -#include - -#include - -/* defines */ -#define T(x) model->triangles[(x)] - - -/* enums */ -enum { X, Y, Z, W }; /* elements of a vertex */ - - -/* typedefs */ - -/* _GLMnode: general purpose node - */ -typedef struct _GLMnode { - unsigned int index; - GLboolean averaged; - struct _GLMnode* next; -} GLMnode; - - -/* private functions */ - -/* _glmMax: returns the maximum of two floats */ -static GLfloat -_glmMax(GLfloat a, GLfloat b) -{ - if (a > b) - return a; - return b; -} - -/* _glmAbs: returns the absolute value of a float */ -static GLfloat -_glmAbs(GLfloat f) -{ - if (f < 0) - return -f; - return f; -} - -/* _glmDot: compute the dot product of two vectors - * - * u - array of 3 GLfloats (GLfloat u[3]) - * v - array of 3 GLfloats (GLfloat v[3]) - */ -static GLfloat -_glmDot(GLfloat* u, GLfloat* v) -{ - assert(u); - assert(v); - - /* compute the dot product */ - return u[X] * v[X] + u[Y] * v[Y] + u[Z] * v[Z]; -} - -/* _glmCross: compute the cross product of two vectors - * - * u - array of 3 GLfloats (GLfloat u[3]) - * v - array of 3 GLfloats (GLfloat v[3]) - * n - array of 3 GLfloats (GLfloat n[3]) to return the cross product in - */ -static GLvoid -_glmCross(GLfloat* u, GLfloat* v, GLfloat* n) -{ - assert(u); - assert(v); - assert(n); - - /* compute the cross product (u x v for right-handed [ccw]) */ - n[X] = u[Y] * v[Z] - u[Z] * v[Y]; - n[Y] = u[Z] * v[X] - u[X] * v[Z]; - n[Z] = u[X] * v[Y] - u[Y] * v[X]; -} - -/* _glmNormalize: normalize a vector - * - * n - array of 3 GLfloats (GLfloat n[3]) to be normalized - */ -static GLvoid -_glmNormalize(GLfloat* n) -{ - GLfloat l; - - assert(n); - - /* normalize */ - l = (GLfloat)sqrt(n[X] * n[X] + n[Y] * n[Y] + n[Z] * n[Z]); - n[0] /= l; - n[1] /= l; - n[2] /= l; -} - -/* _glmEqual: compares two vectors and returns GL_TRUE if they are - * equal (within a certain threshold) or GL_FALSE if not. An epsilon - * that works fairly well is 0.000001. - * - * u - array of 3 GLfloats (GLfloat u[3]) - * v - array of 3 GLfloats (GLfloat v[3]) - */ -static GLboolean -_glmEqual(GLfloat* u, GLfloat* v, GLfloat epsilon) -{ - if (_glmAbs(u[0] - v[0]) < epsilon && - _glmAbs(u[1] - v[1]) < epsilon && - _glmAbs(u[2] - v[2]) < epsilon) - { - return GL_TRUE; - } - return GL_FALSE; -} - -/* _glmWeldVectors: eliminate (weld) vectors that are within an - * epsilon of each other. - * - * vectors - array of GLfloat[3]'s to be welded - * numvectors - number of GLfloat[3]'s in vectors - * epsilon - maximum difference between vectors - * - */ -GLfloat* -_glmWeldVectors(GLfloat* vectors, unsigned int* numvectors, GLfloat epsilon) -{ - GLfloat* copies; - unsigned int copied; - unsigned int i, j; - - copies = (GLfloat*)malloc(sizeof(GLfloat) * 3 * (*numvectors + 1)); - memcpy(copies, vectors, (sizeof(GLfloat) * 3 * (*numvectors + 1))); - - copied = 1; - for (i = 1; i <= *numvectors; i++) { - for (j = 1; j <= copied; j++) { - if (_glmEqual(&vectors[3 * i], &copies[3 * j], epsilon)) { - goto duplicate; - } - } - - /* must not be any duplicates -- add to the copies array */ - copies[3 * copied + 0] = vectors[3 * i + 0]; - copies[3 * copied + 1] = vectors[3 * i + 1]; - copies[3 * copied + 2] = vectors[3 * i + 2]; - j = copied; /* pass this along for below */ - copied++; - - duplicate: - /* set the first component of this vector to point at the correct - index into the new copies array */ - vectors[3 * i + 0] = (GLfloat)j; - } - - *numvectors = copied-1; - return copies; -} - -/* _glmFindGroup: Find a group in the model - */ -GLMgroup* -_glmFindGroup(GLMmodel* model, char* name) -{ - GLMgroup* group; - - assert(model); - - group = model->groups; - while(group) { - if (!strcmp(name, group->name)) - break; - group = group->next; - } - - return group; -} - -/* _glmAddGroup: Add a group to the model - */ -GLMgroup* -_glmAddGroup(GLMmodel* model, char* name) -{ - GLMgroup* group; - - group = _glmFindGroup(model, name); - if (!group) { - group = (GLMgroup*)malloc(sizeof(GLMgroup)); - group->init(); - group->name = strdup(name); - group->material = 0; - group->numtriangles = 0; - group->triangles = NULL; - group->hastexcoords = false; - group->next = model->groups; - model->groups = group; - model->numgroups++; - - std::cout<<"_glmAddGroup="<nummaterials; i++) { - if (!strcmp(model->materials[i].name, name)) - goto found; - } - - /* didn't find the name, so set it as the default material */ - fprintf(stderr,"_glmFindMaterial(): can't find material \"%s\".\n", name); - i = 0; - -found: - return i; -} - - -/* _glmDirName: return the directory given a path - * - * path - filesystem path - * - * The return value should be free'd. - */ -static char* -_glmDirName(char* path) -{ - char* dir; - char* s; - char* s2; - - dir = strdup(path); - - s = strrchr(dir, '/'); - s2 = strrchr(dir, '\\'); // also look for backslashes - if (s2 > s) // take whichever is later - s = s2; - - if (s) - s[1] = '\0'; - else - dir[0] = '\0'; - - return dir; -} - - -/* _glmReadMTLTextureOptions: parses the given line for texture options - * and applies the options to the given model/material - * - * model - properly initialized GLMmodel structure - * materialIndex - the material affected in the given model - * line - white-space separated options - */ -GLvoid -_glmReadMTLTextureOptions(GLMmodel* model, unsigned int materialIndex, char* line) -{ - char *token; - char seps[] = " \t\n\r\f\v"; - token = ::strtok(line, seps); - while(NULL != token) - { - switch(token[0]) - { - case '-': - switch(token[1]) - { - // Scaling: -s - case 's': - float uScale, vScale; - token = ::strtok(NULL, seps); - uScale = token ? (float)::atof(token) : 1.0f; - - token = ::strtok(NULL, seps); - vScale = token ? (float)::atof(token) : 1.0f; - - if ((0.0f != uScale) && (0.0f != vScale)) - { - uScale = 1.0f / uScale; - vScale = 1.0f / vScale; - model->materials[materialIndex].textureUScale = uScale; - model->materials[materialIndex].textureVScale = vScale; - } - break; - - // Offset: -o - case 'o': - float uOffset, vOffset; - token = ::strtok(NULL, seps); - uOffset = token ? (float)::atof(token) : 0.0f; - - token = ::strtok(NULL, seps); - vOffset = token ? (float)::atof(token) : 0.0f; - - model->materials[materialIndex].textureUOffset = uOffset; - model->materials[materialIndex].textureVOffset = vOffset; - break; - - // These options are not handled - so just advance to the next - // valid token - // ================================================================== - // - - // Clamping: -clamp - case 'c': - token = ::strtok(NULL, seps); - break; - - // Bias and gain: -mm - case 'm': - // Turbulence/Noise: -t - case 't': - token = ::strtok(NULL, seps); - token = ::strtok(NULL, seps); - break; - - default: - break; - } - break; - - // Image filename - default: - if (0 != strlen(token)) - { - model->materials[materialIndex].textureName = strdup(token); - } - } - - // Advance to the next token - token = ::strtok(NULL, seps); - } -} - - -/* _glmReadMTL: read a wavefront material library file - * - * model - properly initialized GLMmodel structure - * name - name of the material library - */ -static GLvoid -_glmReadMTL(GLMmodel* model, char* name) -{ - FILE* file; - char* dir; - char* filename; - char buf[128]; - unsigned int nummaterials, i; - - dir = _glmDirName(model->pathname); - filename = (char*)malloc(sizeof(char) * (strlen(dir) + strlen(name) + 1)); - strcpy(filename, dir); - strcat(filename, name); - free(dir); - - /* open the file */ - file = fopen(filename, "r"); - if (!file) { - fprintf(stderr, "_glmReadMTL() failed: can't open material file \"%s\".\n", - filename); - return; - } - free(filename); - - /* count the number of materials in the file */ - nummaterials = 1; - while(fscanf(file, "%s", buf) != EOF) { - switch(buf[0]) { - case '#': /* comment */ - /* eat up rest of line */ - fgets(buf, sizeof(buf), file); - break; - case 'n': /* newmtl */ - fgets(buf, sizeof(buf), file); - nummaterials++; - sscanf(buf, "%s %s", buf, buf); - break; - default: - /* eat up rest of line */ - fgets(buf, sizeof(buf), file); - break; - } - } - - rewind(file); - - /* allocate memory for the materials */ - model->materials = (GLMmaterial*)malloc(sizeof(GLMmaterial) * nummaterials); - model->nummaterials = nummaterials; - - /* set the default material */ - for (i = 0; i < nummaterials; i++) { - model->materials[i].init(); - model->materials[i].name = NULL; - model->materials[i].shininess = 0.0f; - model->materials[i].diffuse[0] = 0.8f; - model->materials[i].diffuse[1] = 0.8f; - model->materials[i].diffuse[2] = 0.8f; - model->materials[i].diffuse[3] = 1.0f; - model->materials[i].ambient[0] = 0.2f; - model->materials[i].ambient[1] = 0.2f; - model->materials[i].ambient[2] = 0.2f; - model->materials[i].ambient[3] = 1.0f; - model->materials[i].specular[0] = 0.0f; - model->materials[i].specular[1] = 0.0f; - model->materials[i].specular[2] = 0.0f; - model->materials[i].textureName = NULL; - model->materials[i].textureReflection = false; - model->materials[i].textureUScale = 1.0f; - model->materials[i].textureVScale = 1.0f; - model->materials[i].textureUOffset = 0.0f; - model->materials[i].textureVOffset = 0.0f; - model->materials[i].alpha = 1.0f; - } - model->materials[0].name = strdup("default"); - - /* now, read in the data */ - nummaterials = 0; - while(fscanf(file, "%s", buf) != EOF) { - switch(buf[0]) { - case '#': /* comment */ - /* eat up rest of line */ - fgets(buf, sizeof(buf), file); - break; - case 'n': /* newmtl */ - fgets(buf, sizeof(buf), file); - sscanf(buf, "%s %s", buf, buf); - nummaterials++; - model->materials[nummaterials].name = strdup(buf); - break; - case 'N': - fscanf(file, "%f", &model->materials[nummaterials].shininess); - /* wavefront shininess is from [0, 1000], so scale for OpenGL */ - model->materials[nummaterials].shininess /= 1000.0; - model->materials[nummaterials].shininess *= 128.0; - break; - case 'd': - fscanf(file, "%f", &model->materials[nummaterials].alpha); - break; - case 'K': - switch(buf[1]) { - case 'd': - fscanf(file, "%f %f %f", - &model->materials[nummaterials].diffuse[0], - &model->materials[nummaterials].diffuse[1], - &model->materials[nummaterials].diffuse[2]); - break; - case 's': - fscanf(file, "%f %f %f", - &model->materials[nummaterials].specular[0], - &model->materials[nummaterials].specular[1], - &model->materials[nummaterials].specular[2]); - break; - case 'a': - fscanf(file, "%f %f %f", - &model->materials[nummaterials].ambient[0], - &model->materials[nummaterials].ambient[1], - &model->materials[nummaterials].ambient[2]); - break; - default: - /* eat up rest of line */ - fgets(buf, sizeof(buf), file); - break; - } - break; - - default: - - /* added by RO */ - if (strcmp(buf,"map_Kd")==0) - { - fgets(buf, sizeof(buf), file); - _glmReadMTLTextureOptions(model, nummaterials, buf); - } - else if (strcmp(buf,"refl")==0) - { - model->materials[nummaterials].textureReflection = true; - } - else - { - /* eat up rest of line */ - fgets(buf, sizeof(buf), file); - } - break; - } - } - fclose(file); -} - -/* _glmWriteMTL: write a wavefront material library file - * - * model - properly initialized GLMmodel structure - * modelpath - pathname of the model being written - * mtllibname - name of the material library to be written - */ -static GLvoid -_glmWriteMTL(GLMmodel* model, char* modelpath, char* mtllibname) -{ - FILE* file; - char* dir; - char* filename; - GLMmaterial* material; - unsigned int i; - - dir = _glmDirName(modelpath); - filename = (char*)malloc(sizeof(char) * (strlen(dir) + strlen(mtllibname))); - strcpy(filename, dir); - strcat(filename, mtllibname); - free(dir); - - /* open the file */ - file = fopen(filename, "w"); - if (!file) { - fprintf(stderr, "_glmWriteMTL() failed: can't open file \"%s\".\n", - filename); - return; - } - free(filename); - - /* spit out a header */ - fprintf(file, "# \n"); - fprintf(file, "# Wavefront MTL generated by GLM library\n"); - fprintf(file, "# \n"); - fprintf(file, "# GLM library copyright (C) 1997 by Nate Robins\n"); - fprintf(file, "# email: ndr@pobox.com\n"); - fprintf(file, "# www: http://www.pobox.com/~ndr\n"); - fprintf(file, "# \n\n"); - - for (i = 0; i < model->nummaterials; i++) { - material = &model->materials[i]; - fprintf(file, "newmtl %s\n", material->name); - fprintf(file, "Ka %f %f %f\n", - material->ambient[0], material->ambient[1], material->ambient[2]); - fprintf(file, "Kd %f %f %f\n", - material->diffuse[0], material->diffuse[1], material->diffuse[2]); - fprintf(file, "Ks %f %f %f\n", - material->specular[0],material->specular[1],material->specular[2]); - fprintf(file, "Ns %f\n", material->shininess); - fprintf(file, "\n"); - } -} -/* Create by RO to help handle g %s %s groups */ -static void createCompositeName(char* buf,char* compositeName) -{ - char *ptr_b = buf; - char *ptr_c = compositeName; - - /* first skip over leading spaces */ - while(*ptr_b!=0 && *ptr_b==' ') ++ptr_b; - - /* copy over rest, changing spaces for underscores, - * to handle faces which are contained in several groups */ - while(*ptr_b>=' ') - { - if (*ptr_b==' ') *ptr_c = '_'; - else *ptr_c = *ptr_b; - ++ptr_c; - ++ptr_b; - } - *ptr_c = 0; -} -/* _glmFirstPass: first pass at a Wavefront OBJ file that gets all the - * statistics of the model (such as #vertices, #normals, etc) - * - * model - properly initialized GLMmodel structure - * file - (fopen'd) file descriptor - */ -static GLvoid -_glmFirstPass(GLMmodel* model, FILE* file) -{ - unsigned int numvertices; /* number of vertices in model */ - unsigned int numnormals; /* number of normals in model */ - unsigned int numtexcoords; /* number of texcoords in model */ - unsigned int numtriangles; /* number of triangles in model */ - GLMgroup* group; /* current group */ - unsigned v, n, t; - char buf[128]; - - /* make a default group */ - group = _glmAddGroup(model, "default"); - - float x,y,z; - int r,g,b; - - numvertices = numnormals = numtexcoords = numtriangles = 0; - - unsigned int numcolors = 0; - - while(fscanf(file, "%s", buf) != EOF) { - - - switch(buf[0]) { - case '#': /* comment */ - /* eat up rest of line */ - fgets(buf, sizeof(buf), file); - break; - case 'v': /* v, vn, vt */ - switch(buf[1]) { - case '\0': /* vertex */ - { - /* eat up rest of line */ - fgets(buf, sizeof(buf), file); - - int noRead = sscanf(buf, "%f %f %f %d %d %d", - &x, &y, &z, &r,&g,&b); - - numvertices++; - if (noRead==6) numcolors++; - - - break; - } - case 'n': /* normal */ - /* eat up rest of line */ - fgets(buf, sizeof(buf), file); - numnormals++; - break; - case 't': /* texcoord */ - /* eat up rest of line */ - fgets(buf, sizeof(buf), file); - numtexcoords++; - break; - default: - printf("_glmFirstPass(): Unknown token \"%s\".\n", buf); - //exit(1); - return; - } - break; - case 'm': - fgets(buf, sizeof(buf), file); - sscanf(buf, "%s %s", buf, buf); - model->mtllibname = strdup(buf); - _glmReadMTL(model, buf); - break; - case 'u': - /* eat up rest of line */ - fgets(buf, sizeof(buf), file); - break; - case 'o': /* group */ - case 's': /* group */ - case 'g': /* group */ - { - /* eat up rest of line */ - fgets(buf, sizeof(buf), file); - - char compositeName[128]; - createCompositeName(buf,compositeName); - - group = _glmAddGroup(model, compositeName); - } - break; - case 'f': /* face */ - v = n = t = 0; - fscanf(file, "%s", buf); - /* can be one of %d, %d//%d, %d/%d, %d/%d/%d %d//%d */ - if (strstr(buf, "//")) { - /* v//n */ - sscanf(buf, "%d//%d", &v, &n); - fscanf(file, "%d//%d", &v, &n); - fscanf(file, "%d//%d", &v, &n); - numtriangles++; - group->numtriangles++; - while(fscanf(file, "%d//%d", &v, &n) > 0) { - numtriangles++; - group->numtriangles++; - } - } else if (sscanf(buf, "%d/%d/%d", &v, &t, &n) == 3) { - /* v/t/n */ - fscanf(file, "%d/%d/%d", &v, &t, &n); - fscanf(file, "%d/%d/%d", &v, &t, &n); - numtriangles++; - group->numtriangles++; - while(fscanf(file, "%d/%d/%d", &v, &t, &n) > 0) { - numtriangles++; - group->numtriangles++; - } - } else if (sscanf(buf, "%d/%d", &v, &t) == 2) { - /* v/t */ - fscanf(file, "%d/%d", &v, &t); - fscanf(file, "%d/%d", &v, &t); - numtriangles++; - group->numtriangles++; - while(fscanf(file, "%d/%d", &v, &t) > 0) { - numtriangles++; - group->numtriangles++; - } - } else { - /* v */ - fscanf(file, "%d", &v); - fscanf(file, "%d", &v); - numtriangles++; - group->numtriangles++; - while(fscanf(file, "%d", &v) > 0) { - numtriangles++; - group->numtriangles++; - } - } - break; - - default: - /* eat up rest of line */ - fgets(buf, sizeof(buf), file); - break; - } - - std::cout<<"line="<numgroups); -#endif - - /* set the stats in the model structure */ - model->numvertices = numvertices; - model->numnormals = numnormals; - model->numtexcoords = numtexcoords; - model->numtriangles = numtriangles; - - /* allocate memory for the triangles in each group */ - group = model->groups; - while(group) { - group->triangles = (unsigned int*)malloc(sizeof(unsigned int) * group->numtriangles); - group->numtriangles = 0; - group = group->next; - } - - - // if all vertices have colours enables per vertex colors - if (numvertices==numcolors) model->useColors = true; - -} - -/* _glmSecondPass: second pass at a Wavefront OBJ file that gets all - * the data. - * - * model - properly initialized GLMmodel structure - * file - (fopen'd) file descriptor - */ -static GLvoid -_glmSecondPass(GLMmodel* model, FILE* file) -{ - unsigned int numvertices; /* number of vertices in model */ - unsigned int numnormals; /* number of normals in model */ - unsigned int numtexcoords; /* number of texcoords in model */ - unsigned int numtriangles; /* number of triangles in model */ - GLfloat* vertices; /* array of vertices */ - GLfloat* normals; /* array of normals */ - GLfloat* texcoords; /* array of texture coordinates */ - GLMgroup* group; /* current group pointer */ - unsigned int material; /* current material */ - unsigned int v, n, t; - char buf[128]; - - /* set the pointer shortcuts */ - vertices = model->vertices; - normals = model->normals; - texcoords = model->texcoords; - group = model->groups; - - /* on the second pass through the file, read all the data into the - allocated arrays */ - numvertices = numnormals = numtexcoords = 1; - numtriangles = 0; - material = 0; - - bool firstGroup = true; - bool previousLineWas_g = false; - - int r,g,b; - while(fscanf(file, "%s", buf) != EOF) { - char c = buf[0]; - switch(c) { - case '#': /* comment */ - /* eat up rest of line */ - fgets(buf, sizeof(buf), file); - break; - case 'v': /* v, vn, vt */ - switch(buf[1]) { - case '\0': /* vertex */ - { - if (model->useColors) - { - fscanf(file, "%f %f %f %d %d %d", - &vertices[3 * numvertices + X], - &vertices[3 * numvertices + Y], - &vertices[3 * numvertices + Z], - &r,&g,&b); - model->colors[numvertices].set(r,g,b,255); - - numvertices++; - } else - { - fscanf(file, "%f %f %f", - &vertices[3 * numvertices + X], - &vertices[3 * numvertices + Y], - &vertices[3 * numvertices + Z]); - numvertices++; - } - } - break; - case 'n': /* normal */ - fscanf(file, "%f %f %f", - &normals[3 * numnormals + X], - &normals[3 * numnormals + Y], - &normals[3 * numnormals + Z]); - numnormals++; - break; - case 't': /* texcoord */ - fscanf(file, "%f %f", - &texcoords[2 * numtexcoords + X], - &texcoords[2 * numtexcoords + Y]); - numtexcoords++; - break; - } - break; - case 'u': - fgets(buf, sizeof(buf), file); - sscanf(buf, "%s %s", buf, buf); - - material = _glmFindMaterial(model, buf); - - group->material = material; - - break; - case 'o': /* group */ - case 's': /* group */ - case 'g': /* group */ - /* eat up rest of line */ - fgets(buf, sizeof(buf), file); - char compositeName[128]; - createCompositeName(buf,compositeName); - group = _glmFindGroup(model, compositeName); - std::cout<<"compositeName="<triangles[group->numtriangles++] = numtriangles; - numtriangles++; - while(fscanf(file, "%d//%d", &v, &n) > 0) { - T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0]; - T(numtriangles).nindices[0] = T(numtriangles-1).nindices[0]; - T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2]; - T(numtriangles).nindices[1] = T(numtriangles-1).nindices[2]; - T(numtriangles).vindices[2] = v; - T(numtriangles).nindices[2] = n; - group->triangles[group->numtriangles++] = numtriangles; - numtriangles++; - } - } else if (sscanf(buf, "%d/%d/%d", &v, &t, &n) == 3) { - /* v/t/n */ - T(numtriangles).vindices[0] = v; - T(numtriangles).tindices[0] = t; - T(numtriangles).nindices[0] = n; - fscanf(file, "%d/%d/%d", &v, &t, &n); - T(numtriangles).vindices[1] = v; - T(numtriangles).tindices[1] = t; - T(numtriangles).nindices[1] = n; - fscanf(file, "%d/%d/%d", &v, &t, &n); - T(numtriangles).vindices[2] = v; - T(numtriangles).tindices[2] = t; - T(numtriangles).nindices[2] = n; - group->triangles[group->numtriangles++] = numtriangles; - group->hastexcoords = true; - numtriangles++; - while(fscanf(file, "%d/%d/%d", &v, &t, &n) > 0) { - T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0]; - T(numtriangles).tindices[0] = T(numtriangles-1).tindices[0]; - T(numtriangles).nindices[0] = T(numtriangles-1).nindices[0]; - T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2]; - T(numtriangles).tindices[1] = T(numtriangles-1).tindices[2]; - T(numtriangles).nindices[1] = T(numtriangles-1).nindices[2]; - T(numtriangles).vindices[2] = v; - T(numtriangles).tindices[2] = t; - T(numtriangles).nindices[2] = n; - group->triangles[group->numtriangles++] = numtriangles; - numtriangles++; - } - } else if (sscanf(buf, "%d/%d", &v, &t) == 2) { - /* v/t */ - T(numtriangles).vindices[0] = v; - T(numtriangles).tindices[0] = t; - fscanf(file, "%d/%d", &v, &t); - T(numtriangles).vindices[1] = v; - T(numtriangles).tindices[1] = t; - fscanf(file, "%d/%d", &v, &t); - T(numtriangles).vindices[2] = v; - T(numtriangles).tindices[2] = t; - group->triangles[group->numtriangles++] = numtriangles; - group->hastexcoords = true; - numtriangles++; - while(fscanf(file, "%d/%d", &v, &t) > 0) { - T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0]; - T(numtriangles).tindices[0] = T(numtriangles-1).tindices[0]; - T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2]; - T(numtriangles).tindices[1] = T(numtriangles-1).tindices[2]; - T(numtriangles).vindices[2] = v; - T(numtriangles).tindices[2] = t; - group->triangles[group->numtriangles++] = numtriangles; - numtriangles++; - } - } else { - /* v */ - sscanf(buf, "%d", &v); - T(numtriangles).vindices[0] = v; - fscanf(file, "%d", &v); - T(numtriangles).vindices[1] = v; - fscanf(file, "%d", &v); - T(numtriangles).vindices[2] = v; - group->triangles[group->numtriangles++] = numtriangles; - numtriangles++; - while(fscanf(file, "%d", &v) > 0) { - T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0]; - T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2]; - T(numtriangles).vindices[2] = v; - group->triangles[group->numtriangles++] = numtriangles; - numtriangles++; - } - } - break; - - default: - /* eat up rest of line */ - fgets(buf, sizeof(buf), file); - break; - } - - // a hack by Robert Osfield to account for usemtl being infront - // or the group, or after - but only one line after. - previousLineWas_g = (c=='g'); - } - -#if 0 - /* announce the memory requirements */ - printf(" Memory: %d bytes\n", - numvertices * 3*sizeof(GLfloat) + - numnormals * 3*sizeof(GLfloat) * (numnormals ? 1 : 0) + - numtexcoords * 3*sizeof(GLfloat) * (numtexcoords ? 1 : 0) + - numtriangles * sizeof(GLMtriangle)); -#endif -} - - - - -/* 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) -{ - unsigned int i; - GLfloat maxx, minx, maxy, miny, maxz, minz; - GLfloat cx, cy, cz, w, h, d; - GLfloat scale; - - assert(model); - assert(model->vertices); - - /* get the max/mins */ - maxx = minx = model->vertices[3 + X]; - maxy = miny = model->vertices[3 + Y]; - maxz = minz = model->vertices[3 + Z]; - for (i = 1; i <= model->numvertices; i++) { - if (maxx < model->vertices[3 * i + X]) - maxx = model->vertices[3 * i + X]; - if (minx > model->vertices[3 * i + X]) - minx = model->vertices[3 * i + X]; - - if (maxy < model->vertices[3 * i + Y]) - maxy = model->vertices[3 * i + Y]; - if (miny > model->vertices[3 * i + Y]) - miny = model->vertices[3 * i + Y]; - - if (maxz < model->vertices[3 * i + Z]) - maxz = model->vertices[3 * i + Z]; - if (minz > model->vertices[3 * i + Z]) - minz = model->vertices[3 * i + Z]; - } - - /* calculate model width, height, and depth */ - w = _glmAbs(maxx) + _glmAbs(minx); - h = _glmAbs(maxy) + _glmAbs(miny); - d = _glmAbs(maxz) + _glmAbs(minz); - - /* calculate center of the model */ - cx = (maxx + minx) / 2.0f; - cy = (maxy + miny) / 2.0f; - cz = (maxz + minz) / 2.0f; - - /* calculate unitizing scale factor */ - scale = 2.0f / _glmMax(_glmMax(w, h), d); - - /* translate around center then scale */ - for (i = 1; i <= model->numvertices; i++) { - model->vertices[3 * i + X] -= cx; - model->vertices[3 * i + Y] -= cy; - model->vertices[3 * i + Z] -= cz; - model->vertices[3 * i + X] *= scale; - model->vertices[3 * i + Y] *= scale; - model->vertices[3 * i + Z] *= scale; - } - - return scale; -} - -/* 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) -{ - unsigned int i; - GLfloat maxx, minx, maxy, miny, maxz, minz; - - assert(model); - assert(model->vertices); - assert(dimensions); - - /* get the max/mins */ - maxx = minx = model->vertices[3 + X]; - maxy = miny = model->vertices[3 + Y]; - maxz = minz = model->vertices[3 + Z]; - for (i = 1; i <= model->numvertices; i++) { - if (maxx < model->vertices[3 * i + X]) - maxx = model->vertices[3 * i + X]; - if (minx > model->vertices[3 * i + X]) - minx = model->vertices[3 * i + X]; - - if (maxy < model->vertices[3 * i + Y]) - maxy = model->vertices[3 * i + Y]; - if (miny > model->vertices[3 * i + Y]) - miny = model->vertices[3 * i + Y]; - - if (maxz < model->vertices[3 * i + Z]) - maxz = model->vertices[3 * i + Z]; - if (minz > model->vertices[3 * i + Z]) - minz = model->vertices[3 * i + Z]; - } - - /* calculate model width, height, and depth */ - dimensions[X] = _glmAbs(maxx) + _glmAbs(minx); - dimensions[Y] = _glmAbs(maxy) + _glmAbs(miny); - dimensions[Z] = _glmAbs(maxz) + _glmAbs(minz); -} - -/* 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) -{ - unsigned int i; - - for (i = 1; i <= model->numvertices; i++) { - model->vertices[3 * i + X] *= scale; - model->vertices[3 * i + Y] *= scale; - model->vertices[3 * i + Z] *= 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) -{ - unsigned int i, swap; - - assert(model); - - for (i = 0; i < model->numtriangles; i++) { - swap = T(i).vindices[0]; - T(i).vindices[0] = T(i).vindices[2]; - T(i).vindices[2] = swap; - - if (model->numnormals) { - swap = T(i).nindices[0]; - T(i).nindices[0] = T(i).nindices[2]; - T(i).nindices[2] = swap; - } - - if (model->numtexcoords) { - swap = T(i).tindices[0]; - T(i).tindices[0] = T(i).tindices[2]; - T(i).tindices[2] = swap; - } - } - - /* reverse facet normals */ - for (i = 1; i <= model->numfacetnorms; i++) { - model->facetnorms[3 * i + X] = -model->facetnorms[3 * i + X]; - model->facetnorms[3 * i + Y] = -model->facetnorms[3 * i + Y]; - model->facetnorms[3 * i + Z] = -model->facetnorms[3 * i + Z]; - } - - /* reverse vertex normals */ - for (i = 1; i <= model->numnormals; i++) { - model->normals[3 * i + X] = -model->normals[3 * i + X]; - model->normals[3 * i + Y] = -model->normals[3 * i + Y]; - model->normals[3 * i + Z] = -model->normals[3 * i + Z]; - } -} - -/* 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) -{ - unsigned int i; - GLfloat u[3]; - GLfloat v[3]; - - assert(model); - assert(model->vertices); - - /* clobber any old facetnormals */ - if (model->facetnorms) - free(model->facetnorms); - - /* allocate memory for the new facet normals */ - model->numfacetnorms = model->numtriangles; - model->facetnorms = (GLfloat*)malloc(sizeof(GLfloat) * - 3 * (model->numfacetnorms + 1)); - - for (i = 0; i < model->numtriangles; i++) { - model->triangles[i].findex = i+1; - - u[X] = model->vertices[3 * T(i).vindices[1] + X] - - model->vertices[3 * T(i).vindices[0] + X]; - u[Y] = model->vertices[3 * T(i).vindices[1] + Y] - - model->vertices[3 * T(i).vindices[0] + Y]; - u[Z] = model->vertices[3 * T(i).vindices[1] + Z] - - model->vertices[3 * T(i).vindices[0] + Z]; - - v[X] = model->vertices[3 * T(i).vindices[2] + X] - - model->vertices[3 * T(i).vindices[0] + X]; - v[Y] = model->vertices[3 * T(i).vindices[2] + Y] - - model->vertices[3 * T(i).vindices[0] + Y]; - v[Z] = model->vertices[3 * T(i).vindices[2] + Z] - - model->vertices[3 * T(i).vindices[0] + Z]; - - _glmCross(u, v, &model->facetnorms[3 * (i+1)]); - _glmNormalize(&model->facetnorms[3 * (i+1)]); - } -} - -/* 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) -{ - GLMnode* node; - GLMnode* tail; - GLMnode** members; - GLfloat* normals; - unsigned int numnormals; - GLfloat average[3]; - GLfloat dot, cos_angle; - unsigned int i, avg; - - assert(model); - assert(model->facetnorms); - - /* calculate the cosine of the angle (in degrees) */ - cos_angle = (float)cos(osg::DegreesToRadians(angle)); - - /* nuke any previous normals */ - if (model->normals) - free(model->normals); - - /* allocate space for new normals */ - model->numnormals = model->numtriangles * 3; /* 3 normals per triangle */ - model->normals = (GLfloat*)malloc(sizeof(GLfloat)* 3* (model->numnormals+1)); - - /* allocate a structure that will hold a linked list of triangle - indices for each vertex */ - members = (GLMnode**)malloc(sizeof(GLMnode*) * (model->numvertices + 1)); - for (i = 1; i <= model->numvertices; i++) - members[i] = NULL; - - /* for every triangle, create a node for each vertex in it */ - for (i = 0; i < model->numtriangles; i++) { - node = (GLMnode*)malloc(sizeof(GLMnode)); - node->index = i; - node->next = members[T(i).vindices[0]]; - members[T(i).vindices[0]] = node; - - node = (GLMnode*)malloc(sizeof(GLMnode)); - node->index = i; - node->next = members[T(i).vindices[1]]; - members[T(i).vindices[1]] = node; - - node = (GLMnode*)malloc(sizeof(GLMnode)); - node->index = i; - node->next = members[T(i).vindices[2]]; - members[T(i).vindices[2]] = node; - } - - /* calculate the average normal for each vertex */ - numnormals = 1; - for (i = 1; i <= model->numvertices; i++) { - /* calculate an average normal for this vertex by averaging the - facet normal of every triangle this vertex is in */ - node = members[i]; - if (!node) - fprintf(stderr, "glmVertexNormals(): vertex w/o a triangle\n"); - average[0] = 0.0; average[1] = 0.0; average[2] = 0.0; - avg = 0; - while (node) { - /* only average if the dot product of the angle between the two - facet normals is greater than the cosine of the threshold - angle -- or, said another way, the angle between the two - facet normals is less than (or equal to) the threshold angle */ - dot = _glmDot(&model->facetnorms[3 * T(node->index).findex], - &model->facetnorms[3 * T(members[i]->index).findex]); - if (dot > cos_angle) { - node->averaged = GL_TRUE; - average[0] += model->facetnorms[3 * T(node->index).findex + 0]; - average[1] += model->facetnorms[3 * T(node->index).findex + 1]; - average[2] += model->facetnorms[3 * T(node->index).findex + 2]; - avg = 1; /* we averaged at least one normal! */ - } else { - node->averaged = GL_FALSE; - } - node = node->next; - } - - if (avg) { - /* normalize the averaged normal */ - _glmNormalize(average); - - /* add the normal to the vertex normals list */ - model->normals[3 * numnormals + 0] = average[0]; - model->normals[3 * numnormals + 1] = average[1]; - model->normals[3 * numnormals + 2] = average[2]; - avg = numnormals; - numnormals++; - } - - /* set the normal of this vertex in each triangle it is in */ - node = members[i]; - while (node) { - if (node->averaged) { - /* if this node was averaged, use the average normal */ - if (T(node->index).vindices[0] == i) - T(node->index).nindices[0] = avg; - else if (T(node->index).vindices[1] == i) - T(node->index).nindices[1] = avg; - else if (T(node->index).vindices[2] == i) - T(node->index).nindices[2] = avg; - } else { - /* if this node wasn't averaged, use the facet normal */ - model->normals[3 * numnormals + 0] = - model->facetnorms[3 * T(node->index).findex + 0]; - model->normals[3 * numnormals + 1] = - model->facetnorms[3 * T(node->index).findex + 1]; - model->normals[3 * numnormals + 2] = - model->facetnorms[3 * T(node->index).findex + 2]; - if (T(node->index).vindices[0] == i) - T(node->index).nindices[0] = numnormals; - else if (T(node->index).vindices[1] == i) - T(node->index).nindices[1] = numnormals; - else if (T(node->index).vindices[2] == i) - T(node->index).nindices[2] = numnormals; - numnormals++; - } - node = node->next; - } - } - - model->numnormals = numnormals - 1; - - /* free the member information */ - for (i = 1; i <= model->numvertices; i++) { - node = members[i]; - while (node) { - tail = node; - node = node->next; - free(tail); - } - } - free(members); - - /* pack the normals array (we previously allocated the maximum - number of normals that could possibly be created (numtriangles * - 3), so get rid of some of them (usually alot unless none of the - facet normals were averaged)) */ - normals = model->normals; - model->normals = (GLfloat*)malloc(sizeof(GLfloat)* 3* (model->numnormals+1)); - for (i = 1; i <= model->numnormals; i++) { - model->normals[3 * i + 0] = normals[3 * i + 0]; - model->normals[3 * i + 1] = normals[3 * i + 1]; - model->normals[3 * i + 2] = normals[3 * i + 2]; - } - free(normals); - - printf("glmVertexNormals(): %d normals generated\n", model->numnormals); -} - - -/* 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) -{ - GLMgroup *group; - GLfloat dimensions[3]; - GLfloat x, y, scalefactor; - unsigned int i; - - assert(model); - - if (model->texcoords) - free(model->texcoords); - model->numtexcoords = model->numvertices; - model->texcoords=(GLfloat*)malloc(sizeof(GLfloat)*2*(model->numtexcoords+1)); - - glmDimensions(model, dimensions); - scalefactor = 2.0f / - _glmAbs(_glmMax(_glmMax(dimensions[0], dimensions[1]), dimensions[2])); - - /* do the calculations */ - for(i = 1; i <= model->numvertices; i++) { - x = model->vertices[3 * i + 0] * scalefactor; - y = model->vertices[3 * i + 2] * scalefactor; - model->texcoords[2 * i + 0] = (x + 1.0f) / 2.0f; - model->texcoords[2 * i + 1] = (y + 1.0f) / 2.0f; - } - - /* go through and put texture coordinate indices in all the triangles */ - group = model->groups; - while(group) { - for(i = 0; i < group->numtriangles; i++) { - T(group->triangles[i]).tindices[0] = T(group->triangles[i]).vindices[0]; - T(group->triangles[i]).tindices[1] = T(group->triangles[i]).vindices[1]; - T(group->triangles[i]).tindices[2] = T(group->triangles[i]).vindices[2]; - } - group = group->next; - } - -#if 0 - printf("glmLinearTexture(): generated %d linear texture coordinates\n", - model->numtexcoords); -#endif -} - -/* 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) -{ - GLMgroup* group; - GLfloat theta, phi, rho, x, y, z, r; - unsigned int i; - - assert(model); - assert(model->normals); - - if (model->texcoords) - free(model->texcoords); - model->numtexcoords = model->numnormals; - model->texcoords=(GLfloat*)malloc(sizeof(GLfloat)*2*(model->numtexcoords+1)); - - /* do the calculations */ - for (i = 1; i <= model->numnormals; i++) { - z = model->normals[3 * i + 0]; /* re-arrange for pole distortion */ - y = model->normals[3 * i + 1]; - x = model->normals[3 * i + 2]; - r = sqrtf((x * x) + (y * y)); - rho = sqrtf((r * r) + (z * z)); - - if(r == 0.0f) { - theta = 0.0f; - phi = 0.0f; - } else { - if(z == 0.0) - phi = 3.14159265f / 2.0f; - else - phi = acosf(z / rho); - -#if WE_DONT_NEED_THIS_CODE - if(x == 0.0) - theta = 3.14159265f / 2.0f; /* asin(y / r); */ - else - theta = acos(x / r); -#endif - - if(y == 0.0) - theta = 3.141592365f / 2.0f; /* acos(x / r); */ - else - theta = asinf(y / r) + 3.14159265f / 2.0f; - } - - model->texcoords[2 * i + 0] = theta / 3.14159265f; - model->texcoords[2 * i + 1] = phi / 3.14159265f; - } - - /* go through and put texcoord indices in all the triangles */ - group = model->groups; - while(group) { - for (i = 0; i < group->numtriangles; i++) { - T(group->triangles[i]).tindices[0] = T(group->triangles[i]).nindices[0]; - T(group->triangles[i]).tindices[1] = T(group->triangles[i]).nindices[1]; - T(group->triangles[i]).tindices[2] = T(group->triangles[i]).nindices[2]; - } - group = group->next; - } - -#if 0 - printf("glmSpheremapTexture(): generated %d spheremap texture coordinates\n", - model->numtexcoords); -#endif -} - -/* glmDelete: Deletes a GLMmodel structure. - * - * model - initialized GLMmodel structure - */ -GLvoid -glmDelete(GLMmodel* model) -{ - GLMgroup* group; - unsigned int i; - - assert(model); - - if (model->pathname) free(model->pathname); - if (model->mtllibname) free(model->mtllibname); - if (model->vertices) free(model->vertices); - if (model->colors) free(model->colors); - if (model->normals) free(model->normals); - if (model->texcoords) free(model->texcoords); - if (model->facetnorms) free(model->facetnorms); - if (model->triangles) free(model->triangles); - if (model->materials) { - for (i = 0; i < model->nummaterials; i++) - { - free(model->materials[i].name); - free(model->materials[i].textureName); - } - } - free(model->materials); - while(model->groups) { - group = model->groups; - model->groups = model->groups->next; - free(group->name); - free(group->triangles); - free(group); - } - - free(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) -{ - GLMmodel* model; - FILE* file; - - /* open the file */ - file = fopen(filename, "r"); - if (!file) { - fprintf(stderr, "glmReadOBJ() failed: can't open data file \"%s\".\n", - filename); - //exit(1); - return NULL; - } - -#if 0 - /* announce the model name */ - printf("Model: %s\n", filename); -#endif - - /* allocate a new model */ - model = (GLMmodel*)malloc(sizeof(GLMmodel)); - model->pathname = strdup(filename); - model->mtllibname = NULL; - model->numvertices = 0; - model->vertices = NULL; - model->useColors = false; - model->colors = NULL; - model->numnormals = 0; - model->normals = NULL; - model->numtexcoords = 0; - model->texcoords = NULL; - model->numfacetnorms = 0; - model->facetnorms = NULL; - model->numtriangles = 0; - model->triangles = NULL; - model->nummaterials = 0; - model->materials = NULL; - model->numgroups = 0; - model->groups = NULL; - model->position[0] = 0.0; - model->position[1] = 0.0; - model->position[2] = 0.0; - - /* make a first pass through the file to get a count of the number - of vertices, normals, texcoords & triangles */ - _glmFirstPass(model, file); - - /* allocate memory */ - model->vertices = (GLfloat*)malloc(sizeof(GLfloat) * - 3 * (model->numvertices + 1)); - - if (model->useColors) - model->colors = (osg::UByte4*)malloc(sizeof(osg::UByte4)*(model->numvertices + 1)); - - model->triangles = (GLMtriangle*)malloc(sizeof(GLMtriangle) * - model->numtriangles); - if (model->numnormals) { - model->normals = (GLfloat*)malloc(sizeof(GLfloat) * - 3 * (model->numnormals + 1)); - } - if (model->numtexcoords) { - model->texcoords = (GLfloat*)malloc(sizeof(GLfloat) * - 2 * (model->numtexcoords + 1)); - } - - /* rewind to beginning of file and read in the data this pass */ - rewind(file); - - _glmSecondPass(model, file); - - /* close the file */ - fclose(file); - - return model; -} - -/* 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 - render with only vertices - * GLM_FLAT - render with facet normals - * GLM_SMOOTH - render with vertex normals - * GLM_TEXTURE - render with texture coords - * GLM_COLOR - render with colors (color material) - * GLM_MATERIAL - render with materials - * GLM_COLOR and GLM_MATERIAL should not both be specified. - * GLM_FLAT and GLM_SMOOTH should not both be specified. - */ -GLvoid -glmWriteOBJ(GLMmodel* model, char* filename, unsigned int mode) -{ - unsigned int i; - FILE* file; - GLMgroup* group; - - assert(model); - - /* do a bit of warning */ - if (mode & GLM_FLAT && !model->facetnorms) { - printf("glmWriteOBJ() warning: flat normal output requested " - "with no facet normals defined.\n"); - mode &= ~GLM_FLAT; - } - if (mode & GLM_SMOOTH && !model->normals) { - printf("glmWriteOBJ() warning: smooth normal output requested " - "with no normals defined.\n"); - mode &= ~GLM_SMOOTH; - } - if (mode & GLM_TEXTURE && !model->texcoords) { - printf("glmWriteOBJ() warning: texture coordinate output requested " - "with no texture coordinates defined.\n"); - mode &= ~GLM_TEXTURE; - } - if (mode & GLM_FLAT && mode & GLM_SMOOTH) { - printf("glmWriteOBJ() warning: flat normal output requested " - "and smooth normal output requested (using smooth).\n"); - mode &= ~GLM_FLAT; - } - - /* open the file */ - file = fopen(filename, "w"); - if (!file) { - fprintf(stderr, "glmWriteOBJ() failed: can't open file \"%s\" to write.\n", - filename); - //exit(1); - return; - } - - /* spit out a header */ - fprintf(file, "# \n"); - fprintf(file, "# Wavefront OBJ generated by GLM library\n"); - fprintf(file, "# \n"); - fprintf(file, "# GLM library copyright (C) 1997 by Nate Robins\n"); - fprintf(file, "# email: ndr@pobox.com\n"); - fprintf(file, "# www: http://www.pobox.com/~ndr\n"); - fprintf(file, "# \n"); - - if (mode & GLM_MATERIAL && model->mtllibname) { - fprintf(file, "\nmtllib %s\n\n", model->mtllibname); - _glmWriteMTL(model, filename, model->mtllibname); - } - - /* spit out the vertices */ - fprintf(file, "\n"); - fprintf(file, "# %d vertices\n", model->numvertices); - for (i = 1; i <= model->numvertices; i++) { - fprintf(file, "v %f %f %f\n", - model->vertices[3 * i + 0], - model->vertices[3 * i + 1], - model->vertices[3 * i + 2]); - } - - /* spit out the smooth/flat normals */ - if (mode & GLM_SMOOTH) { - fprintf(file, "\n"); - fprintf(file, "# %d normals\n", model->numnormals); - for (i = 1; i <= model->numnormals; i++) { - fprintf(file, "vn %f %f %f\n", - model->normals[3 * i + 0], - model->normals[3 * i + 1], - model->normals[3 * i + 2]); - } - } else if (mode & GLM_FLAT) { - fprintf(file, "\n"); - fprintf(file, "# %d normals\n", model->numfacetnorms); - for (i = 1; i <= model->numnormals; i++) { - fprintf(file, "vn %f %f %f\n", - model->facetnorms[3 * i + 0], - model->facetnorms[3 * i + 1], - model->facetnorms[3 * i + 2]); - } - } - - /* spit out the texture coordinates */ - if (mode & GLM_TEXTURE) { - fprintf(file, "\n"); - fprintf(file, "# %d texcoords\n", model->numtexcoords); - for (i = 1; i <= model->numtexcoords; i++) { - fprintf(file, "vt %f %f\n", - model->texcoords[2 * i + 0], - model->texcoords[2 * i + 1]); - } - } - - fprintf(file, "\n"); - fprintf(file, "# %d groups\n", model->numgroups); - fprintf(file, "# %d faces (triangles)\n", model->numtriangles); - fprintf(file, "\n"); - - group = model->groups; - while(group) { - fprintf(file, "g %s\n", group->name); - if (mode & GLM_MATERIAL) - fprintf(file, "usemtl %s\n", model->materials[group->material].name); - for (i = 0; i < group->numtriangles; i++) { - if (mode & GLM_SMOOTH && mode & GLM_TEXTURE) { - fprintf(file, "f %d/%d/%d %d/%d/%d %d/%d/%d\n", - T(group->triangles[i]).vindices[0], - T(group->triangles[i]).nindices[0], - T(group->triangles[i]).tindices[0], - T(group->triangles[i]).vindices[1], - T(group->triangles[i]).nindices[1], - T(group->triangles[i]).tindices[1], - T(group->triangles[i]).vindices[2], - T(group->triangles[i]).nindices[2], - T(group->triangles[i]).tindices[2]); - } else if (mode & GLM_FLAT && mode & GLM_TEXTURE) { - fprintf(file, "f %d/%d %d/%d %d/%d\n", - T(group->triangles[i]).vindices[0], - T(group->triangles[i]).findex, - T(group->triangles[i]).vindices[1], - T(group->triangles[i]).findex, - T(group->triangles[i]).vindices[2], - T(group->triangles[i]).findex); - } else if (mode & GLM_TEXTURE) { - fprintf(file, "f %d/%d %d/%d %d/%d\n", - T(group->triangles[i]).vindices[0], - T(group->triangles[i]).tindices[0], - T(group->triangles[i]).vindices[1], - T(group->triangles[i]).tindices[1], - T(group->triangles[i]).vindices[2], - T(group->triangles[i]).tindices[2]); - } else if (mode & GLM_SMOOTH) { - fprintf(file, "f %d//%d %d//%d %d//%d\n", - T(group->triangles[i]).vindices[0], - T(group->triangles[i]).nindices[0], - T(group->triangles[i]).vindices[1], - T(group->triangles[i]).nindices[1], - T(group->triangles[i]).vindices[2], - T(group->triangles[i]).nindices[2]); - } else if (mode & GLM_FLAT) { - fprintf(file, "f %d//%d %d//%d %d//%d\n", - T(group->triangles[i]).vindices[0], - T(group->triangles[i]).findex, - T(group->triangles[i]).vindices[1], - T(group->triangles[i]).findex, - T(group->triangles[i]).vindices[2], - T(group->triangles[i]).findex); - } else { - fprintf(file, "f %d %d %d\n", - T(group->triangles[i]).vindices[0], - T(group->triangles[i]).vindices[1], - T(group->triangles[i]).vindices[2]); - } - } - fprintf(file, "\n"); - group = group->next; - } - - fclose(file); -} - -/* 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) -{ - GLfloat* vectors; - GLfloat* copies; - unsigned int numvectors; - unsigned int i; - - /* vertices */ - numvectors = model->numvertices; - vectors = model->vertices; - copies = _glmWeldVectors(vectors, &numvectors, epsilon); - - printf("glmWeld(): %d redundant vertices.\n", - model->numvertices - numvectors - 1); - - for (i = 0; i < model->numtriangles; i++) { - T(i).vindices[0] = (unsigned int)vectors[3 * T(i).vindices[0] + 0]; - T(i).vindices[1] = (unsigned int)vectors[3 * T(i).vindices[1] + 0]; - T(i).vindices[2] = (unsigned int)vectors[3 * T(i).vindices[2] + 0]; - } - - /* free space for old vertices */ - free(vectors); - - /* allocate space for the new vertices */ - model->numvertices = numvectors; - model->vertices = (GLfloat*)malloc(sizeof(GLfloat) * - 3 * (model->numvertices + 1)); - - /* copy the optimized vertices into the actual vertex list */ - for (i = 1; i <= model->numvertices; i++) { - model->vertices[3 * i + 0] = copies[3 * i + 0]; - model->vertices[3 * i + 1] = copies[3 * i + 1]; - model->vertices[3 * i + 2] = copies[3 * i + 2]; - } - - free(copies); -} - - -#if 0 - /* normals */ - if (model->numnormals) { - numvectors = model->numnormals; - vectors = model->normals; - copies = _glmOptimizeVectors(vectors, &numvectors); - - printf("glmOptimize(): %d redundant normals.\n", - model->numnormals - numvectors); - - for (i = 0; i < model->numtriangles; i++) { - T(i).nindices[0] = (unsigned int)vectors[3 * T(i).nindices[0] + 0]; - T(i).nindices[1] = (unsigned int)vectors[3 * T(i).nindices[1] + 0]; - T(i).nindices[2] = (unsigned int)vectors[3 * T(i).nindices[2] + 0]; - } - - /* free space for old normals */ - free(vectors); - - /* allocate space for the new normals */ - model->numnormals = numvectors; - model->normals = (GLfloat*)malloc(sizeof(GLfloat) * - 3 * (model->numnormals + 1)); - - /* copy the optimized vertices into the actual vertex list */ - for (i = 1; i <= model->numnormals; i++) { - model->normals[3 * i + 0] = copies[3 * i + 0]; - model->normals[3 * i + 1] = copies[3 * i + 1]; - model->normals[3 * i + 2] = copies[3 * i + 2]; - } - - free(copies); - } - - /* texcoords */ - if (model->numtexcoords) { - numvectors = model->numtexcoords; - vectors = model->texcoords; - copies = _glmOptimizeVectors(vectors, &numvectors); - - printf("glmOptimize(): %d redundant texcoords.\n", - model->numtexcoords - numvectors); - - for (i = 0; i < model->numtriangles; i++) { - for (j = 0; j < 3; j++) { - T(i).tindices[j] = (unsigned int)vectors[3 * T(i).tindices[j] + 0]; - } - } - - /* free space for old texcoords */ - free(vectors); - - /* allocate space for the new texcoords */ - model->numtexcoords = numvectors; - model->texcoords = (GLfloat*)malloc(sizeof(GLfloat) * - 2 * (model->numtexcoords + 1)); - - /* copy the optimized vertices into the actual vertex list */ - for (i = 1; i <= model->numtexcoords; i++) { - model->texcoords[2 * i + 0] = copies[2 * i + 0]; - model->texcoords[2 * i + 1] = copies[2 * i + 1]; - } - - free(copies); - } -#endif - -#if 0 - /* look for unused vertices */ - /* look for unused normals */ - /* look for unused texcoords */ - for (i = 1; i <= model->numvertices; i++) { - for (j = 0; j < model->numtriangles; i++) { - if (T(j).vindices[0] == i || - T(j).vindices[1] == i || - T(j).vindices[1] == i) - break; - } - } -#endif diff --git a/src/osgPlugins/obj/glm.h b/src/osgPlugins/obj/glm.h deleted file mode 100644 index 737b7cd2e..000000000 --- a/src/osgPlugins/obj/glm.h +++ /dev/null @@ -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 -//#include - -// 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 -#include - -#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); diff --git a/src/osgPlugins/obj/obj.cpp b/src/osgPlugins/obj/obj.cpp new file mode 100644 index 000000000..c8a4f0ef7 --- /dev/null +++ b/src/osgPlugins/obj/obj.cpp @@ -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 + +#include "obj.h" + +#include + +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 && ptr0) + { + 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 *** :"<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 *** :"<first; + ElementList& el = itr->second; + osg::notify(osg::NOTICE)<<"ElementState "<