From af22bd70dbcb582fbdd2cef8ff37a90e37ba3132 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 8 Nov 2010 15:49:30 +0000 Subject: [PATCH] From Johan Nouvel, "Some times ago, I have coded an osg to vrml2 writer. Today, I have updated our writer to osg 2.9.9. As it works (for our needs at least) I've done and attached a tar.gz file for the VRML2 plugin with a new part to write a VRML2 file from an osg one. The read part is the same as in osg 2.9.9. The write part code is in convertToVRML.cpp and .h files. It works for some osg nodes (group, geode, matrixTransform, positionAttitudeTransform and geometry). Textures are converted to jpeg (if not translucent) or png (if translucent). There are some options that could be given to the writer (with -O switch) : convertTextures=0 to copy textures without converting them to jpeg or png convertTextures=-1 do not copy textures, keep them in their original format and location convertTextures=-2 do not use textures, parse only geometry convertTextures=-3 (default) convert textures to jpeg or png ones. textureUnit=X in case of multiple textures, X= texture unit to use (default value=0) directoryTexture=aPath when texture will be copied, it will be in this directory, not in the current one." --- src/osgPlugins/vrml/CMakeLists.txt | 2 + src/osgPlugins/vrml/ConvertToVRML.cpp | 1303 +++++++++++++++++++++ src/osgPlugins/vrml/ConvertToVRML.h | 115 ++ src/osgPlugins/vrml/ReaderWriterVRML2.cpp | 21 +- src/osgPlugins/vrml/ReaderWriterVRML2.h | 7 +- 5 files changed, 1446 insertions(+), 2 deletions(-) create mode 100644 src/osgPlugins/vrml/ConvertToVRML.cpp create mode 100644 src/osgPlugins/vrml/ConvertToVRML.h diff --git a/src/osgPlugins/vrml/CMakeLists.txt b/src/osgPlugins/vrml/CMakeLists.txt index 16720b164..867e0dfff 100644 --- a/src/osgPlugins/vrml/CMakeLists.txt +++ b/src/osgPlugins/vrml/CMakeLists.txt @@ -37,10 +37,12 @@ SET(TARGET_SRC IndexedFaceSet.cpp Primitives.cpp ReaderWriterVRML2.cpp + ConvertToVRML.cpp ) SET(TARGET_H ReaderWriterVRML2.h + ConvertToVRML.h ) #### end var setup ### diff --git a/src/osgPlugins/vrml/ConvertToVRML.cpp b/src/osgPlugins/vrml/ConvertToVRML.cpp new file mode 100644 index 000000000..de68a1e74 --- /dev/null +++ b/src/osgPlugins/vrml/ConvertToVRML.cpp @@ -0,0 +1,1303 @@ +/* + * + * OSG to VRML2 converter for OpenSceneGraph. + * + * authors : + * Johan Nouvel (johan_nouvel@yahoo.com) + * + * + */ + +#include "ConvertToVRML.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace std; + +///////////////////////////////////////////////////////////////////////// +// +// transformNode +// +///////////////////////////////////////////////////////////////////////// +osg::Node* transformNode(const osg::Node& root) { + + // create a zup to yup OSG Matrix + osg::MatrixTransform* ret = new osg::MatrixTransform(); + osg::Matrix osgToVRMLMat(osg::Matrix(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0)); + + ret->setDataVariance(osg::Object::STATIC); + ret->setMatrix(osgToVRMLMat); + + if (strcmp(root.className(), "MatrixTransform") == 0) { + const osg::MatrixTransform& aMat = static_cast (root); + osg::MatrixTransform* node = new osg::MatrixTransform(aMat); + ret->addChild(node); + } else if (strcmp(root.className(), "Group") == 0) { + const osg::Group& aGroup = static_cast (root); + osg::Group* node = new osg::Group(aGroup); + ret->addChild(node); + } else if (strcmp(root.className(), "PositionAttitudeTransform") == 0) { + const osg::PositionAttitudeTransform& aPAT = static_cast (root); + osg::PositionAttitudeTransform* node = new osg::PositionAttitudeTransform(aPAT); + ret->addChild(node); + } else if (strcmp(root.className(), "Geode") == 0) { + const osg::Geode& aGeode = static_cast (root); + osg::Geode* node = new osg::Geode(aGeode); + ret->addChild(node); + } else { + osg::notify(osg::ALWAYS) << root.className() << " unsupported" << endl; + } + if (ret->getNumChildren() > 0) { + return ret; + } + return (NULL); +} + +///////////////////////////////////////////////////////////////////////// +// +// convertToVRML +// +///////////////////////////////////////////////////////////////////////// +osgDB::ReaderWriter::WriteResult convertToVRML(const osg::Node& root, const std::string& filename, const osgDB::ReaderWriter::Options* options) { + + ToVRML toVrml(filename, options); + + //cout << root.className() << endl; + osg::Node* aRoot = transformNode(root); + + if (aRoot == NULL) { + return (osgDB::ReaderWriter::WriteResult(osgDB::ReaderWriter::WriteResult::FILE_NOT_HANDLED)); + } + aRoot->accept(toVrml); + + return (toVrml.result()); +} + +///////////////////////////////////////////////////////////////////////// +// +// ToVRML +// +///////////////////////////////////////////////////////////////////////// +ToVRML::ToVRML(const std::string& fileName, const osgDB::ReaderWriter::Options* options) : + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { + + _fout.open(fileName.c_str(), ios::out); + + if (!_fout) { + _res = osgDB::ReaderWriter::WriteResult::FILE_NOT_HANDLED; + return; + } + _res = osgDB::ReaderWriter::WriteResult::FILE_SAVED; + + _pathToOutput = osgDB::getFilePath(fileName.c_str()); + if (_pathToOutput == "") { + _pathToOutput = "."; + } + //std::cout<<" path -"<<_pathToOutput<<"-"<getOptionString(); + if (opt.find("convertTextures=0") != std::string::npos) { + //std::cout << "Read XML stream" << std::endl; + _textureMode = COPY_TEXTURE; + + } else if (opt.find("convertTextures=-1") != std::string::npos) { + _textureMode = KEEP_ORIGINAL_TEXTURE; + + } else if (opt.find("convertTextures=-2") != std::string::npos) { + _textureMode = NO_TEXTURE; + + } else if (opt.find("convertTextures=-3") != std::string::npos) { + _textureMode = CONVERT_TEXTURE; + } + + if (opt.find("directoryTextures=") != std::string::npos) { + std::string dirOpt = opt; + dirOpt.erase(0, dirOpt.find("directoryTextures=") + 18); + _pathRelativeToOutput = dirOpt.substr(0, dirOpt.find(' ')); + } + + if (opt.find("textureUnit=") != std::string::npos) { + std::string dirOpt = opt; + dirOpt.erase(0, dirOpt.find("textureUnit=") + 12); + _txtUnit = atoi(dirOpt.substr(0, dirOpt.find(' ')).c_str()); + } + } + + if (_textureMode != NO_TEXTURE) { + _defaultImage = new osg::Image(); + _defaultImage->setFileName(_pathToOutput + "/" + _pathRelativeToOutput + "/default_texture.png"); + int s = 1; + int t = 1; + unsigned char *data = new unsigned char[s * t * 3]; + data[0] = 255; + data[1] = 255; + data[2] = 255; + _defaultImage->setImage(s, t, 0, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE); + osgDB::writeImageFile(*(_defaultImage.get()), _defaultImage->getFileName()); + } +} + +///////////////////////////////////////////////////////////////////////// +// +// ~ToVRML +// +///////////////////////////////////////////////////////////////////////// +ToVRML::~ToVRML() { + if (_fout) { + _fout.close(); + } + free( _strIndent); + +} + +///////////////////////////////////////////////////////////////////////// +// +// indent +// +///////////////////////////////////////////////////////////////////////// +char* ToVRML::indent() { + return (_strIndent); +} + +///////////////////////////////////////////////////////////////////////// +// +// indentM +// +///////////////////////////////////////////////////////////////////////// +char* ToVRML::indentM() { + _strIndent[_indent] = ' '; + _indent += 2; + + if (_indent > 32) { + _indent = 32; + } + _strIndent[_indent] = '\0'; + + return (_strIndent); +} + +///////////////////////////////////////////////////////////////////////// +// +// indentL +// +///////////////////////////////////////////////////////////////////////// +char* ToVRML::indentL() { + _strIndent[_indent] = ' '; + _indent -= 2; + + if (_indent < 0) { + _indent = 0; + } + _strIndent[_indent] = '\0'; + + return (_strIndent); +} + +///////////////////////////////////////////////////////////////////////// +// +// apply(osg::Geode) +// +///////////////////////////////////////////////////////////////////////// +void ToVRML::apply(osg::Geode& node) { + //cout << "Geode" << endl; + + pushStateSetStack(node.getStateSet()); + + for (unsigned int i = 0; i < node.getNumDrawables(); i++) { + apply(node.getDrawable(i)); + } + popStateSetStack(); +} + +///////////////////////////////////////////////////////////////////////// +// +// apply +// +///////////////////////////////////////////////////////////////////////// +void ToVRML::apply(osg::Drawable* drawable) { + // get the drawable type + //cout<<"ICI "<className()<getStateSet()); + + if (strcmp(drawable->className(), "Geometry") == 0) { + apply(drawable->asGeometry()); + } else { + osg::notify(osg::ALWAYS) << "Drawable " << drawable->className() << " unsupported" << endl; + } + + popStateSetStack(); +} + +///////////////////////////////////////////////////////////////////////// +// +// apply +// +///////////////////////////////////////////////////////////////////////// +void ToVRML::apply(osg::Geometry* geom) { + + // are all primitives faces or line ? + GLenum mode; + osg::PrimitiveSet::Type type; + + _fout << indent() << "Shape {\n"; + indentM(); + writeAppearance( getCurrentStateSet()); + indentL(); + + int modePoints = 0; + int modeLines = 0; + int modeFaces = 0; + + for (unsigned int p = 0; p < geom->getNumPrimitiveSets(); p++) { + mode = geom->getPrimitiveSet(p)->getMode(); + if (mode == osg::PrimitiveSet::POINTS) { + modePoints++; + + } else if ((mode == osg::PrimitiveSet::LINES) || (mode == osg::PrimitiveSet::LINE_STRIP) || (mode == osg::PrimitiveSet::LINE_LOOP)) { + modeLines++; + + } else if ((mode == osg::PrimitiveSet::TRIANGLES) || (mode == osg::PrimitiveSet::TRIANGLE_STRIP) || (mode == osg::PrimitiveSet::TRIANGLE_FAN) || (mode + == osg::PrimitiveSet::QUADS) || (mode == osg::PrimitiveSet::QUAD_STRIP) || (mode == osg::PrimitiveSet::POLYGON)) { + modeFaces++; + } + } + + //std::cout << "primitives type : Points " << modePoints << " Line " << modeLines << " Face " << modeFaces << std::endl; + + if (modePoints > 0) { + _fout << indentM() << "geometry PointSet {\n"; + for (unsigned int p = 0; p < geom->getNumPrimitiveSets(); p++) { + mode = geom->getPrimitiveSet(p)->getMode(); + type = geom->getPrimitiveSet(p)->getType(); + if (mode == osg::PrimitiveSet::POINTS) { + osg::notify(osg::WARN) << " osg::PrimitiveSetMode = POINTS not supported by VRML Writer" << std::endl; + } + } + } + + if (modeLines > 0) { + _fout << indentM() << "geometry IndexedLineSet {\n"; + for (unsigned int p = 0; p < geom->getNumPrimitiveSets(); p++) { + mode = geom->getPrimitiveSet(p)->getMode(); + type = geom->getPrimitiveSet(p)->getType(); + if ((mode == osg::PrimitiveSet::LINES) || (mode == osg::PrimitiveSet::LINE_STRIP) || (mode == osg::PrimitiveSet::LINE_LOOP)) { + osg::notify(osg::WARN) << " osg::PrimitiveSetMode = LINES, LINE_STRIP or LINE_LOOP not supported by VRML Writer" << std::endl; + } + } + } + + if (modeFaces > 0) { + _fout << indentM() << "geometry IndexedFaceSet {\n"; + _fout << indentM() << "solid FALSE\n"; + indentL(); + _fout << indentM() << "coordIndex [\n"; + indentM(); + + std::vector primitiveSetFaces; + int primitiveFaces = 0; + + for (unsigned int p = 0; p < geom->getNumPrimitiveSets(); p++) { + mode = geom->getPrimitiveSet(p)->getMode(); + type = geom->getPrimitiveSet(p)->getType(); + if ((mode == osg::PrimitiveSet::TRIANGLES) || (mode == osg::PrimitiveSet::TRIANGLE_STRIP) || (mode == osg::PrimitiveSet::TRIANGLE_FAN) || (mode == osg::PrimitiveSet::QUADS) + || (mode == osg::PrimitiveSet::QUAD_STRIP) || (mode == osg::PrimitiveSet::POLYGON)) { + if (type == osg::PrimitiveSet::PrimitiveType) { + osg::notify(osg::WARN) << "osg::PrimitiveSet::PrimitiveType not supported by VRML Writer" << std::endl; + + } else if (type == osg::PrimitiveSet::DrawArraysPrimitiveType) { + //std::cout << "osg::PrimitiveSet::DrawArraysPrimitiveType" << std::endl; + osg::ref_ptr < osg::DrawArrays > dra = dynamic_cast (geom->getPrimitiveSet(p)); + + unsigned int* indices = new unsigned int[dra->getCount()]; + for (int j = 0; j < dra->getCount(); j++) { + indices[j] = dra->getFirst() + j; + } + writeCoordIndex(mode, indices, dra->getCount(), primitiveSetFaces, primitiveFaces); + delete[] indices; + + } else if (type == osg::PrimitiveSet::DrawArrayLengthsPrimitiveType) { + //osg::notify(osg::WARN) << " osg::PrimitiveSet::DrawArrayLengthsPrimitiveType not supported by VRML Writer" << std::endl; + osg::ref_ptr < osg::DrawArrayLengths > dal = dynamic_cast (geom->getPrimitiveSet(p)); + + //std::cout<getFirst()<<" "<getNumPrimitives()<<" "<< dal->getNumIndices ()<<" "<< dal->getNumInstances()<getFirst(); prim < dal->getNumPrimitives(); prim++) { + //std::cout<<(*dal)[prim]< drui = dynamic_cast (geom->getPrimitiveSet(p)); + const unsigned char * indices = (const unsigned char*) (drui->getDataPointer()); + writeCoordIndex(mode, indices, drui->getNumIndices(), primitiveSetFaces, primitiveFaces); + + } else if (type == osg::PrimitiveSet::DrawElementsUShortPrimitiveType) { + //std::cout << "osg::PrimitiveSet::DrawElementsUShortPrimitiveType" << std::endl; + + osg::ref_ptr < osg::DrawElementsUShort > drui = dynamic_cast (geom->getPrimitiveSet(p)); + const unsigned short * indices = (const unsigned short*) (drui->getDataPointer()); + writeCoordIndex(mode, indices, drui->getNumIndices(), primitiveSetFaces, primitiveFaces); + + } else if (type == osg::PrimitiveSet::DrawElementsUIntPrimitiveType) { + //std::cout << "osg::PrimitiveSet::DrawElementsUIntPrimitiveType" << std::endl; + + osg::ref_ptr < osg::DrawElementsUInt > drui = dynamic_cast (geom->getPrimitiveSet(p)); + const unsigned int * indices = (const unsigned int*) (drui->getDataPointer()); + writeCoordIndex(mode, indices, drui->getNumIndices(), primitiveSetFaces, primitiveFaces); + } + + } + + } + _fout << indentL() << "]\n"; + indentL(); + + //write vertex + writeCoord((osg::Vec3Array*) (geom->getVertexArray())); + //write texture coordinate + if (_textureMode != NO_TEXTURE) { + writeTexCoord((osg::Vec2Array*) (geom->getTexCoordArray(_txtUnit)), (osg::Vec3Array*) (geom->getVertexArray())); + } + //write normals + writeNormal(geom, primitiveSetFaces, primitiveFaces); + //write colors + writeColor(geom, primitiveSetFaces, primitiveFaces); + } + + _fout << indent() << "}\n"; + _fout << indentL() << "}\n"; + +} + +///////////////////////////////////////////////////////////////////////// +// +// writeAppearance +// +///////////////////////////////////////////////////////////////////////// +void ToVRML::writeAppearance(osg::StateSet* stateset) { + + if (stateset == NULL) { + return; + } + + osg::ref_ptr < osg::StateSet > ss = stateset; + + _fout << indent() << "appearance Appearance {\n"; + osg::Material* mat = (osg::Material*) (ss->getAttribute(osg::StateAttribute::MATERIAL)); + osg::Texture2D* tex; + if (_textureMode == NO_TEXTURE) { + tex = NULL; + } else { + tex = (osg::Texture2D*) (ss->getTextureAttribute(_txtUnit, osg::StateAttribute::TEXTURE)); + } + + if (mat) { + + bool alreadyLoaded; + std::string name; + osg::Vec4 ambient, diffuse, specular, emission; + float shininess; + + ambient = mat->getAmbient(osg::Material::FRONT); + diffuse = mat->getDiffuse(osg::Material::FRONT); + specular = mat->getSpecular(osg::Material::FRONT); + shininess = mat->getShininess(osg::Material::FRONT); + emission = mat->getEmission(osg::Material::FRONT); + + float transp = 1 - (ambient[3] + diffuse[3] + specular[3] + emission[3]) / 4.0; + if (transp < 0) + transp = 0; + + //if (transp == 0 && tex) { + // if (tex->getImage()->isImageTranslucent()) { + // transp = 0.01; + // mat->setTransparency(osg::Material::FRONT,transp); + // } + //} + + findMaterialName(mat, name, alreadyLoaded); + if (alreadyLoaded) { + _fout << indentM() << "material USE " << name << "\n"; + indentL(); + } else { + + _fout << indentM() << "material DEF " << name << " Material {\n"; + //_fout << indentM() << "material Material {\n"; + _fout << indentM() << "diffuseColor " << diffuse[0] << " " << diffuse[1] << " " << diffuse[2] << "\n"; + _fout << indent() << "emissiveColor " << emission[0] << " " << emission[1] << " " << emission[2] << "\n"; + + _fout << indent() << "specularColor " << specular[0] << " " << specular[1] << " " << specular[2] << "\n"; + _fout << indent() << "shininess " << shininess << "\n"; + float ambientI = (ambient[0] + ambient[1] + ambient[2]) / 3.0; + if (ambientI > 1) + ambientI = 1; + _fout << indent() << "ambientIntensity " << ambientI << "\n"; + + _fout << indent() << "transparency " << transp << "\n"; + _fout << indentL() << "}\n"; + indentL(); + } + } + + if (tex) { + bool alreadyLoaded; + std::string name; + findTextureName(tex, name, alreadyLoaded); + if (alreadyLoaded) { + _fout << indentM() << "texture USE " << name << "\n"; + indentL(); + } else { + _fout << indentM() << "texture DEF " << name << " ImageTexture {\n"; + std::string texName = tex->getImage()->getFileName(); + if (_textureMode == COPY_TEXTURE || _textureMode == CONVERT_TEXTURE) { + texName = _pathRelativeToOutput + "/" + osgDB::getSimpleFileName(texName); + + } else if (_textureMode == KEEP_ORIGINAL_TEXTURE) { + texName = _pathRelativeToOutput + "/" + texName; + } + _fout << indentM() << "url [ \"" << texName << "\" ]\n"; + //std::cout<<"WRAP "<getWrap(osg::Texture::WRAP_S)<getWrap(osg::Texture::WRAP_S) == osg::Texture::REPEAT) { + _fout << indent() << "repeatS TRUE\n"; + } else { + _fout << indent() << "repeatS FALSE\n"; + } + if (tex->getWrap(osg::Texture::WRAP_T) == osg::Texture::REPEAT) { + _fout << indent() << "repeatT TRUE\n"; + } else { + _fout << indent() << "repeatT FALSE\n"; + } + _fout << indentL() << "}\n"; + indentL(); + } + } + + _fout << indent() << "}\n"; + +} + +///////////////////////////////////////////////////////////////////////// +// +// apply(osg::Group) +// +///////////////////////////////////////////////////////////////////////// +void ToVRML::apply(osg::Group& node) { + //cout << "Group" << endl; + _fout << indent() << "Group {\n"; + _fout << indentM() << "children [\n"; + + pushStateSetStack(node.getStateSet()); + + indentM(); + traverse(node); + indentL(); + + popStateSetStack(); + + _fout << indent() << "]\n"; + _fout << indentL() << "}\n"; +} + +///////////////////////////////////////////////////////////////////////// +// +// apply(osg::MatrixTransform) +// +///////////////////////////////////////////////////////////////////////// +void ToVRML::apply(osg::MatrixTransform& node) { + //cout << "MatrixTransform" << endl; + osg::Matrixf mat = node.getMatrix(); + // for(int i=0;i<16;i++){ + // cout < 0) { + fakeFirst = true; + } + if (node.getMaxRange(node.getNumRanges() - 1) < std::numeric_limits::max()) { + fakeLast = true; + } + + _fout << indentM() << "level [\n"; + if (fakeFirst) { + _fout << indentM() << "Shape {\n"; + _fout << indent() << "}\n"; + indentL(); + } + pushStateSetStack(node.getStateSet()); + indentM(); + traverse(node); + indentL(); + popStateSetStack(); + + if (fakeLast) { + _fout << indentM() << "Shape {\n"; + _fout << indent() << "}\n"; + indentL(); + } + + _fout << indent() << "]\n"; + + osg::Vec3 center; + if (node.getCenterMode() == osg::LOD::USER_DEFINED_CENTER) { + center = node.getCenter(); + } else { + center = node.getBound().center(); + } + _fout << indent() << "center " << center[0] << " " << center[1] << " " << center[2] << "\n"; + + _fout << indentM() << "range ["; + if (fakeFirst) { + _fout << indentM() << node.getMinRange(0) << ","; + } + for (unsigned int i = 0; i < node.getNumRanges(); i++) { + + _fout << indentM() << node.getMaxRange(i); + if (i < node.getNumRanges() - 1) { + _fout << ","; + } + } + _fout << "]\n"; + + _fout << indentL() << "}\n"; +} + +///////////////////////////////////////////////////////////////////////// +// +// apply(osg::Node) +// +///////////////////////////////////////////////////////////////////////// +void ToVRML::apply(osg::Node& node) { + osg::notify(osg::ALWAYS) << node.className() << " not supported" << endl; + pushStateSetStack(node.getStateSet()); + traverse(node); + popStateSetStack(); +} + +///////////////////////////////////////////////////////////////////////// +// +// pushStateSetStack +// +///////////////////////////////////////////////////////////////////////// +void ToVRML::pushStateSetStack(osg::StateSet* ss) { + _stack.push_back(osg::ref_ptr(ss)); +} + +///////////////////////////////////////////////////////////////////////// +// +// popStateSetStack +// +///////////////////////////////////////////////////////////////////////// +void ToVRML::popStateSetStack() { + if (!_stack.empty()) { + _stack.pop_back(); + } +} + +///////////////////////////////////////////////////////////////////////// +// +// getCurrentStateSet +// +///////////////////////////////////////////////////////////////////////// +osg::StateSet* ToVRML::getCurrentStateSet() { + // return current StateSet by flatten StateSet stack. + // until flatten is done, just return top StateSet + if (!_stack.empty()) { + osg::StateSet* ssFinal = new osg::StateSet(); + ssFinal->setGlobalDefaults(); + //std::cout << "StateSet Stack Size " << _stack.size() << std::endl; + for (unsigned int i = 0; i < _stack.size(); i++) { + osg::StateSet* ssCur = _stack[i].get(); + if (ssCur != NULL) { + ssFinal->merge(*ssCur); + } + } + return (ssFinal); + } else + return (NULL); +} + +///////////////////////////////////////////////////////////////////////// +// +// findMaterialName +// +///////////////////////////////////////////////////////////////////////// +void ToVRML::findMaterialName(osg::Material* mat, std::string& name, bool& alreadyLoaded) { + + osg::Vec4 ambient, diffuse, specular, emission; + //float shininess; + std::map, std::string>::iterator it;// = _matMap.find(obj); + + for (it = _matMap.begin(); it != _matMap.end(); it++) { + osg::ref_ptr < osg::Material > matLoaded = it->first; + ambient = mat->getAmbient(osg::Material::FRONT); + //diffuse = mat->getDiffuse(osg::Material::FRONT); + //specular = mat->getSpecular(osg::Material::FRONT); + //shininess = mat->getShininess(osg::Material::FRONT); + //emission = mat->getEmission(osg::Material::FRONT); + //std::cout << "MATERIAL " << ambient[3] << " " << matLoaded->getAmbient(osg::Material::FRONT)[3] << std::endl; + + if ((matLoaded->getAmbient(osg::Material::FRONT) == mat->getAmbient(osg::Material::FRONT)) && (matLoaded->getDiffuse(osg::Material::FRONT) + == mat->getDiffuse(osg::Material::FRONT)) && (matLoaded->getSpecular(osg::Material::FRONT) == mat->getSpecular(osg::Material::FRONT)) + && (matLoaded->getShininess(osg::Material::FRONT) == mat->getShininess(osg::Material::FRONT)) && (matLoaded->getEmission(osg::Material::FRONT) + == mat->getEmission(osg::Material::FRONT))) { + + name = it->second; + alreadyLoaded = true; + return; + } + } + std::stringstream ss; + ss << "material_" << _matMap.size(); + name = ss.str(); + _matMap[mat] = name; + alreadyLoaded = false; + +} + +///////////////////////////////////////////////////////////////////////// +// +// findTextureName +// +///////////////////////////////////////////////////////////////////////// +void ToVRML::findTextureName(osg::Texture2D* tex, std::string& name, bool& alreadyLoaded) { + + //std::cout << "ORI -" << tex->getImage() << "- " << std::endl; + if (tex->getImage() == NULL) { + tex->setImage(_defaultImage.get()); + } + + std::string nameOri = osgDB::convertFileNameToNativeStyle(tex->getImage()->getFileName()); + std::string nameInput = osgDB::findDataFile(nameOri, NULL); + if (nameInput == "") { + osg::notify(osg::ALWAYS) << "WARNING: couldn't find texture named: -" << nameOri << "- use default one instead -" << _defaultImage->getFileName() << "-" << std::endl; + tex->setImage(_defaultImage.get()); + nameOri = osgDB::convertFileNameToNativeStyle(tex->getImage()->getFileName()); + nameInput = osgDB::findDataFile(nameOri, NULL); + } + + std::string nameOutput; + std::string::size_type pos = nameInput.find_last_of("."); + std::string ext = nameInput.substr(pos, nameInput.length() - pos); + + osg::ref_ptr < osg::Image > imgIn = osgDB::readImageFile(nameInput); + if (!imgIn.valid()) { + osg::notify(osg::ALWAYS) << "WARNING: couldn't read texture named: -" << nameOri << "- use default one instead -" << _defaultImage->getFileName() << "-" << std::endl; + tex->setImage(_defaultImage.get()); + nameOri = osgDB::convertFileNameToNativeStyle(tex->getImage()->getFileName()); + nameInput = osgDB::findDataFile(nameOri, NULL); + pos = nameInput.find_last_of("."); + nameInput.substr(pos, nameInput.length() - pos); + imgIn = _defaultImage.get(); + } + + //int nbBand = poSrcDS->GetRasterCount(); + if (_textureMode == KEEP_ORIGINAL_TEXTURE) { + nameOutput = nameInput; + + } else if (_textureMode == COPY_TEXTURE) { + nameOutput = _pathToOutput + "/" + _pathRelativeToOutput + "/" + osgDB::getSimpleFileName(nameInput); + + } else if (_textureMode == CONVERT_TEXTURE) { + nameOutput = _pathToOutput + "/" + _pathRelativeToOutput + "/" + osgDB::getSimpleFileName(nameInput); + if (ext != ".png" && ext != ".jpg") { + if (imgIn->isImageTranslucent()) {//(nbBand != 1 && nbBand != 3) { + nameOutput = _pathToOutput + "/" + _pathRelativeToOutput + "/" + osgDB::getSimpleFileName(nameInput.substr(0, pos) + ".png"); + } else { + nameOutput = _pathToOutput + "/" + _pathRelativeToOutput + "/" + osgDB::getSimpleFileName(nameInput.substr(0, pos) + ".jpg"); + } + } + } + + std::map, std::string>::iterator it; + for (it = _texMap.begin(); it != _texMap.end(); it++) { + osg::ref_ptr < osg::Texture2D > texLoaded = it->first; + + if ((nameOutput == texLoaded->getImage()->getFileName()) && (tex->getWrap(osg::Texture::WRAP_S) == texLoaded->getWrap(osg::Texture::WRAP_S)) + && (tex->getWrap(osg::Texture::WRAP_T) == texLoaded->getWrap(osg::Texture::WRAP_T))) { + name = it->second; + alreadyLoaded = true; + return; + } + } + + // first time we see these texture + // add it to textureMap + std::stringstream ss; + ss << "texture2D_" << _texMap.size(); + name = ss.str(); + _texMap[tex] = name; + alreadyLoaded = false; + + tex->getImage()->setFileName(nameOutput); + + if (nameInput == nameOutput) { + return; + } + // else write image file + + if (_textureMode == CONVERT_TEXTURE) { + // convert format (from dds to rgb or rgba, or from rgba to rgb) + std::string newName; + GLenum type = GL_UNSIGNED_BYTE; + GLenum pixelFormat; + GLint internalFormat; + int nbC; + if (imgIn->isImageTranslucent()) { + // convert to png if transparency + pixelFormat = GL_RGBA; + internalFormat = GL_RGBA; + nbC = 4; + } else { + // convert to jpeg if no transparency + pixelFormat = GL_RGB; + internalFormat = GL_RGB; + nbC = 3; + } + osg::ref_ptr < osg::Image > curImg = tex->getImage(); + osg::ref_ptr < osg::Image > mmImg = new osg::Image(); + unsigned char* data = new unsigned char[curImg->s() * curImg->t() * nbC]; + for (int j = 0; j < curImg->t(); j++) { + for (int i = 0; i < curImg->s(); i++) { + osg::Vec4 c = curImg->getColor(i, j); + data[(i + j * curImg->s()) * nbC] = c[0] * 255; + data[(i + j * curImg->s()) * nbC + 1] = c[1] * 255; + data[(i + j * curImg->s()) * nbC + 2] = c[2] * 255; + if (nbC == 4) { + data[(i + j * curImg->s()) * nbC + 3] = c[3] * 255; + } + } + } + mmImg->setImage(curImg->s(), curImg->t(), 1, internalFormat, pixelFormat, type, data, osg::Image::USE_NEW_DELETE, 1); + osgDB::writeImageFile(*(mmImg.get()), nameOutput); + + } else { + // no conversion needed, input and output have the same format, but path to image has changed + osgDB::writeImageFile(*(tex->getImage()), nameOutput); + } + +} + +///////////////////////////////////////////////////////////////////////// +// +// writeCoordIndex +// +///////////////////////////////////////////////////////////////////////// +template void ToVRML::writeCoordIndex(GLenum mode, T* indices, unsigned int number, std::vector& primitiveSetFaces, int& primitiveFaces) { + + int currentFaces = 0; + if (mode == osg::PrimitiveSet::TRIANGLES) { + //std::cout << "TRIANGLES" << std::endl; + for (unsigned int j = 0; j < number; j += 3) { + _fout << indent() << indices[j] << "," << indices[j + 1] << "," << indices[j + 2] << ",-1,\n"; + currentFaces++; + } + primitiveSetFaces.push_back(currentFaces); + primitiveFaces += currentFaces; + + } else if (mode == osg::PrimitiveSet::TRIANGLE_FAN) { + //std::cout << "TRIANGLE FAN" << std::endl; + int firstPoint = indices[0]; + int secondPoint = indices[1]; + for (unsigned int j = 2; j < number; j++) { + _fout << indent() << firstPoint << "," << secondPoint << "," << indices[j] << ",-1,\n"; + secondPoint = indices[j]; + currentFaces++; + } + primitiveSetFaces.push_back(currentFaces); + primitiveFaces += currentFaces; + + } else if (mode == osg::PrimitiveSet::TRIANGLE_STRIP) { + //std::cout << "TRIANGLE STRIP" << std::endl; + int firstPoint = indices[0]; + int secondPoint = indices[1]; + bool changeSecond = false; + for (unsigned int j = 2; j < number; j++) { + _fout << indent() << firstPoint << "," << secondPoint << "," << indices[j] << ",-1,\n"; + if (!changeSecond) { + firstPoint = indices[j]; + changeSecond = true; + } else { + secondPoint = indices[j]; + changeSecond = false; + } + currentFaces++; + } + primitiveSetFaces.push_back(currentFaces); + primitiveFaces += currentFaces; + + } else if (mode == osg::PrimitiveSet::QUADS) { + //std::cout << "QUADS" << std::endl; + for (unsigned int j = 0; j < number; j += 4) { + _fout << indent() << indices[j] << "," << indices[j + 1] << "," << indices[j + 2] << "," << indices[j + 3] << ",-1,\n"; + currentFaces++; + } + primitiveSetFaces.push_back(currentFaces); + primitiveFaces += currentFaces; + + } else if (mode == osg::PrimitiveSet::QUAD_STRIP) { + //std::cout << "QUADS STRIP" << std::endl; + int firstPoint = indices[0]; + int secondPoint = indices[1]; + for (unsigned int j = 2; j < number; j += 2) { + _fout << indent() << firstPoint << "," << secondPoint << "," << indices[j + 1] << " " << indices[j] << ",-1,\n"; + firstPoint = indices[j]; + secondPoint = indices[j + 1]; + currentFaces++; + } + primitiveSetFaces.push_back(currentFaces); + primitiveFaces += currentFaces; + + } else if (mode == osg::PrimitiveSet::POLYGON) { + //std::cout << "POLYGON" << std::endl; + _fout << indent(); + for (unsigned int j = 0; j < number; j++) { + _fout << indices[j] << ","; + } + currentFaces++; + _fout << "-1,\n"; + primitiveSetFaces.push_back(currentFaces); + primitiveFaces += currentFaces; + + } else { + osg::notify(osg::ALWAYS) << "Unknown Primitive Set Type : " << mode << std::endl; + } + +} + +///////////////////////////////////////////////////////////////////////// +// +// writeCoord +// +///////////////////////////////////////////////////////////////////////// +void ToVRML::writeCoord(osg::Vec3Array* array) { + + if (array == NULL) { + std::cerr << "Vec3Array is NULL" << std::endl; + return; + } + osg::ref_ptr < osg::Vec3Array > vArray = array; + + _fout << indentM() << "coord Coordinate {\n"; + _fout << indentM() << "point [\n"; + indentM(); + osg::Vec3 xyz; + for (unsigned int j = 0; j < vArray->size(); j++) { + xyz = (*vArray)[j]; + _fout << indent() << xyz[0] << " " << xyz[1] << " " << xyz[2] << ",\n"; + } + _fout << indentL() << "]\n"; + _fout << indentL() << "}\n"; + indentL(); +} + +///////////////////////////////////////////////////////////////////////// +// +// writeTexCoord +// +///////////////////////////////////////////////////////////////////////// +void ToVRML::writeTexCoord(osg::Vec2Array* array, osg::Vec3Array* array2) { + + osg::ref_ptr < osg::StateSet > ss = getCurrentStateSet(); + osg::Texture2D* tex = (osg::Texture2D*) (ss->getTextureAttribute(_txtUnit, osg::StateAttribute::TEXTURE)); + if (tex == NULL) { + return; + } + + osg::ref_ptr < osg::TexGen > texGen = dynamic_cast (ss->getTextureAttribute(_txtUnit, osg::StateAttribute::TEXGEN)); + osg::ref_ptr < osg::TexEnv > texEnv = dynamic_cast (ss->getTextureAttribute(_txtUnit, osg::StateAttribute::TEXENV)); + + osg::Texture::WrapMode wrap_s = tex->getWrap(osg::Texture::WRAP_S);//osg::Texture::REPEAT; + osg::Texture::WrapMode wrap_t = tex->getWrap(osg::Texture::WRAP_T);//osg::Texture::REPEAT; + + if (array != NULL) { + writeUVArray(array, wrap_s, wrap_t); + + } else if (texGen.valid()) { + //std::cout << "TEXGEN" << std::endl; + osg::ref_ptr < osg::Vec2Array > uvArray = buildUVArray(texGen.get(), array2); + if (uvArray.valid()) { + writeUVArray(uvArray.get(), wrap_s, wrap_t); + } + + } else if (texEnv.valid()) { + //std::cout << "TEXENV" << std::endl; + osg::ref_ptr < osg::Vec2Array > uvArray = buildUVArray(texEnv.get(), array2); + if (uvArray.valid()) { + writeUVArray(uvArray.get(), wrap_s, wrap_t); + } + } +} + +///////////////////////////////////////////////////////////////////////// +// +// writeNormal +// +///////////////////////////////////////////////////////////////////////// +void ToVRML::writeNormal(osg::Geometry* geom, std::vector& primitiveSetFaces, int nbFaces) { + + osg::ref_ptr < osg::Vec3Array > nArray = (osg::Vec3Array*) (geom->getNormalArray()); + if (!nArray.valid()) { + return; + } + + if (geom->getNormalBinding() == osg::Geometry::BIND_PER_VERTEX || geom->getNormalBinding() == osg::Geometry::BIND_OVERALL) { + _fout << indentM() << "normalPerVertex TRUE \n"; + } else { + _fout << indentM() << "normalPerVertex FALSE \n"; + } + + _fout << indent() << "normal Normal {\n"; + _fout << indentM() << "vector [\n"; + indentM(); + osg::Vec3 n; + + if (geom->getNormalBinding() == osg::Geometry::BIND_PER_VERTEX) { + for (unsigned int j = 0; j < (*nArray).size(); j++) { + n = (*nArray)[j]; + _fout << indent() << n[0] << " " << n[1] << " " << n[2] << ",\n"; + } + + } else if (geom->getNormalBinding() == osg::Geometry::BIND_OVERALL) { + n = (*nArray)[0]; + int size = ((osg::Vec3Array*) (geom->getVertexArray()))->size(); + for (int j = 0; j < size; j++) { + _fout << indent() << n[0] << " " << n[1] << " " << n[2] << ",\n"; + } + + } else if (geom->getNormalBinding() == osg::Geometry::BIND_PER_PRIMITIVE) { + for (unsigned int j = 0; j < (*nArray).size(); j++) { + n = (*nArray)[j]; + _fout << indent() << n[0] << " " << n[1] << " " << n[2] << ",\n"; + } + + } else if (geom->getNormalBinding() == osg::Geometry::BIND_PER_PRIMITIVE_SET) { + for (unsigned int j = 0; j < (*nArray).size(); j++) { + n = (*nArray)[j]; + for (int k = 0; k < primitiveSetFaces[j]; k++) { + _fout << indent() << n[0] << " " << n[1] << " " << n[2] << ",\n"; + } + } + } + + _fout << indentL() << "]\n"; + _fout << indentL() << "}\n"; + indentL(); +} + +///////////////////////////////////////////////////////////////////////// +// +// writeUVArray +// +///////////////////////////////////////////////////////////////////////// +void ToVRML::writeUVArray(osg::Vec2Array* uvArray, osg::Texture::WrapMode wrap_s, osg::Texture::WrapMode wrap_t) { + + _fout << indentM() << "texCoord TextureCoordinate {\n"; + _fout << indentM() << "point [\n"; + indentM(); + osg::Vec2 uv; + + for (unsigned int j = 0; j < (*uvArray).size(); j++) { + uv = (*uvArray)[j]; + if (wrap_s != osg::Texture::REPEAT) { + // clamp to 0-1 + if (uv[0] < 0) { + uv[0] = 0; + } else if (uv[0] > 1) { + uv[0] = 1; + } + } + if (wrap_t != osg::Texture::REPEAT) { + // clamp to 0-1 + if (uv[1] < 0) { + uv[1] = 0; + } else if (uv[1] > 1) { + uv[1] = 1; + } + } + _fout << indent() << uv[0] << " " << uv[1] << ",\n"; + } + _fout << indentL() << "]\n"; + _fout << indentL() << "}\n"; + indentL(); +} + +///////////////////////////////////////////////////////////////////////// +// +// buildUVArray +// +///////////////////////////////////////////////////////////////////////// +osg::Vec2Array* ToVRML::buildUVArray(osg::TexGen* tGen, osg::Vec3Array* array) { + osg::ref_ptr < osg::TexGen > texGen = tGen; + osg::ref_ptr < osg::Vec3Array > vArray = array; + osg::Vec2Array* uvRet = NULL; + + osg::TexGen::Mode mode = texGen->getMode(); + if (mode == osg::TexGen::OBJECT_LINEAR) { + //std::cout << "I know" << std::endl; + + uvRet = new osg::Vec2Array(); + osg::Plane planS = texGen->getPlane(osg::TexGen::S);//, osg::Vec4(1 / rangeS, 0, 0, -(adfGeoTransform[0] / rangeS))); + osg::Plane planT = texGen->getPlane(osg::TexGen::T);//, osg::Vec4(0, 1 / rangeT, 0, -(adfGeoTransform[3] + sy * adfGeoTransform[5]) / rangeT)); + osg::Vec4 pS = planS.asVec4(); + osg::Vec4 pT = planT.asVec4(); + double width, height, xmin, ymin; + width = 1.0 / pS[0]; + height = 1.0 / pT[1]; + xmin = -width * pS[3]; + ymin = -height * pT[3]; + + for (unsigned int j = 0; j < vArray->size(); j++) { + osg::Vec3d p = (*vArray)[j]; + double x, y; + osg::Vec2 uv; + x = p[0]; + y = p[1]; + uv[0] = (x - xmin) / width; + uv[1] = (y - ymin) / height; + (*uvRet).push_back(uv); + + } + } else { + osg::notify(osg::ALWAYS) << "Unknown TexGen mode" << std::endl; + } + + return (uvRet); +} + +///////////////////////////////////////////////////////////////////////// +// +// buildUVArray +// +///////////////////////////////////////////////////////////////////////// +osg::Vec2Array* ToVRML::buildUVArray(osg::TexEnv* tEnv, osg::Vec3Array* array) { + osg::ref_ptr < osg::TexEnv > texEnv = tEnv; + osg::Vec2Array* uvRet = NULL; + + osg::TexEnv::Mode mode = texEnv->getMode(); + //if (mode == osg::TexEnv::MODULATE) { + // std::cout << "I know" << std::endl; + //} else { + osg::notify(osg::ALWAYS) << "Unknown TexEnv mode" << std::endl; + //} + return (uvRet); +} + +///////////////////////////////////////////////////////////////////////// +// +// writeColor +// +///////////////////////////////////////////////////////////////////////// +void ToVRML::writeColor(osg::Geometry* geom, std::vector& primitiveSetFaces, int nbFaces) { + + osg::ref_ptr < osg::Vec4Array > cArray = (osg::Vec4Array*) (geom->getColorArray()); + if (!cArray.valid()) { + return; + } + + if (geom->getColorBinding() == osg::Geometry::BIND_PER_VERTEX || geom->getColorBinding() == osg::Geometry::BIND_OVERALL) { + _fout << indentM() << "colorPerVertex TRUE \n"; + } else { + _fout << indentM() << "colorPerVertex FALSE \n"; + } + + _fout << indent() << "color Color {\n"; + _fout << indentM() << "color [\n"; + indentM(); + osg::Vec4 c; + + if (geom->getColorBinding() == osg::Geometry::BIND_PER_VERTEX) { + for (unsigned int j = 0; j < (*cArray).size(); j++) { + c = (*cArray)[j]; + _fout << indent() << c[0] << " " << c[1] << " " << c[2] << ",\n"; + } + + } else if (geom->getColorBinding() == osg::Geometry::BIND_OVERALL) { + c = (*cArray)[0]; + int size = ((osg::Vec3Array*) (geom->getVertexArray()))->size(); + for (int j = 0; j < size; j++) { + _fout << indent() << c[0] << " " << c[1] << " " << c[2] << ",\n"; + } + + } else if (geom->getColorBinding() == osg::Geometry::BIND_PER_PRIMITIVE) { + for (unsigned int j = 0; j < (*cArray).size(); j++) { + c = (*cArray)[j]; + _fout << indent() << c[0] << " " << c[1] << " " << c[2] << ",\n"; + } + + } else if (geom->getColorBinding() == osg::Geometry::BIND_PER_PRIMITIVE_SET) { + for (unsigned int j = 0; j < (*cArray).size(); j++) { + c = (*cArray)[j]; + for (int k = 0; k < primitiveSetFaces[j]; k++) { + _fout << indent() << c[0] << " " << c[1] << " " << c[2] << ",\n"; + } + } + } + + _fout << indentL() << "]\n"; + _fout << indentL() << "}\n"; + indentL(); +} diff --git a/src/osgPlugins/vrml/ConvertToVRML.h b/src/osgPlugins/vrml/ConvertToVRML.h new file mode 100644 index 000000000..bf176ebe2 --- /dev/null +++ b/src/osgPlugins/vrml/ConvertToVRML.h @@ -0,0 +1,115 @@ +/* + * + * OSG to VRML2 converter for OpenSceneGraph. + * + * authors : + * Johan Nouvel (johan_nouvel@yahoo.com) + * + * + */ + + +#ifndef __convert_to_vrml_to_osg_ +#define __convert_to_vrml_to_osg_ 1 + +#include +#include + +// OSG headers +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; + +/** + * This function is called to write an osg graph into a VRML file + * + */ +osgDB::ReaderWriter::WriteResult convertToVRML(const osg::Node& root, const std::string& filename, const osgDB::ReaderWriter::Options* options=NULL) ; + +class ToVRML: public osg::NodeVisitor { + public: + + typedef enum { + NO_TEXTURE = 0, KEEP_ORIGINAL_TEXTURE = 1, COPY_TEXTURE = 2, CONVERT_TEXTURE = 3 + } TextureMode; + ToVRML(const std::string& fileName, const osgDB::ReaderWriter::Options* options); + virtual ~ToVRML(); + osgDB::ReaderWriter::WriteResult result() { + return (_res); + } + ; + + virtual void apply(osg::Geode& node); + virtual void apply(osg::Group& node); + virtual void apply(osg::Billboard& node); + virtual void apply(osg::MatrixTransform& node); + virtual void apply(osg::PositionAttitudeTransform& node); + virtual void apply(osg::Node& node); + virtual void apply(osg::LOD& node); + + char *indent(); + char *indentM(); + char *indentL(); + void pushStateSetStack(osg::StateSet* ss); + void popStateSetStack(); + osg::StateSet* getCurrentStateSet(); + + //void findObjectName(osg::Object* obj,std::string& name, bool& alreadyLoaded); + void findMaterialName(osg::Material* mat, std::string& name, bool& alreadyLoaded); + void findTextureName(osg::Texture2D* tex, std::string& name, bool& alreadyLoaded); + + void apply(osg::Geometry* geom); + void apply(osg::Drawable* drawable); + void writeAppearance(osg::StateSet* stateset); + void writeCoord(osg::Vec3Array* array); + template void writeCoordIndex(GLenum mode, T* indices, unsigned int number, std::vector& primitiveSetFaces, int& primitiveFaces); + void writeTexCoord(osg::Vec2Array* array, osg::Vec3Array* array2); + osg::Vec2Array* buildUVArray(osg::TexGen* tGen, osg::Vec3Array* array); + osg::Vec2Array* buildUVArray(osg::TexEnv* tEnv, osg::Vec3Array* array); + void writeUVArray(osg::Vec2Array* uvArray, osg::Texture::WrapMode wrap_s, osg::Texture::WrapMode wrap_t); + void writeNormal(osg::Geometry* geom, std::vector& primitiveSetFaces, int nbFaces); + void writeColor(osg::Geometry* geom, std::vector& primitiveSetFaces, int nbFaces); + + osgDB::ReaderWriter::WriteResult _res; + ofstream _fout; + int _indent; + char* _strIndent; + + map, std::string> _texMap; + map, std::string> _matMap; + vector > _stack; + osg::ref_ptr _defaultImage; + std::string _pathToOutput; + std::string _pathRelativeToOutput; + TextureMode _textureMode; + int _txtUnit; + +}; + +#endif diff --git a/src/osgPlugins/vrml/ReaderWriterVRML2.cpp b/src/osgPlugins/vrml/ReaderWriterVRML2.cpp index 519e5bad5..8b1c97dca 100644 --- a/src/osgPlugins/vrml/ReaderWriterVRML2.cpp +++ b/src/osgPlugins/vrml/ReaderWriterVRML2.cpp @@ -4,7 +4,10 @@ * * VRML2 file converter for OpenSceneGraph. * - * authors : Jan Ciger (jan.ciger@gmail.com), + * authors : + * Johan Nouvel (johan_nouvel@yahoo.com) for the writeNode function. + * + * Jan Ciger (jan.ciger@gmail.com), * Tolga Abaci (tolga.abaci@gmail.com), * Bruno Herbelin (bruno.herbelin@gmail.com) * @@ -16,6 +19,7 @@ */ #include "ReaderWriterVRML2.h" +#include "ConvertToVRML.h" #include #include @@ -223,6 +227,21 @@ osgDB::ReaderWriter::ReadResult ReaderWriterVRML2::readNode(const std::string& f catch (std::invalid_argument) { return ReadResult::FILE_NOT_HANDLED; } } +osgDB::ReaderWriter::WriteResult ReaderWriterVRML2::writeNode(const osg::Node& root,const std::string& filename, const osgDB::ReaderWriter::Options *options) const +{ + std::string ext = osgDB::getLowerCaseFileExtension(filename); + if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED; + + + osg::notify(osg::INFO) << "osgDB::ReaderWriterVRML::writeNode() Writing file " + << filename << std::endl; + + return(convertToVRML(root,filename,options)); +} + + + + osg::ref_ptr ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const { //static int osgLightNum = 0; //light diff --git a/src/osgPlugins/vrml/ReaderWriterVRML2.h b/src/osgPlugins/vrml/ReaderWriterVRML2.h index 7049479e1..64a74774b 100644 --- a/src/osgPlugins/vrml/ReaderWriterVRML2.h +++ b/src/osgPlugins/vrml/ReaderWriterVRML2.h @@ -4,7 +4,10 @@ * * VRML2 file converter for OpenSceneGraph. * - * authors : Jan Ciger (jan.ciger@gmail.com), + * authors : + * Johan Nouvel (johan_nouvel@yahoo.com) for the writeNode function. + * + * Jan Ciger (jan.ciger@gmail.com), * Tolga Abaci (tolga.abaci@gmail.com), * Bruno Herbelin (bruno.herbelin@gmail.com) * @@ -75,6 +78,8 @@ public: virtual ReadResult readNode(const std::string&, const osgDB::Options *options) const; // virtual ReadResult readNode(std::istream& fin, const osgDB::Options* options) const; + virtual WriteResult writeNode(const osg::Node&,const std::string& filename,const osgDB::ReaderWriter::Options *options) const; + private: typedef std::map > SphereLibrary; typedef std::map > BoxLibrary;