示例#1
0
        public static void Read(string fileName, ConversionSettings conversionSettings, ref DisplayList dsp, out Dictionary <string, TextureInfo> allMaterials, out string[] messages)
        {
            messages = new string[0];
            if (conversionSettings.colorInterpretation == ConversionSettings.ColorInterpretation.Undefined)
            {
                if (!conversionSettings.DoColorInterpretationDialog())
                {
                    allMaterials = null;
                    return;
                }
            }
            string rootDirectory = System.IO.Path.GetDirectoryName(fileName);

            System.Xml.XmlDataDocument doc = new XmlDataDocument();
            doc.Load(fileName);
            XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable);

            mgr.AddNamespace("df", doc.DocumentElement.NamespaceURI);
            List <Subset> meshes              = new List <Subset>();
            XmlNode       imageLibraryNode    = doc.SelectSingleNode("//df:COLLADA/df:library_images", mgr);
            XmlNode       materialLibraryNode = doc.SelectSingleNode("//df:COLLADA/df:library_materials", mgr);
            XmlNode       effectLibraryNode   = doc.SelectSingleNode("//df:COLLADA/df:library_effects", mgr);
            XmlNode       geometryLibraryNode = doc.SelectSingleNode("//df:COLLADA/df:library_geometries", mgr);
            XmlNode       sceneLibraryNode    = doc.SelectSingleNode("//df:COLLADA/df:library_visual_scenes", mgr);
            XmlNodeList   geometryNodes       = sceneLibraryNode.SelectNodes("df:visual_scene/df:node/df:instance_geometry", mgr);
            bool          flipYZ              = doc.SelectSingleNode("//df:COLLADA/df:asset/df:up_axis", mgr).InnerText == "Z_UP";

            allMaterials = new Dictionary <string, TextureInfo>();
            allMaterials["<Undefined>"] = new TextureInfo(null);

            foreach (XmlNode geometryNode in geometryNodes)
            {
                XmlNode meshNode      = geometryLibraryNode.SelectSingleNode("df:geometry[@id='" + geometryNode.Attributes["url"].Value.Remove(0, 1) + "']/df:mesh", mgr);
                XmlNode transformNode = geometryNode.SelectSingleNode("../df:matrix[@sid='transform']", mgr);
                Matrix  transform     = Matrix.identity;
                if (transformNode != null)
                {
                    transform.m = Array.ConvertAll <string, float>(transformNode.InnerText.Split(' '), (s) => float.Parse(s, NumberStyles.Any, CultureInfo.InvariantCulture));
                }
                Matrix normalTransform = transform.InvertTranspose();
                foreach (XmlNode trianglesNode in meshNode.SelectNodes("df:triangles", mgr))
                {
                    Subset meshSubset = new Subset();
                    meshes.Add(meshSubset);
                    List <Vertex> vertexBuffer = new List <Vertex>(); //final vertex buffer for this material
                    List <int>    indexBuffer  = new List <int>();    //final index buffer for this material

                    //Data to be read from XML
                    XmlAttribute materialAttribute = trianglesNode.Attributes["material"];
                    if (materialAttribute == null)
                    {
                        messages = new string[] { "Mesh without materials found. Skipping..." };
                        continue;
                    }
                    string  material    = materialAttribute.Value;
                    string  effect      = materialLibraryNode.SelectSingleNode("df:material[@id='" + material + "']/df:instance_effect", mgr).Attributes["url"].Value.Remove(0, 1);
                    XmlNode effectNode  = effectLibraryNode.SelectSingleNode("df:effect[@id='" + effect + "']/df:profile_COMMON", mgr);
                    XmlNode textureNode = effectNode.SelectSingleNode("df:technique/*/df:diffuse/df:texture", mgr);
                    if (textureNode == null)
                    {
                        meshSubset.Texture = allMaterials["<Undefined>"];
                    }
                    else
                    {
                        string surfaceName   = effectNode.SelectSingleNode("df:newparam[@sid='" + textureNode.Attributes["texture"].Value + "']/df:sampler2D/df:source", mgr).InnerText;
                        string init_from     = effectNode.SelectSingleNode("df:newparam[@sid='" + surfaceName + "']/df:surface/df:init_from", mgr).InnerText;
                        string imageFileName = imageLibraryNode.SelectSingleNode("df:image[@id='" + init_from + "']/df:init_from", mgr).InnerText;
                        string fullPath      = imageFileName;
                        if (imageFileName[1] != ':') //Path is not absolute. Make Absolute
                        {
                            fullPath = System.IO.Path.Combine(rootDirectory, imageFileName);
                        }
                        fullPath = Uri.UnescapeDataString(fullPath);
                        if (!allMaterials.TryGetValue(imageFileName, out meshSubset.Texture))
                        {
                            meshSubset.Texture = allMaterials[imageFileName] = new TextureInfo(fullPath);
                        }
                    }

                    int vertexOffset, normalOffset, texCoordOffset, colorOffset;
                    vertexOffset = normalOffset = texCoordOffset = colorOffset = -1;
                    Vec3[]     positions = null, normals = null;
                    TexCoord[] texCoords = null;
                    Color[]    colors    = null;

                    XmlNode vertexNode = trianglesNode.SelectSingleNode("df:input[@semantic='VERTEX']", mgr);
                    if (vertexNode != null)
                    {
                        XmlNode vertexSource = meshNode.SelectSingleNode("df:vertices[@id='" + vertexNode.Attributes["source"].Value.Remove(0, 1) + "']", mgr);
                        XmlNode vertexSourceSource /*jeez pls give me vertex positions now*/ = meshNode.SelectSingleNode("df:source[@id='" + vertexSource.SelectSingleNode("df:input[@semantic='POSITION']", mgr).Attributes["source"].Value.Remove(0, 1) + "']", mgr);
                        positions    = ReadXMLVectorNode <Vec3>(vertexSourceSource, mgr);
                        vertexOffset = int.Parse(vertexNode.Attributes["offset"].Value);
                    }

                    XmlNode normalNode = trianglesNode.SelectSingleNode("df:input[@semantic='NORMAL']", mgr);
                    if (normalNode != null)
                    {
                        XmlNode normalSource = meshNode.SelectSingleNode("df:source[@id='" + normalNode.Attributes["source"].Value.Remove(0, 1) + "']", mgr);
                        normals      = ReadXMLVectorNode <Vec3>(normalSource, mgr);
                        normalOffset = int.Parse(normalNode.Attributes["offset"].Value);
                    }

                    XmlNode texCoordNode = trianglesNode.SelectSingleNode("df:input[@semantic='TEXCOORD']", mgr);
                    if (texCoordNode != null)
                    {
                        XmlNode texCoordSource = meshNode.SelectSingleNode("df:source[@id='" + texCoordNode.Attributes["source"].Value.Remove(0, 1) + "']", mgr);
                        texCoords      = ReadXMLVectorNode <TexCoord>(texCoordSource, mgr);
                        texCoordOffset = int.Parse(texCoordNode.Attributes["offset"].Value);
                    }

                    XmlNode colorNode = trianglesNode.SelectSingleNode("df:input[@semantic='COLOR']", mgr);
                    if (colorNode != null)
                    {
                        XmlNode colorSource = meshNode.SelectSingleNode("df:source[@id='" + colorNode.Attributes["source"].Value.Remove(0, 1) + "']", mgr);
                        colors      = ReadXMLVectorNode <Color>(colorSource, mgr);
                        colorOffset = int.Parse(colorNode.Attributes["offset"].Value);
                    }

                    int[]    indices      = Array.ConvertAll(trianglesNode.SelectSingleNode("df:p", mgr).InnerText.Split(' '), (string s) => int.Parse(s));
                    Vertex[] vertices     = new Vertex[int.Parse(trianglesNode.Attributes["count"].Value) * 3];
                    int      stride       = indices.Length / vertices.Length;
                    int      currentIndex = 0;
                    Color    defaultColor = new Color();
                    defaultColor.R = defaultColor.G = defaultColor.B = defaultColor.A = 1;
                    for (int i = 0; i < vertices.Length; i++)
                    {
                        Vec3 position = positions == null ? new Vec3() : positions[indices[i * stride + vertexOffset]];
                        position = position.TransformPosition(transform);
                        Vec3 normal = normals == null ? new Vec3() : normals[indices[i * stride + normalOffset]];
                        normal = normal.TransformNormal(normalTransform);
                        TexCoord texCoord = texCoords == null ? new TexCoord() : texCoords[indices[i * stride + texCoordOffset]];
                        Color    color    = colors == null ? defaultColor : colors[indices[i * stride + colorOffset]];
                        vertices[i] = flipYZ ? new Vertex(new Vector3(position.X, position.Z, -position.Y), new Vector2(texCoord.S, texCoord.T), new Vector3(normal.X, normal.Z, -normal.Y))
                            : new Vertex(new Vector3(position.X, position.Y, position.Z), new Vector2(texCoord.S, texCoord.T), new Vector3(normal.X, normal.Y, normal.Z));
                        Color c = colors == null ? defaultColor : colors[indices[i * stride + 3]];
                        if (conversionSettings.colorInterpretation == ConversionSettings.ColorInterpretation.ReplaceNormal)
                        {
                            vertices[i].nx = (sbyte)(c.R * 255);
                            vertices[i].ny = (sbyte)(c.G * 255);
                            vertices[i].nz = (sbyte)(c.B * 255);
                            vertices[i].c  = 255;
                        }
                        else if (conversionSettings.colorInterpretation == ConversionSettings.ColorInterpretation.ConvertRedToAlpha)
                        {
                            vertices[i].c = (byte)(c.R * 255);
                        }
                        else if (conversionSettings.colorInterpretation == ConversionSettings.ColorInterpretation.ConvertGreenToAlpha)
                        {
                            vertices[i].c = (byte)(c.G * 255);
                        }
                        else if (conversionSettings.colorInterpretation == ConversionSettings.ColorInterpretation.ConvertBlueToAlpha)
                        {
                            vertices[i].c = (byte)(c.B * 255);
                        }
                        else if (conversionSettings.colorInterpretation == ConversionSettings.ColorInterpretation.ConvertRedToAlpha)
                        {
                            vertices[i].c = (byte)((c.R + c.G + c.B) / 3 * 255);
                        }

                        int k = 0;
                        foreach (Vertex v in vertexBuffer)
                        {
                            if (v.Equals(vertices[i]))
                            {
                                indexBuffer.Add(k);
                                goto skipNewVertex;
                            }
                            k++;
                        }
                        vertexBuffer.Add(vertices[i]);
                        indexBuffer.Add(currentIndex++);
                        skipNewVertex :;
                    }
                    meshSubset.IndexBuffer  = indexBuffer.ToArray();
                    meshSubset.VertexBuffer = vertexBuffer.ToArray();
                    meshSubset.CreatePatches();
                }
            }
            dsp.subsets = meshes.ToArray();
        }
示例#2
0
        public static void Read(string fileName, ConversionSettings conversionSettings, ref DisplayList dsp, out Dictionary <string, TextureInfo> allMaterials, out string[] messages)
        {
            List <string> messageList   = new List <string>();
            string        currentObject = "";

            Subset            LastFrame    = null;
            List <Subset>     Frames       = new List <Subset>();
            List <Vertex>     Vertices     = new List <Vertex>();
            List <int>        Indices      = new List <int>();
            List <FaceVertex> faceVertices = new List <FaceVertex>();

            List <Vertex> dspVertexBuffer = new List <Vertex>();
            List <int[]>  dspIndexBuffers = new List <int[]>();
            List <int>    dspTextureKeys  = new List <int>();

            int[] dspIndices;
            int   minVertexIndex = 0;

            List <Vector3> positions = new List <Vector3>();
            List <Vector2> texCoords = new List <Vector2>();
            List <Vector3> normals   = new List <Vector3>();

            allMaterials = new Dictionary <string, TextureInfo>();
            allMaterials["<Undefined>"] = new TextureInfo(null);

            string[] fileNameSplit    = fileName.Split(new char[] { '/', '\\' });
            string   fileRelativePath = fileName.Remove(fileName.Length - (fileNameSplit[fileNameSplit.Length - 1].Length), fileNameSplit[fileNameSplit.Length - 1].Length);

            if (!System.IO.File.Exists(fileName))
            {
                messages = new string[] { "File " + fileName + " was not found." };
                return;
            }
            StreamReader rd             = new StreamReader(fileName);
            StreamReader materialReader = null;

            while (!rd.EndOfStream)
            {
                string   line  = rd.ReadLine();
                string[] split = line.Split(' ');
                if (split[0] == "mtllib")
                {
                    materialReader = new StreamReader(fileRelativePath + line.Remove(0, split[0].Length + 1));
                    string currentMtl = null;
                    while (!materialReader.EndOfStream)
                    {
                        string   matLine  = materialReader.ReadLine();
                        string[] matSplit = matLine.Split(' ');
                        if (matSplit[0] == "newmtl")
                        {
                            currentMtl = matLine.Remove(0, matSplit[0].Length);
                        }
                        if (matSplit[0] == "map_Kd")
                        {
                            TextureInfo newTex;
                            string      fullPath = matLine.Remove(0, matSplit[0].Length).Trim();
                            if (fullPath[1] != ':')
                            {
                                fullPath = fileRelativePath + fullPath;
                            }
                            allMaterials.Add(currentMtl, newTex = new TextureInfo(fullPath));
                        }
                    }
                }
                else if (split[0] == "o") //Object
                {
                    if (LastFrame == null)
                    {
                        LastFrame = new Subset();
                    }
                    currentObject = split[1];
                }
                else if (split[0] == "v") // Vertex
                {
                    positions.Add(cvt.ParseVector3(split, 1));
                }
                else if (split[0] == "vn")// Vertex Normal
                {
                    normals.Add(cvt.ParseVector3(split, 1));
                }
                else if (split[0] == "vt") // Vertex TexCoord
                {
                    texCoords.Add(cvt.parseVector2(split, 1));
                }
                else if (split[0] == "usemtl")
                {
                    LastFrame.VertexBuffer = Vertices.ToArray();
                    LastFrame.IndexBuffer  = Indices.ToArray();

                    dspIndices = new int[LastFrame.IndexBuffer.Length];
                    for (int i = 0; i < LastFrame.IndexBuffer.Length; i += 3)
                    {
                        dspIndices[i]     = LastFrame.IndexBuffer[i + 2] + minVertexIndex;
                        dspIndices[i + 1] = LastFrame.IndexBuffer[i + 1] + minVertexIndex;
                        dspIndices[i + 2] = LastFrame.IndexBuffer[i] + minVertexIndex;
                    }

                    if (Indices.Count > 0)
                    {
                        dspIndexBuffers.Add(dspIndices);
                        LastFrame.CreatePatches();
                        Frames.Add(LastFrame);
                    }
                    Indices.Clear();
                    LastFrame = new Subset();
                    string mtlName = line.Remove(0, split[0].Length);
                    if (!allMaterials.TryGetValue(mtlName, out LastFrame.Texture))
                    {
                        messageList.Add("Object " + currentObject + " has unassigned faces.");
                        LastFrame.Texture = allMaterials["<Undefined>"];
                    }
                }
                else if (split[0] == "f") // Face
                {
                    int i0 = 0, ix = 0;
                    for (int i = 1; i < split.Length; i++)
                    {
                        string[]   vertexIndices = split[i].Split('/');
                        FaceVertex faceVertex    = new FaceVertex();
                        int.TryParse(vertexIndices[0], out faceVertex.Vertex);
                        if (vertexIndices.Length > 1)
                        {
                            int.TryParse(vertexIndices[1], out faceVertex.Texture);
                        }
                        if (vertexIndices.Length > 2)
                        {
                            int.TryParse(vertexIndices[2], out faceVertex.Normal);
                        }
                        int index = 0;
                        foreach (FaceVertex v in faceVertices)
                        {
                            if (v.Vertex == faceVertex.Vertex && v.Texture == faceVertex.Texture && v.Normal == faceVertex.Normal)
                            {
                                break;
                            }
                            index++;
                        }
                        if (i > 3)
                        {
                            Indices.Add(i0);
                            Indices.Add(ix);
                        }
                        Indices.Add(index);

                        if (i == 1)
                        {
                            i0 = index;
                        }
                        ix = index;
                        if (index == faceVertices.Count)
                        {
                            faceVertices.Add(faceVertex);
                            Vertex  newVertex;
                            Vector2 texCoord = Vector2.Empty;
                            if (faceVertex.Texture > 0)
                            {
                                texCoord = texCoords[faceVertex.Texture - 1];
                            }
                            Vector3 normal = Vector3.Empty;
                            if (faceVertex.Normal > 0)
                            {
                                normal = normals[faceVertex.Normal - 1];
                            }

                            Vertices.Add(newVertex = new Vertex(positions[faceVertex.Vertex - 1], texCoord, normal));
                            dspVertexBuffer.Add(newVertex);
                        }
                    }
                }
            }
            rd.BaseStream.Close();
            materialReader.Close();
            LastFrame.IndexBuffer  = Indices.ToArray();
            LastFrame.VertexBuffer = Vertices.ToArray();

            dspIndices = new int[LastFrame.IndexBuffer.Length];
            for (int i = 0; i < LastFrame.IndexBuffer.Length; i += 3)
            {
                dspIndices[i]     = LastFrame.IndexBuffer[i + 2] + minVertexIndex;
                dspIndices[i + 1] = LastFrame.IndexBuffer[i + 1] + minVertexIndex;
                dspIndices[i + 2] = LastFrame.IndexBuffer[i] + minVertexIndex;
            }
            dspIndexBuffers.Add(dspIndices);

            LastFrame.CreatePatches();
            Frames.Add(LastFrame);

            dsp.subsets = Frames.ToArray();
            messages    = messageList.ToArray();
        }