public void RootNode_AddChildNode_AddsNodeToScene() { // given: var scene = new FbxScene("TheScene"); var root = scene.GetRootNode(); var node = new FbxNode("ChildNode"); // require: Assert.AreEqual(3, scene.GetSrcObjectCount()); Assert.AreEqual(root, scene.GetSrcObject(0)); Assert.AreEqual(scene.GetGlobalSettings(), scene.GetSrcObject(1)); Assert.AreEqual(scene.GetAnimationEvaluator(), scene.GetSrcObject(2)); Assert.AreEqual(0, scene.GetDstObjectCount()); Assert.AreEqual(1, scene.GetNodeCount()); Assert.AreEqual(root, scene.GetNode(0)); Assert.AreEqual(0, root.GetSrcObjectCount()); Assert.AreEqual(1, root.GetDstObjectCount()); Assert.AreEqual(scene, root.GetDstObject(0)); Assert.AreEqual(scene, root.GetScene()); Assert.AreEqual(0, node.GetSrcObjectCount()); Assert.AreEqual(0, node.GetDstObjectCount()); Assert.AreEqual(null, node.GetScene()); // when: root.AddChild(node); // then: Assert.AreEqual(4, scene.GetSrcObjectCount()); Assert.AreEqual(0, scene.GetDstObjectCount()); Assert.AreEqual(root, scene.GetSrcObject(0)); Assert.AreEqual(scene.GetGlobalSettings(), scene.GetSrcObject(1)); Assert.AreEqual(scene.GetAnimationEvaluator(), scene.GetSrcObject(2)); Assert.AreEqual(node, scene.GetSrcObject(3)); Assert.AreEqual(0, scene.GetDstObjectCount()); Assert.AreEqual(2, scene.GetNodeCount()); Assert.AreEqual(root, scene.GetNode(0)); Assert.AreEqual(node, scene.GetNode(1)); Assert.AreEqual(1, root.GetSrcObjectCount()); Assert.AreEqual(node, root.GetSrcObject(0)); Assert.AreEqual(1, root.GetDstObjectCount()); Assert.AreEqual(scene, root.GetDstObject(0)); Assert.AreEqual(scene, root.GetScene()); Assert.AreEqual(0, node.GetSrcObjectCount()); Assert.AreEqual(2, node.GetDstObjectCount()); Assert.AreEqual(root, node.GetDstObject(0)); Assert.AreEqual(scene, node.GetDstObject(1)); Assert.AreEqual(scene, node.GetScene()); }
public void Node_AddMaterial_SetsMaterialScene() { // given: var scene = new FbxScene(""); var root = scene.GetRootNode(); var node = new FbxNode(""); var mat = new FbxSurfacePhong(""); root.AddChild(node); // require: Assert.AreEqual(4, scene.GetSrcObjectCount()); Assert.AreEqual(scene.GetRootNode(), scene.GetSrcObject(0)); Assert.AreEqual(scene.GetGlobalSettings(), scene.GetSrcObject(1)); Assert.AreEqual(scene.GetAnimationEvaluator(), scene.GetSrcObject(2)); Assert.AreEqual(node, scene.GetSrcObject(3)); Assert.AreEqual(0, scene.GetDstObjectCount()); Assert.AreEqual(2, scene.GetNodeCount()); Assert.AreEqual(scene.GetRootNode(), scene.GetNode(0)); Assert.AreEqual(node, scene.GetNode(1)); Assert.AreEqual(0, node.GetSrcObjectCount()); Assert.AreEqual(2, node.GetDstObjectCount()); Assert.AreEqual(root, node.GetDstObject(0)); Assert.AreEqual(scene, node.GetDstObject(1)); Assert.AreEqual(scene, node.GetScene()); Assert.AreEqual(0, node.GetMaterialCount()); Assert.AreEqual(0, mat.GetSrcObjectCount()); Assert.AreEqual(0, mat.GetDstObjectCount()); Assert.AreEqual(null, mat.GetScene()); // when: node.AddMaterial(mat); // then: Assert.AreEqual(5, scene.GetSrcObjectCount()); Assert.AreEqual(mat, scene.GetSrcObject(4)); Assert.AreEqual(2, scene.GetNodeCount()); Assert.AreEqual(scene.GetRootNode(), scene.GetNode(0)); Assert.AreEqual(node, scene.GetNode(1)); Assert.AreEqual(1, node.GetSrcObjectCount()); Assert.AreEqual(mat, node.GetSrcObject(0)); Assert.AreEqual(1, node.GetMaterialCount()); Assert.AreEqual(mat, node.GetMaterial(0)); Assert.AreEqual(0, mat.GetSrcObjectCount()); Assert.AreEqual(2, mat.GetDstObjectCount()); Assert.AreEqual(node, mat.GetDstObject(0)); Assert.AreEqual(scene, mat.GetDstObject(1)); Assert.AreEqual(scene, mat.GetScene()); }
//Calculates global transform of the node. //This function was taken from FBX SDK/Smaples/Transformations. Originaly it did not take into account AxisSystem, so the corrections to use AxisSystem was added. //Has the fbx sdk equivalent pNode.EvaluateGlobalTransform(); // //Note: FBX Documentation for ConvertScene states - "The adjustment will affect the translation animation curves and the objects pivots values //(the rotation transformation is applied as a pre-rotation transform therefore the rotation animation curves do not need to be transformed)" //But ConvertScene, does not realy change node.PreRotation, these changes are in the matrix : node.GetScene().GetGlobalSettings().GetAxisSystem().GetMatrix // /* * Terminology: * Suffix "M" means this is a matrix, suffix "V" means it is a vector. * T is translation. * R is rotation. * S is scaling. * SH is shear. * GlobalRM(x) means the Global Rotation Matrix of node "x". * GlobalRM(P(x)) means the Global Rotation Matrix of the parent node of node "x". * All other transforms are described in the similar way. * * The algorithm description: * To calculate global transform of a node x according to different InheritType, * we need to calculate GlobalTM(x) and [GlobalRM(x) * (GlobalSHM(x) * GlobalSM(x))] separately. * GlobalM(x) = GlobalTM(x) * [GlobalRM(x) * (GlobalSHM(x) * GlobalSM(x))]; * * InhereitType = RrSs: * GlobalRM(x) * (GlobalSHM(x) * GlobalSM(x)) = GlobalRM(P(x)) * LocalRM(x) * [GlobalSHM(P(x)) * GlobalSM(P(x))] * LocalSM(x); * * InhereitType = RSrs: * GlobalRM(x) * (GlobalSHM(x) * GlobalSM(x)) = GlobalRM(P(x)) * [GlobalSHM(P(x)) * GlobalSM(P(x))] * LocalRM(x) * LocalSM(x); * * InhereitType = Rrs: * GlobalRM(x) * (GlobalSHM(x) * GlobalSM(x)) = GlobalRM(P(x)) * LocalRM(x) * LocalSM(x); * * LocalM(x)= TM(x) * RoffsetM(x) * RpivotM(x) * RpreM(x) * RM(x) * RpostM(x) * RpivotM(x)^-1 * SoffsetM(x) *SpivotM(x) * SM(x) * SpivotM(x)^-1 * LocalTWithAllPivotAndOffsetInformationV(x) = Local(x).GetT(); * GlobalTV(x) = GlobalM(P(x)) * LocalTWithAllPivotAndOffsetInformationV(x); * * Notice: FBX SDK does not support shear yet, so all local transform won't have shear. * However, global transform might bring in shear by combine the global transform of node in higher hierarchy. * For example, if you scale the parent by a non-uniform scale and then rotate the child node, then a shear will * be generated on the child node's global transform. * In this case, we always compensates shear and store it in the scale matrix too according to following formula: * Shear*Scaling = RotationMatrix.Inverse * TranslationMatrix.Inverse * WholeTranformMatrix */ // ReSharper disable InconsistentNaming static FbxAMatrix CalculateGlobalTransform(FbxNode node) { if (node == null) { var ret = new FbxAMatrix(); ret.SetIdentity(); return(ret); } var lTranlationM = new FbxAMatrix(); var lScalingM = new FbxAMatrix(); var lScalingPivotM = new FbxAMatrix(); var lScalingOffsetM = new FbxAMatrix(); var lRotationOffsetM = new FbxAMatrix(); var lRotationPivotM = new FbxAMatrix(); var lPreRotationM = new FbxAMatrix(); var lRotationM = new FbxAMatrix(); var lPostRotationM = new FbxAMatrix(); FbxAMatrix lParentGX = new FbxAMatrix(); FbxAMatrix lGlobalT = new FbxAMatrix(); FbxAMatrix lGlobalRS = new FbxAMatrix(); // Construct translation matrix FbxVector4 lTranslation = new FbxVector4(node.LclTranslation.Get()); //The fourth component of this object is assigned 1. lTranlationM.SetT(lTranslation); // Construct rotation matrices FbxVector4 lRotation = new FbxVector4(node.LclRotation.Get()); FbxVector4 lPreRotation = new FbxVector4(node.PreRotation.Get()); FbxVector4 lPostRotation = new FbxVector4(node.PostRotation.Get()); lRotationM.SetR(lRotation); lPreRotationM.SetR(lPreRotation); lPostRotationM.SetR(lPostRotation); // Construct scaling matrix FbxVector4 lScaling = new FbxVector4(node.LclScaling.Get()); lScalingM.SetS(lScaling); // Construct offset and pivot matrices FbxVector4 lScalingOffset = new FbxVector4(node.ScalingOffset.Get()); FbxVector4 lScalingPivot = new FbxVector4(node.ScalingPivot.Get()); FbxVector4 lRotationOffset = new FbxVector4(node.RotationOffset.Get()); FbxVector4 lRotationPivot = new FbxVector4(node.RotationPivot.Get()); lScalingOffsetM.SetT(lScalingOffset); lScalingPivotM.SetT(lScalingPivot); lRotationOffsetM.SetT(lRotationOffset); lRotationPivotM.SetT(lRotationPivot); // Calculate the global transform matrix of the parent node FbxNode lParentNode = node.GetParent(); if (lParentNode != null) { //Children of the root node must take into account the axis matrix. //Warning: this function CalculateGlobalTransform was taken from FBX SDK/Smaples/Transformations. Originaly it did not take into account AxisSystem if (lParentNode.GetParent() == null) { FbxAMatrix axisMarix = new FbxAMatrix(); node.GetScene().GetGlobalSettings().GetAxisSystem().GetMatrix(axisMarix); lPreRotationM = axisMarix.mul(lPreRotationM); } lParentGX = CalculateGlobalTransform(lParentNode); } else { lParentGX.SetIdentity(); } //Construct Global Rotation FbxAMatrix lParentGRM = new FbxAMatrix(); FbxVector4 lParentGR = lParentGX.GetR(); lParentGRM.SetR(lParentGR); var lLRM = lPreRotationM.mul(lRotationM).mul(lPostRotationM); //Construct Global Shear*Scaling //FBX SDK does not support shear, to patch this, we use: //Shear*Scaling = RotationMatrix.Inverse * TranslationMatrix.Inverse * WholeTranformMatrix FbxAMatrix lParentTM = new FbxAMatrix(); FbxVector4 lParentGT = lParentGX.GetT(); lParentTM.SetT(lParentGT); var lParentGRSM = lParentTM.Inverse().mul(lParentGX); var lParentGSM = lParentGRM.Inverse().mul(lParentGRSM); var lLSM = lScalingM; //Do not consider translation now FbxTransform.EInheritType lInheritType = node.InheritType.Get(); if (lInheritType == FbxTransform.EInheritType.eInheritRrSs) { lGlobalRS = lParentGRM.mul(lLRM).mul(lParentGSM).mul(lLSM); } else if (lInheritType == FbxTransform.EInheritType.eInheritRSrs) { lGlobalRS = lParentGRM.mul(lParentGSM).mul(lLRM).mul(lLSM); } else if (lInheritType == FbxTransform.EInheritType.eInheritRrs) { if (lParentNode != null) { FbxAMatrix lParentLSM = new FbxAMatrix(); FbxVector4 lParentLS = new FbxVector4(lParentNode.LclScaling.Get()); lParentLSM.SetS(lParentLS); FbxAMatrix lParentGSM_noLocal = lParentGSM.mul(lParentLSM.Inverse()); lGlobalRS = lParentGRM.mul(lLRM).mul(lParentGSM_noLocal).mul(lLSM); } else { lGlobalRS = lParentGRM.mul(lLRM).mul(lLSM); } } else { FbxImportLog.LogError(node, "error, unknown inherit type!"); } // Construct translation matrix // Calculate the local transform matrix var lTransform = lTranlationM.mul(lRotationOffsetM).mul(lRotationPivotM).mul(lPreRotationM).mul(lRotationM).mul(lPostRotationM) .mul(lRotationPivotM.Inverse()).mul(lScalingOffsetM).mul(lScalingPivotM).mul(lScalingM).mul(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.mul(lGlobalRS); return(lTransform); }
public void Scene_AddObjectWithSrcObjects_AddsAllSrcObjects() { // given: var scene = new FbxScene("s"); var node = new FbxNode("n"); var m1 = new FbxMesh("m1"); var m2 = new FbxMesh("m2"); var v = new FbxVideo("v"); var c = new FbxCluster("c"); var n2 = new FbxNode("n2"); var c2 = new FbxCluster("c2"); node.ConnectSrcObject(m1); node.ConnectSrcObject(m2); node.ConnectSrcObject(v); node.ConnectSrcObject(c); c.ConnectSrcObject(n2);; n2.ConnectSrcObject(c2); // require: Assert.AreEqual(3, scene.GetSrcObjectCount()); Assert.AreEqual(4, node.GetSrcObjectCount()); Assert.AreSame(m1, node.GetSrcObject(0)); Assert.AreSame(m2, node.GetSrcObject(1)); Assert.AreSame(v, node.GetSrcObject(2)); Assert.AreSame(c, node.GetSrcObject(3)); Assert.AreEqual(0, node.GetDstObjectCount()); Assert.Null(node.GetScene()); Assert.AreEqual(0, m1.GetSrcObjectCount()); Assert.AreEqual(1, m1.GetDstObjectCount()); Assert.AreSame(node, m1.GetDstObject(0)); Assert.Null(m1.GetScene()); Assert.AreEqual(0, m2.GetSrcObjectCount()); Assert.AreEqual(1, m2.GetDstObjectCount()); Assert.AreSame(node, m2.GetDstObject(0)); Assert.Null(m2.GetScene()); Assert.AreEqual(0, v.GetSrcObjectCount()); Assert.AreEqual(1, v.GetDstObjectCount()); Assert.AreSame(node, v.GetDstObject(0)); Assert.Null(v.GetScene()); Assert.AreEqual(1, c.GetSrcObjectCount()); Assert.AreSame(n2, c.GetSrcObject());; Assert.AreEqual(1, c.GetDstObjectCount()); Assert.AreSame(node, c.GetDstObject(0)); Assert.Null(c.GetScene()); Assert.AreEqual(1, n2.GetSrcObjectCount()); Assert.AreSame(c2, n2.GetSrcObject());; Assert.AreEqual(1, n2.GetDstObjectCount()); Assert.AreSame(c, n2.GetDstObject(0)); Assert.Null(n2.GetScene()); Assert.AreEqual(0, c2.GetSrcObjectCount()); Assert.AreEqual(1, c2.GetDstObjectCount()); Assert.AreSame(n2, c2.GetDstObject(0)); Assert.Null(c2.GetScene()); // when: scene.ConnectSrcObject(node); // then: Assert.AreEqual(10, scene.GetSrcObjectCount()); Assert.AreSame(node, scene.GetSrcObject(3)); Assert.AreSame(m1, scene.GetSrcObject(4)); Assert.AreSame(m2, scene.GetSrcObject(5)); Assert.AreSame(v, scene.GetSrcObject(6)); Assert.AreSame(c, scene.GetSrcObject(7)); Assert.AreSame(n2, scene.GetSrcObject(8)); Assert.AreSame(c2, scene.GetSrcObject(9)); Assert.AreEqual(4, node.GetSrcObjectCount()); Assert.AreSame(m1, node.GetSrcObject(0)); Assert.AreSame(m2, node.GetSrcObject(1)); Assert.AreSame(v, node.GetSrcObject(2)); Assert.AreSame(c, node.GetSrcObject(3)); Assert.AreEqual(1, node.GetDstObjectCount()); Assert.AreSame(scene, node.GetDstObject(0)); Assert.AreSame(scene, node.GetScene()); Assert.AreEqual(0, m1.GetSrcObjectCount()); Assert.AreEqual(2, m1.GetDstObjectCount()); Assert.AreSame(node, m1.GetDstObject(0)); Assert.AreSame(scene, m1.GetDstObject(1)); Assert.AreSame(scene, m1.GetScene()); Assert.AreEqual(0, m2.GetSrcObjectCount()); Assert.AreEqual(2, m2.GetDstObjectCount()); Assert.AreSame(node, m2.GetDstObject(0)); Assert.AreSame(scene, m2.GetDstObject(1)); Assert.AreSame(scene, m2.GetScene()); Assert.AreEqual(0, v.GetSrcObjectCount()); Assert.AreEqual(2, v.GetDstObjectCount()); Assert.AreSame(node, v.GetDstObject(0)); Assert.AreSame(scene, v.GetDstObject(1)); Assert.AreSame(scene, v.GetScene()); Assert.AreEqual(1, c.GetSrcObjectCount()); Assert.AreSame(n2, c.GetSrcObject(0)); Assert.AreEqual(2, c.GetDstObjectCount()); Assert.AreSame(node, c.GetDstObject(0)); Assert.AreSame(scene, c.GetDstObject(1)); Assert.AreSame(scene, c.GetScene()); Assert.AreEqual(1, n2.GetSrcObjectCount()); Assert.AreSame(c2, n2.GetSrcObject());; Assert.AreEqual(2, n2.GetDstObjectCount()); Assert.AreSame(c, n2.GetDstObject(0)); Assert.AreSame(scene, n2.GetDstObject(1)); Assert.AreSame(scene, n2.GetScene()); Assert.AreEqual(0, c2.GetSrcObjectCount()); Assert.AreEqual(2, c2.GetDstObjectCount()); Assert.AreSame(n2, c2.GetDstObject(0)); Assert.AreSame(scene, c2.GetDstObject(1)); Assert.AreSame(scene, c2.GetScene()); }