| [11109] | 1 | #include <cassert> |
|---|
| [10780] | 2 | #include <memory> |
|---|
| [11109] | 3 | #include <sstream> |
|---|
| [10780] | 4 | |
|---|
| [11109] | 5 | #include <osg/io_utils> |
|---|
| [10780] | 6 | #include <osg/Notify> |
|---|
| 7 | #include <osg/MatrixTransform> |
|---|
| 8 | #include <osg/Material> |
|---|
| 9 | #include <osg/Texture2D> |
|---|
| 10 | |
|---|
| 11 | #include <osgDB/FileNameUtils> |
|---|
| 12 | #include <osgDB/ReadFile> |
|---|
| 13 | |
|---|
| 14 | #include <osgAnimation/AnimationManagerBase> |
|---|
| [11109] | 15 | #include <osgAnimation/Bone> |
|---|
| [10780] | 16 | #include <osgAnimation/Skeleton> |
|---|
| [11109] | 17 | #include <osgAnimation/StackedMatrixElement> |
|---|
| 18 | #include <osgAnimation/StackedQuaternionElement> |
|---|
| 19 | #include <osgAnimation/StackedScaleElement> |
|---|
| 20 | #include <osgAnimation/StackedTranslateElement> |
|---|
| 21 | #include <osgAnimation/UpdateBone> |
|---|
| [10780] | 22 | |
|---|
| 23 | #if defined(_MSC_VER) |
|---|
| 24 | #pragma warning( disable : 4505 ) |
|---|
| 25 | #endif |
|---|
| 26 | #include <fbxsdk.h> |
|---|
| 27 | |
|---|
| 28 | #include "fbxRAnimation.h" |
|---|
| 29 | #include "fbxRCamera.h" |
|---|
| 30 | #include "fbxRLight.h" |
|---|
| 31 | #include "fbxRMesh.h" |
|---|
| [11109] | 32 | #include "fbxRNode.h" |
|---|
| 33 | #include "fbxMaterialToOsgStateSet.h" |
|---|
| [10780] | 34 | |
|---|
| 35 | osg::Quat makeQuat(const fbxDouble3& degrees, ERotationOrder fbxRotOrder) |
|---|
| 36 | { |
|---|
| 37 | double radiansX = osg::DegreesToRadians(degrees[0]); |
|---|
| 38 | double radiansY = osg::DegreesToRadians(degrees[1]); |
|---|
| 39 | double radiansZ = osg::DegreesToRadians(degrees[2]); |
|---|
| 40 | |
|---|
| 41 | switch (fbxRotOrder) |
|---|
| 42 | { |
|---|
| 43 | case eEULER_XYZ: |
|---|
| 44 | return osg::Quat( |
|---|
| 45 | radiansX, osg::Vec3d(1,0,0), |
|---|
| 46 | radiansY, osg::Vec3d(0,1,0), |
|---|
| 47 | radiansZ, osg::Vec3d(0,0,1)); |
|---|
| 48 | case eEULER_XZY: |
|---|
| 49 | return osg::Quat( |
|---|
| [11141] | 50 | radiansX, osg::Vec3d(1,0,0), |
|---|
| 51 | radiansZ, osg::Vec3d(0,0,1), |
|---|
| 52 | radiansY, osg::Vec3d(0,1,0)); |
|---|
| [10780] | 53 | case eEULER_YZX: |
|---|
| [11141] | 54 | return osg::Quat( |
|---|
| 55 | radiansY, osg::Vec3d(0,1,0), |
|---|
| 56 | radiansZ, osg::Vec3d(0,0,1), |
|---|
| 57 | radiansX, osg::Vec3d(1,0,0)); |
|---|
| [10780] | 58 | case eEULER_YXZ: |
|---|
| [11141] | 59 | return osg::Quat( |
|---|
| 60 | radiansY, osg::Vec3d(0,1,0), |
|---|
| 61 | radiansX, osg::Vec3d(1,0,0), |
|---|
| 62 | radiansZ, osg::Vec3d(0,0,1)); |
|---|
| [10780] | 63 | case eEULER_ZXY: |
|---|
| 64 | return osg::Quat( |
|---|
| [11139] | 65 | radiansZ, osg::Vec3d(0,0,1), |
|---|
| 66 | radiansX, osg::Vec3d(1,0,0), |
|---|
| 67 | radiansY, osg::Vec3d(0,1,0)); |
|---|
| [10780] | 68 | case eEULER_ZYX: |
|---|
| [11141] | 69 | return osg::Quat( |
|---|
| 70 | radiansZ, osg::Vec3d(0,0,1), |
|---|
| 71 | radiansY, osg::Vec3d(0,1,0), |
|---|
| 72 | radiansX, osg::Vec3d(1,0,0)); |
|---|
| [10780] | 73 | case eSPHERIC_XYZ: |
|---|
| 74 | { |
|---|
| 75 | |
|---|
| 76 | osg::Quat quat; |
|---|
| 77 | quat.makeRotate(osg::Vec3d(1.0, 0.0, 0.0), osg::Vec3d(degrees[0], degrees[1], degrees[2])); |
|---|
| 78 | return quat; |
|---|
| 79 | } |
|---|
| 80 | default: |
|---|
| 81 | osg::notify(osg::WARN) << "Invalid FBX rotation mode." << std::endl; |
|---|
| 82 | return osg::Quat(); |
|---|
| 83 | } |
|---|
| 84 | } |
|---|
| 85 | |
|---|
| 86 | void makeLocalMatrix(const KFbxNode* pNode, osg::Matrix& m) |
|---|
| 87 | { |
|---|
| 88 | |
|---|
| 89 | |
|---|
| 90 | |
|---|
| 91 | |
|---|
| 92 | |
|---|
| 93 | |
|---|
| 94 | |
|---|
| 95 | |
|---|
| 96 | |
|---|
| 97 | |
|---|
| 98 | |
|---|
| 99 | |
|---|
| 100 | |
|---|
| 101 | |
|---|
| 102 | |
|---|
| 103 | |
|---|
| 104 | |
|---|
| 105 | |
|---|
| 106 | |
|---|
| [11144] | 107 | |
|---|
| 108 | |
|---|
| [11141] | 109 | bool rotationActive = pNode->RotationActive.Get(); |
|---|
| [10780] | 110 | |
|---|
| [11141] | 111 | ERotationOrder fbxRotOrder = rotationActive ? pNode->RotationOrder.Get() : eEULER_XYZ; |
|---|
| 112 | |
|---|
| [10780] | 113 | fbxDouble3 fbxLclPos = pNode->LclTranslation.Get(); |
|---|
| 114 | fbxDouble3 fbxRotOff = pNode->RotationOffset.Get(); |
|---|
| 115 | fbxDouble3 fbxRotPiv = pNode->RotationPivot.Get(); |
|---|
| 116 | fbxDouble3 fbxPreRot = pNode->PreRotation.Get(); |
|---|
| 117 | fbxDouble3 fbxLclRot = pNode->LclRotation.Get(); |
|---|
| 118 | fbxDouble3 fbxPostRot = pNode->PostRotation.Get(); |
|---|
| 119 | fbxDouble3 fbxSclOff = pNode->ScalingOffset.Get(); |
|---|
| 120 | fbxDouble3 fbxSclPiv = pNode->ScalingPivot.Get(); |
|---|
| 121 | fbxDouble3 fbxLclScl = pNode->LclScaling.Get(); |
|---|
| 122 | |
|---|
| 123 | m.makeTranslate(osg::Vec3d( |
|---|
| 124 | fbxLclPos[0] + fbxRotOff[0] + fbxRotPiv[0], |
|---|
| 125 | fbxLclPos[1] + fbxRotOff[1] + fbxRotPiv[1], |
|---|
| 126 | fbxLclPos[2] + fbxRotOff[2] + fbxRotPiv[2])); |
|---|
| [11141] | 127 | if (rotationActive) |
|---|
| 128 | { |
|---|
| 129 | m.preMultRotate( |
|---|
| 130 | makeQuat(fbxPostRot, fbxRotOrder) * |
|---|
| 131 | makeQuat(fbxLclRot, fbxRotOrder) * |
|---|
| 132 | makeQuat(fbxPreRot, fbxRotOrder)); |
|---|
| 133 | } |
|---|
| 134 | else |
|---|
| 135 | { |
|---|
| 136 | m.preMultRotate(makeQuat(fbxLclRot, fbxRotOrder)); |
|---|
| 137 | } |
|---|
| [10780] | 138 | m.preMultTranslate(osg::Vec3d( |
|---|
| 139 | fbxSclOff[0] + fbxSclPiv[0] - fbxRotPiv[0], |
|---|
| 140 | fbxSclOff[1] + fbxSclPiv[1] - fbxRotPiv[1], |
|---|
| 141 | fbxSclOff[2] + fbxSclPiv[2] - fbxRotPiv[2])); |
|---|
| 142 | m.preMultScale(osg::Vec3d(fbxLclScl[0], fbxLclScl[1], fbxLclScl[2])); |
|---|
| 143 | m.preMultTranslate(osg::Vec3d( |
|---|
| 144 | -fbxSclPiv[0], |
|---|
| 145 | -fbxSclPiv[1], |
|---|
| 146 | -fbxSclPiv[2])); |
|---|
| 147 | } |
|---|
| 148 | |
|---|
| [11109] | 149 | void readTranslationElement(KFbxTypedProperty<fbxDouble3>& prop, |
|---|
| 150 | osgAnimation::UpdateMatrixTransform* pUpdate, |
|---|
| 151 | osg::Matrix& staticTransform) |
|---|
| 152 | { |
|---|
| 153 | fbxDouble3 fbxPropValue = prop.Get(); |
|---|
| 154 | osg::Vec3d val( |
|---|
| 155 | fbxPropValue[0], |
|---|
| 156 | fbxPropValue[1], |
|---|
| 157 | fbxPropValue[2]); |
|---|
| [10780] | 158 | |
|---|
| [11109] | 159 | if (prop.GetKFCurve(KFCURVENODE_T_X) || |
|---|
| 160 | prop.GetKFCurve(KFCURVENODE_T_Y) || |
|---|
| 161 | prop.GetKFCurve(KFCURVENODE_T_Z)) |
|---|
| 162 | { |
|---|
| 163 | if (!staticTransform.isIdentity()) |
|---|
| 164 | { |
|---|
| 165 | pUpdate->getStackedTransforms().push_back(new osgAnimation::StackedMatrixElement(staticTransform)); |
|---|
| 166 | staticTransform.makeIdentity(); |
|---|
| 167 | } |
|---|
| 168 | pUpdate->getStackedTransforms().push_back(new osgAnimation::StackedTranslateElement("translate", val)); |
|---|
| 169 | } |
|---|
| 170 | else |
|---|
| 171 | { |
|---|
| 172 | staticTransform.preMultTranslate(val); |
|---|
| 173 | } |
|---|
| [10780] | 174 | } |
|---|
| 175 | |
|---|
| [11109] | 176 | void readRotationElement(KFbxTypedProperty<fbxDouble3>& prop, |
|---|
| 177 | ERotationOrder fbxRotOrder, |
|---|
| 178 | osgAnimation::UpdateMatrixTransform* pUpdate, |
|---|
| 179 | osg::Matrix& staticTransform) |
|---|
| [10780] | 180 | { |
|---|
| [11109] | 181 | osg::Quat quat = makeQuat(prop.Get(), fbxRotOrder); |
|---|
| [10780] | 182 | |
|---|
| [11109] | 183 | if (prop.GetKFCurve(KFCURVENODE_R_X) || |
|---|
| 184 | prop.GetKFCurve(KFCURVENODE_R_Y) || |
|---|
| 185 | prop.GetKFCurve(KFCURVENODE_R_Z)) |
|---|
| 186 | { |
|---|
| 187 | if (!staticTransform.isIdentity()) |
|---|
| 188 | { |
|---|
| 189 | pUpdate->getStackedTransforms().push_back(new osgAnimation::StackedMatrixElement(staticTransform)); |
|---|
| 190 | staticTransform.makeIdentity(); |
|---|
| 191 | } |
|---|
| 192 | pUpdate->getStackedTransforms().push_back(new osgAnimation::StackedQuaternionElement("quaternion", quat)); |
|---|
| 193 | } |
|---|
| 194 | else |
|---|
| 195 | { |
|---|
| 196 | staticTransform.preMultRotate(quat); |
|---|
| 197 | } |
|---|
| 198 | } |
|---|
| [10780] | 199 | |
|---|
| [11109] | 200 | void readScaleElement(KFbxTypedProperty<fbxDouble3>& prop, |
|---|
| 201 | osgAnimation::UpdateMatrixTransform* pUpdate, |
|---|
| 202 | osg::Matrix& staticTransform) |
|---|
| 203 | { |
|---|
| 204 | fbxDouble3 fbxPropValue = prop.Get(); |
|---|
| 205 | osg::Vec3d val( |
|---|
| 206 | fbxPropValue[0], |
|---|
| 207 | fbxPropValue[1], |
|---|
| 208 | fbxPropValue[2]); |
|---|
| [10780] | 209 | |
|---|
| [11109] | 210 | if (prop.GetKFCurve(KFCURVENODE_S_X) || |
|---|
| 211 | prop.GetKFCurve(KFCURVENODE_S_Y) || |
|---|
| 212 | prop.GetKFCurve(KFCURVENODE_S_Z)) |
|---|
| 213 | { |
|---|
| 214 | if (!staticTransform.isIdentity()) |
|---|
| 215 | { |
|---|
| 216 | pUpdate->getStackedTransforms().push_back(new osgAnimation::StackedMatrixElement(staticTransform)); |
|---|
| 217 | staticTransform.makeIdentity(); |
|---|
| 218 | } |
|---|
| 219 | pUpdate->getStackedTransforms().push_back(new osgAnimation::StackedScaleElement("scale", val)); |
|---|
| 220 | } |
|---|
| 221 | else |
|---|
| 222 | { |
|---|
| 223 | staticTransform.preMultScale(val); |
|---|
| 224 | } |
|---|
| [10780] | 225 | } |
|---|
| 226 | |
|---|
| [11109] | 227 | void readUpdateMatrixTransform(osgAnimation::UpdateMatrixTransform* pUpdate, KFbxNode* pNode) |
|---|
| [10780] | 228 | { |
|---|
| [11109] | 229 | osg::Matrix staticTransform; |
|---|
| 230 | |
|---|
| 231 | readTranslationElement(pNode->LclTranslation, pUpdate, staticTransform); |
|---|
| 232 | |
|---|
| 233 | fbxDouble3 fbxRotOffset = pNode->RotationOffset.Get(); |
|---|
| 234 | fbxDouble3 fbxRotPiv = pNode->RotationPivot.Get(); |
|---|
| 235 | staticTransform.preMultTranslate(osg::Vec3d( |
|---|
| 236 | fbxRotPiv[0] + fbxRotOffset[0], |
|---|
| 237 | fbxRotPiv[1] + fbxRotOffset[1], |
|---|
| 238 | fbxRotPiv[2] + fbxRotOffset[2])); |
|---|
| 239 | |
|---|
| [11144] | 240 | |
|---|
| 241 | |
|---|
| [11141] | 242 | bool rotationActive = pNode->RotationActive.Get(); |
|---|
| [11109] | 243 | |
|---|
| [11141] | 244 | ERotationOrder fbxRotOrder = (rotationActive && pNode->RotationOrder.IsValid()) ? |
|---|
| 245 | pNode->RotationOrder.Get() : eEULER_XYZ; |
|---|
| [11109] | 246 | |
|---|
| [11141] | 247 | if (rotationActive) |
|---|
| 248 | { |
|---|
| 249 | staticTransform.preMultRotate(makeQuat(pNode->PreRotation.Get(), fbxRotOrder)); |
|---|
| 250 | } |
|---|
| 251 | |
|---|
| [11109] | 252 | readRotationElement(pNode->LclRotation, fbxRotOrder, pUpdate, staticTransform); |
|---|
| 253 | |
|---|
| [11141] | 254 | if (rotationActive) |
|---|
| 255 | { |
|---|
| 256 | staticTransform.preMultRotate(makeQuat(pNode->PostRotation.Get(), fbxRotOrder)); |
|---|
| 257 | } |
|---|
| [11109] | 258 | |
|---|
| 259 | fbxDouble3 fbxSclOffset = pNode->ScalingOffset.Get(); |
|---|
| 260 | fbxDouble3 fbxSclPiv = pNode->ScalingPivot.Get(); |
|---|
| 261 | staticTransform.preMultTranslate(osg::Vec3d( |
|---|
| 262 | fbxSclOffset[0] + fbxSclPiv[0] - fbxRotPiv[0], |
|---|
| 263 | fbxSclOffset[1] + fbxSclPiv[1] - fbxRotPiv[1], |
|---|
| 264 | fbxSclOffset[2] + fbxSclPiv[2] - fbxRotPiv[2])); |
|---|
| 265 | |
|---|
| 266 | readScaleElement(pNode->LclScaling, pUpdate, staticTransform); |
|---|
| 267 | |
|---|
| 268 | staticTransform.preMultTranslate(osg::Vec3d( |
|---|
| 269 | -fbxSclPiv[0], |
|---|
| 270 | -fbxSclPiv[1], |
|---|
| 271 | -fbxSclPiv[2])); |
|---|
| 272 | |
|---|
| 273 | if (!staticTransform.isIdentity()) |
|---|
| [10780] | 274 | { |
|---|
| [11109] | 275 | pUpdate->getStackedTransforms().push_back(new osgAnimation::StackedMatrixElement(staticTransform)); |
|---|
| [10780] | 276 | } |
|---|
| 277 | } |
|---|
| 278 | |
|---|
| 279 | osg::Group* createGroupNode(KFbxSdkManager& pSdkManager, KFbxNode* pNode, |
|---|
| [11139] | 280 | const std::string& animName, const osg::Matrix& localMatrix, bool bNeedSkeleton, |
|---|
| [11141] | 281 | std::map<KFbxNode*, osg::Node*>& nodeMap) |
|---|
| [10780] | 282 | { |
|---|
| 283 | if (bNeedSkeleton) |
|---|
| 284 | { |
|---|
| 285 | osgAnimation::Bone* osgBone = new osgAnimation::Bone; |
|---|
| 286 | osgBone->setDataVariance(osg::Object::DYNAMIC); |
|---|
| 287 | osgBone->setName(pNode->GetName()); |
|---|
| [11109] | 288 | osgAnimation::UpdateBone* pUpdate = new osgAnimation::UpdateBone(animName); |
|---|
| 289 | readUpdateMatrixTransform(pUpdate, pNode); |
|---|
| 290 | osgBone->setUpdateCallback(pUpdate); |
|---|
| [10780] | 291 | |
|---|
| [11141] | 292 | nodeMap.insert(std::pair<KFbxNode*, osg::Node*>(pNode, osgBone)); |
|---|
| [10780] | 293 | |
|---|
| 294 | return osgBone; |
|---|
| 295 | } |
|---|
| 296 | else |
|---|
| 297 | { |
|---|
| 298 | bool bAnimated = !animName.empty(); |
|---|
| 299 | if (!bAnimated && localMatrix.isIdentity()) |
|---|
| 300 | { |
|---|
| 301 | osg::Group* pGroup = new osg::Group; |
|---|
| 302 | pGroup->setName(pNode->GetName()); |
|---|
| 303 | return pGroup; |
|---|
| 304 | } |
|---|
| 305 | |
|---|
| 306 | osg::MatrixTransform* pTransform = new osg::MatrixTransform(localMatrix); |
|---|
| 307 | pTransform->setName(pNode->GetName()); |
|---|
| [11109] | 308 | |
|---|
| [10780] | 309 | if (bAnimated) |
|---|
| 310 | { |
|---|
| [11109] | 311 | osgAnimation::UpdateMatrixTransform* pUpdate = new osgAnimation::UpdateMatrixTransform(animName); |
|---|
| 312 | readUpdateMatrixTransform(pUpdate, pNode); |
|---|
| [10780] | 313 | pTransform->setUpdateCallback(pUpdate); |
|---|
| 314 | } |
|---|
| [11109] | 315 | |
|---|
| [10780] | 316 | return pTransform; |
|---|
| 317 | } |
|---|
| 318 | } |
|---|
| 319 | |
|---|
| 320 | osgDB::ReaderWriter::ReadResult readFbxNode( |
|---|
| 321 | KFbxSdkManager& pSdkManager, KFbxNode* pNode, |
|---|
| 322 | osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager, |
|---|
| [11139] | 323 | bool& bIsBone, int& nLightCount, |
|---|
| [11109] | 324 | FbxMaterialToOsgStateSet& fbxMaterialToOsgStateSet, |
|---|
| [11141] | 325 | std::map<KFbxNode*, osg::Node*>& nodeMap, |
|---|
| [11153] | 326 | BindMatrixMap& boneBindMatrices, |
|---|
| [11262] | 327 | const std::set<const KFbxNode*>& fbxSkeletons, |
|---|
| [11141] | 328 | std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap, |
|---|
| [11109] | 329 | const osgDB::Options* options) |
|---|
| [10780] | 330 | { |
|---|
| 331 | if (KFbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute()) |
|---|
| 332 | { |
|---|
| 333 | if (lNodeAttribute->GetAttributeType() == KFbxNodeAttribute::eNURB || |
|---|
| 334 | lNodeAttribute->GetAttributeType() == KFbxNodeAttribute::ePATCH) |
|---|
| 335 | { |
|---|
| 336 | KFbxGeometryConverter lConverter(&pSdkManager); |
|---|
| 337 | lConverter.TriangulateInPlace(pNode); |
|---|
| 338 | } |
|---|
| 339 | } |
|---|
| 340 | |
|---|
| [11141] | 341 | bIsBone = false; |
|---|
| 342 | bool bCreateSkeleton = false; |
|---|
| [11139] | 343 | |
|---|
| [10780] | 344 | KFbxNodeAttribute::EAttributeType lAttributeType = KFbxNodeAttribute::eUNIDENTIFIED; |
|---|
| 345 | if (pNode->GetNodeAttribute()) |
|---|
| 346 | { |
|---|
| 347 | lAttributeType = pNode->GetNodeAttribute()->GetAttributeType(); |
|---|
| 348 | if (lAttributeType == KFbxNodeAttribute::eSKELETON) |
|---|
| 349 | { |
|---|
| [11139] | 350 | bIsBone = true; |
|---|
| [10780] | 351 | } |
|---|
| 352 | } |
|---|
| 353 | |
|---|
| [11262] | 354 | if (!bIsBone && fbxSkeletons.find(pNode) != fbxSkeletons.end()) |
|---|
| 355 | { |
|---|
| 356 | bIsBone = true; |
|---|
| 357 | } |
|---|
| 358 | |
|---|
| [10780] | 359 | unsigned nMaterials = pNode->GetMaterialCount(); |
|---|
| [11109] | 360 | std::vector<StateSetContent > stateSetList; |
|---|
| [10780] | 361 | |
|---|
| 362 | for (unsigned i = 0; i < nMaterials; ++i) |
|---|
| 363 | { |
|---|
| [11109] | 364 | KFbxSurfaceMaterial* fbxMaterial = pNode->GetMaterial(i); |
|---|
| 365 | assert(fbxMaterial); |
|---|
| 366 | stateSetList.push_back(fbxMaterialToOsgStateSet.convert(fbxMaterial)); |
|---|
| [10780] | 367 | } |
|---|
| 368 | |
|---|
| 369 | osg::NodeList skeletal, children; |
|---|
| 370 | |
|---|
| 371 | int nChildCount = pNode->GetChildCount(); |
|---|
| 372 | for (int i = 0; i < nChildCount; ++i) |
|---|
| 373 | { |
|---|
| 374 | KFbxNode* pChildNode = pNode->GetChild(i); |
|---|
| 375 | |
|---|
| 376 | if (pChildNode->GetParent() != pNode) |
|---|
| 377 | { |
|---|
| 378 | |
|---|
| 379 | continue; |
|---|
| 380 | } |
|---|
| 381 | |
|---|
| [11139] | 382 | bool bChildIsBone = false; |
|---|
| [10780] | 383 | osgDB::ReaderWriter::ReadResult childResult = readFbxNode( |
|---|
| [11109] | 384 | pSdkManager, pChildNode, pAnimationManager, |
|---|
| [11139] | 385 | bChildIsBone, nLightCount, fbxMaterialToOsgStateSet, nodeMap, |
|---|
| [11262] | 386 | boneBindMatrices, fbxSkeletons, skeletonMap, options); |
|---|
| [10780] | 387 | if (childResult.error()) |
|---|
| 388 | { |
|---|
| 389 | return childResult; |
|---|
| 390 | } |
|---|
| 391 | else if (osg::Node* osgChild = childResult.getNode()) |
|---|
| 392 | { |
|---|
| [11139] | 393 | if (bChildIsBone) |
|---|
| [10780] | 394 | { |
|---|
| [11141] | 395 | if (!bIsBone) bCreateSkeleton = true; |
|---|
| [10780] | 396 | skeletal.push_back(osgChild); |
|---|
| 397 | } |
|---|
| 398 | else |
|---|
| 399 | { |
|---|
| 400 | children.push_back(osgChild); |
|---|
| 401 | } |
|---|
| 402 | } |
|---|
| 403 | } |
|---|
| 404 | |
|---|
| [11109] | 405 | std::string animName = readFbxAnimation(pNode, pAnimationManager, pNode->GetName()); |
|---|
| [10780] | 406 | |
|---|
| 407 | osg::Matrix localMatrix; |
|---|
| 408 | makeLocalMatrix(pNode, localMatrix); |
|---|
| 409 | bool bLocalMatrixIdentity = localMatrix.isIdentity(); |
|---|
| 410 | |
|---|
| 411 | osg::ref_ptr<osg::Group> osgGroup; |
|---|
| 412 | |
|---|
| [11139] | 413 | bool bEmpty = children.empty() && !bIsBone; |
|---|
| [10780] | 414 | |
|---|
| 415 | switch (lAttributeType) |
|---|
| 416 | { |
|---|
| 417 | case KFbxNodeAttribute::eUNIDENTIFIED: |
|---|
| [11109] | 418 | if (bLocalMatrixIdentity && children.size() + skeletal.size() == 1) |
|---|
| [10780] | 419 | { |
|---|
| 420 | if (children.size() == 1) |
|---|
| 421 | { |
|---|
| 422 | return osgDB::ReaderWriter::ReadResult(children.front().get()); |
|---|
| 423 | } |
|---|
| 424 | else |
|---|
| 425 | { |
|---|
| 426 | return osgDB::ReaderWriter::ReadResult(skeletal.front().get()); |
|---|
| 427 | } |
|---|
| 428 | } |
|---|
| 429 | break; |
|---|
| 430 | case KFbxNodeAttribute::eMESH: |
|---|
| 431 | { |
|---|
| [11141] | 432 | size_t bindMatrixCount = boneBindMatrices.size(); |
|---|
| [11139] | 433 | osgDB::ReaderWriter::ReadResult meshRes = readFbxMesh(pSdkManager, |
|---|
| [11262] | 434 | pNode, pAnimationManager, stateSetList, boneBindMatrices, |
|---|
| 435 | fbxSkeletons, skeletonMap); |
|---|
| [10780] | 436 | if (meshRes.error()) |
|---|
| 437 | { |
|---|
| 438 | return meshRes; |
|---|
| 439 | } |
|---|
| 440 | else if (osg::Node* node = meshRes.getNode()) |
|---|
| 441 | { |
|---|
| [11141] | 442 | bEmpty = false; |
|---|
| [11139] | 443 | |
|---|
| [11141] | 444 | if (bindMatrixCount != boneBindMatrices.size()) |
|---|
| 445 | { |
|---|
| 446 | |
|---|
| 447 | localMatrix.makeIdentity(); |
|---|
| 448 | bLocalMatrixIdentity = true; |
|---|
| 449 | } |
|---|
| [11139] | 450 | |
|---|
| [10780] | 451 | if (animName.empty() && |
|---|
| 452 | children.empty() && |
|---|
| 453 | skeletal.empty() && |
|---|
| 454 | bLocalMatrixIdentity) |
|---|
| 455 | { |
|---|
| 456 | return osgDB::ReaderWriter::ReadResult(node); |
|---|
| 457 | } |
|---|
| 458 | |
|---|
| [11141] | 459 | children.insert(children.begin(), node); |
|---|
| [10780] | 460 | } |
|---|
| 461 | } |
|---|
| 462 | break; |
|---|
| 463 | case KFbxNodeAttribute::eCAMERA: |
|---|
| 464 | case KFbxNodeAttribute::eLIGHT: |
|---|
| 465 | { |
|---|
| 466 | osgDB::ReaderWriter::ReadResult res = |
|---|
| 467 | lAttributeType == KFbxNodeAttribute::eCAMERA ? |
|---|
| 468 | readFbxCamera(pNode) : readFbxLight(pNode, nLightCount); |
|---|
| 469 | if (res.error()) |
|---|
| 470 | { |
|---|
| 471 | return res; |
|---|
| 472 | } |
|---|
| 473 | else if (osg::Group* resGroup = dynamic_cast<osg::Group*>(res.getObject())) |
|---|
| 474 | { |
|---|
| 475 | bEmpty = false; |
|---|
| 476 | if (animName.empty() && |
|---|
| 477 | bLocalMatrixIdentity) |
|---|
| 478 | { |
|---|
| 479 | osgGroup = resGroup; |
|---|
| 480 | } |
|---|
| 481 | else |
|---|
| 482 | { |
|---|
| [11141] | 483 | children.insert(children.begin(), resGroup); |
|---|
| [10780] | 484 | } |
|---|
| 485 | } |
|---|
| 486 | } |
|---|
| 487 | break; |
|---|
| 488 | } |
|---|
| 489 | |
|---|
| 490 | if (bEmpty) |
|---|
| 491 | { |
|---|
| 492 | osgDB::ReaderWriter::ReadResult(0); |
|---|
| 493 | } |
|---|
| 494 | |
|---|
| [11139] | 495 | if (!osgGroup) osgGroup = createGroupNode(pSdkManager, pNode, animName, localMatrix, bIsBone, nodeMap); |
|---|
| 496 | |
|---|
| [11141] | 497 | osg::Group* pAddChildrenTo = osgGroup.get(); |
|---|
| 498 | if (bCreateSkeleton) |
|---|
| 499 | { |
|---|
| [11262] | 500 | osgAnimation::Skeleton* osgSkeleton = getSkeleton(pNode, fbxSkeletons, skeletonMap); |
|---|
| [11141] | 501 | osgSkeleton->setDefaultUpdateCallback(); |
|---|
| 502 | pAddChildrenTo->addChild(osgSkeleton); |
|---|
| 503 | pAddChildrenTo = osgSkeleton; |
|---|
| 504 | } |
|---|
| [11139] | 505 | |
|---|
| [10780] | 506 | for (osg::NodeList::iterator it = skeletal.begin(); it != skeletal.end(); ++it) |
|---|
| 507 | { |
|---|
| [11139] | 508 | pAddChildrenTo->addChild(it->get()); |
|---|
| [10780] | 509 | } |
|---|
| 510 | for (osg::NodeList::iterator it = children.begin(); it != children.end(); ++it) |
|---|
| 511 | { |
|---|
| [11139] | 512 | pAddChildrenTo->addChild(it->get()); |
|---|
| [10780] | 513 | } |
|---|
| 514 | |
|---|
| [11139] | 515 | |
|---|
| [10780] | 516 | return osgDB::ReaderWriter::ReadResult(osgGroup.get()); |
|---|
| 517 | } |
|---|
| [11139] | 518 | |
|---|
| 519 | osgAnimation::Skeleton* getSkeleton(KFbxNode* fbxNode, |
|---|
| [11262] | 520 | const std::set<const KFbxNode*>& fbxSkeletons, |
|---|
| [11141] | 521 | std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap) |
|---|
| [11139] | 522 | { |
|---|
| [11141] | 523 | |
|---|
| 524 | while (fbxNode && |
|---|
| [11262] | 525 | ((fbxNode->GetNodeAttribute() && |
|---|
| 526 | fbxNode->GetNodeAttribute()->GetAttributeType() == KFbxNodeAttribute::eSKELETON) || |
|---|
| 527 | fbxSkeletons.find(fbxNode) != fbxSkeletons.end())) |
|---|
| [11141] | 528 | { |
|---|
| 529 | fbxNode = fbxNode->GetParent(); |
|---|
| 530 | } |
|---|
| [11139] | 531 | |
|---|
| [11141] | 532 | std::map<KFbxNode*, osgAnimation::Skeleton*>::const_iterator it = skeletonMap.find(fbxNode); |
|---|
| 533 | if (it == skeletonMap.end()) |
|---|
| 534 | { |
|---|
| 535 | osgAnimation::Skeleton* skel = new osgAnimation::Skeleton; |
|---|
| 536 | skel->setDefaultUpdateCallback(); |
|---|
| 537 | skeletonMap.insert(std::pair<KFbxNode*, osgAnimation::Skeleton*>(fbxNode, skel)); |
|---|
| 538 | return skel; |
|---|
| 539 | } |
|---|
| 540 | else |
|---|
| 541 | { |
|---|
| 542 | return it->second; |
|---|
| 543 | } |
|---|
| [11139] | 544 | } |
|---|