10 using namespace System::IO;
11 using namespace System::Collections::Generic;
12 using namespace System::Runtime::InteropServices;
13 using namespace SiliconStudio::BuildEngine;
14 using namespace SiliconStudio::Core::Diagnostics;
15 using namespace SiliconStudio::Core::IO;
16 using namespace SiliconStudio::Core::Mathematics;
17 using namespace SiliconStudio::Core::Serialization;
18 using namespace SiliconStudio::Core::Serialization::Assets;
19 using namespace SiliconStudio::Core::Serialization::Contents;
20 using namespace SiliconStudio::Paradox::Assets::Materials;
21 using namespace SiliconStudio::Paradox::Assets::Materials::Nodes;
22 using namespace SiliconStudio::Paradox::DataModel;
23 using namespace SiliconStudio::Paradox::EntityModel;
24 using namespace SiliconStudio::Paradox::EntityModel::Data;
25 using namespace SiliconStudio::Paradox::Effects;
26 using namespace SiliconStudio::Paradox::Effects::Data;
27 using namespace SiliconStudio::Paradox::Effects::Modules;
28 using namespace SiliconStudio::Paradox::Engine;
29 using namespace SiliconStudio::Paradox::Engine::Data;
30 using namespace SiliconStudio::Paradox::Extensions;
31 using namespace SiliconStudio::Paradox::Graphics;
32 using namespace SiliconStudio::Paradox::Graphics::Data;
33 using namespace SiliconStudio::Paradox::Shaders;
35 using namespace SiliconStudio::Paradox::Importer::Common;
37 namespace SiliconStudio {
namespace Paradox {
namespace Importer {
namespace FBX {
44 Instances =
gcnew List<MaterialInstanciation^>();
65 FbxManager* lSdkManager;
79 List<ModelNodeDefinition>
nodes;
87 logger = Core::Diagnostics::GlobalLogger::GetLogger(
"Importer FBX");
90 exportedFromMaya =
false;
99 currentBuffer =
nullptr;
102 lImporter->Destroy();
105 lSdkManager->Destroy();
113 System::Threading::Monitor::Exit( globalLock );
117 static bool WeightGreater(
const std::pair<short, float>& elem1,
const std::pair<short, float>& elem2)
119 return elem1.second > elem2.second;
122 void ProcessMesh(FbxMesh* pMesh, std::map<FbxMesh*, std::string> meshNames)
124 FbxVector4* controlPoints = pMesh->GetControlPoints();
125 FbxGeometryElementNormal* normalElement = pMesh->GetElementNormal();
128 std::map<std::string, int> uvElementMapping;
129 std::vector<FbxGeometryElementUV*> uvElements;
131 for (
int i = 0; i < pMesh->GetElementUVCount(); ++i)
133 uvElements.push_back(pMesh->GetElementUV(i));
136 bool hasSkinningPosition =
false;
137 bool hasSkinningNormal =
false;
138 int totalClusterCount = 0;
139 std::vector<std::vector<std::pair<short, float> > > controlPointWeights;
141 List<MeshBoneDefinition>^ bones =
nullptr;
144 if (pMesh->GetDeformerCount() > 0)
146 if (pMesh->GetDeformerCount() != 1)
148 logger->Error(
"Multiple mesh deformers are not supported yet. Mesh '{0}' will not be properly deformed.",
gcnew String(meshNames[pMesh].c_str()));
151 FbxDeformer* deformer = pMesh->GetDeformer(0);
152 FbxDeformer::EDeformerType deformerType = deformer->GetDeformerType();
153 if (deformerType == FbxDeformer::eSkin)
155 auto lPose = scene->GetPose(0);
157 FbxSkin* skin = FbxCast<FbxSkin>(deformer);
159 FbxSkin::EType lSkinningType = skin->GetSkinningType();
161 controlPointWeights.resize(pMesh->GetControlPointsCount());
163 bones =
gcnew List<MeshBoneDefinition>();
165 totalClusterCount = skin->GetClusterCount();
166 for (
int clusterIndex = 0 ; clusterIndex < totalClusterCount; ++clusterIndex)
168 FbxCluster* cluster = skin->GetCluster(clusterIndex);
169 FbxNode* link = cluster->GetLink();
170 FbxCluster::ELinkMode lClusterMode = cluster->GetLinkMode();
171 const char* boneName = link->GetName();
173 int indexCount = cluster->GetControlPointIndicesCount();
174 int *indices = cluster->GetControlPointIndices();
175 double *weights = cluster->GetControlPointWeights();
177 FbxAMatrix lReferenceGlobalInitPosition;
178 FbxAMatrix lClusterGlobalInitPosition;
179 FbxAMatrix lClusterRelativeInitPosition;
181 cluster->GetTransformLinkMatrix(lClusterGlobalInitPosition);
182 cluster->GetTransformMatrix(lReferenceGlobalInitPosition);
185 bool test = cluster->IsTransformParentSet();
192 logger->Warning(
"Bones transformation from left handed to right handed need to be checked.",
nullptr, CallerInfo::Get(__FILEW__, __FUNCTIONW__, __LINE__));
210 auto nodeIndex = nodeMapping[(IntPtr)link];
213 bone.
NodeIndex = nodeMapping[(IntPtr)link];
214 bone.LinkToMeshMatrix = meshMatrix * Matrix::Invert(linkMatrix);
217 for (
int j = 0 ; j < indexCount; j++)
219 int controlPointIndex = indices[j];
220 controlPointWeights[controlPointIndex].push_back(std::pair<short, float>((
short)clusterIndex, (
float)weights[j]));
225 if (pMesh->GetControlPointsCount() > 0)
227 hasSkinningPosition =
true;
228 hasSkinningNormal = (pMesh->GetElementNormal() != NULL);
231 for (
int i = 0 ; i < pMesh->GetControlPointsCount(); i++)
233 std::sort(controlPointWeights[i].begin(), controlPointWeights[i].end(), WeightGreater);
234 controlPointWeights[i].resize(4, std::pair<short, float>(0, 0.0f));
235 float totalWeight = 0.0f;
236 for (
int j = 0; j < 4; ++j)
237 totalWeight += controlPointWeights[i][j].second;
238 if (totalWeight == 0.0f)
240 for (
int j = 0; j < 4; ++j)
241 controlPointWeights[i][j].second = (j == 0) ? 1.0f : 0.0f;
245 totalWeight = 1.0f / totalWeight;
246 for (
int j = 0; j < 4; ++j)
247 controlPointWeights[i][j].second *= totalWeight;
254 auto vertexElements =
gcnew List<VertexElement>();
256 int vertexStride = 0;
257 int positionOffset = vertexStride;
258 vertexElements->Add(VertexElement::Position<Vector3>(0, vertexStride));
261 int normalOffset = vertexStride;
262 if (normalElement != NULL)
264 vertexElements->Add(VertexElement::Normal<Vector3>(0, vertexStride));
268 std::vector<int> uvOffsets;
269 for (
int i = 0; i < (int)uvElements.size(); ++i)
271 uvOffsets.push_back(vertexStride);
272 vertexElements->Add(VertexElement::TextureCoordinate<Vector2>(i, vertexStride));
274 uvElementMapping[pMesh->GetElementUV(i)->GetName()] = i;
277 int blendIndicesOffset = vertexStride;
278 bool controlPointIndices16 = (AllowUnsignedBlendIndices && totalClusterCount > 256) || (!AllowUnsignedBlendIndices && totalClusterCount > 128);
279 if (!controlPointWeights.empty())
281 if (controlPointIndices16)
283 if (AllowUnsignedBlendIndices)
285 vertexElements->Add(
VertexElement(
"BLENDINDICES", 0, PixelFormat::R16G16B16A16_UInt, vertexStride));
286 vertexStride +=
sizeof(
unsigned short) * 4;
290 vertexElements->Add(
VertexElement(
"BLENDINDICES", 0, PixelFormat::R16G16B16A16_SInt, vertexStride));
291 vertexStride +=
sizeof(short) * 4;
296 if (AllowUnsignedBlendIndices)
298 vertexElements->Add(
VertexElement(
"BLENDINDICES", 0, PixelFormat::R8G8B8A8_UInt, vertexStride));
299 vertexStride +=
sizeof(
unsigned char) * 4;
303 vertexElements->Add(
VertexElement(
"BLENDINDICES", 0, PixelFormat::R8G8B8A8_SInt, vertexStride));
304 vertexStride +=
sizeof(char) * 4;
309 int blendWeightOffset = vertexStride;
310 if (!controlPointWeights.empty())
312 vertexElements->Add(
VertexElement(
"BLENDWEIGHT", 0, PixelFormat::R32G32B32A32_Float, vertexStride));
313 vertexStride +=
sizeof(float) * 4;
316 int polygonCount = pMesh->GetPolygonCount();
318 FbxGeometryElement::EMappingMode materialMappingMode = FbxGeometryElement::eNone;
319 FbxLayerElementArrayTemplate<int>* materialIndices = NULL;
321 if (pMesh->GetElementMaterial())
323 materialMappingMode = pMesh->GetElementMaterial()->GetMappingMode();
324 materialIndices = &pMesh->GetElementMaterial()->GetIndexArray();
327 auto buildMeshes =
gcnew List<BuildMesh^>();
330 for (
int i = 0; i < polygonCount; i++)
332 int materialIndex = 0;
333 if (materialMappingMode == FbxGeometryElement::eByPolygon)
335 materialIndex = materialIndices->GetAt(i);
339 while (materialIndex >= buildMeshes->Count)
341 buildMeshes->Add(
nullptr);
344 if (buildMeshes[materialIndex] ==
nullptr)
345 buildMeshes[materialIndex] =
gcnew BuildMesh();
347 int polygonSize = pMesh->GetPolygonSize(i) - 2;
349 buildMeshes[materialIndex]->polygonCount += polygonSize;
353 for each(
BuildMesh^ buildMesh
in buildMeshes)
355 if (buildMesh ==
nullptr)
362 int polygonVertexStartIndex = 0;
363 for (
int i = 0; i < polygonCount; i++)
365 int materialIndex = 0;
366 if (materialMappingMode == FbxGeometryElement::eByPolygon)
368 materialIndex = materialIndices->GetAt(i);
371 auto buildMesh = buildMeshes[materialIndex];
372 auto buffer = buildMesh->
buffer;
374 int polygonSize = pMesh->GetPolygonSize(i);
376 for (
int polygonFanIndex = 2; polygonFanIndex < polygonSize; ++polygonFanIndex)
378 pin_ptr<Byte> vbPointer = &buffer[buildMesh->
bufferOffset];
381 int vertexInPolygon[3] = { 0, polygonFanIndex - 1, polygonFanIndex };
384 int temp = vertexInPolygon[1];
385 vertexInPolygon[1] = vertexInPolygon[2];
386 vertexInPolygon[2] = temp;
388 int controlPointIndices[3] = { pMesh->GetPolygonVertex(i, vertexInPolygon[0]), pMesh->GetPolygonVertex(i, vertexInPolygon[1]), pMesh->GetPolygonVertex(i, vertexInPolygon[2]) };
390 for (
int polygonFanVertex = 0; polygonFanVertex < 3; ++polygonFanVertex)
392 int j = vertexInPolygon[polygonFanVertex];
393 int vertexIndex = polygonVertexStartIndex + j;
394 int controlPointIndex = controlPointIndices[polygonFanVertex];
396 FbxVector4 controlPoint = controlPoints[controlPointIndex];
399 controlPoint[2] = -controlPoint[2];
401 ((
float*)(vbPointer + positionOffset))[0] = (
float)controlPoint[0];
402 ((
float*)(vbPointer + positionOffset))[1] = (
float)controlPoint[1];
403 ((
float*)(vbPointer + positionOffset))[2] = (
float)controlPoint[2];
405 if (normalElement != NULL)
408 if (normalElement->GetMappingMode() == FbxLayerElement::eByControlPoint)
410 int normalIndex = (normalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
411 ? normalElement->GetIndexArray().GetAt(controlPointIndex)
413 normal = normalElement->GetDirectArray().GetAt(normalIndex);
415 else if (normalElement->GetMappingMode() == FbxLayerElement::eByPolygonVertex)
417 int normalIndex = (normalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
418 ? normalElement->GetIndexArray().GetAt(vertexIndex)
420 normal = normalElement->GetDirectArray().GetAt(normalIndex);
424 normal[2] = -normal[2];
428 ((
float*)(vbPointer + normalOffset))[0] = (
float)normal[0];
429 ((
float*)(vbPointer + normalOffset))[1] = (
float)normal[1];
430 ((
float*)(vbPointer + normalOffset))[2] = (
float)normal[2];
433 for (
int uvGroupIndex = 0; uvGroupIndex < (int)uvElements.size(); ++uvGroupIndex)
435 auto uvElement = uvElements[uvGroupIndex];
437 if (uvElement->GetMappingMode() == FbxLayerElement::eByControlPoint)
439 int uvIndex = (uvElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
440 ? uvElement->GetIndexArray().GetAt(controlPointIndex)
442 uv = uvElement->GetDirectArray().GetAt(uvIndex);
444 else if (uvElement->GetMappingMode() == FbxLayerElement::eByPolygonVertex)
446 int uvIndex = (uvElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
447 ? uvElement->GetIndexArray().GetAt(vertexIndex)
449 uv = uvElement->GetDirectArray().GetAt(uvIndex);
453 logger->Error(
"The texture mapping mode '{0}' is not supported yet by the FBX importer "
454 +
"(currently only mapping by control point and by polygon vertex are supported). "
455 +
"Texture mapping will not be correct for mesh '{1}'.",
gcnew Int32(uvElement->GetMappingMode()),
gcnew String(meshNames[pMesh].c_str()));
458 ((
float*)(vbPointer + uvOffsets[uvGroupIndex]))[0] = (
float)uv[0];
459 ((
float*)(vbPointer + uvOffsets[uvGroupIndex]))[1] = 1.0f - (
float)uv[1];
462 if (!controlPointWeights.empty())
464 const auto& blendWeights = controlPointWeights[controlPointIndex];
465 for (
int i = 0; i < 4; ++i)
467 if (controlPointIndices16)
469 if (AllowUnsignedBlendIndices)
470 ((
unsigned short*)(vbPointer + blendIndicesOffset))[i] = (
unsigned short)blendWeights[i].first;
472 ((
short*)(vbPointer + blendIndicesOffset))[i] = (short)blendWeights[i].first;
476 if (AllowUnsignedBlendIndices)
477 ((
unsigned char*)(vbPointer + blendIndicesOffset))[i] = (
unsigned char)blendWeights[i].first;
479 ((
char*)(vbPointer + blendIndicesOffset))[i] = (char)blendWeights[i].first;
481 ((
float*)(vbPointer + blendWeightOffset))[i] = blendWeights[i].second;
485 vbPointer += vertexStride;
489 polygonVertexStartIndex += polygonSize;
494 for (
int i = 0; i < buildMeshes->Count; ++i)
496 auto buildMesh = buildMeshes[i];
497 if (buildMesh ==
nullptr)
500 auto buffer = buildMesh->
buffer;
504 auto vbb =
gcnew List<VertexBufferBindingData^>();
505 vbb->Add(vertexBufferBinding);
506 drawData->VertexBuffers = vbb->ToArray();
507 drawData->PrimitiveType = PrimitiveType::TriangleList;
513 IndexExtensions::GenerateIndexBuffer(drawData);
523 auto lMaterial = pMesh->GetNode()->GetMaterial(i);
526 if (normalElement != NULL && uvElements.size() > 0)
527 TNBExtensions::GenerateTangentBinormal(drawData);
530 meshData->NodeIndex = nodeMapping[(IntPtr)pMesh->GetNode()];
531 meshData->Draw = drawData;
532 if (!controlPointWeights.empty())
535 meshData->Skinning->Bones = bones->ToArray();
539 FbxGeometryElementMaterial* lMaterialElement = pMesh->GetElementMaterial();
540 if (lMaterialElement != NULL && lMaterial != NULL)
542 auto isTransparent = IsTransparent(lMaterial);
544 auto meshName = meshNames[pMesh];
545 if (buildMeshes->Count > 1)
546 meshName = meshName +
"_" + std::to_string(i+1);
547 meshData->Name =
gcnew String(meshName.c_str());
549 bool sortTransparentMeshes =
true;
550 if (isTransparent && sortTransparentMeshes)
552 PolySortExtensions::SortMeshPolygons(drawData, ViewDirectionForTransparentZSort);
555 if (hasSkinningPosition || hasSkinningNormal || totalClusterCount > 0)
559 if (hasSkinningPosition)
560 meshData->Parameters->Set(MaterialParameters::HasSkinningPosition,
true);
561 if (hasSkinningNormal)
562 meshData->Parameters->Set(MaterialParameters::HasSkinningNormal,
true);
563 if (totalClusterCount > 0)
564 meshData->Parameters->Set(MaterialParameters::SkinningBones, totalClusterCount);
567 modelData->Meshes->Add(meshData);
575 auto uvEltMappingOverride = uvElementMapping;
576 std::map<FbxFileTexture*, std::string> textureMap;
577 std::map<std::string, int> textureNameCount;
581 auto phongSurface = FbxCast<FbxSurfacePhong>(lMaterial);
582 auto lambertSurface = FbxCast<FbxSurfaceLambert>(lMaterial);
585 auto diffuseTree = GenerateSurfaceTextureTree(lMaterial, uvEltMappingOverride, textureMap, textureNameCount, FbxSurfaceMaterial::sDiffuse, FbxSurfaceMaterial::sDiffuseFactor, finalMaterial);
586 if(lambertSurface || diffuseTree !=
nullptr)
588 if(diffuseTree ==
nullptr)
590 auto diffuseColor = lambertSurface->Diffuse.Get();
591 auto diffuseFactor = lambertSurface->DiffuseFactor.Get();
592 auto diffuseColorValue = diffuseFactor * diffuseColor;
601 if(diffuseTree !=
nullptr)
602 finalMaterial->AddColorNode(MaterialParameters::AlbedoDiffuse,
"diffuse", diffuseTree);
606 auto emissiveTree = GenerateSurfaceTextureTree(lMaterial, uvEltMappingOverride, textureMap, textureNameCount, FbxSurfaceMaterial::sEmissive, FbxSurfaceMaterial::sEmissiveFactor, finalMaterial);
607 if(lambertSurface || emissiveTree !=
nullptr)
609 if(emissiveTree ==
nullptr)
611 auto emissiveColor = lambertSurface->Emissive.Get();
612 auto emissiveFactor = lambertSurface->EmissiveFactor.Get();
613 auto emissiveColorValue = emissiveFactor * emissiveColor;
616 if(emissiveColorValue != FbxDouble3(0))
625 if(emissiveTree !=
nullptr)
626 finalMaterial->AddColorNode(MaterialParameters::EmissiveMap,
"emissive", emissiveTree);
630 auto ambientTree = GenerateSurfaceTextureTree(lMaterial, uvEltMappingOverride, textureMap, textureNameCount, FbxSurfaceMaterial::sAmbient, FbxSurfaceMaterial::sAmbientFactor, finalMaterial);
631 if(lambertSurface || ambientTree !=
nullptr)
633 if(ambientTree ==
nullptr)
635 auto ambientColor = lambertSurface->Emissive.Get();
636 auto ambientFactor = lambertSurface->EmissiveFactor.Get();
637 auto ambientColorValue = ambientFactor * ambientColor;
640 if(ambientColorValue != FbxDouble3(0))
649 if(ambientTree !=
nullptr)
650 finalMaterial->AddColorNode(MaterialParameters::AmbientMap,
"ambient", ambientTree);
654 auto normalMapTree = GenerateSurfaceTextureTree(lMaterial, uvEltMappingOverride, textureMap, textureNameCount, FbxSurfaceMaterial::sNormalMap, NULL, finalMaterial);
655 if(lambertSurface || normalMapTree !=
nullptr)
657 if(normalMapTree ==
nullptr)
659 auto normalMapValue = lambertSurface->NormalMap.Get();
662 if(normalMapValue != FbxDouble3(0))
671 if(normalMapTree !=
nullptr)
672 finalMaterial->AddColorNode(MaterialParameters::NormalMap,
"normalMap", normalMapTree);
676 auto bumpMapTree = GenerateSurfaceTextureTree(lMaterial, uvEltMappingOverride, textureMap, textureNameCount, FbxSurfaceMaterial::sBump, FbxSurfaceMaterial::sBumpFactor, finalMaterial);
677 if(lambertSurface || bumpMapTree !=
nullptr)
679 if(bumpMapTree ==
nullptr)
681 auto bumpValue = lambertSurface->Bump.Get();
682 auto bumpFactor = lambertSurface->BumpFactor.Get();
683 auto bumpMapValue = bumpFactor * bumpValue;
686 if(bumpMapValue != FbxDouble3(0))
695 if(bumpMapTree !=
nullptr)
696 finalMaterial->AddColorNode(MaterialParameters::BumpMap,
"bumpMap", bumpMapTree);
700 auto transparencyTree = GenerateSurfaceTextureTree(lMaterial, uvEltMappingOverride, textureMap, textureNameCount, FbxSurfaceMaterial::sTransparentColor, FbxSurfaceMaterial::sTransparencyFactor, finalMaterial);
701 if(lambertSurface || transparencyTree !=
nullptr)
703 if(transparencyTree ==
nullptr)
705 auto transparencyColor = lambertSurface->TransparentColor.Get();
706 auto transparencyFactor = lambertSurface->TransparencyFactor.Get();
707 auto transparencyValue = transparencyFactor * transparencyColor;
708 auto opacityValue = std::min(1.0f, std::max(0.0f, 1-(
float)transparencyValue[0]));
720 if(transparencyTree !=
nullptr)
721 finalMaterial->AddColorNode(MaterialParameters::TransparencyMap,
"transparencyMap", transparencyTree);
725 auto displacementColorTree = GenerateSurfaceTextureTree(lMaterial, uvEltMappingOverride, textureMap, textureNameCount, FbxSurfaceMaterial::sDisplacementColor, FbxSurfaceMaterial::sDisplacementFactor, finalMaterial);
726 if(lambertSurface || displacementColorTree !=
nullptr)
728 if(displacementColorTree ==
nullptr)
730 auto displacementColor = lambertSurface->DisplacementColor.Get();
731 auto displacementFactor = lambertSurface->DisplacementFactor.Get();
732 auto displacementValue = displacementFactor * displacementColor;
735 if(displacementValue != FbxDouble3(0))
744 if(displacementColorTree !=
nullptr)
745 finalMaterial->AddColorNode(MaterialParameters::DisplacementMap,
"displacementMap", displacementColorTree);
749 auto specularTree = GenerateSurfaceTextureTree(lMaterial, uvEltMappingOverride, textureMap, textureNameCount, FbxSurfaceMaterial::sSpecular, NULL, finalMaterial);
750 if(phongSurface || specularTree !=
nullptr)
752 if(specularTree ==
nullptr)
754 auto specularColor = phongSurface->Specular.Get();
757 if(specularColor != FbxDouble3(0))
766 if(specularTree !=
nullptr)
767 finalMaterial->AddColorNode(MaterialParameters::AlbedoSpecular,
"specular", specularTree);
771 auto specularIntensityTree = GenerateSurfaceTextureTree(lMaterial, uvEltMappingOverride, textureMap, textureNameCount, FbxSurfaceMaterial::sSpecularFactor, NULL, finalMaterial);
772 if(phongSurface || specularIntensityTree !=
nullptr)
774 if(specularIntensityTree ==
nullptr)
776 auto specularIntensity = phongSurface->SpecularFactor.Get();
779 if(specularIntensity > 0)
782 ((
MaterialFloatNode^)specularIntensityTree)->Key = MaterialKeys::SpecularIntensity;
788 if(specularIntensityTree !=
nullptr)
789 finalMaterial->AddColorNode(MaterialParameters::SpecularIntensityMap,
"specularIntensity", specularIntensityTree);
793 auto specularPowerTree = GenerateSurfaceTextureTree(lMaterial, uvEltMappingOverride, textureMap, textureNameCount, FbxSurfaceMaterial::sShininess, NULL, finalMaterial);
794 if(phongSurface || specularPowerTree !=
nullptr)
796 if(specularPowerTree ==
nullptr)
798 auto specularPower = phongSurface->Shininess.Get();
801 if(specularPower > 0)
810 if(specularPowerTree !=
nullptr)
811 finalMaterial->AddColorNode(MaterialParameters::SpecularPowerMap,
"specularPower", specularPowerTree);
815 auto reflectionMapTree = GenerateSurfaceTextureTree(lMaterial, uvEltMappingOverride, textureMap, textureNameCount, FbxSurfaceMaterial::sReflection, FbxSurfaceMaterial::sReflectionFactor, finalMaterial);
816 if(phongSurface || reflectionMapTree !=
nullptr)
818 if(reflectionMapTree ==
nullptr)
820 auto reflectionColor = lambertSurface->DisplacementColor.Get();
821 auto reflectionFactor = lambertSurface->DisplacementFactor.Get();
822 auto reflectionValue = reflectionFactor * reflectionColor;
825 if(reflectionValue != FbxDouble3(0))
828 ((
MaterialColorNode^)reflectionMapTree)->Key = MaterialKeys::ReflectionColorValue;
834 if(reflectionMapTree !=
nullptr)
835 finalMaterial->AddColorNode(MaterialParameters::ReflectionMap,
"reflectionMap", reflectionMapTree);
838 return finalMaterial;
843 for (
int i = 0; i < 2; ++i)
845 auto propertyName = i == 0 ? FbxSurfaceMaterial::sTransparentColor : FbxSurfaceMaterial::sTransparencyFactor;
846 if (propertyName == NULL)
849 FbxProperty lProperty = lMaterial->FindProperty(propertyName);
850 if (lProperty.IsValid())
852 const int lTextureCount = lProperty.GetSrcObjectCount<FbxTexture>();
853 for (
int j = 0; j < lTextureCount; ++j)
855 FbxLayeredTexture *lLayeredTexture = FbxCast<FbxLayeredTexture>(lProperty.GetSrcObject<FbxTexture>(j));
856 FbxFileTexture *lFileTexture = FbxCast<FbxFileTexture>(lProperty.GetSrcObject<FbxTexture>(j));
859 int lNbTextures = lLayeredTexture->GetSrcObjectCount<FbxFileTexture>();
863 else if (lFileTexture)
866 if (lTextureCount == 0)
869 if (val == Vector3::Zero || val != Vector3::One)
878 std::map<std::string, int>& textureNameCount,
char const* surfaceMaterial,
char const* surfaceMaterialFactor,
881 auto compositionTrees =
gcnew cli::array<IMaterialNode^>(2);
883 for (
int i = 0; i < 2; ++i)
886 auto propertyName = i == 0 ? surfaceMaterial : surfaceMaterialFactor;
887 if (propertyName == NULL)
890 int compositionCount = 0;
892 FbxProperty lProperty = lMaterial->FindProperty(propertyName);
893 if (lProperty.IsValid())
896 const int lTextureCount = lProperty.GetSrcObjectCount<FbxTexture>();
897 for (
int j = 0; j < lTextureCount; ++j)
899 FbxLayeredTexture *lLayeredTexture = FbxCast<FbxLayeredTexture>(lProperty.GetSrcObject<FbxTexture>(j));
900 FbxFileTexture *lFileTexture = FbxCast<FbxFileTexture>(lProperty.GetSrcObject<FbxTexture>(j));
903 int lNbTextures = lLayeredTexture->GetSrcObjectCount<FbxFileTexture>();
904 for (
int k = 0; k < lNbTextures; ++k)
906 FbxFileTexture* lSubTexture = FbxCast<FbxFileTexture>(lLayeredTexture->GetSrcObject<FbxFileTexture>(k));
908 auto uvName = std::string(lSubTexture->UVSet.Get());
909 if (uvElementMapping.find(uvName) == uvElementMapping.end())
910 uvElementMapping[uvName] = uvElementMapping.size();
912 auto currentMaterialReference = GenerateMaterialTextureNodeFBX(lSubTexture, uvElementMapping, textureMap, textureNameCount, finalMaterial);
914 if (lNbTextures == 1 || compositionCount == 0)
916 if (previousNode ==
nullptr)
917 previousNode = currentMaterialReference;
919 previousNode =
gcnew MaterialBinaryNode(previousNode, currentMaterialReference, MaterialBinaryOperand::Add);
923 auto newNode =
gcnew MaterialBinaryNode(previousNode, currentMaterialReference, MaterialBinaryOperand::Add);
924 previousNode = newNode;
926 FbxLayeredTexture::EBlendMode blendMode;
927 lLayeredTexture->GetTextureBlendMode(k, blendMode);
928 newNode->Operand = BlendModeToBlendOperand(blendMode);
934 else if (lFileTexture)
938 auto newMaterialReference = GenerateMaterialTextureNodeFBX(lFileTexture, uvElementMapping, textureMap, textureNameCount, finalMaterial);
940 if (previousNode ==
nullptr)
941 previousNode = newMaterialReference;
943 previousNode =
gcnew MaterialBinaryNode(previousNode, newMaterialReference, MaterialBinaryOperand::Add);
947 compositionTrees[i] = previousNode;
953 if (compositionTrees[0] ==
nullptr)
955 compositionTree = compositionTrees[1];
957 else if (compositionTrees[1] ==
nullptr)
959 compositionTree = compositionTrees[0];
963 compositionTree =
gcnew MaterialBinaryNode(compositionTrees[0], compositionTrees[1], MaterialBinaryOperand::Multiply);
966 return compositionTree;
973 case FbxLayeredTexture::eOver:
974 return MaterialBinaryOperand::Over;
975 case FbxLayeredTexture::eAdditive:
976 return MaterialBinaryOperand::Add;
977 case FbxLayeredTexture::eModulate:
978 return MaterialBinaryOperand::Multiply;
987 case FbxLayeredTexture::eDarken:
988 return MaterialBinaryOperand::Darken;
989 case FbxLayeredTexture::eColorBurn:
990 return MaterialBinaryOperand::ColorBurn;
991 case FbxLayeredTexture::eLinearBurn:
992 return MaterialBinaryOperand::LinearBurn;
995 case FbxLayeredTexture::eLighten:
996 return MaterialBinaryOperand::Lighten;
997 case FbxLayeredTexture::eScreen:
998 return MaterialBinaryOperand::Screen;
999 case FbxLayeredTexture::eColorDodge:
1000 return MaterialBinaryOperand::ColorDodge;
1001 case FbxLayeredTexture::eLinearDodge:
1002 return MaterialBinaryOperand::LinearDodge;
1005 case FbxLayeredTexture::eSoftLight:
1006 return MaterialBinaryOperand::SoftLight;
1007 case FbxLayeredTexture::eHardLight:
1008 return MaterialBinaryOperand::HardLight;
1013 case FbxLayeredTexture::ePinLight:
1014 return MaterialBinaryOperand::PinLight;
1015 case FbxLayeredTexture::eHardMix:
1016 return MaterialBinaryOperand::HardMix;
1017 case FbxLayeredTexture::eDifference:
1018 return MaterialBinaryOperand::Difference;
1019 case FbxLayeredTexture::eExclusion:
1020 return MaterialBinaryOperand::Exclusion;
1021 case FbxLayeredTexture::eSubtract:
1022 return MaterialBinaryOperand::Subtract;
1023 case FbxLayeredTexture::eDivide:
1024 return MaterialBinaryOperand::Divide;
1025 case FbxLayeredTexture::eHue:
1026 return MaterialBinaryOperand::Hue;
1027 case FbxLayeredTexture::eSaturation:
1028 return MaterialBinaryOperand::Saturation;
1033 case FbxLayeredTexture::eOverlay:
1034 return MaterialBinaryOperand::Overlay;
1036 logger->Error(
"Material blending mode '{0}' is not supported yet. Multiplying blending mode will be used instead.",
gcnew Int32(blendMode));
1037 return MaterialBinaryOperand::Multiply;
1043 auto texScale = lFileTexture->GetUVScaling();
1044 auto texturePath = FindFilePath(lFileTexture);
1046 return TextureLayerGenerator::GenerateTextureLayer(vfsOutputFilename, texturePath, uvElementMapping[std::string(lFileTexture->UVSet.Get())],
Vector2((
float)texScale[0], (float)texScale[1]) ,
1047 textureCount, surfaceMaterialKey,
1054 auto relFileName =
gcnew String(lFileTexture->GetRelativeFileName());
1055 auto absFileName =
gcnew String(lFileTexture->GetFileName());
1059 auto fileNameToUse = Path::Combine(inputPath, relFileName);
1060 if(fileNameToUse->StartsWith(
"\\\\"))
1062 logger->Warning(
"Importer detected a network address in referenced assets. This may temporary block the build if the file does not exist. [Address='{0}']", fileNameToUse);
1064 if (!File::Exists(fileNameToUse))
1066 fileNameToUse = absFileName;
1069 return fileNameToUse;
1074 auto texScale = lFileTexture->GetUVScaling();
1075 auto texturePath = FindFilePath(lFileTexture);
1076 auto wrapModeU = lFileTexture->GetWrapModeU();
1077 auto wrapModeV = lFileTexture->GetWrapModeV();
1078 bool wrapTextureU = (wrapModeU == FbxTexture::EWrapMode::eRepeat);
1079 bool wrapTextureV = (wrapModeV == FbxTexture::EWrapMode::eRepeat);
1081 auto index = textureMap.find(lFileTexture);
1082 if (index != textureMap.end())
1084 auto textureName = textureMap[lFileTexture];
1086 return materialReference;
1090 auto textureValue = TextureLayerGenerator::GenerateMaterialTextureNode(vfsOutputFilename, texturePath, uvElementMapping[std::string(lFileTexture->UVSet.Get())],
Vector2((
float)texScale[0], (float)texScale[1]), wrapTextureU, wrapTextureV,
nullptr);
1092 auto textureNamePtr = Marshal::StringToHGlobalAnsi(textureValue->TextureName);
1093 std::string textureName = std::string((
char*)textureNamePtr.ToPointer());
1094 Marshal:: FreeHGlobal(textureNamePtr);
1096 auto textureCount = GetTextureNameCount(textureNameCount, textureName);
1097 if (textureCount > 1)
1098 textureName = textureName +
"_" + std::to_string(textureCount - 1);
1100 auto referenceName =
gcnew String(textureName.c_str());
1102 finalMaterial->
AddNode(referenceName, textureValue);
1103 textureMap[lFileTexture] = textureName;
1104 return materialReference;
1112 auto textureFound = textureNameCount.find(textureName);
1113 if (textureFound == textureNameCount.end())
1114 textureNameCount[textureName] = 1;
1116 textureNameCount[textureName] = textureNameCount[textureName] + 1;
1117 return textureNameCount[textureName];
1120 void ProcessCamera(List<CameraInfo^>^ cameras, FbxNode* pNode, FbxCamera* pCamera, std::map<FbxNode*, std::string>& nodeNames)
1124 cameraInfo->Data = cameraData;
1126 cameraInfo->NodeName =
gcnew String(nodeNames[pNode].c_str());
1128 if (pCamera->FilmAspectRatio.IsValid())
1130 cameraData->AspectRatio = (float)pCamera->FilmAspectRatio.Get();
1134 if (!exportedFromMaya && pCamera->FieldOfView.IsValid() && pCamera->FilmAspectRatio.IsValid())
1136 auto aspectRatio = pCamera->FilmAspectRatio.Get();
1137 auto diagonalFov = pCamera->FieldOfView.Get();
1138 cameraData->VerticalFieldOfView = (float)(2.0 * Math::Atan(Math::Tan(diagonalFov * Math::PI / 180.0 / 2.0) / Math::Sqrt(1 + aspectRatio * aspectRatio)));
1140 else if (pCamera->FocalLength.IsValid() && pCamera->FilmHeight.IsValid())
1142 cameraData->VerticalFieldOfView = (float)
FocalLengthToVerticalFov(pCamera->FilmHeight.Get(), pCamera->FocalLength.Get());
1145 if (pNode->GetTarget() != NULL)
1147 auto targetNodeIndex = nodeMapping[(IntPtr)pNode->GetTarget()];
1148 cameraInfo->TargetNodeName = nodes[targetNodeIndex].Name;
1150 if (pCamera->NearPlane.IsValid())
1152 cameraData->NearPlane = (float)pCamera->NearPlane.Get();
1154 if (pCamera->FarPlane.IsValid())
1156 cameraData->FarPlane = (float)pCamera->FarPlane.Get();
1159 cameras->Add(cameraInfo);
1162 void ProcessLight(List<LightInfo^>^ lights, FbxNode* pNode, FbxLight* pLight, std::map<FbxNode*, std::string>& nodeNames)
1166 lightInfo->Data = lightData;
1168 lightInfo->NodeName =
gcnew String(nodeNames[pNode].c_str());
1171 lightData->LightDirection =
Vector3(0.0f, -1.0f, 0.0f);
1173 switch (pLight->LightType.Get())
1175 case FbxLight::ePoint:
1176 lightData->Deferred =
true;
1178 lightData->DecayStart = (float)pLight->DecayStart.Get();
1180 if (lightData->DecayStart == 0.0)
1183 case FbxLight::eDirectional:
1184 lightData->Deferred =
false;
1185 lightData->Type = LightType::Directional;
1188 logger->Error(
"The light type '{0}' is not supported yet. The light will be ignored.",
gcnew Int32(pLight->LightType.Get()));
1191 auto lightColor = pLight->Color.IsValid() ? pLight->Color.Get() : FbxDouble3(1.0, 1.0, 1.0);
1192 lightData->Color =
Color3((
float)lightColor[0], (
float)lightColor[1], (
float)lightColor[2]);
1193 lightData->Intensity = (float)(pLight->Intensity.IsValid() ? pLight->Intensity.Get() * 0.01 : 1.0);
1194 lightData->Layers = RenderLayers::RenderLayerAll;
1195 lights->Add(lightInfo);
1198 void ProcessAttribute(FbxNode* pNode, FbxNodeAttribute* pAttribute, std::map<FbxMesh*, std::string> meshNames)
1200 if(!pAttribute)
return;
1202 if (pAttribute->GetAttributeType() == FbxNodeAttribute::eMesh)
1204 ProcessMesh((FbxMesh*)pAttribute, meshNames);
1208 void RegisterNode(FbxNode* pNode,
int parentIndex, std::map<FbxNode*, std::string>& nodeNames)
1213 int currentIndex = nodes.Count;
1215 nodeMapping[(IntPtr)pNode] = currentIndex;
1220 modelNodeDefinition.Transform.Scaling = Vector3::One;
1221 modelNodeDefinition.Name =
gcnew String(nodeNames[pNode].c_str());
1222 modelNodeDefinition.Flags = ModelNodeFlags::Default;
1223 nodes.Add(modelNodeDefinition);
1226 for(
int j = 0; j < pNode->GetChildCount(); j++)
1228 RegisterNode(pNode->GetChild(j), currentIndex, nodeNames);
1232 void ProcessNode(FbxNode* pNode, std::map<FbxMesh*, std::string> meshNames)
1234 auto resultNode = nodeMapping[(IntPtr)pNode];
1235 auto node = &modelData->Hierarchy->Nodes[resultNode];
1237 auto localTransform = pNode->EvaluateLocalTransform();
1245 translation.
Z = -translation.Z;
1246 rotation.Y = -rotation.Y;
1247 rotation.X = -rotation.X;
1252 Quaternion::RotationX(rotation.X, quatX);
1253 Quaternion::RotationY(rotation.Y, quatY);
1254 Quaternion::RotationZ(rotation.Z, quatZ);
1256 auto rotationQuaternion = quatX * quatY * quatZ;
1258 node->Transform.Translation = (
Vector3)translation;
1259 node->Transform.Rotation = rotationQuaternion;
1260 node->Transform.Scaling = (
Vector3)scaling;
1262 const char* nodeName = pNode->GetName();
1265 for(
int i = 0; i < pNode->GetNodeAttributeCount(); i++)
1266 ProcessAttribute(pNode, pNode->GetNodeAttributeByIndex(i), meshNames);
1269 for(
int j = 0; j < pNode->GetChildCount(); j++)
1271 ProcessNode(pNode->GetChild(j), meshNames);
1282 : curve(curve), index(0)
1288 auto fbxTime = FbxTime((
long long)time.
Ticks * FBXSDK_TIME_ONE_SECOND.Get() / (
long long)CompressedTimeSpan::TicksPerSecond);
1289 int currentIndex = index;
1290 auto result = curve->Evaluate(fbxTime, ¤tIndex);
1291 index = currentIndex;
1300 auto keyFrames = ProcessAnimationCurveFloatsHelper<T>(curves, numCurves);
1301 if (keyFrames ==
nullptr)
1311 for (
int i = 0; i < keyFrames->Count; ++i)
1313 animationCurve->KeyFrames->Add(keyFrames[i]);
1316 animationClip->
AddCurve(name, animationCurve);
1318 if (keyFrames->Count > 0)
1320 auto curveDuration = keyFrames[keyFrames->Count - 1].Time;
1321 if (animationClip->
Duration < curveDuration)
1322 animationClip->
Duration = curveDuration;
1325 return animationCurve;
1330 auto keyFrames = ProcessAnimationCurveFloatsHelper<Vector3>(curves, 3);
1331 if (keyFrames ==
nullptr)
1335 for (
int i = 0; i < keyFrames->Count; ++i)
1337 auto keyFrame = keyFrames[i];
1338 keyFrame.Value *= (float)Math::PI / 180.0f;
1339 keyFrames[i] = keyFrame;
1346 for (
int i = 0; i < keyFrames->Count; ++i)
1348 auto keyFrame = keyFrames[i];
1351 keyFrame.Value.X = -keyFrame.Value.X;
1352 keyFrame.Value.Y = -keyFrame.Value.Y;
1357 Quaternion::RotationX(keyFrame.Value.X, quatX);
1358 Quaternion::RotationY(keyFrame.Value.Y, quatY);
1359 Quaternion::RotationZ(keyFrame.Value.Z, quatZ);
1361 auto rotationQuaternion = quatX * quatY * quatZ;
1363 KeyFrameData<Quaternion> newKeyFrame;
1364 newKeyFrame.Time = keyFrame.Time;
1365 newKeyFrame.Value = rotationQuaternion;
1366 animationCurve->KeyFrames->
Add(newKeyFrame);
1369 animationClip->
AddCurve(name, animationCurve);
1371 if (keyFrames->Count > 0)
1373 auto curveDuration = keyFrames[keyFrames->Count - 1].Time;
1374 if (animationClip->
Duration < curveDuration)
1375 animationClip->
Duration = curveDuration;
1379 template <
typename T>
1382 FbxTime startTime = FBXSDK_TIME_INFINITE;
1383 FbxTime endTime = FBXSDK_TIME_MINUS_INFINITE;
1384 for (
int i = 0; i < numCurves; ++i)
1386 auto curve = curves[i];
1394 FbxTimeSpan timeSpan;
1395 curve->GetTimeInterval(timeSpan);
1397 if (curve != NULL && curve->KeyGetCount() > 0)
1399 auto firstKeyTime = curve->KeyGetTime(0);
1400 auto lastKeyTime = curve->KeyGetTime(curve->KeyGetCount() - 1);
1401 if (startTime > firstKeyTime)
1402 startTime = firstKeyTime;
1403 if (endTime < lastKeyTime)
1404 endTime = lastKeyTime;
1408 if (startTime == FBXSDK_TIME_INFINITE
1409 || endTime == FBXSDK_TIME_MINUS_INFINITE)
1415 auto keyFrames =
gcnew List<KeyFrameData<T>>();
1417 const float framerate =
static_cast<float>(FbxTime::GetFrameRate(scene->GetGlobalSettings().GetTimeMode()));
1418 auto oneFrame = FbxTime::GetOneFrameValue(scene->GetGlobalSettings().GetTimeMode());
1422 bool discontinuity =
false;
1424 int currentKeyIndices[4];
1425 int currentEvaluationIndices[4];
1427 bool hasDiscontinuity[4];
1429 for (
int i = 0; i < numCurves; ++i)
1431 auto curve = curves[i];
1432 currentKeyIndices[i] = 0;
1433 currentEvaluationIndices[i] = 0;
1434 isConstant[i] =
false;
1435 hasDiscontinuity[i] =
false;
1440 float* values = (
float*)&key.
Value;
1443 bool lastFrame =
false;
1444 for (time = startTime; time < endTime || !lastFrame; time += oneFrame)
1447 if (time >= endTime)
1455 bool hasDiscontinuity =
false;
1456 bool needUpdate =
false;
1458 for (
int i = 0; i < numCurves; ++i)
1460 auto curve = curves[i];
1461 int currentIndex = currentKeyIndices[i];
1463 FbxAnimCurveKey curveKey;
1466 while (curve->KeyGetTime(currentIndex) <= time && currentIndex + 1 < curve->KeyGetCount())
1471 bool wasConstant = isConstant[i];
1472 hasDiscontinuity |= wasConstant;
1474 auto interpolation = curve->KeyGetInterpolation(currentIndex);
1475 isConstant[i] = interpolation == FbxAnimCurveDef::eInterpolationConstant;
1478 currentKeyIndices[i] = currentIndex;
1483 values[i] = curve->Evaluate(time, ¤tEvaluationIndices[i]);
1493 if (hasDiscontinuity)
1495 keyFrames->Add(key);
1496 keyFrames->Add(key);
1500 for (
int i = 0; i < numCurves; ++i)
1502 auto curve = curves[i];
1504 values[i] = curve->Evaluate(time, ¤tEvaluationIndices[i]);
1507 keyFrames->Add(key);
1508 if (hasDiscontinuity)
1509 keyFrames->Add(key);
1517 for (
int i = 0; i < channel->KeyFrames->Count; ++i)
1519 auto keyFrame = channel->KeyFrames[i];
1520 keyFrame.Value *= (float)Math::PI / 180.0f;
1521 channel->KeyFrames[i] = keyFrame;
1528 for (
int i = 0; i < channel->KeyFrames->Count; ++i)
1530 auto keyFrame = channel->KeyFrames[i];
1531 keyFrame.Value.Z = -keyFrame.Value.Z;
1532 channel->KeyFrames[i] = keyFrame;
1539 for (
int i = 0; i < channel->KeyFrames->Count; ++i)
1541 auto keyFrame = channel->KeyFrames[i];
1543 channel->KeyFrames[i] = keyFrame;
1550 for (
int i = 0; i < channel->KeyFrames->Count; ++i)
1552 auto keyFrame = channel->KeyFrames[i];
1553 keyFrame.Value = (float)(factor * keyFrame.Value);
1554 channel->KeyFrames[i] = keyFrame;
1560 auto nodeData = nodeMapping[(IntPtr)node];
1592 auto rotationOffset = node->RotationOffset.Get();
1593 auto rotationPivot = node->RotationPivot.Get();
1594 auto quatInterpolate = node->QuaternionInterpolate.Get();
1595 auto rotationOrder = node->RotationOrder.Get();
1597 FbxAnimCurve* curves[3];
1599 auto nodeName = nodes[nodeData].Name;
1601 curves[0] = node->LclTranslation.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_X);
1602 curves[1] = node->LclTranslation.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_Y);
1603 curves[2] = node->LclTranslation.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_Z);
1604 auto translation = ProcessAnimationCurveVector<Vector3>(animationClip, nodeData, String::Format(
"Transformation.Translation[{0}]", nodeName), 3, curves, 0.005f);
1606 curves[0] = node->LclRotation.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_X);
1607 curves[1] = node->LclRotation.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_Y);
1608 curves[2] = node->LclRotation.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_Z);
1609 ProcessAnimationCurveRotation(animationClip, nodeData, String::Format(
"Transformation.Rotation[{0}]", nodeName), curves, 0.01f);
1611 curves[0] = node->LclScaling.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_X);
1612 curves[1] = node->LclScaling.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_Y);
1613 curves[2] = node->LclScaling.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_Z);
1614 auto scaling = ProcessAnimationCurveVector<Vector3>(animationClip, nodeData, String::Format(
"Transformation.Scaling[{0}]", nodeName), 3, curves, 0.005f);
1618 if (translation !=
nullptr)
1619 ReverseChannelZ(translation);
1628 FbxCamera* camera = node->GetCamera();
1631 if(camera->FieldOfViewY.GetCurve(animLayer))
1633 curves[0] = camera->FieldOfViewY.GetCurve(animLayer);
1634 auto FovAnimChannel = ProcessAnimationCurveVector<float>(animationClip, nodeData,
"Camera.FieldOfViewVertical", 1, curves, 0.01f);
1635 ConvertDegreeToRadians(FovAnimChannel);
1637 if(!exportedFromMaya)
1638 MultiplyChannel(FovAnimChannel, 0.6);
1642 if(camera->FocalLength.GetCurve(animLayer))
1644 curves[0] = camera->FocalLength.GetCurve(animLayer);
1645 auto flAnimChannel = ProcessAnimationCurveVector<float>(animationClip, nodeData,
"Camera.FieldOfViewVertical", 1, curves, 0.01f);
1646 ComputeFovFromFL(flAnimChannel, camera);
1650 for(
int i = 0; i < node->GetChildCount(); ++i)
1652 ProcessAnimation(animationClip, animLayer, node->GetChild(i));
1658 node->SetPivotState(FbxNode::eSourcePivot, FbxNode::ePivotActive);
1659 node->SetPivotState(FbxNode::eDestinationPivot, FbxNode::ePivotActive);
1661 for(
int i = 0; i < node->GetChildCount(); ++i)
1663 SetPivotStateRecursive(node->GetChild(i));
1671 int animStackCount = scene->GetMemberCount<FbxAnimStack>();
1674 for (
int i = 0; i < animStackCount; ++i)
1676 FbxAnimStack* animStack = scene->GetMember<FbxAnimStack>(i);
1677 int animLayerCount = animStack->GetMemberCount<FbxAnimLayer>();
1678 FbxAnimLayer* animLayer = animStack->GetMember<FbxAnimLayer>(0);
1681 scene->GetRootNode()->ResetPivotSet(FbxNode::eDestinationPivot);
1682 SetPivotStateRecursive(scene->GetRootNode());
1683 scene->GetRootNode()->ConvertPivotAnimationRecursive(animStack, FbxNode::eDestinationPivot, 30.0f);
1685 ProcessAnimation(animationClip, animLayer, scene->GetRootNode());
1687 scene->GetRootNode()->ResetPivotSet(FbxNode::eSourcePivot);
1690 if (animationClip->Curves->Count == 0)
1691 animationClip =
nullptr;
1693 return animationClip;
1726 config->ImportTemplates =
true;
1727 config->ImportPivots =
true;
1728 config->ImportGlobalSettings =
true;
1729 config->ImportCharacters =
true;
1730 config->ImportConstraints =
true;
1731 config->ImportGobos =
true;
1732 config->ImportShapes =
true;
1733 config->ImportLinks =
true;
1734 config->ImportMaterials =
true;
1735 config->ImportTextures =
true;
1736 config->ImportModels =
true;
1737 config->ImportAnimations =
true;
1738 config->ExtractEmbeddedData =
true;
1747 config->ImportTemplates =
false;
1748 config->ImportPivots =
false;
1749 config->ImportGlobalSettings =
false;
1750 config->ImportCharacters =
false;
1751 config->ImportConstraints =
false;
1752 config->ImportGobos =
false;
1753 config->ImportShapes =
false;
1754 config->ImportLinks =
false;
1755 config->ImportMaterials =
true;
1756 config->ImportTextures =
false;
1757 config->ImportModels =
true;
1758 config->ImportAnimations =
false;
1759 config->ExtractEmbeddedData =
false;
1768 config->ImportTemplates =
false;
1769 config->ImportPivots =
false;
1770 config->ImportGlobalSettings =
false;
1771 config->ImportCharacters =
false;
1772 config->ImportConstraints =
false;
1773 config->ImportGobos =
false;
1774 config->ImportShapes =
false;
1775 config->ImportLinks =
false;
1776 config->ImportMaterials =
true;
1777 config->ImportTextures =
false;
1778 config->ImportModels =
false;
1779 config->ImportAnimations =
false;
1780 config->ExtractEmbeddedData =
false;
1789 config->ImportTemplates =
false;
1790 config->ImportPivots =
false;
1791 config->ImportGlobalSettings =
false;
1792 config->ImportCharacters =
false;
1793 config->ImportConstraints =
false;
1794 config->ImportGobos =
false;
1795 config->ImportShapes =
false;
1796 config->ImportLinks =
false;
1797 config->ImportMaterials =
false;
1798 config->ImportTextures =
false;
1799 config->ImportModels =
false;
1800 config->ImportAnimations =
true;
1801 config->ExtractEmbeddedData =
false;
1810 config->ImportTemplates =
false;
1811 config->ImportPivots =
false;
1812 config->ImportGlobalSettings =
false;
1813 config->ImportCharacters =
false;
1814 config->ImportConstraints =
false;
1815 config->ImportGobos =
false;
1816 config->ImportShapes =
false;
1817 config->ImportLinks =
false;
1818 config->ImportMaterials =
false;
1819 config->ImportTextures =
true;
1820 config->ImportModels =
false;
1821 config->ImportAnimations =
false;
1822 config->ExtractEmbeddedData =
false;
1831 config->ImportTemplates =
false;
1832 config->ImportPivots =
false;
1833 config->ImportGlobalSettings =
false;
1834 config->ImportCharacters =
false;
1835 config->ImportConstraints =
false;
1836 config->ImportGobos =
false;
1837 config->ImportShapes =
false;
1838 config->ImportLinks =
false;
1839 config->ImportMaterials =
true;
1840 config->ImportTextures =
true;
1841 config->ImportModels =
true;
1842 config->ImportAnimations =
true;
1843 config->ExtractEmbeddedData =
false;
1852 config->ImportGlobalSettings =
true;
1859 static System::Object^ globalLock =
gcnew System::Object();
1861 void Initialize(String^ inputFilename, String^ vfsOutputFilename, ImportConfiguration^ importConfig)
1869 System::Threading::Monitor::Enter( globalLock );
1872 this->inputFilename = inputFilename;
1873 this->vfsOutputFilename = vfsOutputFilename;
1874 this->inputPath = Path::GetDirectoryName(inputFilename);
1876 polygonSwap =
false;
1879 lSdkManager = FbxManager::Create();
1882 FbxIOSettings *ios = FbxIOSettings::Create(lSdkManager, IOSROOT);
1883 ios->SetBoolProp(IMP_FBX_TEMPLATE, importConfig->ImportTemplates);
1884 ios->SetBoolProp(IMP_FBX_PIVOT, importConfig->ImportPivots);
1885 ios->SetBoolProp(IMP_FBX_GLOBAL_SETTINGS, importConfig->ImportGlobalSettings);
1886 ios->SetBoolProp(IMP_FBX_CHARACTER, importConfig->ImportCharacters);
1887 ios->SetBoolProp(IMP_FBX_CONSTRAINT, importConfig->ImportConstraints);
1888 ios->SetBoolProp(IMP_FBX_GOBO, importConfig->ImportGobos);
1889 ios->SetBoolProp(IMP_FBX_SHAPE, importConfig->ImportShapes);
1890 ios->SetBoolProp(IMP_FBX_LINK, importConfig->ImportLinks);
1891 ios->SetBoolProp(IMP_FBX_MATERIAL, importConfig->ImportMaterials);
1892 ios->SetBoolProp(IMP_FBX_TEXTURE, importConfig->ImportTextures);
1893 ios->SetBoolProp(IMP_FBX_MODEL, importConfig->ImportModels);
1894 ios->SetBoolProp(IMP_FBX_ANIMATION, importConfig->ImportAnimations);
1895 ios->SetBoolProp(IMP_FBX_EXTRACT_EMBEDDED_DATA, importConfig->ExtractEmbeddedData);
1896 lSdkManager->SetIOSettings(ios);
1899 lImporter = FbxImporter::Create(lSdkManager,
"");
1901 auto inputFilenameUtf8 = System::Text::Encoding::UTF8->GetBytes(inputFilename);
1902 pin_ptr<Byte> inputFilenameUtf8Ptr = &inputFilenameUtf8[0];
1904 if(!lImporter->Initialize((
const char*)inputFilenameUtf8Ptr, -1, lSdkManager->GetIOSettings()))
1906 throw gcnew InvalidOperationException(String::Format(
"Call to FbxImporter::Initialize() failed.\n"
1907 "Error returned: {0}\n\n",
gcnew String(lImporter->GetStatus().GetErrorString())));
1911 scene = FbxScene::Create(lSdkManager,
"myScene");
1914 lImporter->Import(scene);
1916 auto documentInfo = scene->GetDocumentInfo();
1917 auto appliWhichExported =
gcnew String(std::string(documentInfo->Original_ApplicationName.Get()).c_str());
1918 if(appliWhichExported ==
"Maya")
1919 exportedFromMaya =
true;
1921 const float framerate =
static_cast<float>(FbxTime::GetFrameRate(scene->GetGlobalSettings().GetTimeMode()));
1922 scene->GetRootNode()->ResetPivotSetAndConvertAnimation(framerate,
false,
false);
1928 auto sceneAxisSystem = scene->GetGlobalSettings().GetAxisSystem();
1930 swapHandedness = sceneAxisSystem.GetCoorSystem() == FbxAxisSystem::eLeftHanded;
1931 polygonSwap = !swapHandedness;
1935 auto rotationAngle = swapHandedness ? 180 : 0;
1943 auto sceneRootNode = scene->GetRootNode();
1946 sceneRootNode->SetRotationActive(
true);
1947 sceneRootNode->SetPreRotation(FbxNode::eSourcePivot, FbxVector4(rotationAngle, 0, 0));
1949 std::map<FbxNode*, std::string> nodeNames;
1950 GenerateNodesName(nodeNames);
1952 RegisterNode(scene->GetRootNode(), -1, nodeNames);
1955 bool CheckAnimationData(FbxAnimLayer* animLayer, FbxNode* node)
1957 if ((node->LclTranslation.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_X) != NULL
1958 && node->LclTranslation.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_Y) != NULL
1959 && node->LclTranslation.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_Z) != NULL)
1961 (node->LclRotation.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_X) != NULL
1962 && node->LclRotation.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_Y) != NULL
1963 && node->LclRotation.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_Z) != NULL)
1965 (node->LclScaling.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_X) != NULL
1966 && node->LclScaling.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_Y) != NULL
1967 && node->LclScaling.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_Z) != NULL))
1970 FbxCamera* camera = node->GetCamera();
1973 if(camera->FieldOfViewY.GetCurve(animLayer))
1976 if(camera->FocalLength.GetCurve(animLayer))
1980 for(
int i = 0; i < node->GetChildCount(); ++i)
1982 if (CheckAnimationData(animLayer, node->GetChild(i)))
1989 bool HasAnimationData(String^ inputFile)
1993 Initialize(inputFile,
nullptr, ImportConfiguration::ImportAnimationsOnly());
1995 int animStackCount = scene->GetMemberCount<FbxAnimStack>();
1997 if (animStackCount > 0)
2000 for (
int i = 0; i < animStackCount && check; ++i)
2002 FbxAnimStack* animStack = scene->GetMember<FbxAnimStack>(i);
2003 int animLayerCount = animStack->GetMemberCount<FbxAnimLayer>();
2004 FbxAnimLayer* animLayer = animStack->GetMember<FbxAnimLayer>(0);
2006 check = check && CheckAnimationData(animLayer, scene->GetRootNode());
2020 void GetAnimationNodes(FbxAnimLayer* animLayer, FbxNode* node, List<String^>^ animationNodes)
2022 auto nodeData = nodeMapping[(IntPtr)node];
2023 auto nodeName = nodes[nodeData].Name;
2025 bool checkTranslation =
true;
2026 checkTranslation = checkTranslation && node->LclTranslation.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_X) != NULL;
2027 checkTranslation = checkTranslation && node->LclTranslation.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_Y) != NULL;
2028 checkTranslation = checkTranslation && node->LclTranslation.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_Z) != NULL;
2030 bool checkRotation =
true;
2031 checkRotation = checkRotation && node->LclRotation.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_X) != NULL;
2032 checkRotation = checkRotation && node->LclRotation.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_Y) != NULL;
2033 checkRotation = checkRotation && node->LclRotation.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_Z) != NULL;
2035 bool checkScale =
true;
2036 checkScale = checkScale && node->LclScaling.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_X) != NULL;
2037 checkScale = checkScale && node->LclScaling.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_Y) != NULL;
2038 checkScale = checkScale && node->LclScaling.GetCurve(animLayer, FBXSDK_CURVENODE_COMPONENT_Z) != NULL;
2040 if (checkTranslation || checkRotation || checkScale)
2042 animationNodes->Add(nodeName);
2046 bool checkCamera =
true;
2047 FbxCamera* camera = node->GetCamera();
2050 if(camera->FieldOfViewY.GetCurve(animLayer))
2051 checkCamera = checkCamera && camera->FieldOfViewY.GetCurve(animLayer) != NULL;
2053 if(camera->FocalLength.GetCurve(animLayer))
2054 checkCamera = checkCamera && camera->FocalLength.GetCurve(animLayer) != NULL;
2057 animationNodes->Add(nodeName);
2061 for(
int i = 0; i < node->GetChildCount(); ++i)
2063 GetAnimationNodes(animLayer, node->GetChild(i), animationNodes);
2067 void GenerateMaterialNames(std::map<FbxSurfaceMaterial*, std::string>& materialNames)
2069 auto materials =
gcnew List<MaterialDescription^>();
2070 std::map<std::string, int> materialNameTotalCount;
2071 std::map<std::string, int> materialNameCurrentCount;
2072 std::map<FbxSurfaceMaterial*, std::string> tempNames;
2073 auto materialCount = scene->GetMaterialCount();
2075 for (
int i = 0; i < materialCount; i++)
2077 auto lMaterial = scene->GetMaterial(i);
2078 auto materialName = std::string(lMaterial->GetName());
2079 auto materialPart = std::string();
2081 int materialNameSplitPosition = materialName.find(
'#');
2082 if (materialNameSplitPosition != std::string::npos)
2084 materialPart = materialName.substr(materialNameSplitPosition + 1);
2085 materialName = materialName.substr(0, materialNameSplitPosition);
2088 materialNameSplitPosition = materialNameSplitPosition = materialName.find(
"__");
2089 if (materialNameSplitPosition != std::string::npos)
2091 materialPart = materialName.substr(materialNameSplitPosition + 2);
2092 materialName = materialName.substr(0, materialNameSplitPosition);
2096 int nextCharacterPos = materialName.find(
':');
2097 while (nextCharacterPos != std::string::npos)
2099 materialName.replace(nextCharacterPos, 1, 1,
'_');
2100 nextCharacterPos = materialName.find(
':', nextCharacterPos);
2102 tempNames[lMaterial] = materialName;
2104 if (materialNameTotalCount.count(materialName) == 0)
2105 materialNameTotalCount[materialName] = 1;
2107 materialNameTotalCount[materialName] = materialNameTotalCount[materialName] + 1;
2110 for (
int i = 0; i < materialCount; i++)
2112 auto lMaterial = scene->GetMaterial(i);
2113 auto materialName = tempNames[lMaterial];
2114 int currentCount = 0;
2116 if (materialNameCurrentCount.count(materialName) == 0)
2117 materialNameCurrentCount[materialName] = 1;
2119 materialNameCurrentCount[materialName] = materialNameCurrentCount[materialName] + 1;
2121 if(materialNameTotalCount[materialName] > 1)
2122 materialName = materialName +
"_" + std::to_string(materialNameCurrentCount[materialName]);
2124 materialNames[lMaterial] = materialName;
2128 void GetMeshes(FbxNode* pNode, std::vector<FbxMesh*>& meshes)
2131 for(
int i = 0; i < pNode->GetNodeAttributeCount(); i++)
2133 auto pAttribute = pNode->GetNodeAttributeByIndex(i);
2135 if(!pAttribute)
return;
2137 if (pAttribute->GetAttributeType() == FbxNodeAttribute::eMesh)
2139 auto pMesh = (FbxMesh*)pAttribute;
2140 meshes.push_back(pMesh);
2145 for(
int j = 0; j < pNode->GetChildCount(); j++)
2147 GetMeshes(pNode->GetChild(j), meshes);
2151 void GenerateMeshesName(std::map<FbxMesh*, std::string>& meshNames)
2153 std::vector<FbxMesh*> meshes;
2154 GetMeshes(scene->GetRootNode(), meshes);
2156 std::map<std::string, int> meshNameTotalCount;
2157 std::map<std::string, int> meshNameCurrentCount;
2158 std::map<FbxMesh*, std::string> tempNames;
2160 for (
auto iter = meshes.begin(); iter != meshes.end(); ++iter)
2163 auto meshName = std::string(pMesh->GetNode()->GetName());
2164 tempNames[pMesh] = meshName;
2166 if (meshNameTotalCount.count(meshName) == 0)
2167 meshNameTotalCount[meshName] = 1;
2169 meshNameTotalCount[meshName] = meshNameTotalCount[meshName] + 1;
2172 for (
auto iter = meshes.begin(); iter != meshes.end(); ++iter)
2175 auto meshName = tempNames[pMesh];
2176 int currentCount = 0;
2178 if (meshNameCurrentCount.count(meshName) == 0)
2179 meshNameCurrentCount[meshName] = 1;
2181 meshNameCurrentCount[meshName] = meshNameCurrentCount[meshName] + 1;
2183 if(meshNameTotalCount[meshName] > 1)
2184 meshName = meshName +
"_" + std::to_string(meshNameCurrentCount[meshName]);
2186 meshNames[pMesh] = meshName;
2190 void GetNodes(FbxNode* pNode, std::vector<FbxNode*>& nodes)
2192 nodes.push_back(pNode);
2195 for(
int j = 0; j < pNode->GetChildCount(); j++)
2196 GetNodes(pNode->GetChild(j), nodes);
2199 void GenerateNodesName(std::map<FbxNode*, std::string>& nodeNames)
2201 std::vector<FbxNode*> nodes;
2202 GetNodes(scene->GetRootNode(), nodes);
2204 std::map<std::string, int> nodeNameTotalCount;
2205 std::map<std::string, int> nodeNameCurrentCount;
2206 std::map<FbxNode*, std::string> tempNames;
2208 for (
auto iter = nodes.begin(); iter != nodes.end(); ++iter)
2211 auto nodeName = std::string(pNode->GetName());
2212 auto subBegin = nodeName.find_last_of(
':');
2213 if (subBegin != std::string::npos)
2214 nodeName = nodeName.substr(subBegin + 1);
2215 tempNames[pNode] = nodeName;
2217 if (nodeNameTotalCount.count(nodeName) == 0)
2218 nodeNameTotalCount[nodeName] = 1;
2220 nodeNameTotalCount[nodeName] = nodeNameTotalCount[nodeName] + 1;
2223 for (
auto iter = nodes.begin(); iter != nodes.end(); ++iter)
2226 auto nodeName = tempNames[pNode];
2227 int currentCount = 0;
2229 if (nodeNameCurrentCount.count(nodeName) == 0)
2230 nodeNameCurrentCount[nodeName] = 1;
2232 nodeNameCurrentCount[nodeName] = nodeNameCurrentCount[nodeName] + 1;
2234 if(nodeNameTotalCount[nodeName] > 1)
2235 nodeName = nodeName +
"_" + std::to_string(nodeNameCurrentCount[nodeName]);
2237 nodeNames[pNode] = nodeName;
2241 MaterialInstances^ GetOrCreateInstances(FbxSurfaceMaterial* lMaterial, List<MaterialInstances^>^ instances, std::map<FbxSurfaceMaterial*, std::string>& materialNames)
2243 for (
int i = 0; i < instances->Count; ++i)
2245 if (lMaterial == instances[i]->SourceMaterial)
2246 return instances[i];
2249 auto newInstance =
gcnew MaterialInstances();
2250 newInstance->SourceMaterial = lMaterial;
2251 newInstance->MaterialsName =
gcnew String(materialNames[lMaterial].c_str());
2252 instances->Add(newInstance);
2256 MaterialInstanciation^ GetOrCreateMaterial(FbxSurfaceMaterial* lMaterial, List<String^>^ uvNames, List<MaterialInstances^>^ instances, std::map<std::string, int>& uvElements, std::map<FbxSurfaceMaterial*, std::string>& materialNames)
2258 auto materialInstances = GetOrCreateInstances(lMaterial, instances, materialNames);
2260 for (
int i = 0; i < materialInstances->Instances->Count; ++i)
2262 auto parameters = materialInstances->Instances[i]->Parameters;
2263 if (uvNames->Count == parameters->Count)
2266 for (
int j = 0; j < parameters->Count; ++j)
2268 equals = equals && (parameters[j] == uvNames[j]);
2272 return materialInstances->Instances[i];
2277 newInstanciation->Parameters = uvNames;
2279 if (materialInstances->Instances->Count > 0)
2280 newInstanciation->MaterialName = materialInstances->MaterialsName +
"_" + materialInstances->Instances->Count;
2282 newInstanciation->MaterialName = materialInstances->MaterialsName;
2284 newInstanciation->Material = ProcessMeshMaterialAsset(lMaterial, uvElements);
2285 materialInstances->Instances->Add(newInstanciation);
2286 return newInstanciation;
2289 void SearchMeshInAttribute(FbxNode* pNode, FbxNodeAttribute* pAttribute, std::map<FbxSurfaceMaterial*, std::string> materialNames, std::map<FbxMesh*, std::string> meshNames, std::map<FbxNode*, std::string>& nodeNames, List<MeshParameters^>^ models, List<MaterialInstances^>^ materialInstances, List<CameraInfo^>^ cameras, List<LightInfo^>^ lights)
2291 if(!pAttribute)
return;
2293 if (pAttribute->GetAttributeType() == FbxNodeAttribute::eMesh)
2295 auto pMesh = (FbxMesh*)pAttribute;
2296 int polygonCount = pMesh->GetPolygonCount();
2297 FbxGeometryElement::EMappingMode materialMappingMode = FbxGeometryElement::eNone;
2298 FbxLayerElementArrayTemplate<int>* materialIndices = NULL;
2300 if (pMesh->GetElementMaterial())
2302 materialMappingMode = pMesh->GetElementMaterial()->GetMappingMode();
2303 materialIndices = &pMesh->GetElementMaterial()->GetIndexArray();
2306 auto buildMeshes =
gcnew List<BuildMesh^>();
2309 for (
int i = 0; i < polygonCount; i++)
2311 int materialIndex = 0;
2312 if (materialMappingMode == FbxGeometryElement::eByPolygon)
2314 materialIndex = materialIndices->GetAt(i);
2318 while (materialIndex >= buildMeshes->Count)
2320 buildMeshes->Add(
nullptr);
2323 if (buildMeshes[materialIndex] ==
nullptr)
2324 buildMeshes[materialIndex] =
gcnew BuildMesh();
2326 int polygonSize = pMesh->GetPolygonSize(i) - 2;
2327 if (polygonSize > 0)
2328 buildMeshes[materialIndex]->polygonCount += polygonSize;
2331 for (
int i = 0; i < buildMeshes->Count; ++i)
2333 FbxGeometryElementMaterial* lMaterialElement = pMesh->GetElementMaterial();
2334 if (lMaterialElement != NULL)
2338 FbxSurfaceMaterial* lMaterial = pNode->GetMaterial(i);
2339 std::map<std::string, int> uvElements;
2340 auto uvNames =
gcnew List<String^>();
2341 for (
int j = 0; j < pMesh->GetElementUVCount(); ++j)
2343 uvElements[pMesh->GetElementUV(j)->GetName()] = j;
2344 uvNames->Add(
gcnew String(pMesh->GetElementUV(j)->GetName()));
2347 auto material = GetOrCreateMaterial(lMaterial, uvNames, materialInstances, uvElements, materialNames);
2348 auto meshName = meshNames[pMesh];
2349 if (buildMeshes->Count > 1)
2350 meshName = meshName +
"_" + std::to_string(i+1);
2352 meshParams->MeshName =
gcnew String(meshName.c_str());
2353 meshParams->MaterialName = material->MaterialName;
2354 meshParams->NodeName =
gcnew String(nodeNames[pNode].c_str());
2355 models->Add(meshParams);
2359 else if (pAttribute->GetAttributeType() == FbxNodeAttribute::eCamera)
2361 auto pCamera = (FbxCamera*)pAttribute;
2362 ProcessCamera(cameras, pNode, pCamera, nodeNames);
2364 else if (pAttribute->GetAttributeType() == FbxNodeAttribute::eLight)
2366 auto pLight = (FbxLight*)pAttribute;
2367 ProcessLight(lights, pNode, pLight, nodeNames);
2371 void SearchMesh(FbxNode* pNode, std::map<FbxSurfaceMaterial*, std::string> materialNames, std::map<FbxMesh*, std::string> meshNames, std::map<FbxNode*, std::string>& nodeNames, List<MeshParameters^>^ models, List<MaterialInstances^>^ materialInstances, List<CameraInfo^>^ cameras, List<LightInfo^>^ lights)
2374 for(
int i = 0; i < pNode->GetNodeAttributeCount(); i++)
2375 SearchMeshInAttribute(pNode, pNode->GetNodeAttributeByIndex(i), materialNames, meshNames, nodeNames, models, materialInstances, cameras, lights);
2378 for(
int j = 0; j < pNode->GetChildCount(); j++)
2380 SearchMesh(pNode->GetChild(j), materialNames, meshNames, nodeNames, models, materialInstances, cameras, lights);
2384 Dictionary<String^, MaterialDescription^>^ ExtractMaterialsNoInit()
2386 std::map<FbxSurfaceMaterial*, std::string> materialNames;
2387 GenerateMaterialNames(materialNames);
2389 auto materials =
gcnew Dictionary<String^, MaterialDescription^>();
2390 for (
int i = 0; i < scene->GetMaterialCount(); i++)
2392 std::map<std::string, int> dict;
2393 auto lMaterial = scene->GetMaterial(i);
2394 auto materialName = materialNames[lMaterial];
2395 materials->Add(
gcnew String(materialName.c_str()), ProcessMeshMaterialAsset(lMaterial, dict));
2400 MeshMaterials^ ExtractModelNoInit(std::map<FbxNode*, std::string>& nodeNames)
2402 std::map<FbxSurfaceMaterial*, std::string> materialNames;
2403 GenerateMaterialNames(materialNames);
2405 std::map<FbxMesh*, std::string> meshNames;
2406 GenerateMeshesName(meshNames);
2408 std::map<std::string, FbxSurfaceMaterial*> materialPerMesh;
2409 auto models =
gcnew List<MeshParameters^>();
2410 auto materialInstances =
gcnew List<MaterialInstances^>();
2411 auto cameras =
gcnew List<CameraInfo^>();
2412 auto lights =
gcnew List<LightInfo^>();
2413 SearchMesh(scene->GetRootNode(), materialNames, meshNames, nodeNames, models, materialInstances, cameras, lights);
2416 ret->Models = models;
2417 ret->Cameras = cameras;
2418 ret->Lights = lights;
2419 ret->Materials =
gcnew Dictionary<String^, MaterialDescription^>();
2420 for (
int i = 0; i < materialInstances->Count; ++i)
2422 for (
int j = 0; j < materialInstances[i]->Instances->Count; ++j)
2424 ret->Materials->Add(materialInstances[i]->Instances[j]->MaterialName, materialInstances[i]->Instances[j]->
Material);
2429 int numPointLights = 0;
2430 int numSpotLights = 0;
2431 int numDirectionalLights = 0;
2432 for (
int i = 0; i < lights->Count; ++i)
2434 auto lightType = lights[i]->Data->Type;
2437 else if (lightType == LightType::Directional)
2438 ++numDirectionalLights;
2439 else if (lightType == LightType::Spot)
2443 for (
int i = 0; i < models->Count; ++i)
2445 models[i]->Parameters->Add(LightingKeys::MaxPointLights, numPointLights);
2446 models[i]->Parameters->Add(LightingKeys::MaxDirectionalLights, numDirectionalLights);
2447 models[i]->Parameters->Add(LightingKeys::MaxSpotLights, numSpotLights);
2453 List<String^>^ ExtractTextureDependenciesNoInit()
2455 auto textureNames =
gcnew List<String^>();
2457 auto textureCount = scene->GetTextureCount();
2458 for(
int i=0; i<textureCount; ++i)
2460 auto texture = FbxCast<FbxFileTexture>(scene->GetTexture(i));
2462 if(texture ==
nullptr)
2465 auto texturePath = FindFilePath(texture);
2466 if(!String::IsNullOrEmpty(texturePath)
2467 && File::Exists(texturePath))
2468 textureNames->Add(texturePath);
2471 return textureNames;
2474 List<String^>^ ExtractAnimationNodesNoInit()
2476 int animStackCount = scene->GetMemberCount<FbxAnimStack>();
2477 List<String^>^ animationNodes =
nullptr;
2479 if (animStackCount > 0)
2481 animationNodes =
gcnew List<String^>();
2482 for (
int i = 0; i < animStackCount; ++i)
2484 FbxAnimStack* animStack = scene->GetMember<FbxAnimStack>(i);
2485 int animLayerCount = animStack->GetMemberCount<FbxAnimLayer>();
2486 FbxAnimLayer* animLayer = animStack->GetMember<FbxAnimLayer>(0);
2487 GetAnimationNodes(animLayer, scene->GetRootNode(), animationNodes);
2491 return animationNodes;
2494 List<String^>^ GetAllAnimationNodes(String^ inputFile)
2498 Initialize(inputFile,
nullptr, ImportConfiguration::ImportAnimationsOnly());
2499 return ExtractAnimationNodesNoInit();
2508 List<String^>^ ExtractTextureDependencies(String^ inputFile)
2512 Initialize(inputFile,
nullptr, ImportConfiguration::ImportTexturesOnly());
2513 return ExtractTextureDependenciesNoInit();
2522 Dictionary<String^, MaterialDescription^>^ ExtractMaterials(String^ inputFilename)
2526 Initialize(inputFilename,
nullptr, ImportConfiguration::ImportMaterialsOnly());
2527 return ExtractMaterialsNoInit();
2536 void GetNodes(FbxNode* node,
int depth, std::map<FbxNode*, std::string>& nodeNames, List<NodeInfo^>^ allNodes)
2538 auto newNodeInfo =
gcnew NodeInfo();
2539 newNodeInfo->Name =
gcnew String(nodeNames[node].c_str());
2540 newNodeInfo->Depth = depth;
2541 newNodeInfo->Preserve =
false;
2543 allNodes->Add(newNodeInfo);
2544 for (
int i = 0; i < node->GetChildCount(); ++i)
2545 GetNodes(node->GetChild(i), depth + 1, nodeNames, allNodes);
2548 List<NodeInfo^>^ ExtractNodeHierarchy(std::map<FbxNode*, std::string>& nodeNames)
2550 auto allNodes =
gcnew List<NodeInfo^>();
2551 GetNodes(scene->GetRootNode(), 0, nodeNames, allNodes);
2560 Initialize(inputFileName,
nullptr, ImportConfiguration::ImportEntityConfig());
2562 auto index = scene->GetGlobalSettings().GetOriginalUpAxis();
2563 auto originalUpAxis = Vector3::Zero;
2564 if (index < 0 || index > 2)
2565 originalUpAxis[2] = 1;
2567 originalUpAxis[index] = 1;
2569 std::map<FbxNode*, std::string> nodeNames;
2570 GenerateNodesName(nodeNames);
2573 entityInfo->TextureDependencies = ExtractTextureDependenciesNoInit();
2574 entityInfo->AnimationNodes = ExtractAnimationNodesNoInit();
2575 auto models = ExtractModelNoInit(nodeNames);
2576 entityInfo->Models = models->Models;
2577 entityInfo->Materials = models->Materials;
2578 entityInfo->Nodes = ExtractNodeHierarchy(nodeNames);
2579 entityInfo->Lights = models->Lights;
2580 entityInfo->Cameras = models->Cameras;
2581 entityInfo->UpAxis = originalUpAxis;
2596 Initialize(inputFilename, vfsOutputFilename, ImportConfiguration::ImportAll());
2601 modelData->Hierarchy->Nodes = nodes.ToArray();
2614 std::map<FbxMesh*, std::string> meshNames;
2615 GenerateMeshesName(meshNames);
2618 ProcessNode(scene->GetRootNode(), meshNames);
2637 Initialize(inputFilename, vfsOutputFilename, ImportConfiguration::ImportAnimationsOnly());
2640 auto animationClip = ProcessAnimation(scene);
2642 return animationClip;
property bool ImportPivots
void ConvertDegreeToRadians(AnimationCurve< float >^channel)
Key of an effect parameter.
property TagSymbol TextureTagSymbol
CompressedTimeSpan FBXTimeToTimeSpane(const FbxTime &time)
Vector3 FbxDouble3ToVector3(FbxDouble3 vector)
TimeSpan Duration
Gets or sets the duration of this clip.
SiliconStudio.Paradox.Games.Mathematics.Vector2 Vector2
CurveEvaluator(FbxAnimCurve *curve)
The layout of a vertex buffer with a set of VertexElement.
property bool ImportMaterials
ModelData Convert(String^inputFilename, String^vfsOutputFilename)
A node that describe a binary operation between two IMaterialNode
property bool ImportModels
Vector4 FbxDouble4ToVector4(FbxDouble4 vector)
FbxSurfaceMaterial * SourceMaterial
property bool ImportConstraints
static ImportConfiguration ImportEntityConfig()
property bool InverseNormals
ComponentBase.Destroy() event.
Describes hiderarchical nodes in a flattened array.
Represents a color in the form of rgb.
void AddCurve(string propertyName, AnimationCurve curve)
Adds a named curve.
static ImportConfiguration ImportMaterialsOnly()
String FindFilePath(FbxFileTexture *lFileTexture)
Vector4 FbxDouble3ToVector4(FbxDouble3 vector, float wValue)
AnimationClip ProcessAnimation(FbxScene *scene)
Description of a material.
void MultiplyChannel(AnimationCurve< float >^channel, double factor)
List< KeyFrameData< T > > ProcessAnimationCurveFloatsHelper(FbxAnimCurve **curves, int numCurves)
Describes skinning for a Mesh, through a collection of MeshBoneDefinition.
void ProcessAnimation(AnimationClip^animationClip, FbxAnimLayer *animLayer, FbxNode *node)
double FocalLengthToVerticalFov(double filmHeight, double focalLength)
static ImportConfiguration ImportGlobalSettingsOnly()
property Vector3 ViewDirectionForTransparentZSort
static bool WeightGreater(const std::pair< short, float > &elem1, const std::pair< short, float > &elem2)
Represents a three dimensional mathematical vector.
int NodeIndex
The node index in ModelViewHierarchyUpdater.NodeTransformations.
List< ModelNodeDefinition > nodes
property bool ImportShapes
AnimationCurveInterpolationType InterpolationType
Gets or sets the interpolation type.
Data type for SiliconStudio.Paradox.Effects.ParameterCollection.
property bool ImportGlobalSettings
void ProcessNode(FbxNode *pNode, std::map< FbxMesh *, std::string > meshNames)
static array< Byte > currentBuffer
An aggregation of AnimationCurve with their channel names.
property bool ImportAnimations
Base implementation for ILogger.
property bool AllowUnsignedBlendIndices
static ImportConfiguration ImportTexturesOnly()
EntityInfo ExtractEntity(String^inputFileName)
MaterialBinaryOperand
Operands of the MaterialNode.
Dictionary< IntPtr, int > nodeMapping
property bool ImportLinks
IMaterialNode GenerateSurfaceTextureTree(FbxSurfaceMaterial *lMaterial, std::map< std::string, int > &uvElementMapping, std::map< FbxFileTexture *, std::string > &textureMap, std::map< std::string, int > &textureNameCount, char const *surfaceMaterial, char const *surfaceMaterialFactor, SiliconStudio::Paradox::Assets::Materials::MaterialDescription^finalMaterial)
Represents a four dimensional mathematical quaternion.
void RegisterNode(FbxNode *pNode, int parentIndex, std::map< FbxNode *, std::string > &nodeNames)
static ImportConfiguration ImportModelOnly()
Data type for SiliconStudio.Paradox.Graphics.VertexBufferBinding.
void AddNode(string referenceName, IMaterialNode node)
Inserts a new tree in the material
Data type for SiliconStudio.Paradox.EntityModel.Entity.
static ImportConfiguration ImportAnimationsOnly()
void ProcessAttribute(FbxNode *pNode, FbxNodeAttribute *pAttribute, std::map< FbxMesh *, std::string > meshNames)
property bool ExtractEmbeddedData
void SetPivotStateRecursive(FbxNode *node)
float Evaluate(CompressedTimeSpan time)
MaterialReferenceNode GenerateMaterialTextureNodeFBX(FbxFileTexture *lFileTexture, std::map< std::string, int > &uvElementMapping, std::map< FbxFileTexture *, std::string > &textureMap, std::map< std::string, int > &textureNameCount, SiliconStudio::Paradox::Assets::Materials::MaterialDescription^finalMaterial)
Data type for SiliconStudio.Paradox.Effects.Mesh.
Data type for SiliconStudio.Paradox.Effects.MeshDraw.
int GetTextureNameCount(std::map< std::string, int > &textureNameCount, std::string textureName)
Untyped base class for animation curves.
void ProcessAnimationCurveRotation(AnimationClip^animationClip, int nodeData, String^name, FbxAnimCurve **curves, float maxErrorThreshold)
property bool ImportTextures
List< MaterialInstanciation^> Instances
Data type for SiliconStudio.Paradox.Effects.Model.
static void Add(ref Quaternion left, ref Quaternion right, out Quaternion result)
Adds two quaternions.
void ProcessLight(List< LightInfo^>^lights, FbxNode *pNode, FbxLight *pLight, std::map< FbxNode *, std::string > &nodeNames)
Matrix FBXMatrixToMatrix(FbxAMatrix &matrix)
bool IsTransparent(FbxSurfaceMaterial *lMaterial)
AnimationClip ConvertAnimation(String^inputFilename, String^vfsOutputFilename)
Describes a single transformation node, usually in a Model node hierarchy.
Color4 FbxDouble3ToColor4(FbxDouble3 vector, float alphaValue)
property bool ImportCharacters
SiliconStudio.Core.Mathematics.Vector3 Vector3
Typed class for animation curves.
int ParentIndex
The parent node index.
Describes a bone cluster inside a Mesh.
void ReverseChannelZ(AnimationCurve< Vector3 >^channel)
void ComputeFovFromFL(AnimationCurve< float >^channel, FbxCamera *pCamera)
AnimationCurve< T > ProcessAnimationCurveVector(AnimationClip^animationClip, int nodeData, String^name, int numCurves, FbxAnimCurve **curves, float maxErrorThreshold)
void ProcessMesh(FbxMesh *pMesh, std::map< FbxMesh *, std::string > meshNames)
Content of a GPU buffer (vertex buffer, index buffer, etc...).
ShaderClassSource GenerateTextureLayerFBX(FbxFileTexture *lFileTexture, std::map< std::string, int > &uvElementMapping, MeshData^meshData, int &textureCount, ParameterKey< Texture^>^surfaceMaterialKey)
property bool ImportTemplates
float Z
The Z component of the vector.
void ProcessCamera(List< CameraInfo^>^cameras, FbxNode *pNode, FbxCamera *pCamera, std::map< FbxNode *, std::string > &nodeNames)
Base interface for all nodes in the material tree
A single key frame value.
A description of a single element for the input-assembler stage. This structure is related to Direct3...
MaterialBinaryOperand BlendModeToBlendOperand(FbxLayeredTexture::EBlendMode blendMode)
Data type for SiliconStudio.Paradox.Engine.LightComponent.
static ImportConfiguration ImportAll()
Data type for SiliconStudio.Paradox.Engine.CameraComponent.
System.Windows.Point Point
A shader class used for mixin.
property bool ImportGobos
MaterialDescription ProcessMeshMaterialAsset(FbxSurfaceMaterial *lMaterial, std::map< std::string, int > &uvElementMapping)
MeshConverter(Logger^Logger)