public static MeshData[] ProcMesh(FbxManager manager, FbxNode node, FbxMesh mesh, ImportOptions importOptions, Matrix4 additionalTransform) { var transform = additionalTransform * FbxMath.EvaluateGlobalTransform(node).ToMatrix4(); transform = transform * FbxMath.GetGeometryOffset(node).ToMatrix4(); var converter = new FbxGeometryConverter(manager); bool success = false; try { mesh = FbxMesh.Cast(converter.Triangulate(mesh, false)); //ToDo :? Может true? Чтобы не создавать второй mesh в Attribute success = true; } catch (Exception ex) { FbxImportLog.LogError(node, "Inside Triangulate error: " + ex); } if (!success || mesh == null) { return(null); } MeshData data = ReadTriangles(mesh, node); var ret = ReadMaterialsAndSplitByMaterials(data); foreach (var m in ret) { ReadMeshElements(m, importOptions, ref transform); } return(ret); }
//ToDo : учет associate model? // GlobalTransform of the bone at the binding moment. // // (Comments from fbxcluster.h) // Transformation matrices. A link has three transformation matrices: // - Transform refers to the global initial transform of the geometry node(geometry is the attribute of the node) that contains the link node. // - TransformLink refers to global initial transform of the link(bone) node. // - TransformAssociateModel refers to the global initial transform of the associate model. // // For example, given a mesh binding with several bones(links), Transform is the global transform // of the mesh at the binding moment, TransformLink is the global transform of the bone(link) // at the binding moment, TransformAssociateModel is the global transform of the associate model // at the binding moment. FbxAMatrix GetInitialTransform() { if (cluster == null) { return(FbxMath.EvaluateGlobalTransform(Node)); } //Each cluster is associated with a FbxNode (bone) //cluster.GetLink().GetUniqueID() == Node.GetUniqueID(); //??? Учитывать ли AxisSystem? //??? Не совсем понятны отличаи globalMeshTransform == skin.GetGeometry().GetNode().EvaluateGlobalTransform(), от cluster.GetTransformMatrix() //matrix associated with the geometry node containing the link. (global transform of the mesh at the binding moment) FbxAMatrix globalMeshInitialTransform = new FbxAMatrix(); cluster.GetTransformMatrix(globalMeshInitialTransform); //Get matrix associated with the link node (bind pose, bone transform) at the binding moment FbxAMatrix boneInitialTransform = new FbxAMatrix(); cluster.GetTransformLinkMatrix(boneInitialTransform); //Дополнительная матрица которую cluster ассоциирует с Node - Трансформация в момент привязки. //bind pose matrix that is local for the mesh = Inverse(TransformMatrix) * TransformLinkMatrix FbxAMatrix localBindPose = (globalMeshInitialTransform.mul(geometryOffset).Inverse()).mul(boneInitialTransform); //globalMeshTransform * Inverse(globalMeshInitialTransform) * boneInitialTransform return(globalMeshTransform.mul(geometryOffset).mul(localBindPose)); }
//const int maxNameLength = 40; //static void AppendName(ref string name1, string name2) //{ // if (name1.Length < maxNameLength) // { // name1 = name1 + " + " + name2; // if (name1.Length >= maxNameLength) //no more append // name1 += " + ..."; // } //} //void MergeGeometriesByMaterials() //{ // int mergedCount = 0; // for (int i = 0; i < Geometries.Count; i++) // { // MeshData g1 = Geometries[i]; // if(g1 == null) // continue; // for (int j = i + 1; j < Geometries.Count; j++) // { // MeshData g2 = Geometries[j]; // if (g2 != null && g1.MaterialIndex == g2.MaterialIndex && g1.VertexComponents == g2.VertexComponents && g1.PolygonSize == g2.PolygonSize) // { // var newVertices = new VertexInfo[g1.Vertices.Length + g2.Vertices.Length]; // g1.Vertices.CopyTo(newVertices, 0); // g2.Vertices.CopyTo(newVertices, g1.Vertices.Length); // g1.Vertices = newVertices; // g1.ClearCache(); //No longer valid // AppendName(ref g1.Name, g2.Name); // //m1.NormalsSource remains from first // Geometries[j] = null; // mergedCount++; // } // } // } // int count = Geometries.Count - mergedCount; // var res = new List<MeshData>(count); // for (int i = 0; i < count; i++) // if (Geometries[i] != null) // res.Add(Geometries[i]); // Geometries = res; //} static void FillBoneAssignments(MeshData data, Skeleton skeleton) { if (skeleton == null) { for (int i = 0; i < data.Vertices.Length; i++) { data.Vertices[i].Vertex.BlendIndices = new Vector4I(-1, -1, -1, -1); } } data.VertexComponents |= StandardVertex.Components.BlendIndices | StandardVertex.Components.BlendWeights; Dictionary <int, BoneAssignment> boneAssignments = ProcessSkeleton.GetBoneAssignments(data.Mesh, skeleton); if (boneAssignments != null) { for (int i = 0; i < data.Vertices.Length; i++) { ref VertexInfo v = ref data.Vertices[i]; if (boneAssignments.TryGetValue(v.ControlPointIndex, out BoneAssignment ba)) { FbxMath.ConvertBoneAssignment(ref ba, out v.Vertex.BlendIndices, out v.Vertex.BlendWeights); } else { v.Vertex.BlendIndices = new Vector4I(-1, -1, -1, -1); } } }
public SkeletonBone(FbxNode boneNode, SkeletonBone parentBone, FbxSkin[] skins, SceneLoader scene) { //this.scene = scene; this.scene = scene; Node = boneNode; ParentBone = parentBone; //animationTrackKeyFrames = new List<HashSet<double>>(); cluster = Skeleton.FindCluster(Node, skins, out skin); //Поиск по всем skins во всех mesh. Можно было бы сделать эффективнее. globalMeshTransform = new FbxAMatrix(); globalMeshTransform.SetIdentity(); geometryOffset = new FbxAMatrix(); geometryOffset.SetIdentity(); if (cluster != null) { FbxNode meshNode = skin.GetGeometry()?.GetNode(); if (meshNode != null) { globalMeshTransform = meshNode.EvaluateGlobalTransform(FbxExtensions.ToFbxTime(-1)); // FbxMath.GetGlobalPosition( meshNode, FbxExtensions.ToFbxTime( -1 ), null ); geometryOffset = FbxMath.GetGeometryOffset(meshNode); } } InitialTransform = GetInitialTransform().ToMatrix4(); //Во внешнем коде надо использовать это значение, т.к. результат GetInitialTransform() может зависеть от установленного AnimationTrack }