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 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); }
private MeshInfo FindMeshInfo(FbxSDK.Mesh mesh) { return(meshInfoList.Find(v => v.mesh == mesh)); }