Ejemplo n.º 1
0
        /// <summary>
        /// Converts all meshes in the given mesh array. Each mesh is split
        /// up per material, the indices of the generated meshes are stored in
        /// the node structure.
        /// </summary>
        /// <param name="scene">The scene to construct the return data in.</param>
        /// <param name="node">The target node structure that references the constructed meshes.</param>
        /// <param name="meshes">The array of meshes to convert</param>
        protected void CreateMeshes(AssimpSharp.Scene scene, AssimpSharp.Node node, List<AssimpSharp.XFile.Mesh> meshes)
        {
            if (meshes.Count == 0)
            {
                return;
            }

            // create a mesh for each mesh-material combination in the source node
            var result = new List<AssimpSharp.Mesh>();
            for (int a = 0; a < meshes.Count; a++)
            {
                var sourceMesh = meshes[a];
                // first convert its materials so that we can find them with their index afterwards
                ConvertMaterials(scene, sourceMesh.Materials);

                int numMaterials = Math.Max(sourceMesh.Materials.Count, 1);
                for (int b = 0; b < numMaterials; b++)
                {
                    // collect the faces belonging to this material
                    var faces = new List<int>();
                    var numVertices = 0;
                    if (sourceMesh.FaceMaterials.Count > 0)
                    {
                        // if there is a per-face material defined, select the faces with the corresponding material
                        for (int c = 0; c < sourceMesh.FaceMaterials.Count; c++)
                        {
                            if (sourceMesh.FaceMaterials[c] == b)
                            {
                                faces.Add(c);
                                numVertices += sourceMesh.PosFaces[c].Indices.Count;
                            }
                        }
                    }
                    else
                    {
                        // if there is no per-face material, place everything into one mesh
                        for (int c = 0; c < sourceMesh.PosFaces.Count; c++)
                        {
                            faces.Add(c);
                            numVertices += sourceMesh.PosFaces[c].Indices.Count;
                        }
                    }

                    // no faces/vertices using this material? strange...
                    if (numVertices == 0)
                    {
                        continue;
                    }

                    // create a submesh using this material
                    var mesh = new AssimpSharp.Mesh();
                    result.Add(mesh);

                    // find the material in the scene's material list. Either own material
                    // or referenced material, it should already have a valid index
                    if (sourceMesh.FaceMaterials.Count > 0)
                    {
                        mesh.MaterialIndex = sourceMesh.Materials[b].SceneIndex;
                    }
                    else
                    {
                        mesh.MaterialIndex = 0;
                    }

                    // Create properly sized data arrays in the mesh. We store unique vertices per face,
                    // as specified
                    mesh.NumVertices = numVertices;
                    mesh.Vertices = new Vector3[numVertices];
                    mesh.NumFaces = faces.Count;
                    mesh.Faces = new AssimpSharp.Face[mesh.NumFaces];

                    // normals?
                    if (sourceMesh.Normals.Count > 0)
                    {
                        mesh.Normals = new Vector3[numVertices];
                    }
                    // texture coords
                    for (int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; c++)
                    {
                        if (sourceMesh.TexCoords[c] != null && sourceMesh.TexCoords[c].Count > 0)
                        {
                            mesh.TextureCoords[c] = new Vector3[numVertices];
                        }
                    }
                    // vertex colors
                    mesh.Colors = new Color4[AI_MAX_NUMBER_OF_COLOR_SETS][];
                    for (int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; c++)
                    {
                        if (sourceMesh.Colors[c] != null && sourceMesh.Colors[c].Count > 0)
                        {
                            mesh.Colors[c] = new Color4[numVertices];
                        }
                    }

                    // now collect the vertex data of all data streams present in the imported mesh
                    int newIndex = 0;
                    var orgPoints = new int[numVertices];

                    for (int c = 0; c < faces.Count; c++)
                    {
                        int f = faces[c];
                        var pf = sourceMesh.PosFaces[f];

                        // create face. either triangle or triangle fan depending on the index count
                        var df = mesh.Faces[c] = new AssimpSharp.Face();
                        df.Indices = new int[pf.Indices.Count];

                        // collect vertex data for indices of this face
                        for (int d = 0; d < df.Indices.Length; d++)
                        {
                            df.Indices[d] = newIndex;
                            orgPoints[newIndex] = (int)pf.Indices[d];

                            // Position
                            mesh.Vertices[newIndex] = sourceMesh.Positions[(int)pf.Indices[d]];

                            // Normal, if present
                            if (mesh.HasNormals)
                            {
                                mesh.Normals[newIndex] = sourceMesh.Normals[(int)sourceMesh.NormalFaces[f].Indices[d]];
                            }

                            // texture coord sets
                            for (int e = 0; e < AI_MAX_NUMBER_OF_TEXTURECOORDS; e++)
                            {
                                if (mesh.HasTextureCoords(e))
                                {
                                    var tex = sourceMesh.TexCoords[e][(int)pf.Indices[d]];
                                    mesh.TextureCoords[e][newIndex] = new Vector3(tex.X, 1.0f - tex.Y, 0.0f);
                                }
                            }

                            // vertex color sets
                            for (int e = 0; e < AI_MAX_NUMBER_OF_COLOR_SETS; e++)
                            {
                                if (mesh.HasVertexColors(e))
                                {
                                    mesh.Colors[e][newIndex] = sourceMesh.Colors[e][(int)pf.Indices[d]];
                                }
                            }
                            newIndex++;
                        }
                    }

                    Debug.Assert(newIndex == numVertices);

                    var bones = sourceMesh.Bones;
                    var newBones = new List<AssimpSharp.Bone>();
                    for (int c = 0; c < bones.Count; c++)
                    {
                        var obone = bones[c];

                        var oldWeights = new float[sourceMesh.Positions.Count];
                        for (int d = 0; d < obone.Weights.Count; d++)
                        {
                            oldWeights[(int)obone.Weights[d].Vertex] = obone.Weights[d].Weight;
                        }

                        var newWeights = new List<AssimpSharp.VertexWeight>(numVertices);
                        for (int d = 0; d < orgPoints.Length; d++)
                        {
                            float w = oldWeights[orgPoints[d]];
                            if (w > 0.0f)
                            {
                                newWeights.Add(new VertexWeight(d, w));
                            }
                        }

                        if (newWeights.Count == 0)
                        {
                            continue;
                        }

                        // create
                        var nbone = new AssimpSharp.Bone();
                        newBones.Add(nbone);
                        // copy name end matrix
                        nbone.Name = obone.Name;
                        nbone.OffsetMatrix = obone.OffsetMatrix;
                        nbone.NumWeights = newWeights.Count;
                        nbone.Weights = new VertexWeight[nbone.NumWeights];
                        for (int d = 0; d < newWeights.Count; d++)
                        {
                            nbone.Weights[d] = newWeights[d];
                        }
                    }

                    mesh.NumBones = newBones.Count;
                    if (newBones.Count > 0)
                    {
                        mesh.Bones = mesh.Bones.ToArray();
                    }
                }
            }

            // allocate mesh index array in the node
            node.Meshes.Capacity = meshes.Count;

            // store all meshes in the mesh library of the scene and store their indices in the node
            for (int a = 0; a < result.Count; a++)
            {
                scene.Meshes.Add(result[a]);
                node.Meshes.Add(scene.Meshes.Count - 1);
            }
        }
Ejemplo n.º 2
0
        private void ConvertCluster(List<aiBone> bones, Model model, Cluster cl, int[] outIndices, int[] indexOutIndices, int[] countOutIndices, Matrix nodeGlobalTransform)
        {
            var bone = new aiBone();
            bones.Add(bone);

            bone.Name = FixNodeName(cl.TargetNode.Name);

            bone.OffsetMatrix = cl.TransformLink;
            bone.OffsetMatrix.Invert();

            bone.OffsetMatrix = bone.OffsetMatrix * nodeGlobalTransform;

            bone.NumWeights = outIndices.Length;
            var cursor = bone.Weights = new aiVertexWeight[outIndices.Length];
            int cursor_index = 0;

            int noIndexSentinel = int.MaxValue;
            var weights = cl.Weights;

            int c = indexOutIndices.Length;
            for (int i = 0; i < c; i++)
            {
                int indexIndex = indexOutIndices[i];
                if (indexIndex == noIndexSentinel)
                {
                    continue;
                }
                int cc = countOutIndices[i];
                for (int j = 0; j < cc; j++)
                {
                    cursor[cursor_index].VertexId = outIndices[indexIndex + j];
                    cursor[cursor_index].Weight = weights[i];
                    j++;
                }
            }
        }