root/OpenSceneGraph/trunk/src/osgPlugins/fbx/fbxMaterialToOsgStateSet.cpp @ 13466

Revision 13466, 9.1 kB (checked in by robert, 3 hours ago)

Added shaders to support experimental shader based displacement mapping technique osgTerrain::ShaderTerrain?.

  • Property svn:eol-style set to native
Line 
1#include "fbxMaterialToOsgStateSet.h"
2#include <sstream>
3#include <osgDB/ReadFile>
4#include <osgDB/FileUtils>
5#include <osgDB/FileNameUtils>
6
7
8static osg::Texture::WrapMode convertWrap(FbxFileTexture::EWrapMode wrap)
9{
10    return wrap == FbxFileTexture::eRepeat ?
11        osg::Texture2D::REPEAT : osg::Texture2D::CLAMP_TO_EDGE;
12}
13
14StateSetContent
15FbxMaterialToOsgStateSet::convert(const FbxSurfaceMaterial* pFbxMat)
16{
17    FbxMaterialMap::const_iterator it = _fbxMaterialMap.find(pFbxMat);
18    if (it != _fbxMaterialMap.end())
19        return it->second;
20
21    osg::ref_ptr<osg::Material> pOsgMat = new osg::Material;
22    pOsgMat->setName(pFbxMat->GetName());
23
24    StateSetContent result;
25
26    result.material = pOsgMat;
27
28    FbxString shadingModel = pFbxMat->ShadingModel.Get();
29
30    const FbxSurfaceLambert* pFbxLambert = FbxCast<FbxSurfaceLambert>(pFbxMat);
31
32    // diffuse map...
33    const FbxProperty lProperty = pFbxMat->FindProperty(FbxSurfaceMaterial::sDiffuse);
34    if (lProperty.IsValid())
35    {
36        int lNbTex = lProperty.GetSrcObjectCount<FbxFileTexture>();
37        for (int lTextureIndex = 0; lTextureIndex < lNbTex; lTextureIndex++)
38        {
39            FbxFileTexture* lTexture = FbxCast<FbxFileTexture>(lProperty.GetSrcObject<FbxFileTexture>(lTextureIndex));
40            if (lTexture)
41            {
42                result.diffuseTexture = fbxTextureToOsgTexture(lTexture);
43                result.diffuseChannel = lTexture->UVSet.Get();
44                result.diffuseScaleU = lTexture->GetScaleU();
45                result.diffuseScaleV = lTexture->GetScaleV();
46            }
47
48            //For now only allow 1 texture
49            break;
50        }
51    }
52
53    // opacity map...
54    const FbxProperty lOpacityProperty = pFbxMat->FindProperty(FbxSurfaceMaterial::sTransparentColor);
55    if (lOpacityProperty.IsValid())
56    {
57        int lNbTex = lOpacityProperty.GetSrcObjectCount<FbxFileTexture>();
58        for (int lTextureIndex = 0; lTextureIndex < lNbTex; lTextureIndex++)
59        {
60            FbxFileTexture* lTexture = FbxCast<FbxFileTexture>(lOpacityProperty.GetSrcObject<FbxFileTexture>(lTextureIndex));
61            if (lTexture)
62            {
63                // TODO: if texture image does NOT have an alpha channel, should it be added?
64
65                result.opacityTexture = fbxTextureToOsgTexture(lTexture);
66                result.opacityChannel = lTexture->UVSet.Get();
67                result.opacityScaleU = lTexture->GetScaleU();
68                result.opacityScaleV = lTexture->GetScaleV();
69            }
70
71            //For now only allow 1 texture
72            break;
73        }
74    }
75
76    // reflection map...
77    const FbxProperty lReflectionProperty = pFbxMat->FindProperty(FbxSurfaceMaterial::sReflection);
78    if (lReflectionProperty.IsValid())
79    {
80        int lNbTex = lReflectionProperty.GetSrcObjectCount<FbxFileTexture>();
81        for (int lTextureIndex = 0; lTextureIndex < lNbTex; lTextureIndex++)
82        {
83            FbxFileTexture* lTexture = FbxCast<FbxFileTexture>(lReflectionProperty.GetSrcObject<FbxFileTexture>(lTextureIndex));
84            if (lTexture)
85            {
86                // support only spherical reflection maps...
87                if (FbxFileTexture::eUMT_ENVIRONMENT == lTexture->CurrentMappingType.Get())
88                {
89                    result.reflectionTexture = fbxTextureToOsgTexture(lTexture);
90                    result.reflectionChannel = lTexture->UVSet.Get();
91                }
92            }
93
94            //For now only allow 1 texture
95            break;
96        }
97    }
98
99    // emissive map...
100    const FbxProperty lEmissiveProperty = pFbxMat->FindProperty(FbxSurfaceMaterial::sEmissive);
101    if (lEmissiveProperty.IsValid())
102    {
103        int lNbTex = lEmissiveProperty.GetSrcObjectCount<FbxFileTexture>();
104        for (int lTextureIndex = 0; lTextureIndex < lNbTex; lTextureIndex++)
105        {
106            FbxFileTexture* lTexture = FbxCast<FbxFileTexture>(lEmissiveProperty.GetSrcObject<FbxFileTexture>(lTextureIndex));
107            if (lTexture)
108            {
109                result.emissiveTexture = fbxTextureToOsgTexture(lTexture);
110                result.emissiveChannel = lTexture->UVSet.Get();
111                result.emissiveScaleU = lTexture->GetScaleU();
112                result.emissiveScaleV = lTexture->GetScaleV();
113            }
114
115            //For now only allow 1 texture
116            break;
117        }
118    }
119
120    if (pFbxLambert)
121    {
122        FbxDouble3 color = pFbxLambert->Diffuse.Get();
123        double factor = pFbxLambert->DiffuseFactor.Get();
124        pOsgMat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(
125            static_cast<float>(color[0] * factor),
126            static_cast<float>(color[1] * factor),
127            static_cast<float>(color[2] * factor),
128            static_cast<float>(1.0 - pFbxLambert->TransparencyFactor.Get())));
129
130        color = pFbxLambert->Ambient.Get();
131        factor = pFbxLambert->AmbientFactor.Get();
132        pOsgMat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(
133            static_cast<float>(color[0] * factor),
134            static_cast<float>(color[1] * factor),
135            static_cast<float>(color[2] * factor),
136            1.0f));
137
138        color = pFbxLambert->Emissive.Get();
139        factor = pFbxLambert->EmissiveFactor.Get();
140        pOsgMat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(
141            static_cast<float>(color[0] * factor),
142            static_cast<float>(color[1] * factor),
143            static_cast<float>(color[2] * factor),
144            1.0f));
145
146        // get maps factors...
147        result.diffuseFactor = pFbxLambert->DiffuseFactor.Get();
148
149        if (const FbxSurfacePhong* pFbxPhong = FbxCast<FbxSurfacePhong>(pFbxLambert))
150        {
151            color = pFbxPhong->Specular.Get();
152            factor = pFbxPhong->SpecularFactor.Get();
153            pOsgMat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(
154                static_cast<float>(color[0] * factor),
155                static_cast<float>(color[1] * factor),
156                static_cast<float>(color[2] * factor),
157                1.0f));
158
159            pOsgMat->setShininess(osg::Material::FRONT_AND_BACK,
160                static_cast<float>(pFbxPhong->Shininess.Get()));
161
162            // get maps factors...
163            result.reflectionFactor = pFbxPhong->ReflectionFactor.Get();
164            // get more factors here...
165        }
166    }
167
168    if (_lightmapTextures)
169    {
170        // if using an emission map then adjust material properties accordingly...
171        if (result.emissiveTexture)
172        {
173            osg::Vec4 diffuse = pOsgMat->getDiffuse(osg::Material::FRONT_AND_BACK);
174            pOsgMat->setEmission(osg::Material::FRONT_AND_BACK, diffuse);
175            pOsgMat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0,0,0,diffuse.a()));
176            pOsgMat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0,0,0,diffuse.a()));
177        }
178    }
179
180    _fbxMaterialMap.insert(FbxMaterialMap::value_type(pFbxMat, result));
181    return result;
182}
183
184osg::ref_ptr<osg::Texture2D>
185FbxMaterialToOsgStateSet::fbxTextureToOsgTexture(const FbxFileTexture* fbx)
186{
187    ImageMap::iterator it = _imageMap.find(fbx->GetFileName());
188    if (it != _imageMap.end())
189        return it->second;
190    osg::ref_ptr<osg::Image> pImage = NULL;
191
192    // Warning: fbx->GetRelativeFileName() is relative TO EXECUTION DIR
193    //          fbx->GetFileName() is as stored initially in the FBX
194    if ((pImage = osgDB::readImageFile(osgDB::concatPaths(_dir, fbx->GetFileName()), _options)) ||                // First try "export dir/name"
195        (pImage = osgDB::readImageFile(fbx->GetFileName(), _options)) ||                                        // Then try  "name" (if absolute)
196        (pImage = osgDB::readImageFile(osgDB::concatPaths(_dir, fbx->GetRelativeFileName()), _options)))        // Else try  "current dir/name"
197    {
198        osg::ref_ptr<osg::Texture2D> pOsgTex = new osg::Texture2D;
199        pOsgTex->setImage(pImage.get());
200        pOsgTex->setWrap(osg::Texture2D::WRAP_S, convertWrap(fbx->GetWrapModeU()));
201        pOsgTex->setWrap(osg::Texture2D::WRAP_T, convertWrap(fbx->GetWrapModeV()));
202        _imageMap.insert(std::make_pair(fbx->GetFileName(), pOsgTex.get()));
203        return pOsgTex;
204    }
205    else
206    {
207        return NULL;
208    }
209}
210
211void FbxMaterialToOsgStateSet::checkInvertTransparency()
212{
213    int zeroAlpha = 0, oneAlpha = 0;
214    for (FbxMaterialMap::const_iterator it = _fbxMaterialMap.begin(); it != _fbxMaterialMap.end(); ++it)
215    {
216        const osg::Material* pMaterial = it->second.material.get();
217        float alpha = pMaterial->getDiffuse(osg::Material::FRONT).a();
218        if (alpha > 0.999f)
219        {
220            ++oneAlpha;
221        }
222        else if (alpha < 0.001f)
223        {
224            ++zeroAlpha;
225        }
226    }
227
228    if (zeroAlpha > oneAlpha)
229    {
230        //Transparency values seem to be back to front so invert them.
231
232        for (FbxMaterialMap::const_iterator it = _fbxMaterialMap.begin(); it != _fbxMaterialMap.end(); ++it)
233        {
234            osg::Material* pMaterial = it->second.material.get();
235            osg::Vec4 diffuse = pMaterial->getDiffuse(osg::Material::FRONT);
236            diffuse.a() = 1.0f - diffuse.a();
237            pMaterial->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse);
238        }
239    }
240}
Note: See TracBrowser for help on using the browser.