private void UpdateMeshInfoRecursively(FbxSDK.Node node, ref Matrix4 parentMatrix) { int childCount = node.GetChildCount(); Matrix4 globalTransform = GetGlobalTransform(node, parentMatrix); FbxSDK.Mesh mesh = node.GetAttribute() as FbxSDK.Mesh; if (mesh != null) { Matrix4 meshTransform = GetGeometry(node) * globalTransform; MeshInfo meshInfo = FindMeshInfo(mesh); if (meshInfo == null) { meshInfo = LoadMesh(mesh); } meshInfo.geometryToWorld = meshTransform; } for (int i = 0; i < childCount; ++i) { UpdateMeshInfoRecursively(node.GetChild(i), ref globalTransform); } }
private void OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs <object> e) { var item = e.NewValue as TreeViewItem; CurSelected = null; if (item != null) { CurSelected = item.Tag as FbxSDK.Node; } }
private Matrix4 GetGlobalTransform(FbxSDK.Node node, Matrix4?parentGlobalTransform = null) { Matrix4 globalTransform = Matrix4.Identity; bool isGlobalTransformReady = false; if (curPose != null) { int nodeIndex = curPose.Find(node); if (nodeIndex >= 0) { Matrix4 poseMat = Converter.Convert(curPose.GetMatrix(nodeIndex)); if (curPose.IsBindPose() || !curPose.IsLocalMatrix(nodeIndex)) { globalTransform = poseMat; } else { if (parentGlobalTransform.HasValue) { globalTransform = poseMat * parentGlobalTransform.Value; } else { if (node.GetParent() != null) { globalTransform = poseMat * GetGlobalTransform(node.GetParent()); } } } isGlobalTransformReady = true; } } if (isGlobalTransformReady == false) { globalTransform = Converter.Convert(node.EvaluateGlobalTransform(curTime)); } return(globalTransform); }
public void AddNode(ItemCollection collection, FbxSDK.Node node) { TreeViewItem viewItem = new TreeViewItem(); string name = node.GetName(); var attribute = node.GetAttribute(); if (attribute != null) { var attributeType = attribute.GetAttributeType(); name += string.Format(" ({0})", attributeType); } viewItem.Header = name; viewItem.Tag = node; for (int i = 0; i < node.GetChildCount(); ++i) { var child = node.GetChild(i); AddNode(viewItem.Items, child); } collection.Add(viewItem); }
private Matrix4 GetGeometry(FbxSDK.Node node) { return(Converter.Convert(node.GetGeometryOffset())); }
private MeshInfo LoadMesh(FbxSDK.Mesh mesh) { MeshInfo meshInfo = new MeshInfo(); meshInfoList.Add(meshInfo); meshInfo.mesh = mesh; meshInfo.node = mesh.GetNode(); int polygonCount = mesh.GetPolygonCount(); int controlPointsCount = mesh.GetControlPointsCount(); meshInfo.polygonCount = polygonCount; meshInfo.controlPointsCount = controlPointsCount; meshInfo.nextSkinningIndex = new int[controlPointsCount]; meshInfo.boneTrasforms = new Matrix4[MaxBoneCount]; int vertexArray = GL.GenVertexArray(); meshInfo.vertexArray = vertexArray; GL.BindVertexArray(vertexArray); int vertexBuffer = GL.GenBuffer(); GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBuffer); int elementBuffer = GL.GenBuffer(); GL.BindBuffer(BufferTarget.ElementArrayBuffer, elementBuffer); VertexData[] vertexBufferData = new VertexData[controlPointsCount]; int[] vertexBufferBoneCounter = new int[controlPointsCount]; for (int i = 0; i < controlPointsCount; ++i) { Vector3 coordinate = Converter.Convert(mesh.GetControlPoint(i)); vertexBufferData[i] = new VertexData() { x = coordinate.X, y = coordinate.Y, z = coordinate.Z }; } int skinDeformerCount = mesh.GetSkinDeformerCount(); byte boneIndex = 0; for (int i = 0; i < skinDeformerCount; ++i) { FbxSDK.Skin skin = mesh.GetSkinDeformer(i); var skinningType = skin.GetSkinningType(); if (skinningType == FbxSDK.SkinningType.Linear || skinningType == FbxSDK.SkinningType.Rigid) { int clusterCount = skin.GetClusterCount(); for (int j = 0; j < clusterCount; ++j) { FbxSDK.Cluster cluster = skin.GetCluster(j); FbxSDK.Node link = cluster.GetLink(); if (link == null) { continue; } if (cluster.HasAssociateModel()) { DebugUtil.WriteLine("No support for associate model."); } int indexCount = cluster.GetControlIndicesCount(); bool isValidBone = false; for (int k = 0; k < indexCount; ++k) { int controlPointIndex = cluster.GetControlPointIndex(k); float controlPointWeight = (float)cluster.GetControlPointWeight(k); if (vertexBufferBoneCounter[controlPointIndex] == 16) { continue; } isValidBone = true; int fieldIndex = vertexBufferBoneCounter[controlPointIndex]; VertexData.SetBoneInfo(ref vertexBufferData[controlPointIndex], fieldIndex, boneIndex, controlPointWeight); ++vertexBufferBoneCounter[controlPointIndex]; } if (isValidBone) { boneInfoList.Add(new BoneInfo() { cluster = cluster, boneIndex = boneIndex, ownerMeshInfo = meshInfo }); ++boneIndex; } } } else { DebugUtil.WriteLine("No support for dual quaternion and blend."); // TODO : Dual Quaternion rigging } } int[] indices = new int[polygonCount * 3]; for (int i = 0; i < polygonCount; ++i) { indices[3 * i] = mesh.GetControlPointIndex(i, 0); indices[3 * i + 1] = mesh.GetControlPointIndex(i, 1); indices[3 * i + 2] = mesh.GetControlPointIndex(i, 2); } GL.BufferData(BufferTarget.ArrayBuffer, vertexBufferData.Length * VertexData.GetSize(), vertexBufferData, BufferUsageHint.StaticDraw); GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, VertexData.GetSize(), 0); GL.EnableVertexAttribArray(0); for (int i = 0; i < 4; ++i) { int attribIndexIndex = i + 1; GL.VertexAttribIPointer(attribIndexIndex, 4, VertexAttribIntegerType.UnsignedByte, VertexData.GetSize(), new IntPtr(VertexData.GetBoneIndexPos(i))); GL.EnableVertexAttribArray(attribIndexIndex); } for (int i = 0; i < 4; ++i) { int attribIndexIndex = i + 5; GL.VertexAttribPointer(attribIndexIndex, 4, VertexAttribPointerType.Float, false, VertexData.GetSize(), VertexData.GetBoneWeightPos(i)); GL.EnableVertexAttribArray(attribIndexIndex); } GL.BufferData(BufferTarget.ElementArrayBuffer, indices.Length * sizeof(int), indices, BufferUsageHint.StaticDraw); GL.BindVertexArray(0); return(meshInfo); }
public void SetNode(FbxSDK.Node rootNode) { treeView.Items.Clear(); AddNode(treeView.Items, rootNode); }