Browse Source

Animation fixes

Simon Ferquel 10 năm trước cách đây
mục cha
commit
dc6fd6b3a1

+ 4 - 3
Exporters/FBX/BabylonFbxNative/BabylonAbstractMesh.cpp

@@ -8,10 +8,11 @@ BabylonAbstractMesh::BabylonAbstractMesh()
 }
 
 BabylonAbstractMesh::BabylonAbstractMesh(BabylonNode* node)
-	: _position(node->localTranslate()),
-	_rotationQuaternion(node->localRotationQuat()),
-	_scaling(node->localScale())
 {
+	auto localTransform = node->GetLocal();
+	_position = localTransform.translation();
+	_rotationQuaternion = localTransform.rotationQuaternion();
+	_scaling = localTransform.scaling();
 	auto n = node->name();
 	_name = std::wstring(n.begin(), n.end());
 }

+ 10 - 9
Exporters/FBX/BabylonFbxNative/BabylonAnimation.h

@@ -37,6 +37,11 @@ public:
 	bool autoAnimateLoop;
 	BabylonAnimationBase(int loopBehavior, int fps, const std::wstring& name, const std::wstring& animatedProperty, bool autoAnimate, int autoAnimateFrom, int autoAnimateTo, bool autoAnimateLoop);
 	virtual ~BabylonAnimationBase(){}
+
+
+	virtual bool isConstant() = 0;
+
+	virtual web::json::value toJson() const = 0;
 };
 
 template<typename T>
@@ -84,11 +89,11 @@ struct bab_anim_traits < babylon_vector4 >
 };
 
 template<>
-struct bab_anim_traits < FbxAMatrix >
+struct bab_anim_traits < FbxMatrix >
 {
 	static const int dataType = BabylonAnimationBase::dataType_Matrix;
 
-	static web::json::value jsonify(const FbxAMatrix& value){
+	static web::json::value jsonify(const FbxMatrix& value){
 		auto jmat = web::json::value::array();
 		for (auto x = 0; x < 4; ++x){
 			for (auto y = 0; y < 4; ++y){
@@ -120,7 +125,7 @@ inline bool isNear<float>(const float& lhs, const float& rhs){
 }
 
 template <>
-inline bool isNear<FbxAMatrix>(const FbxAMatrix& lhs, const FbxAMatrix& rhs){
+inline bool isNear<FbxMatrix>(const FbxMatrix& lhs, const FbxMatrix& rhs){
 	return lhs == rhs;
 }
 
@@ -143,10 +148,6 @@ inline T lerp(const T& start, const T& end, float factor){
 	return start + (end - start)*factor;
 }
 
-template<>
-inline FbxAMatrix lerp(const FbxAMatrix& start, const FbxAMatrix& end, float factor){
-	return start.Slerp(end, factor);
-}
 template<typename T>
 bool isLinearInterpolation(const babylon_animation_key<T>& key0, const babylon_animation_key<T>& key1, const babylon_animation_key<T>& key2){
 	auto testVal = lerp(key0.values, key2.values, static_cast<float>(key1.frame - key0.frame) / static_cast<float>(key2.frame - key0.frame));
@@ -190,7 +191,7 @@ public:
 		}
 	}
 
-	bool isConstant(){
+	virtual bool isConstant() override{
 		if (keys.size() < 2){
 			return true;
 		}
@@ -201,7 +202,7 @@ public:
 		return isNear(keys[0].values, keys[1].values);
 	}
 
-	web::json::value toJson() const{
+	virtual web::json::value toJson() const override {
 		auto jobj = web::json::value::object();
 
 		/*

+ 8 - 4
Exporters/FBX/BabylonFbxNative/BabylonCamera.cpp

@@ -104,8 +104,9 @@ BabylonCamera::BabylonCamera(BabylonNode& babnode)
 	else {
 		target = camera->InterestPosition.Get();
 	}
-	position = babnode.localTranslate();
-	rotationQuaternion = babnode.localRotationQuat();
+	auto localTransformAtStart = babnode.GetLocal();
+	position = localTransformAtStart.translation();
+	rotationQuaternion = localTransformAtStart.rotationQuaternion();
 	
 	fov = static_cast<float>(camera->FieldOfViewY * Euler2Rad);
 	minZ = static_cast<float>(camera->FrontPlaneDistance.Get());
@@ -137,8 +138,11 @@ BabylonCamera::BabylonCamera(BabylonNode& babnode)
 		poskey.frame = ix;
 		rotkey.frame = ix;
 
-		poskey.values = babnode.localTranslate(currTime);
-		rotkey.values = babnode.localRotationQuat(currTime);
+
+		auto transformAtT = babnode.GetLocal(currTime);
+
+		poskey.values = transformAtT.translation();
+		rotkey.values = transformAtT.rotationQuaternion();
 		posAnim->appendKey(poskey);
 		rotAnim->appendKey(rotkey);
 

+ 1 - 0
Exporters/FBX/BabylonFbxNative/BabylonFbxNative.vcxproj

@@ -189,6 +189,7 @@
     <ClInclude Include="FbxSceneLoader.h" />
     <ClInclude Include="FbxVertexKey.h" />
     <ClInclude Include="GlobalSettings.h" />
+    <ClInclude Include="MatrixDecomposition.h" />
     <ClInclude Include="NodeHelpers.h" />
     <ClInclude Include="SkinInfo.h" />
     <ClInclude Include="stdafx.h" />

+ 3 - 0
Exporters/FBX/BabylonFbxNative/BabylonFbxNative.vcxproj.filters

@@ -84,6 +84,9 @@
     <ClInclude Include="GlobalSettings.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="MatrixDecomposition.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="stdafx.cpp">

+ 80 - 21
Exporters/FBX/BabylonFbxNative/BabylonLight.cpp

@@ -22,7 +22,7 @@ web::json::value BabylonLight::toJson() const
 	jobj[L"angle"] = web::json::value::number(angle);
 	writeVector3(jobj, L"groundColor", groundColor);
 
-	if (animations.size() == 0){
+	if (animations.size() == 0) {
 
 		jobj[L"autoAnimate"] = web::json::value::boolean(false);
 		jobj[L"autoAnimateLoop"] = web::json::value::boolean(false);
@@ -30,7 +30,7 @@ web::json::value BabylonLight::toJson() const
 		jobj[L"autoAnimateTo"] = web::json::value::number(0);
 
 	}
-	else{
+	else {
 
 		jobj[L"autoAnimate"] = web::json::value::boolean(animations[0]->autoAnimate);
 		jobj[L"autoAnimateLoop"] = web::json::value::boolean(animations[0]->autoAnimateLoop);
@@ -39,22 +39,35 @@ web::json::value BabylonLight::toJson() const
 	}
 
 	auto janimations = web::json::value::array();
-	for (const auto& anim : animations){
+	for (const auto& anim : animations) {
 		janimations[janimations.size()] = anim->toJson();
 	}
 	jobj[L"animations"] = janimations;
+
+	auto jarray = web::json::value::array();
+	for (auto& id : excludedMeshesIds) {
+		jarray[jarray.size()] = web::json::value::string(id);
+	}
+	jobj[L"excludedMeshesIds"] = jarray;
+
+	jarray = web::json::value::array();
+	for (auto& id : includedOnlyMeshesIds) {
+		jarray[jarray.size()] = web::json::value::string(id);
+	}
+	jobj[L"includedOnlyMeshesIds"] = jarray;
+
 	return jobj;
 }
 
 BabylonLight::BabylonLight() :
-diffuse(1, 1, 1),
-specular(1, 1, 1)
+	diffuse(1, 1, 1),
+	specular(1, 1, 1)
 {
 }
 
 BabylonLight::BabylonLight(BabylonNode & babnode) :
-diffuse(1, 1, 1),
-specular(1, 1, 1)
+	diffuse(1, 1, 1),
+	specular(1, 1, 1)
 {
 	auto node = babnode.fbxNode();
 	std::string ansiName = node->GetName();
@@ -64,7 +77,8 @@ specular(1, 1, 1)
 	if (parent) {
 		parentId = getNodeId(parent);
 	}
-	position = babnode.localTranslate();
+	auto localTransform = babnode.GetLocal();
+	position = localTransform.translation();
 	auto light = node->GetLight();
 	switch (light->LightType)
 	{
@@ -74,10 +88,11 @@ specular(1, 1, 1)
 	case FbxLight::eDirectional:
 		type = type_direct;
 		{
-			FbxDouble3 vDir(0, 1, 0);
+			FbxDouble3 vDir(0, -1, 0);
 			FbxAMatrix rotM;
 			rotM.SetIdentity();
-			rotM.SetQ(babnode.localTransform().GetQ());
+
+			rotM.SetQ(localTransform.fbxrot());
 			auto transDir = rotM.MultT(vDir);
 			direction = transDir;
 
@@ -86,10 +101,10 @@ specular(1, 1, 1)
 	case FbxLight::eSpot:
 		type = type_Spot;
 		{
-			FbxDouble3 vDir(0, 1, 0);
+			FbxDouble3 vDir(0, -1, 0);
 			FbxAMatrix rotM;
 			rotM.SetIdentity();
-			rotM.SetQ(babnode.localTransform().GetQ());
+			rotM.SetQ(localTransform.fbxrot());
 			auto transDir = rotM.MultT(vDir);
 			direction = transDir;
 			exponent = 1;
@@ -106,9 +121,13 @@ specular(1, 1, 1)
 		range = static_cast<float>(light->FarAttenuationEnd.Get());
 	}
 	auto hasAnimStack = node->GetScene()->GetSrcObjectCount<FbxAnimStack>() > 0;
-	if (!hasAnimStack){
+	if (!hasAnimStack) {
 		return;
 	}
+	castShadows = light->CastShadows.Get();
+	if (castShadows) {
+		shadowGenerator = std::make_shared<BabylonShadowGenerator>(node);
+	}
 	auto animStack = node->GetScene()->GetSrcObject<FbxAnimStack>(0);
 	FbxString animStackName = animStack->GetName();
 	FbxTakeInfo* takeInfo = node->GetScene()->GetTakeInfo(animStackName);
@@ -123,31 +142,31 @@ specular(1, 1, 1)
 	dirAnimName.append(L"_direction");
 	auto posAnim = std::make_shared<BabylonAnimation<babylon_vector3>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), posAnimName, L"position", true, 0, static_cast<int>(animLengthInFrame), true);
 	auto dirAnim = std::make_shared<BabylonAnimation<babylon_vector3>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), dirAnimName, L"direction", true, 0, static_cast<int>(animLengthInFrame), true);
-	for (auto ix = 0; ix < animLengthInFrame; ix++){
+	for (auto ix = 0; ix < animLengthInFrame; ix++) {
 		babylon_animation_key<babylon_vector3> key;
 		key.frame = ix;
 		FbxTime currTime;
 		currTime.SetFrame(startFrame + ix, animTimeMode);
-		key.values = babnode.localTranslate(currTime);
+		auto currTransform = babnode.GetLocal(currTime);
+		key.values = currTransform.translation();
 		posAnim->appendKey(key);
 
-		if (type == type_direct || type == type_Spot){
+		if (type == type_direct || type == type_Spot) {
 			babylon_animation_key<babylon_vector3> dirkey;
 			dirkey.frame = ix;
-			auto transformAtTime = babnode.localTransform(currTime);
-			FbxDouble3 vDir(0, 1, 0);
+			FbxDouble3 vDir(0, -1, 0);
 			FbxAMatrix rotM;
 			rotM.SetIdentity();
-			rotM.SetQ(transformAtTime.GetQ());
+			rotM.SetQ(currTransform.fbxrot());
 			auto transDir = rotM.MultT(vDir);
 			dirkey.values = transDir;
 			dirAnim->appendKey(dirkey);
 		}
 	}
-	if (!posAnim->isConstant()){
+	if (!posAnim->isConstant()) {
 		animations.push_back(posAnim);
 	}
-	if (!dirAnim->isConstant()){
+	if (!dirAnim->isConstant()) {
 		animations.push_back(dirAnim);
 	}
 }
@@ -156,3 +175,43 @@ specular(1, 1, 1)
 BabylonLight::~BabylonLight()
 {
 }
+
+BabylonShadowGenerator::BabylonShadowGenerator(FbxNode * lightNode)
+{
+	auto light = lightNode->GetLight();
+	lightId = getNodeId(lightNode);
+	mapSize = 2048;
+	bias = 0.00005f;
+	useBlurVarianceShadowMap = true;
+	blurScale = 2;
+	blurBoxOffset = 1;
+	useVarianceShadowMap = false;
+	usePoissonSampling = false;
+	auto nodeCount = lightNode->GetScene()->GetNodeCount();
+	for (auto ix = 0;ix < nodeCount;++ix) {
+		auto mnode = lightNode->GetScene()->GetNode(ix);
+		auto mesh = mnode->GetMesh();
+		if (mesh && mesh->CastShadow.Get()) {
+			renderList.push_back(getNodeId(mnode));
+		}
+	}
+
+}
+
+web::json::value BabylonShadowGenerator::toJson()
+{
+	auto jobj =web::json::value::object();
+	jobj[L"mapSize"] = web::json::value::number(mapSize);
+	jobj[L"lightId"] = web::json::value::string(lightId);
+	jobj[L"useVarianceShadowMap"] = web::json::value::boolean(useVarianceShadowMap);
+	jobj[L"usePoissonSampling"] = web::json::value::boolean(usePoissonSampling);
+	/*jobj[L"useBlurVarianceShadowMap"] = web::json::value::boolean(useBlurVarianceShadowMap);
+	jobj[L"blurScale"] = web::json::value::number(blurScale);
+	jobj[L"blurBoxOffset"] = web::json::value::number(blurBoxOffset);*/
+	auto jarr = web::json::value::array();
+	for (auto& id : renderList) {
+		jarr[jarr.size()] = web::json::value::string(id);
+	}
+	jobj[L"renderList"] = jarr;
+	return jobj;
+}

+ 42 - 2
Exporters/FBX/BabylonFbxNative/BabylonLight.h

@@ -4,7 +4,45 @@
 #include "BabylonNode.h"
 #include "BabylonAnimation.h"
 #include <memory>
+#include <string>
 #undef max
+
+class BabylonShadowGenerator
+{
+public:
+
+	int mapSize;
+
+		
+	float bias;
+
+		
+	std::wstring lightId;
+
+		
+	bool useVarianceShadowMap;
+
+		
+	bool usePoissonSampling;
+
+		
+	bool useBlurVarianceShadowMap;
+
+		
+	float blurScale;
+
+		
+	float blurBoxOffset;
+
+		
+	std::vector<std::wstring> renderList;
+
+	BabylonShadowGenerator(FbxNode* lightNode);
+	web::json::value toJson();
+
+};
+
+
 class BabylonLight
 {
 public:
@@ -53,10 +91,12 @@ public:
 		
 	babylon_vector3 groundColor;
 
-		
+	bool castShadows;
+	std::vector<std::wstring> includedOnlyMeshesIds;
+	std::vector<std::wstring> excludedMeshesIds;
 
 		
-	
+	std::shared_ptr<BabylonShadowGenerator> shadowGenerator;
 
 	web::json::value toJson() const;
 

+ 39 - 1
Exporters/FBX/BabylonFbxNative/BabylonMaterial.cpp

@@ -2,6 +2,7 @@
 #include "BabylonMaterial.h"
 #include <Windows.h>
 #include "NodeHelpers.h"
+#include "GlobalSettings.h"
 
 web::json::value BabylonMaterial::toJson() const
 {
@@ -156,7 +157,7 @@ alpha(1){
 	GetMaterialProperty(mat, FbxSurfaceMaterial::sReflection, FbxSurfaceMaterial::sReflectionFactor, reflectionTex);
 	auto shininessProp = mat->FindProperty(FbxSurfaceMaterial::sShininess);
 	if (shininessProp.IsValid()){
-		specularPower = static_cast<float>(shininessProp.Get<FbxDouble>());
+		specularPower = static_cast<float>(shininessProp.Get<FbxDouble>())*12;
 	}
 
 	auto normalMapProp = mat->FindProperty(FbxSurfaceMaterial::sNormalMap);
@@ -250,6 +251,11 @@ web::json::value BabylonTexture::toJson(){
 	jobj[L"wrapV"] = web::json::value::boolean(wrapV);
 	jobj[L"coordinatesIndex"] = web::json::value::number(coordinatesIndex);
 	jobj[L"isRenderTarget"] = web::json::value::boolean(isRenderTarget);
+	auto janims = web::json::value::array();
+	for (auto& anim : animations) {
+		janims[janims.size()] = anim->toJson();
+	}
+	jobj[L"animations"] = janims;
 	return jobj;
 }
 BabylonTexture::BabylonTexture(FbxFileTexture* texture){
@@ -315,7 +321,39 @@ BabylonTexture::BabylonTexture(FbxFileTexture* texture){
 	auto vwrapMode = texture->GetWrapModeV();
 	wrapU = uwrapMode == FbxTexture::eRepeat;
 	wrapV = vwrapMode == FbxTexture::eRepeat;
+
+	auto animStack = texture->GetScene()->GetSrcObject<FbxAnimStack>(0);
+	FbxString animStackName = animStack->GetName();
+	FbxTakeInfo* takeInfo = texture->GetScene()->GetTakeInfo(animStackName);
+	auto animTimeMode = GlobalSettings::Current().AnimationsTimeMode;
+	auto animFrameRate = GlobalSettings::Current().AnimationsFrameRate();
+	auto startFrame = takeInfo->mLocalTimeSpan.GetStart().GetFrameCount(animTimeMode);
+	auto endFrame = takeInfo->mLocalTimeSpan.GetStop().GetFrameCount(animTimeMode);
+	auto animLengthInFrame = endFrame - startFrame + 1;
+	auto uOffsetAnim = std::make_shared<BabylonAnimation<float>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), L"uOffset", L"uOffset", true, 0, static_cast<int>(animLengthInFrame), true);
+	auto vOffsetAnim = std::make_shared<BabylonAnimation<float>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), L"vOffset", L"vOffset", true, 0, static_cast<int>(animLengthInFrame), true);
 	
+	for (auto ix = 0; ix < animLengthInFrame; ix++) {
+		FbxTime currTime;
+		currTime.SetFrame(startFrame + ix, animTimeMode);
+
+		babylon_animation_key<float> uKey;
+		babylon_animation_key<float> vKey;
+		uKey.frame = ix;
+		vKey.frame = ix;
+		auto currTrans = texture->Translation.EvaluateValue(currTime);
+		uKey.values = static_cast<float>(currTrans[0]);
+		vKey.values = static_cast<float>(currTrans[1]);
+		uOffsetAnim->appendKey(uKey);
+		vOffsetAnim->appendKey(vKey);
+
+	}
+	if (!uOffsetAnim->isConstant()) {
+		animations.push_back(uOffsetAnim);
+	}
+	if (!vOffsetAnim->isConstant()) {
+		animations.push_back(vOffsetAnim);
+	}
 	
 
 }

+ 2 - 1
Exporters/FBX/BabylonFbxNative/BabylonMaterial.h

@@ -5,7 +5,7 @@
 #include "BabylonVertex.h"
 #include <vector>
 #include <fbxsdk.h>
-
+#include "BabylonAnimation.h"
 
 
 class BabylonTexture{
@@ -61,6 +61,7 @@ public:
 
 		
 	 bool isRenderTarget = false;
+	 std::vector<std::shared_ptr<BabylonAnimationBase>> animations;
 
 	 BabylonTexture(FbxFileTexture* texture);
 

+ 22 - 18
Exporters/FBX/BabylonFbxNative/BabylonMesh.cpp

@@ -343,7 +343,7 @@ web::json::value BabylonMesh::toJson()
 	if (_boneWeights.size() > 0){
 		jobj[L"matricesWeights"] = convertToJson(_boneWeights);
 	}
-	if (animations.size() == 0 && quatAnimations.size() == 0 && !associatedSkeleton){
+	if (animations.size() == 0 && !associatedSkeleton){
 
 		jobj[L"autoAnimate"] = web::json::value::boolean(false);
 		jobj[L"autoAnimateLoop"] = web::json::value::boolean(false);
@@ -358,12 +358,7 @@ web::json::value BabylonMesh::toJson()
 		jobj[L"autoAnimateFrom"] = web::json::value::number(animations[0]->autoAnimateFrom);
 		jobj[L"autoAnimateTo"] = web::json::value::number(animations[0]->autoAnimateTo);
 	}
-	else if(quatAnimations.size()>0){
-		jobj[L"autoAnimate"] = web::json::value::boolean(quatAnimations[0]->autoAnimate);
-		jobj[L"autoAnimateLoop"] = web::json::value::boolean(quatAnimations[0]->autoAnimateLoop);
-		jobj[L"autoAnimateFrom"] = web::json::value::number(quatAnimations[0]->autoAnimateFrom);
-		jobj[L"autoAnimateTo"] = web::json::value::number(quatAnimations[0]->autoAnimateTo);
-	}
+	
 	else{
 
 		jobj[L"autoAnimate"] = web::json::value::boolean(associatedSkeleton->bones[0].animation->autoAnimate);
@@ -375,11 +370,11 @@ web::json::value BabylonMesh::toJson()
 	auto janimations = web::json::value::array();
 	for (const auto& anim : animations){
 		janimations[janimations.size()] = anim->toJson();
-	}for (const auto& anim : quatAnimations){
-		janimations[janimations.size()] = anim->toJson();
 	}
 	jobj[L"animations"] = janimations;
-	if (!pivotMatrix.IsIdentity()){
+	FbxMatrix identity;
+	identity.SetIdentity();
+	if (pivotMatrix != identity){
 		auto jpivot = web::json::value::array();
 		for (auto x = 0; x < 4; ++x){
 			for (auto y = 0; y < 4; ++y){
@@ -441,17 +436,16 @@ BabylonMesh::BabylonMesh(BabylonNode* node) :
 	auto animStack = fbxNode->GetScene()->GetSrcObject<FbxAnimStack>(0);
 	FbxString animStackName = animStack->GetName();
 	FbxTakeInfo* takeInfo = fbxNode->GetScene()->GetTakeInfo(animStackName);
-
 	auto animTimeMode = GlobalSettings::Current().AnimationsTimeMode;
 	auto animFrameRate = GlobalSettings::Current().AnimationsFrameRate();
 	auto startFrame = takeInfo->mLocalTimeSpan.GetStart().GetFrameCount(animTimeMode);
 	auto endFrame = takeInfo->mLocalTimeSpan.GetStop().GetFrameCount(animTimeMode);
 	auto animLengthInFrame = endFrame - startFrame + 1;
-
+	_visibility = node->fbxNode()->Visibility.Get();
 	auto posAnim = std::make_shared<BabylonAnimation<babylon_vector3>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), L"position", L"position", true, 0, static_cast<int>(animLengthInFrame), true);
 	auto rotAnim = std::make_shared<BabylonAnimation<babylon_vector4>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), L"rotationQuaternion", L"rotationQuaternion", true, 0, static_cast<int>(animLengthInFrame), true);
-	auto scaleAnim = std::make_shared<BabylonAnimation<babylon_vector3>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), L"scale", L"scale", true, 0, static_cast<int>(animLengthInFrame), true);
-
+	auto scaleAnim = std::make_shared<BabylonAnimation<babylon_vector3>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), L"scaling", L"scaling", true, 0, static_cast<int>(animLengthInFrame), true);
+	auto visibilityAnim = std::make_shared<BabylonAnimation<float>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), L"visibility", L"visibility", true, 0, static_cast<int>(animLengthInFrame), true);
 	for (auto ix = 0; ix < animLengthInFrame; ix++){
 		FbxTime currTime;
 		currTime.SetFrame(startFrame + ix, animTimeMode);
@@ -459,15 +453,20 @@ BabylonMesh::BabylonMesh(BabylonNode* node) :
 		babylon_animation_key<babylon_vector3> poskey;
 		babylon_animation_key<babylon_vector4> rotkey;
 		babylon_animation_key<babylon_vector3> scalekey;
+		babylon_animation_key<float> visibilityKey;
 		poskey.frame = ix;
 		rotkey.frame = ix;
 		scalekey.frame = ix;
-		poskey.values = node->localTranslate(currTime);
-		rotkey.values = node->localRotationQuat(currTime);
-		scalekey.values = node->localScale(currTime);
+		visibilityKey.frame = ix;
+		auto currTransform = node->GetLocal(currTime);
+		poskey.values = currTransform.translation();
+		rotkey.values = currTransform.rotationQuaternion();
+		scalekey.values = currTransform.scaling();
+		visibilityKey.values = node->fbxNode()->Visibility.EvaluateValue(currTime);
 		posAnim->appendKey(poskey);
 		rotAnim->appendKey(rotkey);
 		scaleAnim->appendKey(scalekey);
+		visibilityAnim->appendKey(visibilityKey);
 
 		
 	}
@@ -475,11 +474,14 @@ BabylonMesh::BabylonMesh(BabylonNode* node) :
 		animations.push_back(posAnim);
 	}
 	if (!rotAnim->isConstant()){
-		quatAnimations.push_back(rotAnim);
+		animations.push_back(rotAnim);
 	}
 	if (!scaleAnim->isConstant()){
 		animations.push_back(scaleAnim);
 	}
+	if (!visibilityAnim->isConstant()) {
+		animations.push_back(visibilityAnim);
+	}
 	auto mesh = fbxNode->GetMesh();
 	if (!mesh) {
 		return;
@@ -487,6 +489,8 @@ BabylonMesh::BabylonMesh(BabylonNode* node) :
 	if (mesh->GetPolygonCount() == 0){
 		return;
 	}
+
+	_receiveShadows =  mesh->ReceiveShadow.Get();
 	FbxGeometryConverter conv(mesh->GetFbxManager());
 	conv.ComputePolygonSmoothingFromEdgeSmoothing(mesh);
 	if (!mesh->IsTriangleMesh()) {

+ 2 - 3
Exporters/FBX/BabylonFbxNative/BabylonMesh.h

@@ -113,9 +113,8 @@ public:
 
 	std::shared_ptr<BabylonSkeleton> associatedSkeleton;
 
-	std::vector<std::shared_ptr < BabylonAnimation<babylon_vector3>>> animations;
-	std::vector<std::shared_ptr < BabylonAnimation<babylon_vector4>>> quatAnimations;
-	FbxAMatrix pivotMatrix;
+	std::vector<std::shared_ptr < BabylonAnimationBase>> animations;
+	FbxMatrix pivotMatrix;
 
 	virtual web::json::value toJson() override;
 	BabylonMesh();

+ 0 - 24
Exporters/FBX/BabylonFbxNative/BabylonNode.cpp

@@ -3,8 +3,6 @@
 #include "NodeHelpers.h"
 
 BabylonNode::BabylonNode(FbxNode* fbxNode) : _node(fbxNode){
-	_localTransform = ConvertToBabylonCoordinateSystem(CalculateLocalTransform( fbxNode));
-	_globalTransform = ConvertToBabylonCoordinateSystem(CalculateLocalTransform(fbxNode));
 	auto childCount = fbxNode->GetChildCount();
 	for (int i = 0; i < childCount; ++i){
 		_children.emplace_back(fbxNode->GetChild(i));
@@ -63,25 +61,3 @@ bool BabylonNode::isEmptySkeletonOrEmptyMeshRecursive()
 	}
 	return true;
 }
-
-babylon_vector3 BabylonNode::localScale(FbxTime time){
-	auto transform = ConvertToBabylonCoordinateSystem(CalculateLocalTransform(_node,time));
-	return transform.GetS();
-
-}
-
-babylon_vector4 BabylonNode::localRotationQuat(){
-	auto ret = _localTransform.GetQ();
-	return babylon_vector4(static_cast<float>(ret[0]), static_cast<float>(ret[1]), static_cast<float>(ret[2]), static_cast<float>(ret[3]));
-}
-babylon_vector4 BabylonNode::localRotationQuat(FbxTime time){
-
-	auto transform = ConvertToBabylonCoordinateSystem(CalculateLocalTransform(_node, time));
-	auto ret = transform.GetQ();
-	return babylon_vector4(static_cast<float>(ret[0]), static_cast<float>(ret[1]), static_cast<float>(ret[2]), static_cast<float>(ret[3]));
-}
-babylon_vector3 BabylonNode::localTranslate(FbxTime time){
-	auto transform = ConvertToBabylonCoordinateSystem(CalculateLocalTransform(_node, time));
-	return transform.GetT();
-
-}

+ 5 - 22
Exporters/FBX/BabylonFbxNative/BabylonNode.h

@@ -4,6 +4,7 @@
 #include <cstdint>
 #include "NodeHelpers.h"
 #include "BabylonVertex.h"
+#include "MatrixDecomposition.h"
 enum class BabylonNodeType{
 	Camera,
 	Mesh,
@@ -15,8 +16,6 @@ class BabylonNode;
 class BabylonNode
 {
 private:
-	FbxAMatrix _localTransform;
-	FbxAMatrix _globalTransform;
 	FbxNode* _node;
 	std::vector<BabylonNode> _children;
 public:
@@ -59,27 +58,11 @@ public:
 		return true;
 	}
 
-	babylon_vector3 localScale(){
-		auto ret = _localTransform.GetS();
-		return ret;
+	MatrixDecomposition GetLocal() {
+		return MatrixDecomposition(ConvertToBabylonCoordinateSystem(_node->EvaluateLocalTransform()));
 	}
-	babylon_vector4 localRotationQuat();
-	babylon_vector3 localTranslate(){
-
-		auto ret = _localTransform.GetT();
-		return ret;
-	}
-
-
-
-	babylon_vector3 localScale(FbxTime time);
-	babylon_vector4 localRotationQuat(FbxTime time);
-	babylon_vector3 localTranslate(FbxTime time);
-
-	FbxAMatrix localTransform(FbxTime time){
-		return ConvertToBabylonCoordinateSystem(CalculateLocalTransform(_node, time));
+	MatrixDecomposition GetLocal(const FbxTime& time) {
+		return MatrixDecomposition(ConvertToBabylonCoordinateSystem(_node->EvaluateLocalTransform(time)));
 	}
 
-	const FbxAMatrix& localTransform() { return _localTransform; }
-	const FbxAMatrix& globalTransform() { return _globalTransform; }
 };

+ 5 - 1
Exporters/FBX/BabylonFbxNative/BabylonScene.cpp

@@ -54,7 +54,11 @@ web::json::value BabylonScene::toJson()
 		jskeletons[jskeletons.size()] = skel->toJson();
 	}
 	jobj[L"skeletons"] = jskeletons;
-
+	auto jshadowGenerators = web::json::value::array();
+	for (auto& sg : _shadowGenerators) {
+		jshadowGenerators[jshadowGenerators.size()] = sg->toJson();
+	}
+	jobj[L"shadowGenerators"] = jshadowGenerators;
 	return jobj;
 }
 

+ 2 - 0
Exporters/FBX/BabylonFbxNative/BabylonScene.h

@@ -26,6 +26,7 @@ private:
 	std::vector<BabylonMaterial> _materials;
 	std::vector<BabylonMultiMaterial> _multiMaterials;
 	std::vector<BabylonLight> _lights;
+	std::vector<std::shared_ptr<BabylonShadowGenerator>> _shadowGenerators;
 	std::vector<std::shared_ptr<BabylonSkeleton>> _skeletons;
 	// particleSystems
 	// lensFlareSystems
@@ -52,6 +53,7 @@ public:
 	std::vector<BabylonMultiMaterial>& multiMaterials(){ return _multiMaterials; }
 
 	std::vector<BabylonLight>& lights() { return _lights; }
+	std::vector<std::shared_ptr<BabylonShadowGenerator>>& shadowGenerators() { return _shadowGenerators; }
 	std::vector<std::shared_ptr<BabylonSkeleton>>& skeletons() { return _skeletons; }
 	// particleSystems
 	// lensFlareSystems

+ 2 - 2
Exporters/FBX/BabylonFbxNative/BabylonSkeleton.h

@@ -11,8 +11,8 @@ public:
 	std::wstring name;
 	int index;
 	int parentBoneIndex = -1;
-	FbxAMatrix matrix;
-	std::shared_ptr<BabylonAnimation<FbxAMatrix>> animation;
+	FbxMatrix matrix;
+	std::shared_ptr<BabylonAnimation<FbxMatrix>> animation;
 	web::json::value toJson();
 
 	//public BabylonAnimation animation{ get; set; }

+ 2 - 1
Exporters/FBX/BabylonFbxNative/BabylonVertex.h

@@ -13,7 +13,8 @@ struct babylon_vector4{
 	float w;
 	babylon_vector4() :x(0), y(0), z(0), w(0){}
 	babylon_vector4(float x, float y, float z, float w) :x(x), y(y), z(z), w(w){}
-	babylon_vector4(const babylon_vector4& v) :x(v.x), y(v.y), z(v.z), w(v.w){}
+	babylon_vector4(const babylon_vector4& v) :x(v.x), y(v.y), z(v.z), w(v.w) {}
+	babylon_vector4(const FbxQuaternion& v) :x(static_cast<float>(v[0])), y(static_cast<float>(v[1])), z(static_cast<float>(v[2])), w(static_cast<float>(v[3])) {}
 };
 struct babylon_vector3{
 	float x;

+ 33 - 0
Exporters/FBX/BabylonFbxNative/MatrixDecomposition.h

@@ -0,0 +1,33 @@
+#pragma once
+#include <fbxsdk.h>
+#include "BabylonVertex.h"
+class MatrixDecomposition
+{
+	babylon_vector3 _trans;
+	babylon_vector4 _quat;
+	babylon_vector3 _scaling;
+
+	FbxVector4 _fbxtrans;
+	FbxQuaternion _fbxrot;
+	FbxVector4 _fbxshearing;
+	FbxVector4 _fbxscaling;
+public:
+	const babylon_vector3& translation() { return _trans; }
+	const babylon_vector4& rotationQuaternion() { return _quat; }
+	const babylon_vector3& scaling() { return _scaling; }
+
+
+	const FbxVector4& fbxtrans() { return _fbxtrans; };
+	const FbxQuaternion& fbxrot() { return _fbxrot; };
+	const FbxVector4& fbxshearing() { return _fbxshearing; };
+	const FbxVector4& fbxscaling() { return _fbxscaling; };
+	MatrixDecomposition(const FbxMatrix& mat){
+		
+		double sign;
+		mat.GetElements(_fbxtrans, _fbxrot, _fbxshearing, _fbxscaling, sign);
+		_trans = _fbxtrans;
+		_quat = _fbxrot;
+		_scaling = _fbxscaling;
+	}
+};
+

+ 170 - 172
Exporters/FBX/BabylonFbxNative/NodeHelpers.h

@@ -17,7 +17,7 @@ inline std::wstring getNodeId(FbxNode* node) {
 
 const double Euler2Rad = 3.141592653589793238462 / 180;
 
-inline FbxAMatrix GetGeometryTransformation(FbxNode* inNode)
+inline FbxMatrix GetGeometryTransformation(FbxNode* inNode)
 {
 	if (!inNode)
 	{
@@ -28,177 +28,175 @@ inline FbxAMatrix GetGeometryTransformation(FbxNode* inNode)
 	const FbxVector4 lR = inNode->GetGeometricRotation(FbxNode::eSourcePivot);
 	const FbxVector4 lS = inNode->GetGeometricScaling(FbxNode::eSourcePivot);
 
-	return FbxAMatrix(lT, lR, lS);
+	return FbxMatrix(lT, lR, lS);
 }
 
-inline FbxAMatrix ConvertToBabylonCoordinateSystem(const FbxAMatrix& origin){
-	FbxAMatrix input = origin;
-	FbxVector4 translation = input.GetT();
-	auto rotationQ = input.GetQ();
-	translation.Set(translation.mData[0], translation.mData[1], -translation.mData[2]); // This negate Z of Translation Component of the matrix
-	rotationQ[0] = -rotationQ[0];
-	rotationQ[1] = -rotationQ[1];
-	//rotationQ[2] = -rotationQ[2];
-	//rotation.Set(-rotation.mData[0], -rotation.mData[1], rotation.mData[2]); // This negate X,Y of Rotation Component of the matrix
-	// These 2 lines finally set "input" to the eventual converted result
-	input.SetT(translation);
-	input.SetQ(rotationQ);
-	return input;
+inline FbxMatrix ConvertToBabylonCoordinateSystem(const FbxMatrix& origin){
+	FbxVector4 trans;
+	FbxQuaternion rot;
+	FbxVector4 shearing;
+	FbxVector4 scaling;
+	double sign;
+	origin.GetElements(trans, rot, shearing, scaling, sign);
+	trans[2] = -trans[2]; // This negate Z of Translation Component of the matrix
+	rot[0] = -rot[0];
+	rot[1] = -rot[1];
+	return FbxMatrix (trans, rot, scaling);
 }
-
-inline FbxAMatrix CalculateGlobalTransform(FbxNode* pNode, const FbxTime& time = FBXSDK_TIME_INFINITE)
-{
-	FbxAMatrix lTranlationM, lScalingM, lScalingPivotM, lScalingOffsetM, lRotationOffsetM, lRotationPivotM, \
-		lPreRotationM, lRotationM, lPostRotationM, lTransform;
-
-	FbxAMatrix lParentGX, lGlobalT, lGlobalRS;
-
-	if (!pNode)
-	{
-		lTransform.SetIdentity();
-		return lTransform;
-	}
-
-	// Construct translation matrix
-	FbxVector4 lTranslation = pNode->LclTranslation.EvaluateValue(time);
-	lTranlationM.SetT(lTranslation);
-
-	// Construct rotation matrices
-	FbxVector4 lRotation = pNode->LclRotation.EvaluateValue(time);
-	FbxVector4 lPreRotation = pNode->PreRotation.EvaluateValue(time);
-	FbxVector4 lPostRotation = pNode->PostRotation.EvaluateValue(time);
-	lRotationM.SetR(lRotation);
-	lPreRotationM.SetR(lPreRotation);
-	lPostRotationM.SetR(lPostRotation);
-
-	// Construct scaling matrix
-	FbxVector4 lScaling = pNode->LclScaling.EvaluateValue(time);
-	lScalingM.SetS(lScaling);
-
-	// Construct offset and pivot matrices
-	FbxVector4 lScalingOffset = pNode->ScalingOffset.EvaluateValue(time);
-	FbxVector4 lScalingPivot = pNode->ScalingPivot.EvaluateValue(time);
-	FbxVector4 lRotationOffset = pNode->RotationOffset.EvaluateValue(time);
-	FbxVector4 lRotationPivot = pNode->RotationPivot.EvaluateValue(time);
-	lScalingOffsetM.SetT(lScalingOffset);
-	lScalingPivotM.SetT(lScalingPivot);
-	lRotationOffsetM.SetT(lRotationOffset);
-	lRotationPivotM.SetT(lRotationPivot);
-
-	// Calculate the global transform matrix of the parent node
-	FbxNode* lParentNode = pNode->GetParent();
-	if (lParentNode)
-	{
-		lParentGX = CalculateGlobalTransform(lParentNode);
-	}
-	else
-	{
-		lParentGX.SetIdentity();
-	}
-
-	//Construct Global Rotation
-	FbxAMatrix lLRM, lParentGRM;
-	FbxVector4 lParentGR = lParentGX.GetR();
-	lParentGRM.SetR(lParentGR);
-	lLRM = lPreRotationM * lRotationM * lPostRotationM;
-
-	//Construct Global Shear*Scaling
-	//FBX SDK does not support shear, to patch this, we use:
-	//Shear*Scaling = RotationMatrix.Inverse * TranslationMatrix.Inverse * WholeTranformMatrix
-	FbxAMatrix lLSM, lParentGSM, lParentGRSM, lParentTM;
-	FbxVector4 lParentGT = lParentGX.GetT();
-	lParentTM.SetT(lParentGT);
-	lParentGRSM = lParentTM.Inverse() * lParentGX;
-	lParentGSM = lParentGRM.Inverse() * lParentGRSM;
-	lLSM = lScalingM;
-
-	//Do not consider translation now
-	FbxTransform::EInheritType lInheritType = pNode->InheritType.EvaluateValue(time);
-	if (lInheritType == FbxTransform::eInheritRrSs)
-	{
-		lGlobalRS = lParentGRM * lLRM * lParentGSM * lLSM;
-	}
-	else if (lInheritType == FbxTransform::eInheritRSrs)
-	{
-		lGlobalRS = lParentGRM * lParentGSM * lLRM * lLSM;
-	}
-	else if (lInheritType == FbxTransform::eInheritRrs)
-	{
-		FbxAMatrix lParentLSM;
-		FbxVector4 lParentLS = lParentNode->LclScaling.EvaluateValue(time);
-		lParentLSM.SetS(lParentLS);
-
-		FbxAMatrix lParentGSM_noLocal = lParentGSM * lParentLSM.Inverse();
-		lGlobalRS = lParentGRM * lLRM * lParentGSM_noLocal * lLSM;
-	}
-	else
-	{
-		FBXSDK_printf("error, unknown inherit type! \n");
-	}
-
-	// Construct translation matrix
-	// Calculate the local transform matrix
-	lTransform = lTranlationM * lRotationOffsetM * lRotationPivotM * lPreRotationM * lRotationM * lPostRotationM * lRotationPivotM.Inverse()\
-		* lScalingOffsetM * lScalingPivotM * lScalingM * lScalingPivotM.Inverse();
-	FbxVector4 lLocalTWithAllPivotAndOffsetInfo = lTransform.GetT();
-	// Calculate global translation vector according to: 
-	// GlobalTranslation = ParentGlobalTransform * LocalTranslationWithPivotAndOffsetInfo
-	FbxVector4 lGlobalTranslation = lParentGX.MultT(lLocalTWithAllPivotAndOffsetInfo);
-	lGlobalT.SetT(lGlobalTranslation);
-
-	//Construct the whole global transform
-	lTransform = lGlobalT * lGlobalRS;
-
-	return lTransform;
-}
-
-
-inline FbxAMatrix CalculateLocalTransform(FbxNode* pNode, const FbxTime& time = FBXSDK_TIME_INFINITE)
-{
-	FbxAMatrix lTranlationM, lScalingM, lScalingPivotM, lScalingOffsetM, lRotationOffsetM, lRotationPivotM, \
-		lPreRotationM, lRotationM, lPostRotationM, lTransform;
-
-
-	if (!pNode)
-	{
-		lTransform.SetIdentity();
-		return lTransform;
-	}
-
-	// Construct translation matrix
-	FbxVector4 lTranslation = pNode->LclTranslation.EvaluateValue(time);
-	lTranlationM.SetT(lTranslation);
-
-	// Construct rotation matrices
-	FbxVector4 lRotation = pNode->LclRotation.EvaluateValue(time);
-	FbxVector4 lPreRotation = pNode->PreRotation.EvaluateValue(time);
-	FbxVector4 lPostRotation = pNode->PostRotation.EvaluateValue(time);
-	lRotationM.SetR(lRotation);
-	lPreRotationM.SetR(lPreRotation);
-	lPostRotationM.SetR(lPostRotation);
-
-	// Construct scaling matrix
-	FbxVector4 lScaling = pNode->LclScaling.EvaluateValue(time);
-	lScalingM.SetS(lScaling);
-
-	// Construct offset and pivot matrices
-	FbxVector4 lScalingOffset = pNode->ScalingOffset.EvaluateValue(time);
-	FbxVector4 lScalingPivot = pNode->ScalingPivot.EvaluateValue(time);
-	FbxVector4 lRotationOffset = pNode->RotationOffset.EvaluateValue(time);
-	FbxVector4 lRotationPivot = pNode->RotationPivot.EvaluateValue(time);
-	lScalingOffsetM.SetT(lScalingOffset);
-	lScalingPivotM.SetT(lScalingPivot);
-	lRotationOffsetM.SetT(lRotationOffset);
-	lRotationPivotM.SetT(lRotationPivot);
-
-	
-	
-
-	// Construct translation matrix
-	// Calculate the local transform matrix
-	lTransform = lTranlationM * lRotationOffsetM * lRotationPivotM * lPreRotationM * lRotationM * lPostRotationM * lRotationPivotM.Inverse()\
-		* lScalingOffsetM * lScalingPivotM * lScalingM * lScalingPivotM.Inverse();
-	
-
-	return lTransform;
-}
+//
+//inline FbxAMatrix CalculateGlobalTransform(FbxNode* pNode, const FbxTime& time = FBXSDK_TIME_INFINITE)
+//{
+//	FbxAMatrix lTranlationM, lScalingM, lScalingPivotM, lScalingOffsetM, lRotationOffsetM, lRotationPivotM, \
+//		lPreRotationM, lRotationM, lPostRotationM, lTransform;
+//
+//	FbxAMatrix lParentGX, lGlobalT, lGlobalRS;
+//
+//	if (!pNode)
+//	{
+//		lTransform.SetIdentity();
+//		return lTransform;
+//	}
+//
+//	// Construct translation matrix
+//	FbxVector4 lTranslation = pNode->LclTranslation.EvaluateValue(time);
+//	lTranlationM.SetT(lTranslation);
+//
+//	// Construct rotation matrices
+//	FbxVector4 lRotation = pNode->LclRotation.EvaluateValue(time);
+//	FbxVector4 lPreRotation = pNode->PreRotation.EvaluateValue(time);
+//	FbxVector4 lPostRotation = pNode->PostRotation.EvaluateValue(time);
+//	lRotationM.SetR(lRotation);
+//	lPreRotationM.SetR(lPreRotation);
+//	lPostRotationM.SetR(lPostRotation);
+//
+//	// Construct scaling matrix
+//	FbxVector4 lScaling = pNode->LclScaling.EvaluateValue(time);
+//	lScalingM.SetS(lScaling);
+//
+//	// Construct offset and pivot matrices
+//	FbxVector4 lScalingOffset = pNode->ScalingOffset.EvaluateValue(time);
+//	FbxVector4 lScalingPivot = pNode->ScalingPivot.EvaluateValue(time);
+//	FbxVector4 lRotationOffset = pNode->RotationOffset.EvaluateValue(time);
+//	FbxVector4 lRotationPivot = pNode->RotationPivot.EvaluateValue(time);
+//	lScalingOffsetM.SetT(lScalingOffset);
+//	lScalingPivotM.SetT(lScalingPivot);
+//	lRotationOffsetM.SetT(lRotationOffset);
+//	lRotationPivotM.SetT(lRotationPivot);
+//
+//	// Calculate the global transform matrix of the parent node
+//	FbxNode* lParentNode = pNode->GetParent();
+//	if (lParentNode)
+//	{
+//		lParentGX = CalculateGlobalTransform(lParentNode);
+//	}
+//	else
+//	{
+//		lParentGX.SetIdentity();
+//	}
+//
+//	//Construct Global Rotation
+//	FbxAMatrix lLRM, lParentGRM;
+//	FbxVector4 lParentGR = lParentGX.GetR();
+//	lParentGRM.SetR(lParentGR);
+//	lLRM = lPreRotationM * lRotationM * lPostRotationM;
+//
+//	//Construct Global Shear*Scaling
+//	//FBX SDK does not support shear, to patch this, we use:
+//	//Shear*Scaling = RotationMatrix.Inverse * TranslationMatrix.Inverse * WholeTranformMatrix
+//	FbxAMatrix lLSM, lParentGSM, lParentGRSM, lParentTM;
+//	FbxVector4 lParentGT = lParentGX.GetT();
+//	lParentTM.SetT(lParentGT);
+//	lParentGRSM = lParentTM.Inverse() * lParentGX;
+//	lParentGSM = lParentGRM.Inverse() * lParentGRSM;
+//	lLSM = lScalingM;
+//
+//	//Do not consider translation now
+//	FbxTransform::EInheritType lInheritType = pNode->InheritType.EvaluateValue(time);
+//	if (lInheritType == FbxTransform::eInheritRrSs)
+//	{
+//		lGlobalRS = lParentGRM * lLRM * lParentGSM * lLSM;
+//	}
+//	else if (lInheritType == FbxTransform::eInheritRSrs)
+//	{
+//		lGlobalRS = lParentGRM * lParentGSM * lLRM * lLSM;
+//	}
+//	else if (lInheritType == FbxTransform::eInheritRrs)
+//	{
+//		FbxAMatrix lParentLSM;
+//		FbxVector4 lParentLS = lParentNode->LclScaling.EvaluateValue(time);
+//		lParentLSM.SetS(lParentLS);
+//
+//		FbxAMatrix lParentGSM_noLocal = lParentGSM * lParentLSM.Inverse();
+//		lGlobalRS = lParentGRM * lLRM * lParentGSM_noLocal * lLSM;
+//	}
+//	else
+//	{
+//		FBXSDK_printf("error, unknown inherit type! \n");
+//	}
+//
+//	// Construct translation matrix
+//	// Calculate the local transform matrix
+//	lTransform = lTranlationM * lRotationOffsetM * lRotationPivotM * lPreRotationM * lRotationM * lPostRotationM * lRotationPivotM.Inverse()\
+//		* lScalingOffsetM * lScalingPivotM * lScalingM * lScalingPivotM.Inverse();
+//	FbxVector4 lLocalTWithAllPivotAndOffsetInfo = lTransform.GetT();
+//	// Calculate global translation vector according to: 
+//	// GlobalTranslation = ParentGlobalTransform * LocalTranslationWithPivotAndOffsetInfo
+//	FbxVector4 lGlobalTranslation = lParentGX.MultT(lLocalTWithAllPivotAndOffsetInfo);
+//	lGlobalT.SetT(lGlobalTranslation);
+//
+//	//Construct the whole global transform
+//	lTransform = lGlobalT * lGlobalRS;
+//
+//	return lTransform;
+//}
+
+//
+//inline FbxAMatrix CalculateLocalTransform(FbxNode* pNode, const FbxTime& time = FBXSDK_TIME_INFINITE)
+//{
+//	FbxAMatrix lTranlationM, lScalingM, lScalingPivotM, lScalingOffsetM, lRotationOffsetM, lRotationPivotM, \
+//		lPreRotationM, lRotationM, lPostRotationM, lTransform;
+//
+//
+//	if (!pNode)
+//	{
+//		lTransform.SetIdentity();
+//		return lTransform;
+//	}
+//
+//	// Construct translation matrix
+//	FbxVector4 lTranslation = pNode->LclTranslation.EvaluateValue(time);
+//	lTranlationM.SetT(lTranslation);
+//
+//	// Construct rotation matrices
+//	FbxVector4 lRotation = pNode->LclRotation.EvaluateValue(time);
+//	FbxVector4 lPreRotation = pNode->PreRotation.EvaluateValue(time);
+//	FbxVector4 lPostRotation = pNode->PostRotation.EvaluateValue(time);
+//	lRotationM.SetR(lRotation);
+//	lPreRotationM.SetR(lPreRotation);
+//	lPostRotationM.SetR(lPostRotation);
+//
+//	// Construct scaling matrix
+//	FbxVector4 lScaling = pNode->LclScaling.EvaluateValue(time);
+//	lScalingM.SetS(lScaling);
+//
+//	// Construct offset and pivot matrices
+//	FbxVector4 lScalingOffset = pNode->ScalingOffset.EvaluateValue(time);
+//	FbxVector4 lScalingPivot = pNode->ScalingPivot.EvaluateValue(time);
+//	FbxVector4 lRotationOffset = pNode->RotationOffset.EvaluateValue(time);
+//	FbxVector4 lRotationPivot = pNode->RotationPivot.EvaluateValue(time);
+//	lScalingOffsetM.SetT(lScalingOffset);
+//	lScalingPivotM.SetT(lScalingPivot);
+//	lRotationOffsetM.SetT(lRotationOffset);
+//	lRotationPivotM.SetT(lRotationPivot);
+//
+//	
+//	
+//
+//	// Construct translation matrix
+//	// Calculate the local transform matrix
+//	lTransform = lTranlationM * lRotationOffsetM * lRotationPivotM * lPreRotationM * lRotationM * lPostRotationM * lRotationPivotM.Inverse()\
+//		* lScalingOffsetM * lScalingPivotM * lScalingM * lScalingPivotM.Inverse();
+//	
+//
+//	return lTransform;
+//}

+ 7 - 7
Exporters/FBX/BabylonFbxNative/SkinInfo.cpp

@@ -110,7 +110,7 @@ _node(meshNode), _mesh(meshNode->GetMesh()), _skin(nullptr)
 	for (auto& bone : _bones){
 		FbxAMatrix transformMatrix;
 		FbxAMatrix transformLinkMatrix;
-		FbxAMatrix globalBindposeInverseMatrix;
+		FbxMatrix globalBindposeInverseMatrix;
 
 		bone.cluster->GetTransformMatrix(transformMatrix);	// The transformation of the mesh at binding time
 		bone.cluster->GetTransformLinkMatrix(transformLinkMatrix);	// The transformation of the cluster(joint) at binding time from joint space to world space
@@ -122,7 +122,7 @@ _node(meshNode), _mesh(meshNode->GetMesh()), _skin(nullptr)
 				break;
 			}
 		}*/
-		globalBindposeInverseMatrix = transformLinkMatrix.Inverse() * transformMatrix * geometryTransform;
+		globalBindposeInverseMatrix = FbxMatrix(transformLinkMatrix.Inverse()) * FbxMatrix(transformMatrix) * geometryTransform;
 
 
 		bone.matrixGlobalBindPose = ConvertToBabylonCoordinateSystem(globalBindposeInverseMatrix.Inverse());
@@ -133,7 +133,7 @@ _node(meshNode), _mesh(meshNode->GetMesh()), _skin(nullptr)
 		}
 		else{
 			bone.matrixLocalBindPose =
-				NotDecomposedMultiply(_bones[bone.parentBoneIndex].matrixGlobalBindPose.Inverse(), bone.matrixGlobalBindPose);
+				_bones[bone.parentBoneIndex].matrixGlobalBindPose.Inverse()* bone.matrixGlobalBindPose;
 			
 		}
 	}
@@ -156,7 +156,7 @@ _node(meshNode), _mesh(meshNode->GetMesh()), _skin(nullptr)
 		currTime.SetFrame(startFrame + ix, animTimeMode);
 
 
-		auto currTransformOffset = meshNode->EvaluateGlobalTransform(currTime) * geometryTransform;
+		auto currTransformOffset = FbxMatrix(meshNode->EvaluateGlobalTransform(currTime)) * geometryTransform;
 		auto currTransformOffsetInverse = currTransformOffset.Inverse();
 
 		// compute global transform and local
@@ -174,7 +174,7 @@ _node(meshNode), _mesh(meshNode->GetMesh()), _skin(nullptr)
 				auto& parentBone = _bones[bone.parentBoneIndex];
 				
 				kf.matrixLocal = //bone.matrixLocalBindPose;
-					NotDecomposedMultiply(parentBone.keyFrames[parentBone.keyFrames.size() - 1].matrixGlobal.Inverse(), kf.matrixGlobal);
+					parentBone.keyFrames[parentBone.keyFrames.size() - 1].matrixGlobal.Inverse()* kf.matrixGlobal;
 
 			}
 
@@ -208,10 +208,10 @@ void SkinInfo::buildBabylonSkeleton(BabylonSkeleton& skel){
 		auto endFrame = takeInfo->mLocalTimeSpan.GetStop().GetFrameCount(animTimeMode);
 		auto animLengthInFrame = endFrame - startFrame + 1;
 
-		auto matrixAnim = std::make_shared<BabylonAnimation<FbxAMatrix>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), L"_matrix", L"_matrix", true, 0, static_cast<int>(animLengthInFrame), true);
+		auto matrixAnim = std::make_shared<BabylonAnimation<FbxMatrix>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), L"_matrix", L"_matrix", true, 0, static_cast<int>(animLengthInFrame), true);
 		for (auto& kf : b.keyFrames){
 
-			babylon_animation_key<FbxAMatrix> key;
+			babylon_animation_key<FbxMatrix> key;
 			key.frame = kf.frame;
 			//key.values = ConvertToBabylonCoordinateSystem(kf.matrixLocal);
 			key.values = kf.matrixLocal;

+ 4 - 4
Exporters/FBX/BabylonFbxNative/SkinInfo.h

@@ -8,8 +8,8 @@
 
 struct BoneAnimKeyFrame{
 	int frame;
-	FbxAMatrix matrixLocal;
-	FbxAMatrix matrixGlobal;
+	FbxMatrix matrixLocal;
+	FbxMatrix matrixGlobal;
 };
 struct BoneInfo{
 	FbxNode*  linkNode;
@@ -18,8 +18,8 @@ struct BoneInfo{
 	int parentBoneIndex;
 	std::wstring name;
 
-	FbxAMatrix matrixGlobalBindPose;
-	FbxAMatrix matrixLocalBindPose;
+	FbxMatrix matrixGlobalBindPose;
+	FbxMatrix matrixLocalBindPose;
 	std::vector<BoneAnimKeyFrame> keyFrames;
 };
 

+ 7 - 16
Exporters/FBX/FbxExporter/FbxExporter.cpp

@@ -62,22 +62,6 @@ std::string wstringToUtf8(const std::wstring& src){
 	return result;
 }
 
-bool isNodeOrDescendantVisible(FbxNode* node){
-	if (node == nullptr){
-		return false;
-	}
-	if (node->GetVisibility()){
-		return true;
-	}
-
-	auto childCount = node->GetChildCount();
-	for (auto ix = 0; ix < childCount; ++ix){
-		if (isNodeOrDescendantVisible(node->GetChild(ix))){
-			return true;
-		}
-	}
-	return false;
-}
 
 void exploreMeshes(BabylonScene& scene, BabylonNode& node, bool skipEmptyNodes) {
 	if (node.nodeType() == BabylonNodeType::Skeleton && node.hasOnlySkeletonDescendants()) {
@@ -135,7 +119,14 @@ void exploreMeshes(BabylonScene& scene, BabylonNode& node, bool skipEmptyNodes)
 	}
 	break;
 	case BabylonNodeType::Light:
+	{
 		scene.lights().emplace_back(node);
+		auto& l = scene.lights()[scene.lights().size() - 1];
+		if (l.shadowGenerator) {
+			scene.shadowGenerators().push_back(l.shadowGenerator);
+		}
+	}
+	break;
 	default:
 		break;
 	}