100 lines
3.2 KiB
C++
100 lines
3.2 KiB
C++
#include <osg/LightSource>
|
|
|
|
#include <osgDB/ReadFile>
|
|
|
|
#if defined(_MSC_VER)
|
|
#pragma warning( disable : 4505 )
|
|
#pragma warning( default : 4996 )
|
|
#endif
|
|
#include <fbxsdk.h>
|
|
|
|
#include "fbxReader.h"
|
|
|
|
osgDB::ReaderWriter::ReadResult OsgFbxReader::readFbxLight(FbxNode* pNode, int& nLightCount)
|
|
{
|
|
const FbxLight* fbxLight = FbxCast<FbxLight>(pNode->GetNodeAttribute());
|
|
|
|
if (!fbxLight)
|
|
{
|
|
return osgDB::ReaderWriter::ReadResult::ERROR_IN_READING_FILE;
|
|
}
|
|
|
|
osg::Light* osgLight = new osg::Light;
|
|
osgLight->setLightNum(nLightCount++);
|
|
|
|
osg::LightSource* osgLightSource = new osg::LightSource;
|
|
osgLightSource->setLight(osgLight);
|
|
|
|
FbxLight::EType fbxLightType = fbxLight->LightType.IsValid() ?
|
|
fbxLight->LightType.Get() : FbxLight::ePoint;
|
|
|
|
osgLight->setPosition(osg::Vec4(0,0,0,fbxLightType != FbxLight::eDirectional));
|
|
|
|
if (fbxLightType == FbxLight::eSpot)
|
|
{
|
|
double coneAngle = fbxLight->OuterAngle.Get();
|
|
double hotSpot = fbxLight->InnerAngle.Get();
|
|
const float MIN_HOTSPOT = 0.467532f;
|
|
|
|
osgLight->setSpotCutoff(static_cast<float>(coneAngle));
|
|
|
|
//Approximate the hotspot using the GL light exponent.
|
|
// This formula maps a hotspot of 180 to exponent 0 (uniform light
|
|
// distribution) and a hotspot of 45 to exponent 1 (effective light
|
|
// intensity is attenuated by the cosine of the angle between the
|
|
// direction of the light and the direction from the light to the vertex
|
|
// being lighted). A hotspot close to 0 maps to exponent 128 (maximum).
|
|
float exponent = (180.0f / (std::max)(static_cast<float>(hotSpot),
|
|
MIN_HOTSPOT) - 1.0f) / 3.0f;
|
|
osgLight->setSpotExponent(exponent);
|
|
}
|
|
|
|
if (fbxLight->DecayType.IsValid() &&
|
|
fbxLight->DecayStart.IsValid())
|
|
{
|
|
double fbxDecayStart = fbxLight->DecayStart.Get();
|
|
|
|
switch (fbxLight->DecayType.Get())
|
|
{
|
|
case FbxLight::eNone:
|
|
break;
|
|
case FbxLight::eLinear:
|
|
osgLight->setLinearAttenuation(fbxDecayStart);
|
|
break;
|
|
case FbxLight::eQuadratic:
|
|
case FbxLight::eCubic:
|
|
osgLight->setQuadraticAttenuation(fbxDecayStart);
|
|
break;
|
|
}
|
|
}
|
|
|
|
osg::Vec3f osgDiffuseSpecular(1.0f, 1.0f, 1.0f);
|
|
osg::Vec3f osgAmbient(0.0f, 0.0f, 0.0f);
|
|
if (fbxLight->Color.IsValid())
|
|
{
|
|
FbxDouble3 fbxColor = fbxLight->Color.Get();
|
|
osgDiffuseSpecular.set(
|
|
static_cast<float>(fbxColor[0]),
|
|
static_cast<float>(fbxColor[1]),
|
|
static_cast<float>(fbxColor[2]));
|
|
}
|
|
if (fbxLight->Intensity.IsValid())
|
|
{
|
|
osgDiffuseSpecular *= static_cast<float>(fbxLight->Intensity.Get()) * 0.01f;
|
|
}
|
|
if (fbxLight->ShadowColor.IsValid())
|
|
{
|
|
FbxDouble3 fbxShadowColor = fbxLight->ShadowColor.Get();
|
|
osgAmbient.set(
|
|
static_cast<float>(fbxShadowColor[0]),
|
|
static_cast<float>(fbxShadowColor[1]),
|
|
static_cast<float>(fbxShadowColor[2]));
|
|
}
|
|
|
|
osgLight->setDiffuse(osg::Vec4f(osgDiffuseSpecular, 1.0f));
|
|
osgLight->setSpecular(osg::Vec4f(osgDiffuseSpecular, 1.0f));
|
|
osgLight->setAmbient(osg::Vec4f(osgAmbient, 1.0f));
|
|
|
|
return osgDB::ReaderWriter::ReadResult(osgLightSource);
|
|
}
|