Exemplo n.º 1
0
        public static Software.Mesh ParseCollada(String filename)
        {
            ColladaDocument doc        = new ColladaDocument(filename);
            ColladaMesh     resultMesh = new ColladaMesh();
            Dictionary <String, ColladaMesh> geometryMeshes = new Dictionary <string, ColladaMesh>();

            foreach (ColladaDocument.Geometry g in doc.geometries)
            {
                if (geometryMeshes.ContainsKey(g.id))
                {
                    throw new Exception("Duplicate geometry entries");
                }
                geometryMeshes[g.id] = ExtractColladaGeometry(g);
            }

            if (doc.visualScenes.Count != 1)
            {
                throw new NotImplementedException("There has to be exactly one Visual Scene");
            }

            foreach (ColladaDocument.Node n in doc.visualScenes[0].nodes)
            {
                HandleNode(geometryMeshes, ref resultMesh, n, Matrix.Identity);
            }

            resultMesh.BuildVertexList();

            return(IndexedCollada(resultMesh.Vertices, resultMesh.Indices));
        }
        public static Software.Mesh ParseCollada(String filename)
        {
            ColladaDocument doc = new ColladaDocument(filename);
            ColladaMesh resultMesh = new ColladaMesh();
            Dictionary<String, ColladaMesh> geometryMeshes = new Dictionary<string, ColladaMesh>();

            foreach (ColladaDocument.Geometry g in doc.geometries)
            {
                if (geometryMeshes.ContainsKey(g.id))
                    throw new Exception("Duplicate geometry entries");
                geometryMeshes[g.id] = ExtractColladaGeometry(g);
            }

            if (doc.visualScenes.Count != 1)
                throw new NotImplementedException("There has to be exactly one Visual Scene");

            foreach (ColladaDocument.Node n in doc.visualScenes[0].nodes)
                HandleNode(geometryMeshes, ref resultMesh, n, Matrix.Identity);

            resultMesh.BuildVertexList();

            return IndexedCollada(resultMesh.Vertices, resultMesh.Indices);
        }
        private static ColladaMesh ExtractColladaGeometry(ColladaDocument.Geometry g)
        {
            ColladaMesh mesh = new ColladaMesh();
            var m = g.mesh;
            Vector3[] vertexData = null;
            Vector3[] normalData = null;
            Vector3[] texcoordData = null;

            if (m.primitives.Count != 1)
                throw new NotImplementedException("m.primitives.Count = " + m.primitives.Count);
            var p = m.primitives[0];

            Dictionary<string, float[]> data = new Dictionary<string, float[]>();
            for (int i = 0; i < m.sources.Count; i++)
            {
                ColladaDocument.Array<float> inputArr = (ColladaDocument.Array<float>)m.sources[i].array;
                if (data.ContainsKey(m.sources[i].id))
                    throw new Exception("A data entry called " + m.sources[i].id + " has already been parsed.");
                data[m.sources[i].id] = inputArr.arr;
            }

            int indlen = p.p.Length / p.stride;
            int[] vertexIndices = new int[indlen];
            int[] normalIndices = new int[indlen];
            int[] texcoordIndices = new int[indlen];
            foreach (ColladaDocument.Input input in p.Inputs)
            {
                switch (input.semantic.ToLower())
                {
                    case "vertex":
                        if (!(input.source is ColladaDocument.Vertices))
                            throw new Exception("VERTEX source should be of type ColladaDocument.Vertices");
                        ProcessVertex((ColladaDocument.Vertices)input.source, p.p, p.stride, input.offset, data,
                            ref vertexData, ref vertexIndices, ref normalData, ref normalIndices, ref texcoordData, ref texcoordIndices);
                        break;
                    case "normal":
                        if (!(input.source is ColladaDocument.Source))
                            throw new Exception("NORMAL source should be of type ColladaDocument.Vertices");
                        var nsource = (ColladaDocument.Source)input.source;
                        // set up indices
                        for (int i = 0; i < indlen; i++)
                            normalIndices[i] = p.p[i * p.stride + input.offset];
                        // load data
                        normalData = ParseNormalData(data[nsource.id]);
                        break;
                    case "texcoord":
                        if (!(input.source is ColladaDocument.Source))
                            throw new Exception("TEXCOORD source should be of type ColladaDocument.Vertices");
                        var tsource = (ColladaDocument.Source)input.source;
                        // set up indices
                        for (int i = 0; i < indlen; i++)
                            texcoordIndices[i] = p.p[i * p.stride + input.offset];
                        // load data
                        texcoordData = ParseTexcoordData(data[tsource.id], tsource.accessor.stride);
                        break;
                    default:
                        throw new NotImplementedException();
                }
            }

            if (vertexIndices.Length != normalIndices.Length || normalIndices.Length != texcoordIndices.Length)
                throw new NotImplementedException("all of them needs to be supplied and of the same amount right now");

            mesh.VertexData = new List<Vector3>(vertexData);
            mesh.VertexIndices = new List<int>(vertexIndices);

            if (normalData != null)
            {
                mesh.NormalData = new List<Vector3>(normalData);
                mesh.NormalIndices = new List<int>(normalIndices);
            }

            if (texcoordData != null)
            {
                mesh.TexcoordData = new List<Vector3>(texcoordData);
                mesh.TexcoordIndices = new List<int>(texcoordIndices);
            }

            return mesh;
        }
        private static void ProcessVertex(ColladaDocument.Vertices source, int[] p, int stride, int offset, Dictionary<string, float[]> data,
            ref Vector3[] vertexData, ref int[] vertexIndices,
            ref Vector3[] normalData, ref int[] normalIndices,
            ref Vector3[] texcoordData, ref int[] texcoordIndices)
        {
            int length = p.Length / stride;
            for (int i = 0; i < length; i++)
            {
                int value = p[i * stride + offset];
                foreach (var input in source.inputs)
                {
                    switch (input.semantic.ToLower())
                    {
                        case "position":
                            vertexIndices[i] = value;
                            break;
                        case "normal":
                            normalIndices[i] = value;
                            break;
                        case "texcoord":
                            texcoordIndices[i] = value;
                            break;
                        default:
                            throw new NotImplementedException();
                    }
                }
            }

            foreach (var input in source.inputs)
            {
                if (!(input.source is ColladaDocument.Source))
                    throw new Exception("CHILD OF VERTEX source should be of type ColladaDocument.Source");
                var csource = (ColladaDocument.Source)input.source;
                switch (input.semantic.ToLower())
                {
                    case "position":
                        vertexData = ParseVertexData(data[csource.id]);
                        break;
                    case "normal":
                        normalData = ParseNormalData(data[csource.id]);
                        break;
                    case "texcoord":
                        texcoordData = ParseTexcoordData(data[csource.id], csource.accessor.stride);
                        break;
                }
            }
        }
        private static void HandleNode(Dictionary<string, ColladaMesh> geometryMeshes, ref ColladaMesh resultMesh, ColladaDocument.Node node, Matrix world)
        {
            if(node.transforms != null)
                world = ConcatTransforms(node.transforms, world);

            if (node.instances != null)
            {
                if (node.instances.Count != 1)
                    throw new Exception("Nodes need to have exactly one instance right now");

                if (!(node.instances[0] is ColladaDocument.InstanceGeometry))
                    return;     // SILENT FAIL

                ColladaDocument.Instance i = node.instances[0];
                ColladaMesh mesh = geometryMeshes[i.url.Fragment];
                resultMesh.AppendMesh(mesh, world);
                if (node.children != null && node.children.Count > 0)
                    throw new Exception("Tell Joakim.");
            }
            else if (node.children != null && node.children.Count > 0)
            {
                foreach (ColladaDocument.Node n in node.children)
                    HandleNode(geometryMeshes, ref resultMesh, n, world);
            }
            else
            {
                //throw new Exception("Node has no instance and no child. Keh?");
            }
        }