From 5ea4a8c0f35c8b13bb51bc7cc8c601fa90207c98 Mon Sep 17 00:00:00 2001 From: Michael PLATINGS Date: Wed, 9 Jun 2010 09:12:20 +0000 Subject: [PATCH] From Alessandro Terenzi: previously the plugin ignored UV scaling values eventually stored in the FBX file, now they are read and set for each supported texture map (not considering reflection maps). From Michael Platings: fixed UVs for files that don't explicitly reference the name of a UV channel. --- src/osgPlugins/fbx/ReaderWriterFBX.cpp | 3 +- .../fbx/fbxMaterialToOsgStateSet.cpp | 29 ++++--- src/osgPlugins/fbx/fbxMaterialToOsgStateSet.h | 7 ++ src/osgPlugins/fbx/fbxRMesh.cpp | 76 ++++++++++++++----- 4 files changed, 79 insertions(+), 36 deletions(-) diff --git a/src/osgPlugins/fbx/ReaderWriterFBX.cpp b/src/osgPlugins/fbx/ReaderWriterFBX.cpp index 9bc26f322..8d1c72c60 100644 --- a/src/osgPlugins/fbx/ReaderWriterFBX.cpp +++ b/src/osgPlugins/fbx/ReaderWriterFBX.cpp @@ -464,7 +464,8 @@ osgDB::ReaderWriter::WriteResult ReaderWriterFBX::writeNode( { // If root node is a simple group, put all elements under the FBX root const osg::Group * osgGroup = node.asGroup(); - for(unsigned int child=0; childgetNumChildren(); ++child) { + for (unsigned int child = 0; child < osgGroup->getNumChildren(); ++child) + { const_cast(osgGroup->getChild(child))->accept(writerNodeVisitor); } } diff --git a/src/osgPlugins/fbx/fbxMaterialToOsgStateSet.cpp b/src/osgPlugins/fbx/fbxMaterialToOsgStateSet.cpp index 8183e25b8..3f488d72b 100644 --- a/src/osgPlugins/fbx/fbxMaterialToOsgStateSet.cpp +++ b/src/osgPlugins/fbx/fbxMaterialToOsgStateSet.cpp @@ -22,13 +22,6 @@ FbxMaterialToOsgStateSet::convert(const KFbxSurfaceMaterial* pFbxMat) osg::ref_ptr pOsgMat = new osg::Material; pOsgMat->setName(pFbxMat->GetName()); - // texture maps... - osg::ref_ptr pOsgDiffuseTex = NULL; - osg::ref_ptr pOsgReflectionTex = NULL; - osg::ref_ptr pOsgOpacityTex = NULL; - osg::ref_ptr pOsgEmissiveTex = NULL; - // add more maps here... - StateSetContent result; result.material = pOsgMat; @@ -47,9 +40,10 @@ FbxMaterialToOsgStateSet::convert(const KFbxSurfaceMaterial* pFbxMat) KFbxTexture* lTexture = KFbxCast(lProperty.GetSrcObject(KFbxTexture::ClassId, lTextureIndex)); if (lTexture) { - pOsgDiffuseTex = fbxTextureToOsgTexture(lTexture); - result.diffuseTexture = pOsgDiffuseTex.release(); + result.diffuseTexture = fbxTextureToOsgTexture(lTexture); result.diffuseChannel = lTexture->UVSet.Get(); + result.diffuseScaleU = lTexture->GetScaleU(); + result.diffuseScaleV = lTexture->GetScaleV(); } //For now only allow 1 texture @@ -67,9 +61,12 @@ FbxMaterialToOsgStateSet::convert(const KFbxSurfaceMaterial* pFbxMat) KFbxTexture* lTexture = KFbxCast(lOpacityProperty.GetSrcObject(KFbxTexture::ClassId, lTextureIndex)); if (lTexture) { - pOsgOpacityTex = fbxTextureToOsgTexture(lTexture); - result.opacityTexture = pOsgOpacityTex.release(); + // TODO: if texture image does NOT have an alpha channel, should it be added? + + result.opacityTexture = fbxTextureToOsgTexture(lTexture); result.opacityChannel = lTexture->UVSet.Get(); + result.opacityScaleU = lTexture->GetScaleU(); + result.opacityScaleV = lTexture->GetScaleV(); } //For now only allow 1 texture @@ -90,8 +87,7 @@ FbxMaterialToOsgStateSet::convert(const KFbxSurfaceMaterial* pFbxMat) // support only spherical reflection maps... if (KFbxTexture::eUMT_ENVIRONMENT == lTexture->GetMappingType()) { - pOsgReflectionTex = fbxTextureToOsgTexture(lTexture); - result.reflectionTexture = pOsgReflectionTex.release(); + result.reflectionTexture = fbxTextureToOsgTexture(lTexture); result.reflectionChannel = lTexture->UVSet.Get(); } } @@ -111,9 +107,10 @@ FbxMaterialToOsgStateSet::convert(const KFbxSurfaceMaterial* pFbxMat) KFbxTexture* lTexture = KFbxCast(lEmissiveProperty.GetSrcObject(KFbxTexture::ClassId, lTextureIndex)); if (lTexture) { - pOsgEmissiveTex = fbxTextureToOsgTexture(lTexture); - result.emissiveTexture = pOsgEmissiveTex.release(); + result.emissiveTexture = fbxTextureToOsgTexture(lTexture); result.emissiveChannel = lTexture->UVSet.Get(); + result.emissiveScaleU = lTexture->GetScaleU(); + result.emissiveScaleV = lTexture->GetScaleV(); } //For now only allow 1 texture @@ -203,7 +200,7 @@ FbxMaterialToOsgStateSet::fbxTextureToOsgTexture(const KFbxTexture* fbx) pOsgTex->setWrap(osg::Texture2D::WRAP_S, convertWrap(fbx->GetWrapModeU())); pOsgTex->setWrap(osg::Texture2D::WRAP_T, convertWrap(fbx->GetWrapModeV())); _imageMap.insert(std::make_pair(fbx->GetFileName(), pOsgTex.get())); - return pOsgTex.release(); + return pOsgTex; } else { diff --git a/src/osgPlugins/fbx/fbxMaterialToOsgStateSet.h b/src/osgPlugins/fbx/fbxMaterialToOsgStateSet.h index b69d2c3e0..2e2bc97cc 100644 --- a/src/osgPlugins/fbx/fbxMaterialToOsgStateSet.h +++ b/src/osgPlugins/fbx/fbxMaterialToOsgStateSet.h @@ -49,6 +49,13 @@ struct StateSetContent double emissiveFactor; // more combining factors here... + double diffuseScaleU; + double diffuseScaleV; + double opacityScaleU; + double opacityScaleV; + double emissiveScaleU; + double emissiveScaleV; + // texture units (eventually used for each texture map)... enum TextureUnit { diff --git a/src/osgPlugins/fbx/fbxRMesh.cpp b/src/osgPlugins/fbx/fbxRMesh.cpp index 8052ea548..a20841cf9 100644 --- a/src/osgPlugins/fbx/fbxRMesh.cpp +++ b/src/osgPlugins/fbx/fbxRMesh.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -202,6 +203,16 @@ osg::Geometry* getGeometry(osg::Geode* pGeode, GeometryMap& geometryMap, { stateSet->setTextureAttributeAndModes(StateSetContent::DIFFUSE_TEXTURE_UNIT, ssc.diffuseTexture.get()); + if (ssc.diffuseScaleU != 1.0 || ssc.diffuseScaleV != 1.0) + { + // set UV scaling... + osg::ref_ptr texmat = new osg::TexMat(); + osg::Matrix uvScaling; + uvScaling.makeScale(osg::Vec3(ssc.diffuseScaleU, ssc.diffuseScaleV, 1.0)); + texmat->setMatrix(uvScaling); + stateSet->setTextureAttributeAndModes(StateSetContent::DIFFUSE_TEXTURE_UNIT, texmat.get(), osg::StateAttribute::ON); + } + if (lightmapTextures) { double factor = ssc.diffuseFactor; @@ -224,6 +235,16 @@ osg::Geometry* getGeometry(osg::Geode* pGeode, GeometryMap& geometryMap, { stateSet->setTextureAttributeAndModes(StateSetContent::OPACITY_TEXTURE_UNIT, ssc.opacityTexture.get()); + if (ssc.opacityScaleU != 1.0 || ssc.opacityScaleV != 1.0) + { + // set UV scaling... + osg::ref_ptr texmat = new osg::TexMat(); + osg::Matrix uvScaling; + uvScaling.makeScale(osg::Vec3(ssc.opacityScaleU, ssc.opacityScaleV, 1.0)); + texmat->setMatrix(uvScaling); + stateSet->setTextureAttributeAndModes(StateSetContent::OPACITY_TEXTURE_UNIT, texmat.get(), osg::StateAttribute::ON); + } + // setup combiner for factor... //In practice factor will always be zero, hence the RGB of the //opacity map will be ignored. The alpha will modulate the previous alpha. @@ -265,6 +286,16 @@ osg::Geometry* getGeometry(osg::Geode* pGeode, GeometryMap& geometryMap, // emissive texture map if (ssc.emissiveTexture) { + if (ssc.emissiveScaleU != 1.0 || ssc.emissiveScaleV != 1.0) + { + // set UV scaling... + osg::ref_ptr texmat = new osg::TexMat(); + osg::Matrix uvScaling; + uvScaling.makeScale(osg::Vec3(ssc.emissiveScaleU, ssc.emissiveScaleV, 1.0)); + texmat->setMatrix(uvScaling); + stateSet->setTextureAttributeAndModes(StateSetContent::EMISSIVE_TEXTURE_UNIT, texmat.get(), osg::StateAttribute::ON); + } + stateSet->setTextureAttributeAndModes(StateSetContent::EMISSIVE_TEXTURE_UNIT, ssc.emissiveTexture.get()); } @@ -442,7 +473,7 @@ std::string getUVChannelForTextureMap(std::vector& stateSetList { // will return the first occurrence in the state set list... // TODO: what if more than one channel for the same map type? - for (unsigned int i=0; i < stateSetList.size(); i++) + for (unsigned int i = 0; i < stateSetList.size(); i++) { if (0 == strcmp(pName, KFbxSurfaceMaterial::sDiffuse)) return stateSetList[i].diffuseChannel; @@ -458,27 +489,36 @@ std::string getUVChannelForTextureMap(std::vector& stateSetList return ""; } -// scans mesh layers looking for the UV element corrensponding to the specified channel name... -const KFbxLayerElementUV* getUVElementForChannel(std::string pUVChannel, KFbxMesh* pFbxMesh) +// scans mesh layers looking for the UV element corresponding to the specified channel name... +const KFbxLayerElementUV* getUVElementForChannel(std::string uvChannelName, + KFbxLayerElement::ELayerElementType elementType, KFbxMesh* pFbxMesh) { - const KFbxLayer* pFbxLayer = 0; - const KFbxLayerElementUV* uv = 0; - // scan layers for specified UV channel... - for (int cLayerIndex=0; cLayerIndex < pFbxMesh->GetLayerCount(); cLayerIndex++) + for (int cLayerIndex = 0; cLayerIndex < pFbxMesh->GetLayerCount(); cLayerIndex++) { - pFbxLayer = pFbxMesh->GetLayer(cLayerIndex); + const KFbxLayer* pFbxLayer = pFbxMesh->GetLayer(cLayerIndex); if (!pFbxLayer) continue; - uv = pFbxLayer->GetUVs(); - if (uv) + if (const KFbxLayerElementUV* uv = pFbxLayer->GetUVs()) { - if (0 == pUVChannel.compare(uv->GetName())) + if (0 == uvChannelName.compare(uv->GetName())) return uv; } } + for (int cLayerIndex = 0; cLayerIndex < pFbxMesh->GetLayerCount(); cLayerIndex++) + { + const KFbxLayer* pFbxLayer = pFbxMesh->GetLayer(cLayerIndex); + if (!pFbxLayer) + continue; + + if (const KFbxLayerElementUV* uv = pFbxLayer->GetUVs(elementType)) + { + return uv; + } + } + return 0; } @@ -493,8 +533,6 @@ osgDB::ReaderWriter::ReadResult OsgFbxReader::readMesh( osg::Geode* pGeode = new osg::Geode; pGeode->setName(szName); - const KFbxLayer* pFbxLayer = 0; - const KFbxLayerElementNormal* pFbxNormals = 0; const KFbxLayerElementVertexColor* pFbxColors = 0; const KFbxLayerElementMaterial* pFbxMaterials = 0; @@ -502,9 +540,9 @@ osgDB::ReaderWriter::ReadResult OsgFbxReader::readMesh( const KFbxVector4* pFbxVertices = fbxMesh->GetControlPoints(); // scan layers for Normals, Colors and Materials elements (this will get the first available elements)... - for (int cLayerIndex=0; cLayerIndex < fbxMesh->GetLayerCount(); cLayerIndex++) + for (int cLayerIndex = 0; cLayerIndex < fbxMesh->GetLayerCount(); cLayerIndex++) { - pFbxLayer = fbxMesh->GetLayer(cLayerIndex); + const KFbxLayer* pFbxLayer = fbxMesh->GetLayer(cLayerIndex); if (!pFbxLayer) continue; @@ -520,13 +558,13 @@ osgDB::ReaderWriter::ReadResult OsgFbxReader::readMesh( // look for UV elements (diffuse, opacity, reflection, emissive, ...) and get their channels names... std::string diffuseChannel = getUVChannelForTextureMap(stateSetList, KFbxSurfaceMaterial::sDiffuse); std::string opacityChannel = getUVChannelForTextureMap(stateSetList, KFbxSurfaceMaterial::sTransparentColor); - std::string emissiveChannel = getUVChannelForTextureMap(stateSetList, KFbxSurfaceMaterial::sEmissive);; + std::string emissiveChannel = getUVChannelForTextureMap(stateSetList, KFbxSurfaceMaterial::sEmissive); // look for more UV elements here... // UV elements... - const KFbxLayerElementUV* pFbxUVs_diffuse = getUVElementForChannel(diffuseChannel, fbxMesh); - const KFbxLayerElementUV* pFbxUVs_opacity = getUVElementForChannel(opacityChannel, fbxMesh); - const KFbxLayerElementUV* pFbxUVs_emissive = getUVElementForChannel(emissiveChannel, fbxMesh); + const KFbxLayerElementUV* pFbxUVs_diffuse = getUVElementForChannel(diffuseChannel, KFbxLayerElement::eDIFFUSE_TEXTURES, fbxMesh); + const KFbxLayerElementUV* pFbxUVs_opacity = getUVElementForChannel(opacityChannel, KFbxLayerElement::eTRANSPARENT_TEXTURES, fbxMesh); + const KFbxLayerElementUV* pFbxUVs_emissive = getUVElementForChannel(emissiveChannel, KFbxLayerElement::eEMISSIVE_TEXTURES, fbxMesh); // more UV elements here... // check elements validity...