diff --git a/CMakeLists.txt b/CMakeLists.txt index 667421266..dd35e4799 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/CMakeModules/FindFBX.cmake b/CMakeModules/FindFBX.cmake new file mode 100644 index 000000000..7716e885d --- /dev/null +++ b/CMakeModules/FindFBX.cmake @@ -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) diff --git a/src/osgPlugins/CMakeLists.txt b/src/osgPlugins/CMakeLists.txt index 4bc8b365f..10feaf03b 100644 --- a/src/osgPlugins/CMakeLists.txt +++ b/src/osgPlugins/CMakeLists.txt @@ -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) diff --git a/src/osgPlugins/fbx/CMakeLists.txt b/src/osgPlugins/fbx/CMakeLists.txt new file mode 100644 index 000000000..858fa1822 --- /dev/null +++ b/src/osgPlugins/fbx/CMakeLists.txt @@ -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) diff --git a/src/osgPlugins/fbx/ReaderWriterFBX.cpp b/src/osgPlugins/fbx/ReaderWriterFBX.cpp new file mode 100644 index 000000000..612dbf0c4 --- /dev/null +++ b/src/osgPlugins/fbx/ReaderWriterFBX.cpp @@ -0,0 +1,168 @@ +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#if defined(_MSC_VER) + #pragma warning( disable : 4505 ) +#endif +#include + +#include "ReaderWriterFBX.h" +#include "fbxRNode.h" + +osgDB::ReaderWriter::ReadResult +ReaderWriterFBX::readNode(const std::string& utf8filename, + const osgDB::ReaderWriter::Options* options) const +{ + OpenThreads::ScopedLock 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 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) diff --git a/src/osgPlugins/fbx/ReaderWriterFBX.h b/src/osgPlugins/fbx/ReaderWriterFBX.h new file mode 100644 index 000000000..3055304a7 --- /dev/null +++ b/src/osgPlugins/fbx/ReaderWriterFBX.h @@ -0,0 +1,30 @@ +#ifndef READERWRITERFBX_H +#define READERWRITERFBX_H + +#include +#include + +/////////////////////////////////////////////////////////////////////////// +// 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 diff --git a/src/osgPlugins/fbx/fbxRAnimation.cpp b/src/osgPlugins/fbx/fbxRAnimation.cpp new file mode 100644 index 000000000..01bdeda63 --- /dev/null +++ b/src/osgPlugins/fbx/fbxRAnimation.cpp @@ -0,0 +1,310 @@ +#include + +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) + #pragma warning( disable : 4505 ) +#endif +#include +#include + +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 >& keyFrameCntr) +{ + KFCurve* curves[3] = {curveX, curveY, curveZ}; + + typedef std::set TimeSet; + typedef std::map 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(pCurve->GetValue()) * scalar; + } + + for (int i = 0; i < nKeys; ++i) + { + KFCurveKey key = pCurve->KeyGet(i); + float fTime = static_cast(key.GetTime().GetSecondDouble()); + times.insert(fTime); + curveTimeMap[nCurve][fTime] = static_cast(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& 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 > KeyFrameCntr; + KeyFrameCntr eulerFrameCntr; + readKeys(curveX, curveY, curveZ, static_cast(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 &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& 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(fbxBaseValue[0]), + -static_cast(fbxBaseValue[1]), + -static_cast(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( + *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& 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(fbxPreRot[0] + fbxPostRot[0]), + static_cast(fbxPreRot[1] + fbxPostRot[1]), + static_cast(fbxPreRot[2] + fbxPostRot[2])); + + osgAnimation::Channel* pRotationChannel = readFbxChannels( + pNode->LclRotation, pTakeName, targetName, "euler", eulerOffset, static_cast(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& 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& 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; +} diff --git a/src/osgPlugins/fbx/fbxRAnimation.h b/src/osgPlugins/fbx/fbxRAnimation.h new file mode 100644 index 000000000..60a9f152e --- /dev/null +++ b/src/osgPlugins/fbx/fbxRAnimation.h @@ -0,0 +1,16 @@ +#ifndef FBXRANIMATION_H +#define FBXRANIMATION_H + +#include + +std::string readFbxBoneAnimation( + FBXFILESDK_NAMESPACE::KFbxNode*, + osg::ref_ptr&, + const char* targetName); + +std::string readFbxAnimation( + FBXFILESDK_NAMESPACE::KFbxNode*, + osg::ref_ptr&, + const char* targetName); + +#endif diff --git a/src/osgPlugins/fbx/fbxRCamera.cpp b/src/osgPlugins/fbx/fbxRCamera.cpp new file mode 100644 index 000000000..9607352a8 --- /dev/null +++ b/src/osgPlugins/fbx/fbxRCamera.cpp @@ -0,0 +1,53 @@ +#include +#include + +#include + +#if defined(_MSC_VER) +#pragma warning( disable : 4505 ) +#endif +#include + +#include "fbxRCamera.h" + +osgDB::ReaderWriter::ReadResult readFbxCamera(KFbxNode* pNode) +{ + const KFbxCamera* fbxCamera = dynamic_cast(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); +} diff --git a/src/osgPlugins/fbx/fbxRCamera.h b/src/osgPlugins/fbx/fbxRCamera.h new file mode 100644 index 000000000..09c65946f --- /dev/null +++ b/src/osgPlugins/fbx/fbxRCamera.h @@ -0,0 +1,10 @@ +#ifndef FBXRCAMERA_H +#define FBXRCAMERA_H + +#include +#include + +osgDB::ReaderWriter::ReadResult readFbxCamera( + FBXFILESDK_NAMESPACE::KFbxNode* pNode); + +#endif diff --git a/src/osgPlugins/fbx/fbxRLight.cpp b/src/osgPlugins/fbx/fbxRLight.cpp new file mode 100644 index 000000000..f643f6090 --- /dev/null +++ b/src/osgPlugins/fbx/fbxRLight.cpp @@ -0,0 +1,96 @@ +#include + +#include + +#if defined(_MSC_VER) +#pragma warning( disable : 4505 ) +#endif +#include + +#include "fbxRLight.h" + +osgDB::ReaderWriter::ReadResult readFbxLight(KFbxNode* pNode, int& nLightCount) +{ + const KFbxLight* fbxLight = dynamic_cast(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(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(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(fbxColor[0]), + static_cast(fbxColor[1]), + static_cast(fbxColor[2])); + } + if (fbxLight->Intensity.IsValid()) + { + osgDiffuseSpecular *= static_cast(fbxLight->Intensity.Get()) * 0.01f; + } + if (fbxLight->ShadowColor.IsValid()) + { + fbxDouble3 fbxShadowColor = fbxLight->ShadowColor.Get(); + osgAmbient.set( + static_cast(fbxShadowColor[0]), + static_cast(fbxShadowColor[1]), + static_cast(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); +} diff --git a/src/osgPlugins/fbx/fbxRLight.h b/src/osgPlugins/fbx/fbxRLight.h new file mode 100644 index 000000000..96872cb96 --- /dev/null +++ b/src/osgPlugins/fbx/fbxRLight.h @@ -0,0 +1,10 @@ +#ifndef FBXRLIGHT_H +#define FBXRLIGHT_H + +#include +#include + +osgDB::ReaderWriter::ReadResult readFbxLight( + FBXFILESDK_NAMESPACE::KFbxNode* pNode, int& nLightCount); + +#endif diff --git a/src/osgPlugins/fbx/fbxRMesh.cpp b/src/osgPlugins/fbx/fbxRMesh.cpp new file mode 100644 index 000000000..26bfb4271 --- /dev/null +++ b/src/osgPlugins/fbx/fbxRMesh.cpp @@ -0,0 +1,547 @@ +#include +#include + +#include + +#include + +#include +#include +#include + +#if defined(_MSC_VER) +#pragma warning( disable : 4505 ) +#endif +#include + +#include "fbxRMesh.h" + +enum GeometryType +{ + GEOMETRY_STATIC, + GEOMETRY_RIG, + GEOMETRY_MORPH +}; + +osg::Vec3 convertVec3(const KFbxVector4& v) +{ + return osg::Vec3( + static_cast(v[0]), + static_cast(v[1]), + static_cast(v[2])); +} + +osg::Vec2 convertVec2(const KFbxVector2& v) +{ + return osg::Vec2( + static_cast(v[0]), + static_cast(v[1])); +} + +osg::Vec4 convertColor(const KFbxColor& color) +{ + return osg::Vec4( + static_cast(color.mRed), + static_cast(color.mGreen), + static_cast(color.mBlue), + static_cast(color.mAlpha)); +} + +template +bool layerElementValid(const KFbxLayerElementTemplate* 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 +int getVertexIndex(const KFbxLayerElementTemplate* 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 +int getPolygonIndex(const KFbxLayerElementTemplate* 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 +FbxT getElement(const KFbxLayerElementTemplate* pLayerElement, + KFbxMesh* fbxMesh, + int nPolygon, int nPolyVertex, int nMeshVertex) +{ + return pLayerElement->GetDirectArray().GetAt(getVertexIndex( + pLayerElement, fbxMesh, nPolygon, nPolyVertex, nMeshVertex)); +} + +typedef std::map > GeometryMap; + +osg::Geometry* getGeometry(osg::Geode* pGeode, GeometryMap& geometryMap, + const std::vector>& materialList, + const std::vector>& 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 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>(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 &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& 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 >& keyFrameCntr = *pChannel->getOrCreateSampler()->getOrCreateKeyframeContainer(); + + int nKeys = pCurve->KeyGetCount(); + if (!nKeys) + { + float fValue = static_cast(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(key.GetTime().GetSecondDouble()); + float fValue = static_cast(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& pAnimationManager, + const std::vector>& materialList, + const std::vector>& 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 GIPair; + typedef std::multimap FbxToOsgVertexMap; + typedef std::map 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( + pGeometry->getVertexArray()); + osg::Vec3Array* pNormals = static_cast( + pGeometry->getNormalArray()); + osg::Vec2Array* pTexCoords = static_cast( + pGeometry->getTexCoordArray(0)); + osg::Vec4Array* pColors = static_cast( + 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(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(*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(*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( + pMorphTarget->getVertexArray()->clone(osg::CopyOp::DEEP_COPY_ARRAYS))); + if (pFbxShapeNormals) + { + if (osg::Array* pNormals = pMorphTarget->getNormalArray()) + { + pMorphTarget->setNormalArray(static_cast( + 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(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(*gi.first); + osg::Geometry* pGeometry = morphGeom.getMorphTarget(i).getGeometry(); + osg::Vec3Array* pVertices = static_cast(pGeometry->getVertexArray()); + (*pVertices)[gi.second] = vPos; + + if (pFbxShapeNormals) + { + if (osg::Vec3Array* pNormals = static_cast(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& pAnimationManager, + const std::vector>& materialList, + const std::vector>& textureList) +{ + KFbxMesh* lMesh = dynamic_cast(pNode->GetNodeAttribute()); + + if (!lMesh) + { + return osgDB::ReaderWriter::ReadResult::ERROR_IN_READING_FILE; + } + + return readMesh(pNode, lMesh, pAnimationManager, materialList, textureList, pNode->GetName()); +} diff --git a/src/osgPlugins/fbx/fbxRMesh.h b/src/osgPlugins/fbx/fbxRMesh.h new file mode 100644 index 000000000..20a9d5c95 --- /dev/null +++ b/src/osgPlugins/fbx/fbxRMesh.h @@ -0,0 +1,14 @@ +#ifndef FBXRMESH_H +#define FBXRMESH_H + +#include +#include +#include + +osgDB::ReaderWriter::ReadResult readFbxMesh( + FBXFILESDK_NAMESPACE::KFbxNode* pNode, + osg::ref_ptr& pAnimationManager, + const std::vector>&, + const std::vector>&); + +#endif diff --git a/src/osgPlugins/fbx/fbxRNode.cpp b/src/osgPlugins/fbx/fbxRNode.cpp new file mode 100644 index 000000000..cd48f97ce --- /dev/null +++ b/src/osgPlugins/fbx/fbxRNode.cpp @@ -0,0 +1,560 @@ +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#if defined(_MSC_VER) + #pragma warning( disable : 4505 ) +#endif +#include + +#include "fbxRAnimation.h" +#include "fbxRCamera.h" +#include "fbxRLight.h" +#include "fbxRMesh.h" + +template +class FbxToOsgMap +{ + std::map> m_map; +public: + ConvertFunc m_convertFunc; + + FbxToOsgMap(ConvertFunc convertFunc) : m_convertFunc(convertFunc) {} + + osg::ref_ptr Get(const FbxT* fbx) + { + if (!fbx) + return 0; + std::map>::iterator it = m_map.find(fbx); + if (it != m_map.end()) + { + return it->second; + } + osg::ref_ptr osgObj = m_convertFunc(fbx); + m_map.insert(std::pair>(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 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 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 TextureMap; + TextureMap m_textureMap; + +public: + osg::ref_ptr m_pTexture; + + GetOsgMaterial(const std::string& dir) : m_textureMap(GetOsgTexture(dir)){} + + osg::ref_ptr operator () (const KFbxSurfaceMaterial* pFbxMat) + { + osg::ref_ptr pOsgMat = new osg::Material; + + const KFbxSurfaceLambert* pFbxLambert = dynamic_cast(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(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(color[0] * factor), + static_cast(color[1] * factor), + static_cast(color[2] * factor), + static_cast(1.0 - pFbxLambert->GetTransparencyFactor().Get()))); + + color = pFbxLambert->GetAmbientColor().Get(); + factor = pFbxLambert->GetAmbientFactor().Get(); + pOsgMat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4( + static_cast(color[0] * factor), + static_cast(color[1] * factor), + static_cast(color[2] * factor), + 1.0f)); + + color = pFbxLambert->GetEmissiveColor().Get(); + factor = pFbxLambert->GetEmissiveFactor().Get(); + pOsgMat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4( + static_cast(color[0] * factor), + static_cast(color[1] * factor), + static_cast(color[2] * factor), + 1.0f)); + + if (const KFbxSurfacePhong* pFbxPhong = dynamic_cast(pFbxLambert)) + { + color = pFbxPhong->GetSpecularColor().Get(); + factor = pFbxPhong->GetSpecularFactor().Get(); + pOsgMat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4( + static_cast(color[0] * factor), + static_cast(color[1] * factor), + static_cast(color[2] * factor), + 1.0f)); + + pOsgMat->setShininess(osg::Material::FRONT_AND_BACK, + static_cast(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(fbxLclPos[0]), + static_cast(fbxLclPos[1]), + static_cast(fbxLclPos[2])); + + quat = + makeQuat(fbxPostRot, fbxRotOrder) * + makeQuat(fbxLclRot, fbxRotOrder) * + makeQuat(fbxPreRot, fbxRotOrder); + + scale.set( + static_cast(fbxLclScl[0]), + static_cast(fbxLclScl[1]), + static_cast(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(fbxLclPos[0]), + static_cast(fbxLclPos[1]), + static_cast(fbxLclPos[2])); + + //TODO: Convert each rotation to a quaternion, concatenate them and extract euler from that. + euler.set( + osg::DegreesToRadians(static_cast(fbxPreRot[0] + fbxLclRot[0] + fbxPostRot[0])), + osg::DegreesToRadians(static_cast(fbxPreRot[1] + fbxLclRot[1] + fbxPostRot[1])), + osg::DegreesToRadians(static_cast(fbxPreRot[2] + fbxLclRot[2] + fbxPostRot[2]))); + + scale.set( + static_cast(fbxLclScl[0]), + static_cast(fbxLclScl[1]), + static_cast(fbxLclScl[2])); +} + +bool readBindPose(KFbxSdkManager& pManager, KFbxNode* pNode, + osgAnimation::Bone* osgBone) +{ + KArrayTemplate pPoseList; + KArrayTemplate 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& 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> materialList; + std::vector> textureList; + materialList.reserve(nMaterials); + + typedef FbxToOsgMap 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 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(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()); +} diff --git a/src/osgPlugins/fbx/fbxRNode.h b/src/osgPlugins/fbx/fbxRNode.h new file mode 100644 index 000000000..a00ad2afe --- /dev/null +++ b/src/osgPlugins/fbx/fbxRNode.h @@ -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& pAnimationManager, + const std::string& dir, + bool& bNeedSkeleton, + int& nLightCount); + +#endif diff --git a/src/osgWrappers/osgWidget/EventInterface.cpp b/src/osgWrappers/osgWidget/EventInterface.cpp index bbc488099..aa0154074 100644 --- a/src/osgWrappers/osgWidget/EventInterface.cpp +++ b/src/osgWrappers/osgWidget/EventInterface.cpp @@ -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, diff --git a/src/osgWrappers/osgWidget/Widget.cpp b/src/osgWrappers/osgWidget/Widget.cpp index 9dbb81cd3..13d866080 100644 --- a/src/osgWrappers/osgWidget/Widget.cpp +++ b/src/osgWrappers/osgWidget/Widget.cpp @@ -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, "", "");