From Michael Platings, "This plugin adds support for the Autodesk FBX file format. It imports animations, including skeletal and morph animations, hence all my previous submissions to osgAnimation. The plugin won't build without the changes made in the "osgAnimation small additions" submission (14th August).

The plugin requires the FBX SDK to be installed, available from http://usa.autodesk.com/adsk/servlet/index?siteID=123112&id=6837478"
This commit is contained in:
Robert Osfield 2009-11-19 11:44:44 +00:00
parent 6cc2ce5e4a
commit 2e11c49742
18 changed files with 1958 additions and 40 deletions

View File

@ -350,6 +350,7 @@ FIND_PACKAGE(Inventor)
FIND_PACKAGE(Jasper)
FIND_PACKAGE(OpenEXR)
FIND_PACKAGE(COLLADA)
FIND_PACKAGE(FBX)
FIND_PACKAGE(ZLIB)
FIND_PACKAGE(Xine)
FIND_PACKAGE(OpenVRML)

View File

@ -0,0 +1,51 @@
# Locate FBX
# This module defines:
# FBX_INCLUDE_DIR, where to find the headers
#
# FBX_LIBRARY, FBX_LIBRARY_DEBUG
# FBX_FOUND
#
# $FBX_DIR is an environment variable that would
# correspond to the ./configure --prefix=$FBX_DIR
IF(WIN32)
SET(FBX_ROOT "$ENV{PROGRAMFILES}/Autodesk/FBX/FbxSdk/2010.2" CACHE PATH "Location of FBX SDK directory")
ELSE(WIN32)
SET(FBX_ROOT $ENV{FBX_DIR} CACHE PATH "Location of FBX SDK directory")
ENDIF(WIN32)
IF(APPLE)
SET(FBX_LIBNAME "libfbxsdk_gcc4_ub")
ELSEIF(CMAKE_COMPILER_IS_GNUCXX)
SET(FBX_LIBNAME "libfbxsdk_gcc4")#TODO: libs are provided for GCC 3.4 & 4.0 in both 32 and 64 bit versions, but I don't know how to confgure that here.
ELSEIF(MSVC71)
SET(FBX_LIBNAME "fbxsdk_md2003")
ELSEIF(MSVC80)
SET(FBX_LIBNAME "fbxsdk_md2005")
ELSEIF(MSVC90 OR MSVC_VER>1500)
SET(FBX_LIBNAME "fbxsdk_md2008")
ENDIF(APPLE)
IF(CMAKE_CL_64)
SET(FBX_LIBNAME ${FBX_LIBNAME}_amd64)
ENDIF(CMAKE_CL_64)
IF(APPLE)
SET(FBX_LIBNAME_DEBUG ${FBX_LIBNAME})
ELSE(APPLE)
SET(FBX_LIBNAME_DEBUG ${FBX_LIBNAME}d)
ENDIF(APPLE)
FIND_PATH(FBX_INCLUDE_DIR fbxsdk.h
${FBX_ROOT}/include
)
FIND_LIBRARY(FBX_LIBRARY ${FBX_LIBNAME} ${FBX_ROOT}/lib)
FIND_LIBRARY(FBX_LIBRARY_DEBUG ${FBX_LIBNAME_DEBUG} ${FBX_ROOT}/lib)
IF(FBX_LIBRARY AND FBX_LIBRARY_DEBUG AND FBX_INCLUDE_DIR)
SET(FBX_FOUND "YES")
ELSE(FBX_LIBRARY AND FBX_LIBRARY_DEBUG AND FBX_INCLUDE_DIR)
SET(FBX_FOUND "NO")
ENDIF(FBX_LIBRARY AND FBX_LIBRARY_DEBUG AND FBX_INCLUDE_DIR)

View File

@ -157,6 +157,10 @@ IF(COLLADA_FOUND)
ADD_SUBDIRECTORY(dae)
ENDIF()
IF(FBX_FOUND)
ADD_SUBDIRECTORY(fbx)
ENDIF()
IF(OSG_GLU_AVAILABLE)
ADD_SUBDIRECTORY(lwo)
ADD_SUBDIRECTORY(dw)

View File

@ -0,0 +1,31 @@
INCLUDE_DIRECTORIES(${FBX_ROOT}/include)
SET(TARGET_SRC
fbxRAnimation.cpp
fbxRCamera.cpp
fbxRLight.cpp
fbxRMesh.cpp
fbxRNode.cpp
ReaderWriterFBX.cpp
)
SET(TARGET_H
fbxRAnimation.h
fbxRCamera.h
fbxRLight.h
fbxRMesh.h
fbxRNode.h
ReaderWriterFBX.h
)
ADD_DEFINITIONS(-DKFBX_PLUGIN -DKFBX_FBXSDK -DKFBX_NODLL)
IF(WIN32)
SET(TARGET_EXTERNAL_LIBRARIES wininet)
ENDIF(WIN32)
SET(TARGET_LIBRARIES_VARS FBX_LIBRARY)
SET(TARGET_ADDED_LIBRARIES osgAnimation)
#### end var setup ###
SETUP_PLUGIN(fbx)

View File

@ -0,0 +1,168 @@
#include <sstream>
#include <memory>
#include <osg/Notify>
#include <osg/MatrixTransform>
#include <osg/Material>
#include <osg/Texture2D>
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/ReadFile>
#include <osgDB/Registry>
#include <osgAnimation/AnimationManagerBase>
#include <osgAnimation/Skeleton>
#include <OpenThreads/ScopedLock>
#if defined(_MSC_VER)
#pragma warning( disable : 4505 )
#endif
#include <fbxsdk.h>
#include "ReaderWriterFBX.h"
#include "fbxRNode.h"
osgDB::ReaderWriter::ReadResult
ReaderWriterFBX::readNode(const std::string& utf8filename,
const osgDB::ReaderWriter::Options* options) const
{
OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_serializerMutex);
try
{
std::string ext(osgDB::getLowerCaseFileExtension(utf8filename));
if(!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
std::string fileName(osgDB::findDataFile(utf8filename, options));
if( fileName.empty()) return ReadResult::FILE_NOT_FOUND;
KFbxSdkManager* pSdkManager = KFbxSdkManager::Create();
if (!pSdkManager)
{
return ReadResult::ERROR_IN_READING_FILE;
}
class CleanUpFbx
{
KFbxSdkManager* m_pSdkManager;
public:
CleanUpFbx(KFbxSdkManager* pSdkManager) : m_pSdkManager(pSdkManager)
{}
~CleanUpFbx()
{
KFbxIOSettings::IOSettingsRef().FreeIOSettings();
m_pSdkManager->Destroy();
}
} cleanUpFbx(pSdkManager);
KFbxScene* pScene = KFbxScene::Create(pSdkManager,"");
int fileFormat;
if (!pSdkManager->GetIOPluginRegistry()->DetectFileFormat(utf8filename.c_str(), fileFormat))
{
return ReadResult::FILE_NOT_HANDLED;
}
KFbxImporter* lImporter = KFbxImporter::Create(pSdkManager,"");
lImporter->SetFileFormat(fileFormat);
if (!lImporter->Initialize(utf8filename.c_str()))
{
return std::string(lImporter->GetLastErrorString());
}
if (!lImporter->IsFBX())
{
return ReadResult::ERROR_IN_READING_FILE;
}
for(int i = 0; i < lImporter->GetTakeCount(); i++)
{
KFbxTakeInfo* lTakeInfo = lImporter->GetTakeInfo(i);
lTakeInfo->mSelect = true;
}
if (!lImporter->Import(pScene))
{
return std::string(lImporter->GetLastErrorString());
}
if (KFbxNode* pNode = pScene->GetRootNode())
{
osg::ref_ptr<osgAnimation::AnimationManagerBase> pAnimationManager;
bool bNeedSkeleton = false;
int nLightCount = 0;
ReadResult res = readFbxNode(*pSdkManager, pNode, pAnimationManager,
osgDB::getFilePath(fileName), bNeedSkeleton, nLightCount);
if (res.success())
{
osg::Node* osgNode = res.getNode();
if (bNeedSkeleton)
{
osgAnimation::Skeleton* osgSkeleton = new osgAnimation::Skeleton;
osgSkeleton->setDefaultUpdateCallback();
osgSkeleton->addChild(osgNode);
osgNode = osgSkeleton;
}
if (pAnimationManager.valid())
{
if (osgNode->getUpdateCallback())
{
osg::Group* osgGroup = new osg::Group;
osgGroup->addChild(osgNode);
osgNode = osgGroup;
}
//because the animations may be altered after registering
pAnimationManager->buildTargetReference();
osgNode->setUpdateCallback(pAnimationManager.get());
}
KFbxAxisSystem fbxAxis = pScene->GetGlobalSettings().GetAxisSystem();
int upSign;
KFbxAxisSystem::eUpVector eUp = fbxAxis.GetUpVector(upSign);
bool bLeftHanded = fbxAxis.GetCoorSystem() == KFbxAxisSystem::LeftHanded;
if (eUp != KFbxAxisSystem::YAxis || upSign < 0 || bLeftHanded)
{
float fSign = upSign < 0 ? -1.0f : 1.0f;
float zScale = bLeftHanded ? -1.0f : 1.0f;
osg::Matrix mat;
switch (eUp)
{
case KFbxAxisSystem::XAxis:
mat.set(0,fSign,0,0,-fSign,0,0,0,0,0,zScale,0,0,0,0,1);
break;
case KFbxAxisSystem::YAxis:
mat.set(1,0,0,0,0,fSign,0,0,0,0,fSign*zScale,0,0,0,0,1);
break;
case KFbxAxisSystem::ZAxis:
mat.set(1,0,0,0,0,0,-fSign*zScale,0,0,fSign,0,0,0,0,0,1);
break;
}
osg::MatrixTransform* pTransform = new osg::MatrixTransform(mat);
pTransform->addChild(osgNode);
osgNode = pTransform;
}
return osgNode;
}
}
}
catch (...)
{
}
return ReadResult::ERROR_IN_READING_FILE;
}
///////////////////////////////////////////////////////////////////////////
// Add ourself to the Registry to instantiate the reader/writer.
REGISTER_OSGPLUGIN(fbx, ReaderWriterFBX)

View File

@ -0,0 +1,30 @@
#ifndef READERWRITERFBX_H
#define READERWRITERFBX_H
#include <OpenThreads/ReentrantMutex>
#include <osgDB/ReaderWriter>
///////////////////////////////////////////////////////////////////////////
// OSG reader plugin for the ".fbx" format.
// See http://usa.autodesk.com/adsk/servlet/index?siteID=123112&id=6837478
class ReaderWriterFBX : public osgDB::ReaderWriter
{
public:
ReaderWriterFBX()
{
supportsExtension("fbx", "FBX format");
}
const char* className() const { return "FBX reader/writer"; }
/// The FBX SDK interprets the filename as UTF-8
ReadResult readNode(const std::string& utf8filename, const Options*) const;
private:
mutable OpenThreads::ReentrantMutex _serializerMutex;
};
///////////////////////////////////////////////////////////////////////////
#endif

View File

@ -0,0 +1,310 @@
#include <osg/MatrixTransform>
#include <osgAnimation/Animation>
#include <osgAnimation/BasicAnimationManager>
#include <osgAnimation/Channel>
#include <osgAnimation/Sampler>
#include <osgAnimation/UpdateCallback>
#if defined(_MSC_VER)
#pragma warning( disable : 4505 )
#endif
#include <fbxsdk.h>
#include <fbxfilesdk/fbxfilesdk_nsuse.h>
osg::Quat makeQuat(const fbxDouble3&, ERotationOrder);
osg::Quat makeQuat(const osg::Vec3& radians, ERotationOrder fbxRotOrder)
{
fbxDouble3 degrees(
osg::RadiansToDegrees(radians.x()),
osg::RadiansToDegrees(radians.y()),
osg::RadiansToDegrees(radians.z()));
return makeQuat(degrees, fbxRotOrder);
}
void readKeys(KFCurve* curveX, KFCurve* curveY, KFCurve* curveZ,
float scalar, const osg::Vec3& baseValue, bool multiply,
std::vector<osgAnimation::TemplateKeyframe<osg::Vec3> >& keyFrameCntr)
{
KFCurve* curves[3] = {curveX, curveY, curveZ};
typedef std::set<float> TimeSet;
typedef std::map<float, float> TimeFloatMap;
TimeSet times;
TimeFloatMap curveTimeMap[3];
for (int nCurve = 0; nCurve < 3; ++nCurve)
{
KFCurve* pCurve = curves[nCurve];
int nKeys = pCurve->KeyGetCount();
if (!nKeys)
{
times.insert(0.0f);
curveTimeMap[nCurve][0.0f] = static_cast<float>(pCurve->GetValue()) * scalar;
}
for (int i = 0; i < nKeys; ++i)
{
KFCurveKey key = pCurve->KeyGet(i);
float fTime = static_cast<float>(key.GetTime().GetSecondDouble());
times.insert(fTime);
curveTimeMap[nCurve][fTime] = static_cast<float>(key.GetValue()) * scalar;
}
}
for (TimeSet::iterator it = times.begin(); it != times.end(); ++it)
{
float fTime = *it;
osg::Vec3 val(baseValue);
for (int i = 0; i < 3; ++i)
{
if (curveTimeMap[i].empty()) continue;
TimeFloatMap::iterator lb = curveTimeMap[i].lower_bound(fTime);
if (lb == curveTimeMap[i].end()) --lb;
if (multiply)
{
val[i] *= lb->second;
}
else
{
val[i] += lb->second;
}
}
keyFrameCntr.push_back(osgAnimation::Vec3Keyframe(fTime, val));
}
}
osgAnimation::Channel* readFbxChannels(KFCurve* curveX, KFCurve* curveY,
KFCurve* curveZ, const char* targetName, const char* channelName,
float scalar, const osg::Vec3& baseValue, bool multiply)
{
if (!curveX && !curveY && !curveZ)
{
return 0;
}
if (!curveX->KeyGetCount() && !curveY->KeyGetCount() && !curveZ->KeyGetCount())
{
return 0;
}
osgAnimation::Vec3LinearChannel* pChannel = new osgAnimation::Vec3LinearChannel;
osgAnimation::Vec3KeyframeContainer* pKeyFrameCntr =
pChannel->getOrCreateSampler()->getOrCreateKeyframeContainer();
pChannel->setTargetName(targetName);
pChannel->setName(channelName);
readKeys(curveX, curveY, curveZ, scalar, baseValue, multiply, *pKeyFrameCntr);
return pChannel;
}
osgAnimation::Channel* readFbxChannels(
KFbxTypedProperty<fbxDouble3>& fbxProp, const char* pTakeName,
const char* targetName, const char* channelName, const osg::Vec3& baseValue, float scalar, bool multiply)
{
if (!fbxProp.IsValid()) return 0;
return readFbxChannels(
fbxProp.GetKFCurve("X", pTakeName),
fbxProp.GetKFCurve("Y", pTakeName),
fbxProp.GetKFCurve("Z", pTakeName),
targetName, channelName, scalar,
baseValue * scalar, multiply);
}
osgAnimation::Channel* readFbxChannelsQuat(
KFCurve* curveX, KFCurve* curveY, KFCurve* curveZ, const char* targetName,
const osg::Quat& baseQuat, ERotationOrder rotOrder)
{
if (!curveX && !curveY && !curveZ)
{
return 0;
}
osgAnimation::QuatSphericalLinearChannel* pChannel = new osgAnimation::QuatSphericalLinearChannel;
pChannel->setTargetName(targetName);
pChannel->setName("quaternion");
typedef std::vector<osgAnimation::TemplateKeyframe<osg::Vec3> > KeyFrameCntr;
KeyFrameCntr eulerFrameCntr;
readKeys(curveX, curveY, curveZ, static_cast<float>(osg::PI / 180.0), osg::Vec3(0,0,0), false, eulerFrameCntr);
osgAnimation::QuatSphericalLinearSampler::KeyframeContainerType& quatFrameCntr =
*pChannel->getOrCreateSampler()->getOrCreateKeyframeContainer();
quatFrameCntr.reserve(eulerFrameCntr.size());
for (KeyFrameCntr::iterator it = eulerFrameCntr.begin(), end = eulerFrameCntr.end();
it != end; ++it)
{
const osg::Vec3& euler = it->getValue();
quatFrameCntr.push_back(osgAnimation::QuatKeyframe(
it->getTime(), makeQuat(euler, rotOrder) * baseQuat));
}
return pChannel;
}
osgAnimation::Animation* addChannels(
osgAnimation::Channel* pTranslationChannel,
osgAnimation::Channel* pRotationChannel,
osgAnimation::Channel* pScaleChannel,
osg::ref_ptr<osgAnimation::AnimationManagerBase> &pAnimManager,
const char* pTakeName)
{
if (pTranslationChannel ||
pRotationChannel ||
pScaleChannel)
{
if (!pAnimManager) pAnimManager = new osgAnimation::BasicAnimationManager;
osgAnimation::Animation* pAnimation = 0;
const osgAnimation::AnimationList& anims = pAnimManager->getAnimationList();
for (size_t i = 0; i < anims.size(); ++i)
{
if (anims[i]->getName() == pTakeName)
{
pAnimation = anims[i].get();
}
}
if (!pAnimation)
{
pAnimation = new osgAnimation::Animation;
pAnimation->setName(pTakeName);
pAnimManager->registerAnimation(pAnimation);
}
if (pTranslationChannel) pAnimation->addChannel(pTranslationChannel);
if (pRotationChannel) pAnimation->addChannel(pRotationChannel);
if (pScaleChannel) pAnimation->addChannel(pScaleChannel);
return pAnimation;
}
return 0;
}
osgAnimation::Animation* readFbxBoneAnimation(KFbxNode* pNode,
const char* pTakeName, const char* targetName,
osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimManager)
{
if (!pTakeName)
{
return 0;
}
ERotationOrder rotOrder = pNode->RotationOrder.IsValid() ? pNode->RotationOrder.Get() : eEULER_XYZ;
osg::Quat inverseRot;
osgAnimation::Channel* pTranslationChannel = 0;
osgAnimation::Channel* pRotationChannel = 0;
if (pNode->LclRotation.IsValid())
{
inverseRot = makeQuat(pNode->LclRotation.Get(), rotOrder).inverse();
pRotationChannel = readFbxChannelsQuat(
pNode->LclRotation.GetKFCurve(KFCURVENODE_R_X, pTakeName),
pNode->LclRotation.GetKFCurve(KFCURVENODE_R_Y, pTakeName),
pNode->LclRotation.GetKFCurve(KFCURVENODE_R_Z, pTakeName),
targetName, inverseRot, rotOrder);
}
if (pNode->LclTranslation.IsValid())
{
fbxDouble3 fbxBaseValue = pNode->LclTranslation.Get();
osg::Vec3 offsetTranslation(
-static_cast<float>(fbxBaseValue[0]),
-static_cast<float>(fbxBaseValue[1]),
-static_cast<float>(fbxBaseValue[2]));
pTranslationChannel = readFbxChannels(
pNode->LclTranslation.GetKFCurve(KFCURVENODE_T_X, pTakeName),
pNode->LclTranslation.GetKFCurve(KFCURVENODE_T_Y, pTakeName),
pNode->LclTranslation.GetKFCurve(KFCURVENODE_T_Z, pTakeName),
targetName, "position", 1.0f, offsetTranslation, false);
if (pTranslationChannel)
{
osgAnimation::Vec3KeyframeContainer& keyFrameCntr =
dynamic_cast<osgAnimation::Vec3KeyframeContainer&>(
*pTranslationChannel->getSampler()->getKeyframeContainer());
for (int i = 0; i < keyFrameCntr.size(); ++i)
{
keyFrameCntr[i].setValue(inverseRot * keyFrameCntr[i].getValue());
}
}
}
osgAnimation::Channel* pScaleChannel = readFbxChannels(
pNode->LclScaling, pTakeName, targetName, "scale", osg::Vec3(0,0,0), 1.0f, true);
return addChannels(pTranslationChannel, pRotationChannel, pScaleChannel, pAnimManager, pTakeName);
}
osgAnimation::Animation* readFbxAnimation(KFbxNode* pNode,
const char* pTakeName, const char* targetName,
osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimManager)
{
if (!pTakeName) return 0;
osgAnimation::Channel* pTranslationChannel = readFbxChannels(
pNode->LclTranslation, pTakeName, targetName, "position", osg::Vec3(0,0,0), 1.0f, false);
//TODO: This will break if there are rotations in more than one of
// Pre/Lcl/Post so really they should each get their own MatrixTransform.
fbxDouble3 fbxPreRot = pNode->PreRotation.Get();
fbxDouble3 fbxPostRot = pNode->PostRotation.Get();
osg::Vec3 eulerOffset(
static_cast<float>(fbxPreRot[0] + fbxPostRot[0]),
static_cast<float>(fbxPreRot[1] + fbxPostRot[1]),
static_cast<float>(fbxPreRot[2] + fbxPostRot[2]));
osgAnimation::Channel* pRotationChannel = readFbxChannels(
pNode->LclRotation, pTakeName, targetName, "euler", eulerOffset, static_cast<float>(osg::PI / 180.0), false);
osgAnimation::Channel* pScaleChannel = readFbxChannels(
pNode->LclScaling, pTakeName, targetName, "scale", osg::Vec3(1,1,1), 1.0f, true);
return addChannels(pTranslationChannel, pRotationChannel, pScaleChannel, pAnimManager, pTakeName);
}
std::string readFbxBoneAnimation(KFbxNode* pNode,
osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimManager,
const char* targetName)
{
std::string result;
for (int i = 1; i < pNode->GetTakeNodeCount(); ++i)
{
const char* pTakeName = pNode->GetTakeNodeName(i);
if (osgAnimation::Animation* pAnimation = readFbxBoneAnimation(
pNode, pTakeName, targetName, pAnimManager))
{
result = targetName;
}
}
return result;
}
std::string readFbxAnimation(KFbxNode* pNode,
osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimManager,
const char* targetName)
{
std::string result;
for (int i = 1; i < pNode->GetTakeNodeCount(); ++i)
{
const char* pTakeName = pNode->GetTakeNodeName(i);
if (osgAnimation::Animation* pAnimation = readFbxAnimation(
pNode, pTakeName, targetName, pAnimManager))
{
result = targetName;
}
}
return result;
}

View File

@ -0,0 +1,16 @@
#ifndef FBXRANIMATION_H
#define FBXRANIMATION_H
#include <fbxfilesdk/fbxfilesdk_def.h>
std::string readFbxBoneAnimation(
FBXFILESDK_NAMESPACE::KFbxNode*,
osg::ref_ptr<osgAnimation::AnimationManagerBase>&,
const char* targetName);
std::string readFbxAnimation(
FBXFILESDK_NAMESPACE::KFbxNode*,
osg::ref_ptr<osgAnimation::AnimationManagerBase>&,
const char* targetName);
#endif

View File

@ -0,0 +1,53 @@
#include <osg/CameraView>
#include <osg/Notify>
#include <osgDB/ReadFile>
#if defined(_MSC_VER)
#pragma warning( disable : 4505 )
#endif
#include <fbxsdk.h>
#include "fbxRCamera.h"
osgDB::ReaderWriter::ReadResult readFbxCamera(KFbxNode* pNode)
{
const KFbxCamera* fbxCamera = dynamic_cast<const KFbxCamera*>(pNode->GetNodeAttribute());
if (!fbxCamera)
{
return osgDB::ReaderWriter::ReadResult::ERROR_IN_READING_FILE;
}
osg::CameraView* osgCameraView = new osg::CameraView;
if (fbxCamera->FieldOfView.IsValid())
{
osgCameraView->setFieldOfView(fbxCamera->FieldOfView.Get());
}
if (fbxCamera->FocalLength.IsValid())
{
osgCameraView->setFocalLength(fbxCamera->FocalLength.Get());
}
if (fbxCamera->ApertureMode.IsValid())
{
switch (fbxCamera->ApertureMode.Get())
{
case KFbxCamera::eHORIZONTAL:
osgCameraView->setFieldOfViewMode(osg::CameraView::HORIZONTAL);
break;
case KFbxCamera::eVERTICAL:
osgCameraView->setFieldOfViewMode(osg::CameraView::VERTICAL);
break;
case KFbxCamera::eHORIZONTAL_AND_VERTICAL:
case KFbxCamera::eFOCAL_LENGTH:
default:
osg::notify(osg::WARN) << "readFbxCamera: Unsupported Camera aperture mode." << std::endl;
break;
}
}
return osgDB::ReaderWriter::ReadResult(osgCameraView);
}

View File

@ -0,0 +1,10 @@
#ifndef FBXRCAMERA_H
#define FBXRCAMERA_H
#include <fbxfilesdk/fbxfilesdk_def.h>
#include <osgDB/ReaderWriter>
osgDB::ReaderWriter::ReadResult readFbxCamera(
FBXFILESDK_NAMESPACE::KFbxNode* pNode);
#endif

View File

@ -0,0 +1,96 @@
#include <osg/LightSource>
#include <osgDB/ReadFile>
#if defined(_MSC_VER)
#pragma warning( disable : 4505 )
#endif
#include <fbxsdk.h>
#include "fbxRLight.h"
osgDB::ReaderWriter::ReadResult readFbxLight(KFbxNode* pNode, int& nLightCount)
{
const KFbxLight* fbxLight = dynamic_cast<const KFbxLight*>(pNode->GetNodeAttribute());
if (!fbxLight)
{
return osgDB::ReaderWriter::ReadResult::ERROR_IN_READING_FILE;
}
osg::Light* osgLight = new osg::Light;
osg::LightSource* osgLightSource = new osg::LightSource;
osgLightSource->setLight(osgLight);
osgLight->setLightNum(nLightCount++);
KFbxLight::ELightType fbxLightType = fbxLight->LightType.IsValid() ?
fbxLight->LightType.Get() : KFbxLight::ePOINT;
osgLight->setPosition(osg::Vec4(0,0,0,fbxLightType != KFbxLight::eDIRECTIONAL));
if (fbxLightType == KFbxLight::eSPOT)
{
double coneAngle = fbxLight->ConeAngle.IsValid() ? fbxLight->ConeAngle.Get() : 45.0;
double hotSpot = fbxLight->HotSpot.IsValid() ? fbxLight->HotSpot.Get() : 45.0;
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 KFbxLight::eLINEAR:
osgLight->setLinearAttenuation(fbxDecayStart);
break;
case KFbxLight::eQUADRATIC:
case KFbxLight::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);
}

View File

@ -0,0 +1,10 @@
#ifndef FBXRLIGHT_H
#define FBXRLIGHT_H
#include <fbxfilesdk/fbxfilesdk_def.h>
#include <osgDB/ReaderWriter>
osgDB::ReaderWriter::ReadResult readFbxLight(
FBXFILESDK_NAMESPACE::KFbxNode* pNode, int& nLightCount);
#endif

View File

@ -0,0 +1,547 @@
#include <osg/Geode>
#include <osg/Image>
#include <osgUtil/TriStripVisitor>
#include <osgDB/ReadFile>
#include <osgAnimation/RigGeometry>
#include <osgAnimation/MorphGeometry>
#include <osgAnimation/BasicAnimationManager>
#if defined(_MSC_VER)
#pragma warning( disable : 4505 )
#endif
#include <fbxsdk.h>
#include "fbxRMesh.h"
enum GeometryType
{
GEOMETRY_STATIC,
GEOMETRY_RIG,
GEOMETRY_MORPH
};
osg::Vec3 convertVec3(const KFbxVector4& v)
{
return osg::Vec3(
static_cast<float>(v[0]),
static_cast<float>(v[1]),
static_cast<float>(v[2]));
}
osg::Vec2 convertVec2(const KFbxVector2& v)
{
return osg::Vec2(
static_cast<float>(v[0]),
static_cast<float>(v[1]));
}
osg::Vec4 convertColor(const KFbxColor& color)
{
return osg::Vec4(
static_cast<float>(color.mRed),
static_cast<float>(color.mGreen),
static_cast<float>(color.mBlue),
static_cast<float>(color.mAlpha));
}
template <typename T>
bool layerElementValid(const KFbxLayerElementTemplate<T>* pLayerElement)
{
if (!pLayerElement)
return false;
switch (pLayerElement->GetMappingMode())
{
case KFbxLayerElement::eBY_CONTROL_POINT:
case KFbxLayerElement::eBY_POLYGON_VERTEX:
case KFbxLayerElement::eBY_POLYGON:
break;
default:
return false;
}
switch (pLayerElement->GetReferenceMode())
{
case KFbxLayerElement::eDIRECT:
case KFbxLayerElement::eINDEX_TO_DIRECT:
return true;
}
return false;
}
template <typename T>
int getVertexIndex(const KFbxLayerElementTemplate<T>* pLayerElement,
KFbxMesh* fbxMesh,
int nPolygon, int nPolyVertex, int nMeshVertex)
{
int index = 0;
switch (pLayerElement->GetMappingMode())
{
case KFbxLayerElement::eBY_CONTROL_POINT:
index = fbxMesh->GetPolygonVertex(nPolygon, nPolyVertex);
break;
case KFbxLayerElement::eBY_POLYGON_VERTEX:
index = nMeshVertex;
break;
case KFbxLayerElement::eBY_POLYGON:
index = nPolygon;
break;
}
if (pLayerElement->GetReferenceMode() == KFbxLayerElement::eDIRECT)
{
return index;
}
return pLayerElement->GetIndexArray().GetAt(index);
}
template <typename T>
int getPolygonIndex(const KFbxLayerElementTemplate<T>* pLayerElement, int nPolygon)
{
if (pLayerElement &&
pLayerElement->GetMappingMode() == KFbxLayerElement::eBY_POLYGON)
{
switch (pLayerElement->GetReferenceMode())
{
case KFbxLayerElement::eDIRECT:
return nPolygon;
case KFbxLayerElement::eINDEX_TO_DIRECT:
return pLayerElement->GetIndexArray().GetAt(nPolygon);
}
}
return 0;
}
template <typename FbxT>
FbxT getElement(const KFbxLayerElementTemplate<FbxT>* pLayerElement,
KFbxMesh* fbxMesh,
int nPolygon, int nPolyVertex, int nMeshVertex)
{
return pLayerElement->GetDirectArray().GetAt(getVertexIndex(
pLayerElement, fbxMesh, nPolygon, nPolyVertex, nMeshVertex));
}
typedef std::map<unsigned, osg::ref_ptr<osg::Geometry> > GeometryMap;
osg::Geometry* getGeometry(osg::Geode* pGeode, GeometryMap& geometryMap,
const std::vector<osg::ref_ptr<osg::Material>>& materialList,
const std::vector<osg::ref_ptr<osg::Texture>>& textureList,
GeometryType gt, unsigned mti, bool bNormal, bool bTexCoord, bool bColor)
{
GeometryMap::iterator it = geometryMap.find(mti);
if (it != geometryMap.end())
{
return it->second.get();
}
osg::ref_ptr<osg::Geometry> pGeometry;
if (gt == GEOMETRY_RIG)
{
osgAnimation::RigGeometry* pRig = new osgAnimation::RigGeometry;
pRig->setInfluenceMap(new osgAnimation::VertexInfluenceMap);
pGeometry = pRig;
}
else if (gt == GEOMETRY_MORPH)
{
pGeometry = new osgAnimation::MorphGeometry;
}
else
{
pGeometry = new osg::Geometry;
}
pGeometry->setVertexData(osg::Geometry::ArrayData(new osg::Vec3Array, osg::Geometry::BIND_PER_VERTEX));
if (bNormal) pGeometry->setNormalData(osg::Geometry::ArrayData(new osg::Vec3Array, osg::Geometry::BIND_PER_VERTEX));
if (bTexCoord) pGeometry->setTexCoordData(0, osg::Geometry::ArrayData(new osg::Vec2Array, osg::Geometry::BIND_PER_VERTEX));
if (bColor) pGeometry->setColorData(osg::Geometry::ArrayData(new osg::Vec4Array, osg::Geometry::BIND_PER_VERTEX));
if (mti < materialList.size())
{
pGeometry->getOrCreateStateSet()->setAttributeAndModes(materialList[mti].get());
}
if (mti < textureList.size())
{
pGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, textureList[mti].get());
}
geometryMap.insert(std::pair<unsigned, osg::ref_ptr<osg::Geometry>>(mti, pGeometry));
pGeode->addDrawable(pGeometry.get());
return pGeometry.get();
}
osgAnimation::VertexInfluence& getVertexInfluence(
osgAnimation::VertexInfluenceMap& vim, const std::string& name)
{
osgAnimation::VertexInfluenceMap::iterator it = vim.lower_bound(name);
if (it == vim.end() || name != it->first)
{
it = vim.insert(it, osgAnimation::VertexInfluenceMap::value_type(
name, osgAnimation::VertexInfluence()));
it->second.setName(name);
}
return it->second;
}
void addChannel(
osgAnimation::Channel* pChannel,
osg::ref_ptr<osgAnimation::AnimationManagerBase> &pAnimManager,
const char* pTakeName)
{
if (!pChannel)
{
return;
}
if (!pAnimManager) pAnimManager = new osgAnimation::BasicAnimationManager;
osgAnimation::Animation* pAnimation = 0;
const osgAnimation::AnimationList& anims = pAnimManager->getAnimationList();
for (size_t i = 0; i < anims.size(); ++i)
{
if (anims[i]->getName() == pTakeName)
{
pAnimation = anims[i].get();
}
}
if (!pAnimation)
{
pAnimation = new osgAnimation::Animation;
pAnimation->setName(pTakeName);
pAnimManager->registerAnimation(pAnimation);
}
pAnimation->addChannel(pChannel);
}
void readAnimation(KFbxNode* pNode, osg::Geode* pGeode,
osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager,
KFbxMesh* pMesh, int nShape)
{
for (int i = 1; i < pNode->GetTakeNodeCount(); ++i)
{
const char* pTakeName = pNode->GetTakeNodeName(i);
KFCurve* pCurve = pMesh->GetShapeChannel(nShape, true, pTakeName);
osgAnimation::FloatLinearChannel* pChannel = new osgAnimation::FloatLinearChannel;
std::vector<osgAnimation::TemplateKeyframe<float> >& keyFrameCntr = *pChannel->getOrCreateSampler()->getOrCreateKeyframeContainer();
int nKeys = pCurve->KeyGetCount();
if (!nKeys)
{
float fValue = static_cast<float>(pCurve->GetValue() * 0.01);
keyFrameCntr.push_back(osgAnimation::FloatKeyframe(0.0f,fValue));
}
for (int k = 0; k < nKeys; ++k)
{
KFCurveKey key = pCurve->KeyGet(k);
float fTime = static_cast<float>(key.GetTime().GetSecondDouble());
float fValue = static_cast<float>(key.GetValue() * 0.01);
keyFrameCntr.push_back(osgAnimation::FloatKeyframe(fTime,fValue));
}
pChannel->setTargetName(pGeode->getName());
pChannel->setName(pMesh->GetShapeName(nShape));
addChannel(pChannel, pAnimationManager, pTakeName);
}
}
osgDB::ReaderWriter::ReadResult readMesh(KFbxNode* pNode, KFbxMesh* fbxMesh,
osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager,
const std::vector<osg::ref_ptr<osg::Material>>& materialList,
const std::vector<osg::ref_ptr<osg::Texture>>& textureList,
const char* szName)
{
GeometryMap geometryMap;
osg::Geode* pGeode = new osg::Geode;
pGeode->setName(szName);
const KFbxLayer* pFbxLayer = 0;
const KFbxLayerElementNormal* pFbxNormals = 0;
const KFbxLayerElementUV* pFbxUVs = 0;
const KFbxLayerElementVertexColor* pFbxColors = 0;
const KFbxLayerElementMaterial* pFbxMaterials = 0;
const KFbxVector4* pFbxVertices = fbxMesh->GetControlPoints();
if (pFbxLayer = fbxMesh->GetLayer(0))
{
pFbxNormals = pFbxLayer->GetNormals();
pFbxColors = pFbxLayer->GetVertexColors();
pFbxUVs = pFbxLayer->GetUVs();
pFbxMaterials = pFbxLayer->GetMaterials();
if (!layerElementValid(pFbxNormals)) pFbxNormals = 0;
if (!layerElementValid(pFbxColors)) pFbxColors = 0;
if (!layerElementValid(pFbxUVs)) pFbxUVs = 0;
}
int nPolys = fbxMesh->GetPolygonCount();
int nDeformerCount = fbxMesh->GetDeformerCount(KFbxDeformer::eSKIN);
int nMorphShapeCount = 0;
GeometryType geomType = GEOMETRY_STATIC;
//determine the type of geometry
if (nDeformerCount)
{
geomType = GEOMETRY_RIG;
}
else if (nMorphShapeCount = fbxMesh->GetShapeCount())
{
geomType = GEOMETRY_MORPH;
}
typedef std::pair<osg::Geometry*, int> GIPair;
typedef std::multimap<int, GIPair> FbxToOsgVertexMap;
typedef std::map<GIPair, int> OsgToFbxNormalMap;
FbxToOsgVertexMap fbxToOsgVertMap;
OsgToFbxNormalMap osgToFbxNormMap;
for (int i = 0, nVertex = 0; i < nPolys; ++i)
{
int lPolygonSize = fbxMesh->GetPolygonSize(i);
int materialIndex = getPolygonIndex(pFbxMaterials, i);
osg::Geometry* pGeometry = getGeometry(pGeode, geometryMap,
materialList, textureList, geomType, materialIndex,
pFbxNormals != 0, pFbxUVs != 0, pFbxColors != 0);
osg::Vec3Array* pVertices = static_cast<osg::Vec3Array*>(
pGeometry->getVertexArray());
osg::Vec3Array* pNormals = static_cast<osg::Vec3Array*>(
pGeometry->getNormalArray());
osg::Vec2Array* pTexCoords = static_cast<osg::Vec2Array*>(
pGeometry->getTexCoordArray(0));
osg::Vec4Array* pColors = static_cast<osg::Vec4Array*>(
pGeometry->getColorArray());
int nVertex0 = nVertex;
nVertex += (std::min)(2, lPolygonSize);
//convert polygon to triangles
for (int j = 2; j < lPolygonSize; ++j, ++nVertex)
{
int v0 = fbxMesh->GetPolygonVertex(i, 0),
v1 = fbxMesh->GetPolygonVertex(i, j - 1),
v2 = fbxMesh->GetPolygonVertex(i, j);
fbxToOsgVertMap.insert(FbxToOsgVertexMap::value_type(v0, GIPair(pGeometry, pVertices->size())));
fbxToOsgVertMap.insert(FbxToOsgVertexMap::value_type(v1, GIPair(pGeometry, pVertices->size() + 1)));
fbxToOsgVertMap.insert(FbxToOsgVertexMap::value_type(v2, GIPair(pGeometry, pVertices->size() + 2)));
pVertices->push_back(convertVec3(pFbxVertices[v0]));
pVertices->push_back(convertVec3(pFbxVertices[v1]));
pVertices->push_back(convertVec3(pFbxVertices[v2]));
if (pNormals)
{
int n0 = getVertexIndex(pFbxNormals, fbxMesh, i, 0, nVertex0);
int n1 = getVertexIndex(pFbxNormals, fbxMesh, i, j - 1, nVertex - 1);
int n2 = getVertexIndex(pFbxNormals, fbxMesh, i, j, nVertex);
osgToFbxNormMap.insert(OsgToFbxNormalMap::value_type(GIPair(pGeometry, pNormals->size()), n0));
osgToFbxNormMap.insert(OsgToFbxNormalMap::value_type(GIPair(pGeometry, pNormals->size() + 1), n1));
osgToFbxNormMap.insert(OsgToFbxNormalMap::value_type(GIPair(pGeometry, pNormals->size() + 2), n2));
pNormals->push_back(convertVec3(pFbxNormals->GetDirectArray().GetAt(n0)));
pNormals->push_back(convertVec3(pFbxNormals->GetDirectArray().GetAt(n1)));
pNormals->push_back(convertVec3(pFbxNormals->GetDirectArray().GetAt(n2)));
}
if (pTexCoords)
{
pTexCoords->push_back(convertVec2(getElement(pFbxUVs, fbxMesh, i, 0, nVertex0)));
pTexCoords->push_back(convertVec2(getElement(pFbxUVs, fbxMesh, i, j - 1, nVertex - 1)));
pTexCoords->push_back(convertVec2(getElement(pFbxUVs, fbxMesh, i, j, nVertex)));
}
if (pColors)
{
pColors->push_back(convertColor(getElement(pFbxColors, fbxMesh, i, 0, nVertex0)));
pColors->push_back(convertColor(getElement(pFbxColors, fbxMesh, i, j - 1, nVertex - 1)));
pColors->push_back(convertColor(getElement(pFbxColors, fbxMesh, i, j, nVertex)));
}
}
}
for (int i = 0; i < pGeode->getNumDrawables(); ++i)
{
osg::Geometry* pGeometry = pGeode->getDrawable(i)->asGeometry();
pGeometry->setName(pGeode->getName());
osg::DrawArrays* pDrawArrays = new osg::DrawArrays(
GL_TRIANGLES, 0, pGeometry->getVertexArray()->getNumElements());
pGeometry->addPrimitiveSet(pDrawArrays);
}
if (geomType == GEOMETRY_RIG)
{
for (int i = 0; i < nDeformerCount; ++i)
{
KFbxSkin* pSkin = (KFbxSkin*)fbxMesh->GetDeformer(i, KFbxDeformer::eSKIN);
int nClusters = pSkin->GetClusterCount();
for (int j = 0; j < nClusters; ++j)
{
KFbxCluster* pCluster = (KFbxCluster*)pSkin->GetCluster(j);
KFbxNode* pBone = pCluster->GetLink();
int nIndices = pCluster->GetControlPointIndicesCount();
int* pIndices = pCluster->GetControlPointIndices();
double* pWeights = pCluster->GetControlPointWeights();
for (int k = 0; k < nIndices; ++k)
{
int fbxIndex = pIndices[k];
float weight = static_cast<float>(pWeights[k]);
for (FbxToOsgVertexMap::const_iterator it =
fbxToOsgVertMap.find(fbxIndex);
it != fbxToOsgVertMap.end() &&
it->first == fbxIndex; ++it)
{
GIPair gi = it->second;
osgAnimation::RigGeometry& rig = dynamic_cast<osgAnimation::RigGeometry&>(*gi.first);
osgAnimation::VertexInfluenceMap& vim = *rig.getInfluenceMap();
osgAnimation::VertexInfluence& vi = getVertexInfluence(vim, pBone->GetName());
vi.push_back(osgAnimation::VertexIndexWeight(
gi.second, weight));
}
}
}
}
}
else if (geomType == GEOMETRY_MORPH)
{
pGeode->addUpdateCallback(new osgAnimation::UpdateMorph(pGeode->getName()));
for (int i = 0; i < pGeode->getNumDrawables(); ++i)
{
osg::Geometry* pGeometry = pGeode->getDrawable(i)->asGeometry();
osgAnimation::MorphGeometry& morph = dynamic_cast<osgAnimation::MorphGeometry&>(*pGeometry);
//read morph geometry
for (int j = 0; j < nMorphShapeCount; ++j)
{
const KFbxGeometryBase* pMorphShape = fbxMesh->GetShape(i);
const KFbxLayerElementNormal* pFbxShapeNormals = 0;
if (const KFbxLayer* pFbxShapeLayer = pMorphShape->GetLayer(0))
{
pFbxShapeNormals = pFbxShapeLayer->GetNormals();
if (!layerElementValid(pFbxShapeNormals)) pFbxShapeNormals = 0;
}
osg::Geometry* pMorphTarget = new osg::Geometry(morph);
pMorphTarget->setVertexArray(static_cast<osg::Array*>(
pMorphTarget->getVertexArray()->clone(osg::CopyOp::DEEP_COPY_ARRAYS)));
if (pFbxShapeNormals)
{
if (osg::Array* pNormals = pMorphTarget->getNormalArray())
{
pMorphTarget->setNormalArray(static_cast<osg::Array*>(
pNormals->clone(osg::CopyOp::DEEP_COPY_ARRAYS)));
}
}
pMorphTarget->setName(fbxMesh->GetShapeName(j));
KFCurve* pCurve = fbxMesh->GetShapeChannel(j);
double defaultWeight = pCurve->GetValue() * 0.01;
morph.addMorphTarget(pMorphTarget, static_cast<float>(defaultWeight));
readAnimation(pNode, pGeode, pAnimationManager, fbxMesh, j);
}
}
for (int i = 0; i < nMorphShapeCount; ++i)
{
const KFbxGeometryBase* pMorphShape = fbxMesh->GetShape(i);
const KFbxLayerElementNormal* pFbxShapeNormals = 0;
if (const KFbxLayer* pFbxShapeLayer = pMorphShape->GetLayer(0))
{
pFbxShapeNormals = pFbxShapeLayer->GetNormals();
if (!layerElementValid(pFbxShapeNormals)) pFbxShapeNormals = 0;
}
const KFbxVector4* pControlPoints = pMorphShape->GetControlPoints();
int nControlPoints = pMorphShape->GetControlPointsCount();
for (int fbxIndex = 0; fbxIndex < nControlPoints; ++fbxIndex)
{
osg::Vec3 vPos = convertVec3(pControlPoints[fbxIndex]);
for (FbxToOsgVertexMap::const_iterator it =
fbxToOsgVertMap.find(fbxIndex);
it != fbxToOsgVertMap.end() &&
it->first == fbxIndex; ++it)
{
GIPair gi = it->second;
osgAnimation::MorphGeometry& morphGeom =
dynamic_cast<osgAnimation::MorphGeometry&>(*gi.first);
osg::Geometry* pGeometry = morphGeom.getMorphTarget(i).getGeometry();
osg::Vec3Array* pVertices = static_cast<osg::Vec3Array*>(pGeometry->getVertexArray());
(*pVertices)[gi.second] = vPos;
if (pFbxShapeNormals)
{
if (osg::Vec3Array* pNormals = static_cast<osg::Vec3Array*>(pGeometry->getNormalArray()))
{
(*pNormals)[gi.second] = convertVec3(
pFbxShapeNormals->GetDirectArray().GetAt(osgToFbxNormMap[gi]));
}
}
}
}
}
}
KFbxXMatrix fbxVertexTransform;
fbxVertexTransform.SetTRS(
pNode->GetGeometricTranslation(KFbxNode::eSOURCE_SET),
pNode->GetGeometricRotation(KFbxNode::eSOURCE_SET),
pNode->GetGeometricScaling(KFbxNode::eSOURCE_SET));
const double* pVertexMat = fbxVertexTransform;
osg::Matrix vertexMat(pVertexMat);
if (vertexMat.isIdentity())
{
return osgDB::ReaderWriter::ReadResult(pGeode);
}
else
{
osg::MatrixTransform* pMatTrans = new osg::MatrixTransform(vertexMat);
pMatTrans->addChild(pGeode);
return osgDB::ReaderWriter::ReadResult(pMatTrans);
}
}
osgDB::ReaderWriter::ReadResult readFbxMesh(KFbxNode* pNode,
osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager,
const std::vector<osg::ref_ptr<osg::Material>>& materialList,
const std::vector<osg::ref_ptr<osg::Texture>>& textureList)
{
KFbxMesh* lMesh = dynamic_cast<KFbxMesh*>(pNode->GetNodeAttribute());
if (!lMesh)
{
return osgDB::ReaderWriter::ReadResult::ERROR_IN_READING_FILE;
}
return readMesh(pNode, lMesh, pAnimationManager, materialList, textureList, pNode->GetName());
}

View File

@ -0,0 +1,14 @@
#ifndef FBXRMESH_H
#define FBXRMESH_H
#include <fbxfilesdk/fbxfilesdk_def.h>
#include <osgDB/ReaderWriter>
#include <osg/Material>
osgDB::ReaderWriter::ReadResult readFbxMesh(
FBXFILESDK_NAMESPACE::KFbxNode* pNode,
osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager,
const std::vector<osg::ref_ptr<osg::Material>>&,
const std::vector<osg::ref_ptr<osg::Texture>>&);
#endif

View File

@ -0,0 +1,560 @@
#include <memory>
#include <osg/Notify>
#include <osg/MatrixTransform>
#include <osg/Material>
#include <osg/Texture2D>
#include <osgDB/FileNameUtils>
#include <osgDB/ReadFile>
#include <osgAnimation/AnimationManagerBase>
#include <osgAnimation/Skeleton>
#include <osgAnimation/UpdateCallback>
#if defined(_MSC_VER)
#pragma warning( disable : 4505 )
#endif
#include <fbxsdk.h>
#include "fbxRAnimation.h"
#include "fbxRCamera.h"
#include "fbxRLight.h"
#include "fbxRMesh.h"
template <typename FbxT, typename OsgT, typename ConvertFunc>
class FbxToOsgMap
{
std::map<const FbxT*, osg::ref_ptr<OsgT>> m_map;
public:
ConvertFunc m_convertFunc;
FbxToOsgMap(ConvertFunc convertFunc) : m_convertFunc(convertFunc) {}
osg::ref_ptr<OsgT> Get(const FbxT* fbx)
{
if (!fbx)
return 0;
std::map<const FbxT*, osg::ref_ptr<OsgT>>::iterator it = m_map.find(fbx);
if (it != m_map.end())
{
return it->second;
}
osg::ref_ptr<OsgT> osgObj = m_convertFunc(fbx);
m_map.insert(std::pair<const FbxT*, osg::ref_ptr<OsgT>>(fbx, osgObj));
return osgObj;
}
};
struct GetOsgTexture
{
const std::string& m_dir;
GetOsgTexture(const std::string& dir) : m_dir(dir) {}
static osg::Texture::WrapMode convertWrap(KFbxTexture::EWrapMode wrap)
{
return wrap == KFbxTexture::eREPEAT ?
osg::Texture2D::REPEAT : osg::Texture2D::CLAMP_TO_EDGE;
}
osg::ref_ptr<osg::Texture2D> operator () (const KFbxTexture* fbx)
{
osg::Image* pImage;
if ((pImage = osgDB::readImageFile(osgDB::concatPaths(m_dir, fbx->GetRelativeFileName()))) ||
(pImage = osgDB::readImageFile(osgDB::concatPaths(m_dir, fbx->GetFileName()))))
{
osg::ref_ptr<osg::Texture2D> pOsgTex = new osg::Texture2D;
pOsgTex->setImage(pImage);
pOsgTex->setWrap(osg::Texture2D::WRAP_S, convertWrap(fbx->GetWrapModeU()));
pOsgTex->setWrap(osg::Texture2D::WRAP_T, convertWrap(fbx->GetWrapModeV()));
return pOsgTex;
}
else
{
return 0;
}
}
};
struct GetOsgMaterial
{
typedef FbxToOsgMap<KFbxTexture, osg::Texture2D, GetOsgTexture> TextureMap;
TextureMap m_textureMap;
public:
osg::ref_ptr<osg::Texture2D> m_pTexture;
GetOsgMaterial(const std::string& dir) : m_textureMap(GetOsgTexture(dir)){}
osg::ref_ptr<osg::Material> operator () (const KFbxSurfaceMaterial* pFbxMat)
{
osg::ref_ptr<osg::Material> pOsgMat = new osg::Material;
const KFbxSurfaceLambert* pFbxLambert = dynamic_cast<const KFbxSurfaceLambert*>(pFbxMat);
const KFbxProperty lProperty = pFbxMat->FindProperty(KFbxSurfaceMaterial::sDiffuse);
if(lProperty.IsValid()){
int lNbTex = lProperty.GetSrcObjectCount(KFbxTexture::ClassId);
for (int lTextureIndex = 0; lTextureIndex < lNbTex; lTextureIndex++)
{
const KFbxTexture* lTexture = KFbxCast<KFbxTexture>(lProperty.GetSrcObject(KFbxTexture::ClassId, lTextureIndex));
if(lTexture)
{
m_pTexture = m_textureMap.Get(lTexture);
}
//For now only allow 1 texture
break;
}
}
if (pFbxLambert)
{
fbxDouble3 color = pFbxLambert->GetDiffuseColor().Get();
double factor = pFbxLambert->GetDiffuseFactor().Get();
pOsgMat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(
static_cast<float>(color[0] * factor),
static_cast<float>(color[1] * factor),
static_cast<float>(color[2] * factor),
static_cast<float>(1.0 - pFbxLambert->GetTransparencyFactor().Get())));
color = pFbxLambert->GetAmbientColor().Get();
factor = pFbxLambert->GetAmbientFactor().Get();
pOsgMat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(
static_cast<float>(color[0] * factor),
static_cast<float>(color[1] * factor),
static_cast<float>(color[2] * factor),
1.0f));
color = pFbxLambert->GetEmissiveColor().Get();
factor = pFbxLambert->GetEmissiveFactor().Get();
pOsgMat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(
static_cast<float>(color[0] * factor),
static_cast<float>(color[1] * factor),
static_cast<float>(color[2] * factor),
1.0f));
if (const KFbxSurfacePhong* pFbxPhong = dynamic_cast<const KFbxSurfacePhong*>(pFbxLambert))
{
color = pFbxPhong->GetSpecularColor().Get();
factor = pFbxPhong->GetSpecularFactor().Get();
pOsgMat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(
static_cast<float>(color[0] * factor),
static_cast<float>(color[1] * factor),
static_cast<float>(color[2] * factor),
1.0f));
pOsgMat->setShininess(osg::Material::FRONT_AND_BACK,
static_cast<float>(pFbxPhong->GetShininess().Get()));
}
}
return pOsgMat;
}
};
osg::Quat makeQuat(const fbxDouble3& degrees, ERotationOrder fbxRotOrder)
{
double radiansX = osg::DegreesToRadians(degrees[0]);
double radiansY = osg::DegreesToRadians(degrees[1]);
double radiansZ = osg::DegreesToRadians(degrees[2]);
switch (fbxRotOrder)
{
case eEULER_XYZ:
return osg::Quat(
radiansX, osg::Vec3d(1,0,0),
radiansY, osg::Vec3d(0,1,0),
radiansZ, osg::Vec3d(0,0,1));
case eEULER_XZY:
return osg::Quat(
radiansX, osg::Vec3d(1,0,0),
radiansY, osg::Vec3d(0,0,1),
radiansZ, osg::Vec3d(0,1,0));
case eEULER_YZX:
return osg::Quat(
radiansX, osg::Vec3d(0,1,0),
radiansY, osg::Vec3d(0,0,1),
radiansZ, osg::Vec3d(1,0,0));
case eEULER_YXZ:
return osg::Quat(
radiansX, osg::Vec3d(0,1,0),
radiansY, osg::Vec3d(1,0,0),
radiansZ, osg::Vec3d(0,0,1));
case eEULER_ZXY:
return osg::Quat(
radiansX, osg::Vec3d(0,0,1),
radiansY, osg::Vec3d(1,0,0),
radiansZ, osg::Vec3d(0,1,0));
case eEULER_ZYX:
return osg::Quat(
radiansX, osg::Vec3d(0,0,1),
radiansY, osg::Vec3d(0,1,0),
radiansZ, osg::Vec3d(1,0,0));
case eSPHERIC_XYZ:
{
//I don't know what eSPHERIC_XYZ means, so this is a complete guess.
osg::Quat quat;
quat.makeRotate(osg::Vec3d(1.0, 0.0, 0.0), osg::Vec3d(degrees[0], degrees[1], degrees[2]));
return quat;
}
default:
osg::notify(osg::WARN) << "Invalid FBX rotation mode." << std::endl;
return osg::Quat();
}
}
void makeLocalMatrix(const KFbxNode* pNode, osg::Matrix& m)
{
/*From http://area.autodesk.com/forum/autodesk-fbx/fbx-sdk/the-makeup-of-the-local-matrix-of-an-kfbxnode/
Local Matrix = LclTranslation * RotationOffset * RotationPivot *
PreRotation * LclRotation * PostRotation * RotationPivotInverse *
ScalingOffset * ScalingPivot * LclScaling * ScalingPivotInverse
LocalTranslation : translate (xform -query -translation)
RotationOffset: translation compensates for the change in the rotate pivot point (xform -q -rotateTranslation)
RotationPivot: current rotate pivot position (xform -q -rotatePivot)
PreRotation : joint orientation(pre rotation)
LocalRotation: rotate transform (xform -q -rotation & xform -q -rotateOrder)
PostRotation : rotate axis (xform -q -rotateAxis)
RotationPivotInverse: inverse of RotationPivot
ScalingOffset: translation compensates for the change in the scale pivot point (xform -q -scaleTranslation)
ScalingPivot: current scale pivot position (xform -q -scalePivot)
LocalScaling: scale transform (xform -q -scale)
ScalingPivotInverse: inverse of ScalingPivot
*/
ERotationOrder fbxRotOrder = pNode->RotationOrder.Get();
fbxDouble3 fbxLclPos = pNode->LclTranslation.Get();
fbxDouble3 fbxRotOff = pNode->RotationOffset.Get();
fbxDouble3 fbxRotPiv = pNode->RotationPivot.Get();
fbxDouble3 fbxPreRot = pNode->PreRotation.Get();
fbxDouble3 fbxLclRot = pNode->LclRotation.Get();
fbxDouble3 fbxPostRot = pNode->PostRotation.Get();
fbxDouble3 fbxSclOff = pNode->ScalingOffset.Get();
fbxDouble3 fbxSclPiv = pNode->ScalingPivot.Get();
fbxDouble3 fbxLclScl = pNode->LclScaling.Get();
m.makeTranslate(osg::Vec3d(
fbxLclPos[0] + fbxRotOff[0] + fbxRotPiv[0],
fbxLclPos[1] + fbxRotOff[1] + fbxRotPiv[1],
fbxLclPos[2] + fbxRotOff[2] + fbxRotPiv[2]));
m.preMultRotate(
makeQuat(fbxPostRot, fbxRotOrder) *
makeQuat(fbxLclRot, fbxRotOrder) *
makeQuat(fbxPreRot, fbxRotOrder));
m.preMultTranslate(osg::Vec3d(
fbxSclOff[0] + fbxSclPiv[0] - fbxRotPiv[0],
fbxSclOff[1] + fbxSclPiv[1] - fbxRotPiv[1],
fbxSclOff[2] + fbxSclPiv[2] - fbxRotPiv[2]));
m.preMultScale(osg::Vec3d(fbxLclScl[0], fbxLclScl[1], fbxLclScl[2]));
m.preMultTranslate(osg::Vec3d(
-fbxSclPiv[0],
-fbxSclPiv[1],
-fbxSclPiv[2]));
}
void getApproximateTransform(const KFbxNode* pNode, osg::Vec3& trans, osg::Quat& quat, osg::Vec3& scale)
{
ERotationOrder fbxRotOrder = pNode->RotationOrder.Get();
fbxDouble3 fbxLclPos = pNode->LclTranslation.Get();
//fbxDouble3 fbxRotOff = pNode->RotationOffset.Get();
//fbxDouble3 fbxRotPiv = pNode->RotationPivot.Get();
fbxDouble3 fbxPreRot = pNode->PreRotation.Get();
fbxDouble3 fbxLclRot = pNode->LclRotation.Get();
fbxDouble3 fbxPostRot = pNode->PostRotation.Get();
//fbxDouble3 fbxSclOff = pNode->ScalingOffset.Get();
//fbxDouble3 fbxSclPiv = pNode->ScalingPivot.Get();
fbxDouble3 fbxLclScl = pNode->LclScaling.Get();
trans.set(
static_cast<float>(fbxLclPos[0]),
static_cast<float>(fbxLclPos[1]),
static_cast<float>(fbxLclPos[2]));
quat =
makeQuat(fbxPostRot, fbxRotOrder) *
makeQuat(fbxLclRot, fbxRotOrder) *
makeQuat(fbxPreRot, fbxRotOrder);
scale.set(
static_cast<float>(fbxLclScl[0]),
static_cast<float>(fbxLclScl[1]),
static_cast<float>(fbxLclScl[2]));
}
void getApproximateTransform(const KFbxNode* pNode, osg::Vec3& trans, osg::Vec3& euler, osg::Vec3& scale)
{
//ERotationOrder fbxRotOrder = pNode->RotationOrder.Get();
fbxDouble3 fbxLclPos = pNode->LclTranslation.Get();
//fbxDouble3 fbxRotOff = pNode->RotationOffset.Get();
//fbxDouble3 fbxRotPiv = pNode->RotationPivot.Get();
fbxDouble3 fbxPreRot = pNode->PreRotation.Get();
fbxDouble3 fbxLclRot = pNode->LclRotation.Get();
fbxDouble3 fbxPostRot = pNode->PostRotation.Get();
//fbxDouble3 fbxSclOff = pNode->ScalingOffset.Get();
//fbxDouble3 fbxSclPiv = pNode->ScalingPivot.Get();
fbxDouble3 fbxLclScl = pNode->LclScaling.Get();
trans.set(
static_cast<float>(fbxLclPos[0]),
static_cast<float>(fbxLclPos[1]),
static_cast<float>(fbxLclPos[2]));
//TODO: Convert each rotation to a quaternion, concatenate them and extract euler from that.
euler.set(
osg::DegreesToRadians(static_cast<float>(fbxPreRot[0] + fbxLclRot[0] + fbxPostRot[0])),
osg::DegreesToRadians(static_cast<float>(fbxPreRot[1] + fbxLclRot[1] + fbxPostRot[1])),
osg::DegreesToRadians(static_cast<float>(fbxPreRot[2] + fbxLclRot[2] + fbxPostRot[2])));
scale.set(
static_cast<float>(fbxLclScl[0]),
static_cast<float>(fbxLclScl[1]),
static_cast<float>(fbxLclScl[2]));
}
bool readBindPose(KFbxSdkManager& pManager, KFbxNode* pNode,
osgAnimation::Bone* osgBone)
{
KArrayTemplate<KFbxPose*> pPoseList;
KArrayTemplate<int> pIndex;
if (!pNode || !KFbxPose::GetBindPoseContaining(
pManager, pNode, pPoseList, pIndex))
{
return false;
}
const double* pMat = pPoseList[0]->GetMatrix(pIndex[0]);
osgBone->setBindMatrixInBoneSpace(osg::Matrix(pMat));
return true;
}
osg::Group* createGroupNode(KFbxSdkManager& pSdkManager, KFbxNode* pNode,
const std::string& animName, const osg::Matrix& localMatrix, bool bNeedSkeleton)
{
if (bNeedSkeleton)
{
osgAnimation::Bone* osgBone = new osgAnimation::Bone;
osgBone->setDataVariance(osg::Object::DYNAMIC);
osgBone->setName(pNode->GetName());
osgBone->setDefaultUpdateCallback(animName);
readBindPose(pSdkManager, pNode, osgBone);
return osgBone;
}
else
{
bool bAnimated = !animName.empty();
if (!bAnimated && localMatrix.isIdentity())
{
osg::Group* pGroup = new osg::Group;
pGroup->setName(pNode->GetName());
return pGroup;
}
osg::MatrixTransform* pTransform = new osg::MatrixTransform(localMatrix);
pTransform->setName(pNode->GetName());
if (bAnimated)
{
osgAnimation::UpdateTransform* pUpdate = new osgAnimation::UpdateTransform(animName);
osg::Vec3 trans, rot, scale;
getApproximateTransform(pNode, trans, rot, scale);
pUpdate->getPosition()->setValue(trans);
pUpdate->getEuler()->setValue(rot);
pUpdate->getScale()->setValue(scale);
pTransform->setUpdateCallback(pUpdate);
}
return pTransform;
}
}
osgDB::ReaderWriter::ReadResult readFbxNode(
KFbxSdkManager& pSdkManager, KFbxNode* pNode,
osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager,
const std::string& dir, bool& bNeedSkeleton, int& nLightCount)
{
if (KFbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute())
{
if (lNodeAttribute->GetAttributeType() == KFbxNodeAttribute::eNURB ||
lNodeAttribute->GetAttributeType() == KFbxNodeAttribute::ePATCH)
{
KFbxGeometryConverter lConverter(&pSdkManager);
lConverter.TriangulateInPlace(pNode);
}
}
KFbxNodeAttribute::EAttributeType lAttributeType = KFbxNodeAttribute::eUNIDENTIFIED;
if (pNode->GetNodeAttribute())
{
lAttributeType = pNode->GetNodeAttribute()->GetAttributeType();
if (lAttributeType == KFbxNodeAttribute::eSKELETON)
{
bNeedSkeleton = true;
}
}
unsigned nMaterials = pNode->GetMaterialCount();
std::vector<osg::ref_ptr<osg::Material>> materialList;
std::vector<osg::ref_ptr<osg::Texture>> textureList;
materialList.reserve(nMaterials);
typedef FbxToOsgMap<KFbxSurfaceMaterial, osg::Material, GetOsgMaterial> MaterialMap;
MaterialMap materialMap(dir);
for (unsigned i = 0; i < nMaterials; ++i)
{
materialList.push_back(materialMap.Get(pNode->GetMaterial(i)));
textureList.push_back(materialMap.m_convertFunc.m_pTexture);
}
osg::NodeList skeletal, children;
int nChildCount = pNode->GetChildCount();
for (int i = 0; i < nChildCount; ++i)
{
KFbxNode* pChildNode = pNode->GetChild(i);
if (pChildNode->GetParent() != pNode)
{
//workaround for bug that occurs in some files exported from Blender
continue;
}
bool bChildNeedSkeleton = false;
osgDB::ReaderWriter::ReadResult childResult = readFbxNode(
pSdkManager, pChildNode, pAnimationManager, dir,
bChildNeedSkeleton, nLightCount);
if (childResult.error())
{
return childResult;
}
else if (osg::Node* osgChild = childResult.getNode())
{
if (bChildNeedSkeleton)
{
bNeedSkeleton = true;
skeletal.push_back(osgChild);
}
else
{
children.push_back(osgChild);
}
}
}
std::string animName;
if (bNeedSkeleton)
{
animName = readFbxBoneAnimation(pNode, pAnimationManager,
pNode->GetName());
}
else
{
animName = readFbxAnimation(pNode, pAnimationManager, pNode->GetName());
}
osg::Matrix localMatrix;
makeLocalMatrix(pNode, localMatrix);
bool bLocalMatrixIdentity = localMatrix.isIdentity();
osg::ref_ptr<osg::Group> osgGroup;
bool bEmpty = children.empty() && !bNeedSkeleton;
switch (lAttributeType)
{
case KFbxNodeAttribute::eUNIDENTIFIED:
if (children.size() + skeletal.size() == 1)
{
if (children.size() == 1)
{
return osgDB::ReaderWriter::ReadResult(children.front().get());
}
else
{
return osgDB::ReaderWriter::ReadResult(skeletal.front().get());
}
}
break;
case KFbxNodeAttribute::eMESH:
{
osgDB::ReaderWriter::ReadResult meshRes = readFbxMesh(pNode,
pAnimationManager, materialList, textureList);
if (meshRes.error())
{
return meshRes;
}
else if (osg::Node* node = meshRes.getNode())
{
bEmpty = false;
if (animName.empty() &&
children.empty() &&
skeletal.empty() &&
bLocalMatrixIdentity)
{
return osgDB::ReaderWriter::ReadResult(node);
}
osgGroup = createGroupNode(pSdkManager, pNode, animName, localMatrix, bNeedSkeleton);
osgGroup->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL,osg::StateAttribute::ON);
osgGroup->addChild(node);
}
}
break;
case KFbxNodeAttribute::eCAMERA:
case KFbxNodeAttribute::eLIGHT:
{
osgDB::ReaderWriter::ReadResult res =
lAttributeType == KFbxNodeAttribute::eCAMERA ?
readFbxCamera(pNode) : readFbxLight(pNode, nLightCount);
if (res.error())
{
return res;
}
else if (osg::Group* resGroup = dynamic_cast<osg::Group*>(res.getObject()))
{
bEmpty = false;
if (animName.empty() &&
bLocalMatrixIdentity)
{
osgGroup = resGroup;
}
else
{
osgGroup = createGroupNode(pSdkManager, pNode, animName,
localMatrix, bNeedSkeleton);
osgGroup->addChild(resGroup);
}
}
}
break;
}
if (bEmpty)
{
osgDB::ReaderWriter::ReadResult(0);
}
if (!osgGroup) osgGroup = createGroupNode(pSdkManager, pNode, animName, localMatrix, bNeedSkeleton);
for (osg::NodeList::iterator it = skeletal.begin(); it != skeletal.end(); ++it)
{
osgGroup->addChild(it->get());
}
for (osg::NodeList::iterator it = children.begin(); it != children.end(); ++it)
{
osgGroup->addChild(it->get());
}
return osgDB::ReaderWriter::ReadResult(osgGroup.get());
}

View File

@ -0,0 +1,17 @@
#ifndef FBXRNODE_H
#define FBXRNODE_H
namespace osgAnimation
{
class AnimationManagerBase;
}
osgDB::ReaderWriter::ReadResult readFbxNode(
FBXFILESDK_NAMESPACE::KFbxSdkManager& pSdkManager,
FBXFILESDK_NAMESPACE::KFbxNode* pNode,
osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager,
const std::string& dir,
bool& bNeedSkeleton,
int& nLightCount);
#endif

View File

@ -164,59 +164,59 @@ BEGIN_VALUE_REFLECTOR(osgWidget::EventInterface)
____EventInterface__C5_EventInterface_R1,
"",
"");
I_Method1(bool, focus, IN, osgWidget::WindowManager *, x,
I_Method1(bool, focus, IN, const osgWidget::WindowManager *, x,
Properties::VIRTUAL,
__bool__focus__WindowManager_P1,
__bool__focus__C5_WindowManager_P1,
"",
"");
I_Method1(bool, unfocus, IN, osgWidget::WindowManager *, x,
I_Method1(bool, unfocus, IN, const osgWidget::WindowManager *, x,
Properties::VIRTUAL,
__bool__unfocus__WindowManager_P1,
__bool__unfocus__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mouseEnter, IN, double, x, IN, double, x, IN, osgWidget::WindowManager *, x,
I_Method3(bool, mouseEnter, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::VIRTUAL,
__bool__mouseEnter__double__double__WindowManager_P1,
__bool__mouseEnter__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mouseOver, IN, double, x, IN, double, x, IN, osgWidget::WindowManager *, x,
I_Method3(bool, mouseOver, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::VIRTUAL,
__bool__mouseOver__double__double__WindowManager_P1,
__bool__mouseOver__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mouseLeave, IN, double, x, IN, double, x, IN, osgWidget::WindowManager *, x,
I_Method3(bool, mouseLeave, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::VIRTUAL,
__bool__mouseLeave__double__double__WindowManager_P1,
__bool__mouseLeave__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mouseDrag, IN, double, x, IN, double, x, IN, osgWidget::WindowManager *, x,
I_Method3(bool, mouseDrag, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::VIRTUAL,
__bool__mouseDrag__double__double__WindowManager_P1,
__bool__mouseDrag__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mousePush, IN, double, x, IN, double, x, IN, osgWidget::WindowManager *, x,
I_Method3(bool, mousePush, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::VIRTUAL,
__bool__mousePush__double__double__WindowManager_P1,
__bool__mousePush__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mouseRelease, IN, double, x, IN, double, x, IN, osgWidget::WindowManager *, x,
I_Method3(bool, mouseRelease, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::VIRTUAL,
__bool__mouseRelease__double__double__WindowManager_P1,
__bool__mouseRelease__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mouseScroll, IN, double, x, IN, double, x, IN, osgWidget::WindowManager *, x,
I_Method3(bool, mouseScroll, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::VIRTUAL,
__bool__mouseScroll__double__double__WindowManager_P1,
__bool__mouseScroll__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, keyDown, IN, int, x, IN, int, x, IN, osgWidget::WindowManager *, x,
I_Method3(bool, keyDown, IN, int, x, IN, int, x, IN, const osgWidget::WindowManager *, x,
Properties::VIRTUAL,
__bool__keyDown__int__int__WindowManager_P1,
__bool__keyDown__int__int__C5_WindowManager_P1,
"",
"");
I_Method3(bool, keyUp, IN, int, x, IN, int, x, IN, osgWidget::WindowManager *, x,
I_Method3(bool, keyUp, IN, int, x, IN, int, x, IN, const osgWidget::WindowManager *, x,
Properties::VIRTUAL,
__bool__keyUp__int__int__WindowManager_P1,
__bool__keyUp__int__int__C5_WindowManager_P1,
"",
"");
I_Method1(void, setEventMask, IN, unsigned int, mask,

View File

@ -64,47 +64,47 @@ BEGIN_OBJECT_REFLECTOR(osgWidget::NotifyWidget)
"",
"");
I_Method1(bool, focus, IN, const osgWidget::WindowManager *, x,
Properties::NON_VIRTUAL,
Properties::VIRTUAL,
__bool__focus__C5_WindowManager_P1,
"",
"");
I_Method1(bool, unfocus, IN, const osgWidget::WindowManager *, x,
Properties::NON_VIRTUAL,
Properties::VIRTUAL,
__bool__unfocus__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mouseEnter, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::NON_VIRTUAL,
Properties::VIRTUAL,
__bool__mouseEnter__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mouseOver, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::NON_VIRTUAL,
Properties::VIRTUAL,
__bool__mouseOver__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mouseLeave, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::NON_VIRTUAL,
Properties::VIRTUAL,
__bool__mouseLeave__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mouseDrag, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::NON_VIRTUAL,
Properties::VIRTUAL,
__bool__mouseDrag__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mousePush, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::NON_VIRTUAL,
Properties::VIRTUAL,
__bool__mousePush__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mouseRelease, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::NON_VIRTUAL,
Properties::VIRTUAL,
__bool__mouseRelease__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mouseScroll, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::NON_VIRTUAL,
Properties::VIRTUAL,
__bool__mouseScroll__double__double__C5_WindowManager_P1,
"",
"");
@ -157,47 +157,47 @@ BEGIN_OBJECT_REFLECTOR(osgWidget::NullWidget)
"",
"");
I_Method1(bool, focus, IN, const osgWidget::WindowManager *, x,
Properties::NON_VIRTUAL,
Properties::VIRTUAL,
__bool__focus__C5_WindowManager_P1,
"",
"");
I_Method1(bool, unfocus, IN, const osgWidget::WindowManager *, x,
Properties::NON_VIRTUAL,
Properties::VIRTUAL,
__bool__unfocus__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mouseEnter, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::NON_VIRTUAL,
Properties::VIRTUAL,
__bool__mouseEnter__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mouseOver, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::NON_VIRTUAL,
Properties::VIRTUAL,
__bool__mouseOver__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mouseLeave, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::NON_VIRTUAL,
Properties::VIRTUAL,
__bool__mouseLeave__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mouseDrag, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::NON_VIRTUAL,
Properties::VIRTUAL,
__bool__mouseDrag__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mousePush, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::NON_VIRTUAL,
Properties::VIRTUAL,
__bool__mousePush__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mouseRelease, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::NON_VIRTUAL,
Properties::VIRTUAL,
__bool__mouseRelease__double__double__C5_WindowManager_P1,
"",
"");
I_Method3(bool, mouseScroll, IN, double, x, IN, double, x, IN, const osgWidget::WindowManager *, x,
Properties::NON_VIRTUAL,
Properties::VIRTUAL,
__bool__mouseScroll__double__double__C5_WindowManager_P1,
"",
"");