예제 #1
0
        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);
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
 private MeshInfo FindMeshInfo(FbxSDK.Mesh mesh)
 {
     return(meshInfoList.Find(v => v.mesh == mesh));
 }