Пример #1
0
        private static void Main(string[] args)
        {
            CASC.InitCasc(null, @"C:\World of Warcraft", "wow");
            Console.WriteLine("CASC loaded!");
            var reader   = new M2Reader();
            var filename = @"item\objectcomponents\shield\shield_1h_artifactnorgannon_d_01.m2";

            reader.LoadM2(filename);
            var fileDataID = CASC.getFileDataIdByName(filename);

            for (int i = 0; i < reader.model.textures.Length; i++)
            {
                Console.WriteLine("Doing type " + reader.model.textures[i].type + " lookup for texture #" + i);
                switch (reader.model.textures[i].type)
                {
                case 1:
                case 2:
                case 11:
                    uint[] cdifilenames = DBCHelper.getTexturesByModelFilename(fileDataID, (int)reader.model.textures[i].type);
                    for (int ti = 0; ti < cdifilenames.Length; ti++)
                    {
                        Console.WriteLine("Found (texture #" + ti + ") " + cdifilenames[ti]);
                        var blpreader = new BLPReader();
                        blpreader.LoadBLP((int)cdifilenames[ti]);
                    }
                    break;

                default:
                    throw new Exception("Unhandled texture type");
                    break;
                }
            }
            Console.WriteLine("Done.");
            Console.ReadLine();
        }
Пример #2
0
        private void Form_M2Export_Load(object sender, EventArgs e)
        {
            button1.Text = "Export";
            this.Text    = filename;
            label10.Text = "Export format:";
            comboBox1.Items.AddRange(formats);
            comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
            comboBox1.SelectedIndex = 0;
            label11.Hide();

            try
            {
                M2Reader reader = new M2Reader();
                reader.LoadM2(filename);

                //Populate model details:

                label1.Text = "Version: " + reader.model.version;
                label2.Text = "Name: " + reader.model.name;
                label3.Text = "Sequences: " + reader.model.sequences.Count();
                label4.Text = "Animations: " + reader.model.animations.Count();
                label5.Text = "Bones: " + reader.model.bones.Count();
                label6.Text = "Vertices: " + reader.model.vertices.Count();
                label7.Text = "Skins: " + reader.model.skins.Count();
                label8.Text = "Textures: " + reader.model.textures.Count();
                label9.Text = "Submeshes:" + reader.model.skins[0].submeshes.Count();
            }
            catch (Exception ex)
            {
                throw new Exception("Could not read the model to display details" + " - exception: " + ex.Message);
            }
        }
Пример #3
0
        public static void ExportM2(uint fileDataID, BackgroundWorker exportWorker = null, string destinationOverride = null, string fileName = "", bool[] enabledGeosets = null)
        {
            if (!CASC.FileExists(fileDataID))
            {
                throw new Exception("404 M2 Not Found!");
            }

            var reader = new M2Reader();

            reader.LoadM2(fileDataID);

            // Default to using fileDataID as a name if nothing is provided.
            if (string.IsNullOrEmpty(fileName))
            {
                fileName = fileDataID.ToString();
            }

            ExportM2(reader, fileName, exportWorker, destinationOverride, false, enabledGeosets);
        }
Пример #4
0
        public static void ExportM2(uint fileDataID, BackgroundWorker exportworker = null, string destinationOverride = null, string filename = "")
        {
            if (exportworker == null)
            {
                exportworker = new BackgroundWorker
                {
                    WorkerReportsProgress = true
                };
            }

            var customCulture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();

            customCulture.NumberFormat.NumberDecimalSeparator    = ".";
            System.Threading.Thread.CurrentThread.CurrentCulture = customCulture;

            var outdir = ConfigurationManager.AppSettings["outdir"];
            var reader = new M2Reader();

            exportworker.ReportProgress(15, "Reading M2..");

            if (!CASC.FileExists(fileDataID))
            {
                throw new Exception("404 M2 not found!");
            }

            reader.LoadM2(fileDataID);

            // Don't export models without vertices
            if (reader.model.vertices.Count() == 0)
            {
                return;
            }

            var vertices = new Structs.Vertex[reader.model.vertices.Count()];

            for (var i = 0; i < reader.model.vertices.Count(); i++)
            {
                vertices[i].Position = new Structs.Vector3D()
                {
                    X = reader.model.vertices[i].position.X,
                    Y = reader.model.vertices[i].position.Z,
                    Z = reader.model.vertices[i].position.Y * -1
                };

                vertices[i].Normal = new Structs.Vector3D()
                {
                    X = reader.model.vertices[i].normal.X,
                    Y = reader.model.vertices[i].normal.Z,
                    Z = reader.model.vertices[i].normal.Y
                };

                vertices[i].TexCoord = new Structs.Vector2D()
                {
                    X = reader.model.vertices[i].textureCoordX,
                    Y = reader.model.vertices[i].textureCoordY
                };
            }

            StreamWriter objsw;

            if (destinationOverride == null)
            {
                if (!string.IsNullOrEmpty(filename))
                {
                    if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(filename))))
                    {
                        Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(filename)));
                    }

                    objsw = new StreamWriter(Path.Combine(outdir, filename.Replace(".m2", ".obj")));
                }
                else
                {
                    if (!Directory.Exists(outdir))
                    {
                        Directory.CreateDirectory(outdir);
                    }

                    objsw = new StreamWriter(Path.Combine(outdir, fileDataID + ".obj"));
                }
            }
            else
            {
                if (!string.IsNullOrEmpty(filename))
                {
                    objsw = new StreamWriter(Path.Combine(outdir, destinationOverride, Path.GetFileName(filename.ToLower()).Replace(".m2", ".obj")));
                }
                else
                {
                    objsw = new StreamWriter(Path.Combine(outdir, destinationOverride, fileDataID + ".obj"));
                }
            }

            if (!string.IsNullOrEmpty(filename))
            {
                objsw.WriteLine("# Written by Marlamin's WoW Export Tools. Original file: " + filename);
                objsw.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(filename) + ".mtl");
            }
            else
            {
                objsw.WriteLine("# Written by Marlamin's WoW Export Tools. Original fileDataID: " + fileDataID);
                objsw.WriteLine("mtllib " + fileDataID + ".mtl");
            }

            foreach (var vertex in vertices)
            {
                objsw.WriteLine("v " + vertex.Position.X + " " + vertex.Position.Y + " " + vertex.Position.Z);
                objsw.WriteLine("vt " + vertex.TexCoord.X + " " + (vertex.TexCoord.Y - 1) * -1);
                objsw.WriteLine("vn " + (-vertex.Normal.X).ToString("F12") + " " + vertex.Normal.Y.ToString("F12") + " " + vertex.Normal.Z.ToString("F12"));
            }

            var indicelist = new List <uint>();

            for (var i = 0; i < reader.model.skins[0].triangles.Count(); i++)
            {
                var t = reader.model.skins[0].triangles[i];
                indicelist.Add(t.pt1);
                indicelist.Add(t.pt2);
                indicelist.Add(t.pt3);
            }

            var indices = indicelist.ToArray();

            exportworker.ReportProgress(35, "Writing files..");

            var renderbatches = new Structs.RenderBatch[reader.model.skins[0].submeshes.Count()];

            for (var i = 0; i < reader.model.skins[0].submeshes.Count(); i++)
            {
                renderbatches[i].firstFace = reader.model.skins[0].submeshes[i].startTriangle;
                renderbatches[i].numFaces  = reader.model.skins[0].submeshes[i].nTriangles;
                renderbatches[i].groupID   = (uint)i;
                for (var tu = 0; tu < reader.model.skins[0].textureunit.Count(); tu++)
                {
                    if (reader.model.skins[0].textureunit[tu].submeshIndex == i)
                    {
                        renderbatches[i].blendType  = reader.model.renderflags[reader.model.skins[0].textureunit[tu].renderFlags].blendingMode;
                        renderbatches[i].materialID = reader.model.texlookup[reader.model.skins[0].textureunit[tu].texture].textureID;
                    }
                }
            }

            exportworker.ReportProgress(65, "Exporting textures..");

            StreamWriter mtlsb;

            if (destinationOverride == null)
            {
                if (!string.IsNullOrEmpty(filename))
                {
                    mtlsb = new StreamWriter(Path.Combine(outdir, filename.Replace(".m2", ".mtl")));
                }
                else
                {
                    mtlsb = new StreamWriter(Path.Combine(outdir, fileDataID + ".mtl"));
                }
            }
            else
            {
                if (!string.IsNullOrEmpty(filename))
                {
                    mtlsb = new StreamWriter(Path.Combine(outdir, destinationOverride, Path.GetFileName(filename.ToLower()).Replace(".m2", ".mtl")));
                }
                else
                {
                    mtlsb = new StreamWriter(Path.Combine(outdir, destinationOverride, fileDataID + ".mtl"));
                }
            }

            var textureID = 0;
            var materials = new Structs.Material[reader.model.textures.Count()];

            for (var i = 0; i < reader.model.textures.Count(); i++)
            {
                uint textureFileDataID = 840426;
                materials[i].flags = reader.model.textures[i].flags;
                switch (reader.model.textures[i].type)
                {
                case 0:
                    if (reader.model.textureFileDataIDs != null && reader.model.textureFileDataIDs.Length > 0 && reader.model.textureFileDataIDs[i] != 0)
                    {
                        textureFileDataID = reader.model.textureFileDataIDs[i];
                    }
                    else
                    {
                        Listfile.TryGetFileDataID(reader.model.textures[i].filename, out textureFileDataID);
                    }
                    break;

                case 1:
                case 2:
                case 11:
                default:
                    Console.WriteLine("Texture type " + reader.model.textures[i].type + " not supported, falling back to placeholder texture");
                    break;
                }

                materials[i].textureID = textureID + i;

                if (!Listfile.TryGetFilename(textureFileDataID, out var textureFilename))
                {
                    textureFilename = textureFileDataID.ToString();
                }

                materials[i].filename = Path.GetFileNameWithoutExtension(textureFilename);

                string textureSaveLocation;

                if (destinationOverride == null)
                {
                    if (!string.IsNullOrEmpty(filename))
                    {
                        textureSaveLocation = Path.Combine(outdir, Path.GetDirectoryName(filename), materials[i].filename + ".png");
                    }
                    else
                    {
                        textureSaveLocation = Path.Combine(outdir, materials[i].filename + ".png");
                    }
                }
                else
                {
                    textureSaveLocation = Path.Combine(outdir, destinationOverride, materials[i].filename + ".png");
                }

                try
                {
                    var blpreader = new BLPReader();
                    blpreader.LoadBLP(textureFileDataID);
                    blpreader.bmp.Save(textureSaveLocation);
                }
                catch (Exception e)
                {
                    CASCLib.Logger.WriteLine("Exception while saving BLP " + materials[i].filename + ": " + e.Message);
                }
            }

            exportworker.ReportProgress(85, "Writing files..");

            foreach (var material in materials)
            {
                mtlsb.WriteLine("newmtl " + material.filename);
                mtlsb.WriteLine("illum 1");
                //mtlsb.WriteLine("map_Ka " + material.filename + ".png");
                mtlsb.WriteLine("map_Kd " + material.filename + ".png");
            }

            mtlsb.Close();

            if (!string.IsNullOrEmpty(filename))
            {
                objsw.WriteLine("g " + Path.GetFileNameWithoutExtension(filename));
            }
            else
            {
                objsw.WriteLine("g " + fileDataID);
            }

            foreach (var renderbatch in renderbatches)
            {
                var i = renderbatch.firstFace;
                if (!string.IsNullOrEmpty(filename))
                {
                    objsw.WriteLine("o " + Path.GetFileNameWithoutExtension(filename) + renderbatch.groupID);
                }
                else
                {
                    objsw.WriteLine("g " + fileDataID.ToString() + renderbatch.groupID.ToString());
                }

                objsw.WriteLine("usemtl " + materials[renderbatch.materialID].filename);
                objsw.WriteLine("s 1");
                while (i < (renderbatch.firstFace + renderbatch.numFaces))
                {
                    objsw.WriteLine("f " + (indices[i] + 1) + "/" + (indices[i] + 1) + "/" + (indices[i] + 1) + " " + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + " " + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1));
                    i = i + 3;
                }
            }

            objsw.Close();

            // Only export phys when exporting a single M2, causes issues for some users when combined with WMO/ADT
            if (destinationOverride == null)
            {
                exportworker.ReportProgress(90, "Exporting collision..");

                if (!string.IsNullOrEmpty(filename))
                {
                    objsw = new StreamWriter(Path.Combine(outdir, Path.GetFileName(filename.ToLower()).Replace(".m2", ".phys.obj")));
                }
                else
                {
                    objsw = new StreamWriter(Path.Combine(outdir, fileDataID + ".phys.obj"));
                }

                objsw.WriteLine("# Written by Marlamin's WoW Export Tools. Original file id: " + fileDataID);

                for (var i = 0; i < reader.model.boundingvertices.Count(); i++)
                {
                    objsw.WriteLine("v " +
                                    reader.model.boundingvertices[i].vertex.X + " " +
                                    reader.model.boundingvertices[i].vertex.Z + " " +
                                    -reader.model.boundingvertices[i].vertex.Y);
                }

                for (var i = 0; i < reader.model.boundingtriangles.Count(); i++)
                {
                    var t = reader.model.boundingtriangles[i];
                    objsw.WriteLine("f " + (t.index_0 + 1) + " " + (t.index_1 + 1) + " " + (t.index_2 + 1));
                }

                objsw.Close();
            }

            // https://en.wikipedia.org/wiki/Wavefront_.obj_file#Basic_materials
            // http://wiki.unity3d.com/index.php?title=ExportOBJ
            // http://web.cse.ohio-state.edu/~hwshen/581/Site/Lab3_files/Labhelp_Obj_parser.htm
        }
Пример #5
0
        public static void LoadM2(string filename, CacheStorage cache, int modelShader)
        {
            filename = filename.ToLower().Replace(".mdx", ".m2");
            filename = filename.ToLower().Replace(".mdl", ".m2");

            if (cache.doodadBatches.ContainsKey(filename))
            {
                return;
            }

            WoWFormatLib.Structs.M2.M2Model model = new WoWFormatLib.Structs.M2.M2Model();

            if (cache.models.ContainsKey(filename))
            {
                model = cache.models[filename];
            }
            else
            {
                //Load model from file
                if (WoWFormatLib.Utils.CASC.FileExists(filename))
                {
                    var modelreader = new M2Reader();
                    modelreader.LoadM2(filename);
                    cache.models.Add(filename, modelreader.model);
                    model = modelreader.model;
                }
                else
                {
                    throw new Exception("Model " + filename + " does not exist!");
                }
            }

            var ddBatch = new DoodadBatch();

            // Textures
            ddBatch.mats = new Material[model.textures.Count()];

            for (int i = 0; i < model.textures.Count(); i++)
            {
                string texturefilename = model.textures[i].filename;
                ddBatch.mats[i].flags = model.textures[i].flags;

                switch (model.textures[i].type)
                {
                case 0:
                    // Console.WriteLine("      Texture given in file!");
                    texturefilename = model.textures[i].filename;
                    break;

                case 1:
                    string[] csfilenames = WoWFormatLib.DBC.DBCHelper.getTexturesByModelFilename(filename, (int)model.textures[i].type, i);
                    if (csfilenames.Count() > 0)
                    {
                        texturefilename = csfilenames[0];
                    }
                    else
                    {
                        //Console.WriteLine("      No type 1 texture found, falling back to placeholder texture");
                    }
                    break;

                case 2:
                    if (WoWFormatLib.Utils.CASC.FileExists(System.IO.Path.ChangeExtension(filename, ".blp")))
                    {
                        // Console.WriteLine("      BLP exists!");
                        texturefilename = System.IO.Path.ChangeExtension(filename, ".blp");
                    }
                    else
                    {
                        //Console.WriteLine("      Type 2 does not exist!");
                        //needs lookup?
                    }
                    break;

                case 11:
                    string[] cdifilenames = WoWFormatLib.DBC.DBCHelper.getTexturesByModelFilename(filename, (int)model.textures[i].type);
                    for (int ti = 0; ti < cdifilenames.Count(); ti++)
                    {
                        if (WoWFormatLib.Utils.CASC.FileExists(filename.Replace(model.name + ".M2", cdifilenames[ti] + ".blp")))
                        {
                            texturefilename = filename.Replace(model.name + ".M2", cdifilenames[ti] + ".blp");
                        }
                    }
                    break;

                default:
                    //Console.WriteLine("      Falling back to placeholder texture");
                    texturefilename = "Dungeons\\Textures\\testing\\COLOR_13.blp";
                    break;
                }
                ddBatch.mats[i].textureID = BLPLoader.LoadTexture(texturefilename, cache);
                ddBatch.mats[i].filename  = texturefilename;
            }

            // Submeshes
            ddBatch.submeshes = new Submesh[model.skins[0].submeshes.Count()];
            for (int i = 0; i < model.skins[0].submeshes.Count(); i++)
            {
                if (filename.StartsWith("character"))
                {
                    if (model.skins[0].submeshes[i].submeshID != 0)
                    {
                        if (!model.skins[0].submeshes[i].submeshID.ToString().EndsWith("01"))
                        {
                            continue;
                        }
                    }
                }

                ddBatch.submeshes[i].firstFace = model.skins[0].submeshes[i].startTriangle;
                ddBatch.submeshes[i].numFaces  = model.skins[0].submeshes[i].nTriangles;
                for (int tu = 0; tu < model.skins[0].textureunit.Count(); tu++)
                {
                    if (model.skins[0].textureunit[tu].submeshIndex == i)
                    {
                        ddBatch.submeshes[i].blendType = model.renderflags[model.skins[0].textureunit[tu].renderFlags].blendingMode;
                        if (!cache.materials.ContainsKey(model.textures[model.texlookup[model.skins[0].textureunit[tu].texture].textureID].filename.ToLower()))
                        {
                            throw new Exception("MaterialCache does not have texture " + model.textures[model.texlookup[model.skins[0].textureunit[tu].texture].textureID].filename.ToLower());
                        }

                        ddBatch.submeshes[i].material = (uint)cache.materials[model.textures[model.texlookup[model.skins[0].textureunit[tu].texture].textureID].filename.ToLower()];
                    }
                }
            }

            ddBatch.vao = GL.GenVertexArray();
            GL.BindVertexArray(ddBatch.vao);

            // Vertices & indices
            ddBatch.vertexBuffer = GL.GenBuffer();
            ddBatch.indiceBuffer = GL.GenBuffer();

            GL.BindBuffer(BufferTarget.ArrayBuffer, ddBatch.vertexBuffer);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, ddBatch.indiceBuffer);

            List <uint> modelindicelist = new List <uint>();

            for (int i = 0; i < model.skins[0].triangles.Count(); i++)
            {
                modelindicelist.Add(model.skins[0].triangles[i].pt1);
                modelindicelist.Add(model.skins[0].triangles[i].pt2);
                modelindicelist.Add(model.skins[0].triangles[i].pt3);
            }

            uint[] modelindices = modelindicelist.ToArray();

            //Console.WriteLine(modelindicelist.Count() + " indices!");
            ddBatch.indices = modelindices;

            GL.BindBuffer(BufferTarget.ElementArrayBuffer, ddBatch.indiceBuffer);
            GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(ddBatch.indices.Length * sizeof(uint)), ddBatch.indices, BufferUsageHint.StaticDraw);

            M2Vertex[] modelvertices = new M2Vertex[model.vertices.Count()];

            for (int i = 0; i < model.vertices.Count(); i++)
            {
                modelvertices[i].Position = new Vector3(model.vertices[i].position.X, model.vertices[i].position.Y, model.vertices[i].position.Z);
                modelvertices[i].Normal   = new Vector3(model.vertices[i].normal.X, model.vertices[i].normal.Y, model.vertices[i].normal.Z);
                modelvertices[i].TexCoord = new Vector2(model.vertices[i].textureCoordX, model.vertices[i].textureCoordY);
            }
            GL.BindBuffer(BufferTarget.ArrayBuffer, ddBatch.vertexBuffer);
            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(modelvertices.Length * 8 * sizeof(float)), modelvertices, BufferUsageHint.StaticDraw);

            var texCoordLoc = GL.GetAttribLocation(modelShader, "vTexCoord");

            GL.EnableVertexAttribArray(texCoordLoc);
            GL.VertexAttribPointer(texCoordLoc, 2, VertexAttribPointerType.Float, false, 8 * sizeof(float), 3 * sizeof(float));

            var posLoc = GL.GetAttribLocation(modelShader, "vPosition");

            GL.EnableVertexAttribArray(posLoc);
            GL.VertexAttribPointer(posLoc, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 5 * sizeof(float));

            GL.BindVertexArray(0);

            cache.doodadBatches.Add(filename, ddBatch);
        }
Пример #6
0
        public static void ExportM2(string filename, string outdir, BackgroundWorker exportworker = null, string destinationOverride = null)
        {
            if (exportworker == null)
            {
                exportworker = new BackgroundWorker
                {
                    WorkerReportsProgress = true
                };
            }

            filename = filename.ToLower();

            var customCulture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();

            customCulture.NumberFormat.NumberDecimalSeparator    = ".";
            System.Threading.Thread.CurrentThread.CurrentCulture = customCulture;

            var reader = new M2Reader();

            exportworker.ReportProgress(15, "Reading M2..");

            //If the missing file is an ".mdx", try to look for a ".m2" alternative
            if (!Managers.ArchiveManager.FileExists(filename))
            {
                if (Path.GetExtension(filename) == ".mdx")
                {
                    if (!Managers.ArchiveManager.FileExists(filename.Replace(".mdx", ".m2")))
                    {
                        throw new Exception("404 M2 not found!");
                    }
                    else
                    {
                        filename = filename.Replace(".mdx", ".m2");
                    }
                }
                else
                {
                    throw new Exception("404 M2 not found!");
                }
            }

            reader.LoadM2(filename);

            // Don't export models without vertices
            if (reader.model.vertices.Count() == 0)
            {
                return;
            }

            var vertices = new Structs.Vertex[reader.model.vertices.Count()];

            for (var i = 0; i < reader.model.vertices.Count(); i++)
            {
                vertices[i].Position = new Structs.Vector3D()
                {
                    X = reader.model.vertices[i].position.X,
                    Y = reader.model.vertices[i].position.Z,
                    Z = reader.model.vertices[i].position.Y * -1
                };

                vertices[i].Normal = new Structs.Vector3D()
                {
                    X = reader.model.vertices[i].normal.X,
                    Y = reader.model.vertices[i].normal.Z,
                    Z = reader.model.vertices[i].normal.Y
                };

                vertices[i].TexCoord = new Structs.Vector2D()
                {
                    X = reader.model.vertices[i].textureCoordX,
                    Y = reader.model.vertices[i].textureCoordY
                };
            }

            StreamWriter objsw;

            if (destinationOverride == null)
            {
                if (!string.IsNullOrEmpty(filename))
                {
                    if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(filename))))
                    {
                        Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(filename)));
                    }

                    objsw = new StreamWriter(Path.Combine(outdir, filename.Replace(".m2", ".obj")));
                }
                else
                {
                    if (!Directory.Exists(outdir))
                    {
                        Directory.CreateDirectory(outdir);
                    }

                    objsw = new StreamWriter(Path.Combine(outdir, filename + ".obj"));
                }
            }
            else
            {
                if (!string.IsNullOrEmpty(filename))
                {
                    objsw = new StreamWriter(Path.Combine(outdir, destinationOverride, Path.GetFileName(filename.ToLower()).Replace(".m2", ".obj")));
                }
                else
                {
                    objsw = new StreamWriter(Path.Combine(outdir, destinationOverride, filename + ".obj"));
                }
            }

            if (!string.IsNullOrEmpty(filename))
            {
                objsw.WriteLine("# Written by Marlamin's WoW Export Tools. Original file: " + filename);
                objsw.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(filename) + ".mtl");
            }
            else
            {
                objsw.WriteLine("# Written by Marlamin's WoW Export Tools. Original fileDataID: " + filename);
                objsw.WriteLine("mtllib " + filename + ".mtl");
            }

            //Added thunderysteak's adjustment (original commit: ed067c7c6e8321c33ef0f3679d33c9c472dcefc3)
            foreach (var vertex in vertices)
            {
                objsw.WriteLine("v " + -vertex.Position.X + " " + vertex.Position.Y + " " + -vertex.Position.Z);
            }
            foreach (var vertex in vertices)
            {
                objsw.WriteLine("vt " + vertex.TexCoord.X + " " + (vertex.TexCoord.Y - 1) * -1);
            }
            foreach (var vertex in vertices)
            {
                objsw.WriteLine("vn " + (-vertex.Normal.X).ToString("F12") + " " + vertex.Normal.Y.ToString("F12") + " " + vertex.Normal.Z.ToString("F12"));
            }

            var indicelist = new List <uint>();

            for (var i = 0; i < reader.model.skins[0].triangles.Count(); i++)
            {
                var t = reader.model.skins[0].triangles[i];
                indicelist.Add(t.pt1);
                indicelist.Add(t.pt2);
                indicelist.Add(t.pt3);
            }

            var indices = indicelist.ToArray();

            exportworker.ReportProgress(35, "Writing files..");

            var renderbatches = new Structs.RenderBatch[reader.model.skins[0].submeshes.Count()];

            for (var i = 0; i < reader.model.skins[0].submeshes.Count(); i++)
            {
                renderbatches[i].firstFace = reader.model.skins[0].submeshes[i].startTriangle;
                renderbatches[i].numFaces  = reader.model.skins[0].submeshes[i].nTriangles;
                renderbatches[i].groupID   = (uint)i;
                for (var tu = 0; tu < reader.model.skins[0].textureunit.Count(); tu++)
                {
                    if (reader.model.skins[0].textureunit[tu].submeshIndex == i)
                    {
                        renderbatches[i].blendType  = reader.model.renderflags[reader.model.skins[0].textureunit[tu].renderFlags].blendingMode;
                        renderbatches[i].materialID = reader.model.texlookup[reader.model.skins[0].textureunit[tu].texture].textureID;
                    }
                }
            }

            exportworker.ReportProgress(65, "Exporting textures..");

            StreamWriter mtlsb;

            if (destinationOverride == null)
            {
                if (!string.IsNullOrEmpty(filename))
                {
                    mtlsb = new StreamWriter(Path.Combine(outdir, filename.Replace(".m2", ".mtl")));
                }
                else
                {
                    mtlsb = new StreamWriter(Path.Combine(outdir, filename + ".mtl"));
                }
            }
            else
            {
                if (!string.IsNullOrEmpty(filename))
                {
                    mtlsb = new StreamWriter(Path.Combine(outdir, destinationOverride, Path.GetFileName(filename.ToLower()).Replace(".m2", ".mtl")));
                }
                else
                {
                    mtlsb = new StreamWriter(Path.Combine(outdir, destinationOverride, filename + ".mtl"));
                }
            }

            var textureID = 0;
            var materials = new Structs.Material[reader.model.textures.Count()];


            for (var i = 0; i < reader.model.textures.Count(); i++)
            {
                //uint textureFileDataID = 840426;
                string textureUsed = @"Test\QA_TEST_BLP_1.blp"; //Placeholder
                materials[i].flags = reader.model.textures[i].flags;
                switch (reader.model.textures[i].type)
                {
                case 0:
                    textureUsed = reader.model.textures[i].filename;
                    break;

                case 1:
                case 2:
                case 11:
                default:
                    //Falling back to placeholder texture
                    break;
                }

                materials[i].textureID = textureID + i;
                materials[i].filename  = Path.GetFileNameWithoutExtension(textureUsed);

                string textureSaveLocation;

                if (destinationOverride == null)
                {
                    if (!string.IsNullOrEmpty(filename))
                    {
                        textureSaveLocation = Path.Combine(outdir, Path.GetDirectoryName(filename), materials[i].filename + ".png");
                    }
                    else
                    {
                        textureSaveLocation = Path.Combine(outdir, materials[i].filename + ".png");
                    }
                }
                else
                {
                    textureSaveLocation = Path.Combine(outdir, destinationOverride, materials[i].filename + ".png");
                }

                try
                {
                    var blpreader = new BLPReader();
                    blpreader.LoadBLP(Managers.ArchiveManager.ReadThisFile(textureUsed));
                    blpreader.bmp.Save(textureSaveLocation);
                }
                catch
                {
                    //Error on file save
                }
            }

            exportworker.ReportProgress(85, "Writing files..");

            foreach (var material in materials)
            {
                mtlsb.WriteLine("newmtl " + material.filename);
                mtlsb.WriteLine("illum 1");
                mtlsb.WriteLine("map_Kd " + material.filename + ".png");
            }

            mtlsb.Close();

            if (!string.IsNullOrEmpty(filename))
            {
                objsw.WriteLine("g " + Path.GetFileNameWithoutExtension(filename));
            }
            else
            {
                objsw.WriteLine("g " + filename);
            }

            foreach (var renderbatch in renderbatches)
            {
                var i = renderbatch.firstFace;
                if (!string.IsNullOrEmpty(filename))
                {
                    objsw.WriteLine("o " + Path.GetFileNameWithoutExtension(filename) + renderbatch.groupID);
                }
                else
                {
                    objsw.WriteLine("g " + filename + renderbatch.groupID.ToString());
                }

                objsw.WriteLine("usemtl " + materials[renderbatch.materialID].filename);
                objsw.WriteLine("s 1");
                while (i < (renderbatch.firstFace + renderbatch.numFaces))
                {
                    objsw.WriteLine("f " + (indices[i] + 1) + "/" + (indices[i] + 1) + "/" + (indices[i] + 1) + " " + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + " " + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1));
                    i += 3;
                }
            }

            objsw.Close();

            //COLLISION MODEL -- not implemented

            /*
             * // Only export phys when exporting a single M2, causes issues for some users when combined with WMO/ADT
             * if (destinationOverride == null)
             * {
             *  //exportworker.ReportProgress(90, "Exporting collision..");
             *
             *  if (!string.IsNullOrEmpty(filename))
             *  {
             *      objsw = new StreamWriter(Path.Combine(outdir, Path.GetFileName(filename.ToLower()).Replace(".m2", ".phys.obj")));
             *  }
             *  else
             *  {
             *      //objsw = new StreamWriter(Path.Combine(outdir, fileDataID + ".phys.obj"));
             *      objsw = new StreamWriter(Path.Combine(outdir, filename + ".phys.obj"));
             *  }
             *
             *  //objsw.WriteLine("# Written by Marlamin's WoW Export Tools. Original file id: " + fileDataID);
             *  objsw.WriteLine("# Written by Marlamin's WoW Export Tools. Original file id: " + filename);
             *
             *  for (var i = 0; i < reader.model.boundingvertices.Count(); i++)
             *  {
             *      objsw.WriteLine("v " +
             *           reader.model.boundingvertices[i].vertex.X + " " +
             *           reader.model.boundingvertices[i].vertex.Z + " " +
             *          -reader.model.boundingvertices[i].vertex.Y);
             *  }
             *
             *  for (var i = 0; i < reader.model.boundingtriangles.Count(); i++)
             *  {
             *      var t = reader.model.boundingtriangles[i];
             *      objsw.WriteLine("f " + (t.index_0 + 1) + " " + (t.index_1 + 1) + " " + (t.index_2 + 1));
             *  }
             *
             *  objsw.Close();
             * }
             */

            // https://en.wikipedia.org/wiki/Wavefront_.obj_file#Basic_materials
            // http://wiki.unity3d.com/index.php?title=ExportOBJ
            // http://web.cse.ohio-state.edu/~hwshen/581/Site/Lab3_files/Labhelp_Obj_parser.htm
        }
Пример #7
0
        public void LoadM2()
        {
            //Load model
            M2Reader reader   = new M2Reader(basedir);
            string   filename = modelPath;

            reader.LoadM2(filename);

            //Load vertices
            List <float> verticelist = new List <float>();

            for (int i = 0; i < reader.model.vertices.Count(); i++)
            {
                verticelist.Add(reader.model.vertices[i].position.X);
                verticelist.Add(reader.model.vertices[i].position.Z * -1);
                verticelist.Add(reader.model.vertices[i].position.Y);
                verticelist.Add(1.0f);
                verticelist.Add(reader.model.vertices[i].normal.X);
                verticelist.Add(reader.model.vertices[i].normal.Z * -1);
                verticelist.Add(reader.model.vertices[i].normal.Y);
                verticelist.Add(reader.model.vertices[i].textureCoordX);
                verticelist.Add(reader.model.vertices[i].textureCoordY);
            }

            //Load indices
            List <ushort> indicelist = new List <ushort>();

            for (int i = 0; i < reader.model.skins[0].triangles.Count(); i++)
            {
                indicelist.Add(reader.model.skins[0].triangles[i].pt1);
                indicelist.Add(reader.model.skins[0].triangles[i].pt2);
                indicelist.Add(reader.model.skins[0].triangles[i].pt3);
            }

            //Convert to array
            ushort[] indices  = indicelist.ToArray();
            float[]  vertices = verticelist.ToArray();

            //Get texture, what a mess this could be much better

            M2Material[] materials = new M2Material[reader.model.textures.Count()];
            for (int i = 0; i < reader.model.textures.Count(); i++)
            {
                materials[i].flags = reader.model.textures[i].flags;

                var blp = new BLPReader(basedir);
                if (File.Exists(Path.Combine(basedir, reader.model.filename.Replace("M2", "blp"))))
                {
                    blp.LoadBLP(reader.model.filename.Replace("M2", "blp"));
                }
                else
                {
                    blp.LoadBLP(reader.model.textures[i].filename);
                }

                if (blp.bmp == null)
                {
                    materials[i].texture = Texture2D.FromFile <Texture2D>(device, "missingtexture.jpg");
                }
                else
                {
                    MemoryStream s = new MemoryStream();
                    blp.bmp.Save(s, System.Drawing.Imaging.ImageFormat.Png);
                    s.Seek(0, SeekOrigin.Begin);
                    materials[i].texture = Texture2D.FromMemory <Texture2D>(device, s.ToArray());
                }
            }

            M2RenderBatch[] renderbatches = new M2RenderBatch[reader.model.skins[0].submeshes.Count()];
            for (int i = 0; i < reader.model.skins[0].submeshes.Count(); i++)
            {
                renderbatches[i].firstFace = reader.model.skins[0].submeshes[i].startTriangle;
                renderbatches[i].numFaces  = reader.model.skins[0].submeshes[i].nTriangles;
                for (int tu = 0; tu < reader.model.skins[0].textureunit.Count(); tu++)
                {
                    if (reader.model.skins[0].textureunit[tu].submeshIndex == i)
                    {
                        renderbatches[i].materialID = reader.model.skins[0].textureunit[tu].texture;
                    }
                }
            }

            m2.indices       = indices;
            m2.vertices      = vertices;
            m2.materials     = materials;
            m2.renderBatches = renderbatches;
        }
Пример #8
0
        public static void LoadM2(string filename, CacheStorage cache)
        {
            filename = filename.ToLower().Replace(".mdx", ".m2");
            filename = filename.ToLower().Replace(".mdl", ".m2");

            if (cache.doodadBatches.ContainsKey(filename))
            {
                return;
            }

            var fileDataID = CASC.getFileDataIdByName(filename);

            WoWFormatLib.Structs.M2.M2Model model = new WoWFormatLib.Structs.M2.M2Model();

            if (cache.models.ContainsKey(filename))
            {
                model = cache.models[filename];
            }
            else
            {
                //Load model from file
                if (CASC.cascHandler.FileExists(filename))
                {
                    var modelreader = new M2Reader();
                    modelreader.LoadM2(filename);
                    cache.models.Add(filename, modelreader.model);
                    model = modelreader.model;
                }
                else
                {
                    throw new Exception("Model " + filename + " does not exist!");
                }
            }

            var ddBatch = new TerrainWindow.DoodadBatch();

            // Textures
            ddBatch.mats = new TerrainWindow.Material[model.textures.Count()];

            // Always load error texture
            BLPLoader.LoadTexture(CASC.getFileDataIdByName(@"test/qa_test_blp_1.blp"), cache);
            for (int i = 0; i < model.textures.Count(); i++)
            {
                int textureFileDataID = 840426;
                ddBatch.mats[i].flags = model.textures[i].flags;

                switch (model.textures[i].type)
                {
                case 0:
                    // Console.WriteLine("      Texture given in file!");
                    textureFileDataID = CASC.getFileDataIdByName(model.textures[i].filename);
                    break;

                case 1:
                    uint[] csfilenames = WoWFormatLib.DBC.DBCHelper.getTexturesByModelFilename(fileDataID, (int)model.textures[i].type, i);
                    if (csfilenames.Count() > 0)
                    {
                        textureFileDataID = (int)csfilenames[0];
                    }
                    else
                    {
                        //Console.WriteLine("      No type 1 texture found, falling back to placeholder texture");
                    }
                    break;

                case 2:
                    if (WoWFormatLib.Utils.CASC.cascHandler.FileExists(System.IO.Path.ChangeExtension(filename, ".blp")))
                    {
                        // Console.WriteLine("      BLP exists!");
                        textureFileDataID = CASC.getFileDataIdByName(System.IO.Path.ChangeExtension(filename, ".blp"));
                    }
                    else
                    {
                        //Console.WriteLine("      Type 2 does not exist!");
                        //needs lookup?
                    }
                    break;

                case 11:
                    uint[] cdifilenames = WoWFormatLib.DBC.DBCHelper.getTexturesByModelFilename(fileDataID, (int)model.textures[i].type);
                    for (int ti = 0; ti < cdifilenames.Count(); ti++)
                    {
                        textureFileDataID = (int)cdifilenames[ti];
                    }
                    break;

                default:
                    textureFileDataID = 840426;
                    break;
                }
                ddBatch.mats[i].textureID = BLPLoader.LoadTexture(textureFileDataID, cache);
                ddBatch.mats[i].filename  = textureFileDataID.ToString();
            }

            // Submeshes
            ddBatch.submeshes = new TerrainWindow.Submesh[model.skins[0].submeshes.Count()];
            for (int i = 0; i < model.skins[0].submeshes.Count(); i++)
            {
                if (filename.StartsWith("character"))
                {
                    if (model.skins[0].submeshes[i].submeshID != 0)
                    {
                        if (!model.skins[0].submeshes[i].submeshID.ToString().EndsWith("01"))
                        {
                            continue;
                        }
                    }
                }

                ddBatch.submeshes[i].firstFace = model.skins[0].submeshes[i].startTriangle;
                ddBatch.submeshes[i].numFaces  = model.skins[0].submeshes[i].nTriangles;
                for (int tu = 0; tu < model.skins[0].textureunit.Count(); tu++)
                {
                    if (model.skins[0].textureunit[tu].submeshIndex == i)
                    {
                        ddBatch.submeshes[i].blendType = model.renderflags[model.skins[0].textureunit[tu].renderFlags].blendingMode;
                        if (!cache.materials.ContainsKey(CASC.getFileDataIdByName(model.textures[model.texlookup[model.skins[0].textureunit[tu].texture].textureID].filename).ToString()))
                        {
                            throw new Exception("MaterialCache does not have texture " + model.textures[model.texlookup[model.skins[0].textureunit[tu].texture].textureID].filename.ToLower());
                        }

                        ddBatch.submeshes[i].material = (uint)cache.materials[CASC.getFileDataIdByName(model.textures[model.texlookup[model.skins[0].textureunit[tu].texture].textureID].filename.ToLower()).ToString()];
                    }
                }
            }

            // Vertices & indices
            ddBatch.vertexBuffer = GL.GenBuffer();
            ddBatch.indiceBuffer = GL.GenBuffer();

            GL.BindBuffer(BufferTarget.ArrayBuffer, ddBatch.vertexBuffer);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, ddBatch.indiceBuffer);

            List <uint> modelindicelist = new List <uint>();

            for (int i = 0; i < model.skins[0].triangles.Count(); i++)
            {
                modelindicelist.Add(model.skins[0].triangles[i].pt1);
                modelindicelist.Add(model.skins[0].triangles[i].pt2);
                modelindicelist.Add(model.skins[0].triangles[i].pt3);
            }

            uint[] modelindices = modelindicelist.ToArray();

            //Console.WriteLine(modelindicelist.Count() + " indices!");
            ddBatch.indices = modelindices;

            GL.BindBuffer(BufferTarget.ElementArrayBuffer, ddBatch.indiceBuffer);
            GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(ddBatch.indices.Length * sizeof(uint)), ddBatch.indices, BufferUsageHint.StaticDraw);

            TerrainWindow.M2Vertex[] modelvertices = new TerrainWindow.M2Vertex[model.vertices.Count()];

            for (int i = 0; i < model.vertices.Count(); i++)
            {
                modelvertices[i].Position = new OpenTK.Vector3(model.vertices[i].position.X, model.vertices[i].position.Y, model.vertices[i].position.Z);
                modelvertices[i].Normal   = new OpenTK.Vector3(model.vertices[i].normal.X, model.vertices[i].normal.Y, model.vertices[i].normal.Z);
                modelvertices[i].TexCoord = new Vector2(model.vertices[i].textureCoordX, model.vertices[i].textureCoordY);
            }
            GL.BindBuffer(BufferTarget.ArrayBuffer, ddBatch.vertexBuffer);
            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(modelvertices.Length * 8 * sizeof(float)), modelvertices, BufferUsageHint.StaticDraw);

            cache.doodadBatches.Add(filename, ddBatch);
        }
Пример #9
0
        public static void exportM2(string file, BackgroundWorker exportworker = null, string destinationOverride = null)
        {
            if (exportworker == null)
            {
                exportworker = new BackgroundWorker();
                exportworker.WorkerReportsProgress = true;
            }

            System.Globalization.CultureInfo customCulture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
            customCulture.NumberFormat.NumberDecimalSeparator    = ".";
            System.Threading.Thread.CurrentThread.CurrentCulture = customCulture;

            var fileDataID = CASC.getFileDataIdByName(file);
            var outdir     = ConfigurationManager.AppSettings["outdir"];
            var reader     = new M2Reader();

            exportworker.ReportProgress(15, "Reading M2..");

            if (!CASC.cascHandler.FileExists(fileDataID))
            {
                throw new Exception("404 M2 not found!");
            }

            reader.LoadM2(fileDataID);

            // Don't export models without vertices
            if (reader.model.vertices.Count() == 0)
            {
                return;
            }

            Structs.Vertex[] vertices = new Structs.Vertex[reader.model.vertices.Count()];

            for (int i = 0; i < reader.model.vertices.Count(); i++)
            {
                vertices[i].Position = new OpenTK.Vector3(reader.model.vertices[i].position.X, reader.model.vertices[i].position.Z, reader.model.vertices[i].position.Y * -1);
                vertices[i].Normal   = new OpenTK.Vector3(reader.model.vertices[i].normal.X, reader.model.vertices[i].normal.Z, reader.model.vertices[i].normal.Y);
                vertices[i].TexCoord = new Vector2(reader.model.vertices[i].textureCoordX, reader.model.vertices[i].textureCoordY);
            }

            StreamWriter objsw;

            if (destinationOverride == null)
            {
                // Create output directory
                if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(file))))
                {
                    Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file)));
                }

                objsw = new StreamWriter(Path.Combine(outdir, file.Replace(".m2", ".obj")));
            }
            else
            {
                objsw = new StreamWriter(Path.Combine(outdir, destinationOverride, Path.GetFileName(file.ToLower()).Replace(".m2", ".obj")));
            }

            objsw.WriteLine("# Written by Marlamin's WoW Exporter. Original file: " + file);
            objsw.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(file) + ".mtl");

            foreach (var vertex in vertices)
            {
                objsw.WriteLine("v " + vertex.Position.X + " " + vertex.Position.Y + " " + vertex.Position.Z);
                objsw.WriteLine("vt " + vertex.TexCoord.X + " " + -vertex.TexCoord.Y);
                objsw.WriteLine("vn " + vertex.Normal.X.ToString("F12") + " " + vertex.Normal.Y.ToString("F12") + " " + vertex.Normal.Z.ToString("F12"));
            }

            List <uint> indicelist = new List <uint>();

            for (int i = 0; i < reader.model.skins[0].triangles.Count(); i++)
            {
                var t = reader.model.skins[0].triangles[i];
                indicelist.Add(t.pt1);
                indicelist.Add(t.pt2);
                indicelist.Add(t.pt3);
            }

            var indices = indicelist.ToArray();

            exportworker.ReportProgress(35, "Writing files..");

            var renderbatches = new Structs.RenderBatch[reader.model.skins[0].submeshes.Count()];

            for (int i = 0; i < reader.model.skins[0].submeshes.Count(); i++)
            {
                if (file.StartsWith("character", StringComparison.CurrentCultureIgnoreCase))
                {
                    if (reader.model.skins[0].submeshes[i].submeshID != 0)
                    {
                        if (!reader.model.skins[0].submeshes[i].submeshID.ToString().EndsWith("01"))
                        {
                            continue;
                        }
                    }
                }

                renderbatches[i].firstFace = reader.model.skins[0].submeshes[i].startTriangle;
                renderbatches[i].numFaces  = reader.model.skins[0].submeshes[i].nTriangles;
                renderbatches[i].groupID   = (uint)i;
                for (int tu = 0; tu < reader.model.skins[0].textureunit.Count(); tu++)
                {
                    if (reader.model.skins[0].textureunit[tu].submeshIndex == i)
                    {
                        renderbatches[i].blendType  = reader.model.renderflags[reader.model.skins[0].textureunit[tu].renderFlags].blendingMode;
                        renderbatches[i].materialID = reader.model.texlookup[reader.model.skins[0].textureunit[tu].texture].textureID;
                    }
                }
            }

            exportworker.ReportProgress(65, "Exporting textures..");

            StreamWriter mtlsb;

            if (destinationOverride == null)
            {
                mtlsb = new StreamWriter(Path.Combine(outdir, file.Replace(".m2", ".mtl")));
            }
            else
            {
                mtlsb = new StreamWriter(Path.Combine(outdir, destinationOverride, Path.GetFileName(file.ToLower()).Replace(".m2", ".mtl")));
            }

            var textureID = 0;
            var materials = new Structs.Material[reader.model.textures.Count()];

            for (int i = 0; i < reader.model.textures.Count(); i++)
            {
                int textureFileDataID = 840426;
                materials[i].flags = reader.model.textures[i].flags;
                switch (reader.model.textures[i].type)
                {
                case 0:
                    //Console.WriteLine("      Texture given in file!");
                    textureFileDataID = CASC.getFileDataIdByName(reader.model.textures[i].filename);
                    break;

                case 1:
                case 2:
                case 11:
                    uint[] cdifilenames = WoWFormatLib.DBC.DBCHelper.getTexturesByModelFilename(fileDataID, (int)reader.model.textures[i].type);
                    for (int ti = 0; ti < cdifilenames.Count(); ti++)
                    {
                        textureFileDataID = (int)cdifilenames[0];
                    }
                    break;

                default:
                    Console.WriteLine("      Falling back to placeholder texture");
                    break;
                }

                materials[i].textureID = textureID + i;
                materials[i].filename  = textureFileDataID.ToString();

                var blpreader = new BLPReader();

                blpreader.LoadBLP(textureFileDataID);

                try
                {
                    if (destinationOverride == null)
                    {
                        blpreader.bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(file), "tex_" + materials[i].filename + ".png"));
                    }
                    else
                    {
                        blpreader.bmp.Save(Path.Combine(outdir, destinationOverride, "tex_" + materials[i].filename.ToLower() + ".png"));
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
            }

            exportworker.ReportProgress(85, "Writing files..");

            foreach (var material in materials)
            {
                mtlsb.WriteLine("newmtl " + "tex_" + material.filename);
                mtlsb.WriteLine("illum 2");
                mtlsb.WriteLine("map_Ka " + "tex_" + material.filename + ".png");
                mtlsb.WriteLine("map_Kd " + "tex_" + material.filename + ".png");
            }

            mtlsb.Close();

            objsw.WriteLine("g " + Path.GetFileNameWithoutExtension(file));

            foreach (var renderbatch in renderbatches)
            {
                var i = renderbatch.firstFace;
                objsw.WriteLine("o " + Path.GetFileNameWithoutExtension(file) + renderbatch.groupID);
                objsw.WriteLine("usemtl tex_" + materials[renderbatch.materialID].filename);
                objsw.WriteLine("s 1");
                while (i < (renderbatch.firstFace + renderbatch.numFaces))
                {
                    objsw.WriteLine("f " + (indices[i] + 1) + "/" + (indices[i] + 1) + "/" + (indices[i] + 1) + " " + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + " " + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1));
                    i = i + 3;
                }
            }

            objsw.Close();

            // Only export phys when exporting a single M2, causes issues for some users when combined with WMO/ADT
            if (destinationOverride == null)
            {
                exportworker.ReportProgress(90, "Exporting collision..");

                objsw = new StreamWriter(Path.Combine(outdir, file.Replace(".m2", ".phys.obj")));

                objsw.WriteLine("# Written by Marlamin's WoW Exporter. Original file: " + file);

                for (int i = 0; i < reader.model.boundingvertices.Count(); i++)
                {
                    objsw.WriteLine("v " +
                                    reader.model.boundingvertices[i].vertex.X + " " +
                                    reader.model.boundingvertices[i].vertex.Z + " " +
                                    -reader.model.boundingvertices[i].vertex.Y);
                }

                for (int i = 0; i < reader.model.boundingtriangles.Count(); i++)
                {
                    var t = reader.model.boundingtriangles[i];
                    objsw.WriteLine("f " + (t.index_0 + 1) + " " + (t.index_1 + 1) + " " + (t.index_2 + 1));
                }

                objsw.Close();
            }

            // https://en.wikipedia.org/wiki/Wavefront_.obj_file#Basic_materials
            // http://wiki.unity3d.com/index.php?title=ExportOBJ
            // http://web.cse.ohio-state.edu/~hwshen/581/Site/Lab3_files/Labhelp_Obj_parser.htm
        }
Пример #10
0
        private void LoadM2(string modelpath)
        {
            if (!WoWFormatLib.Utils.CASC.FileExists(modelpath))
            {
                throw new Exception("Model does not exist!");
            }

            worker.ReportProgress(0, "Loading model..");

            M2Reader reader = new M2Reader();

            string filename = modelpath;

            reader.LoadM2(filename);
            VBOid = new uint[2];
            GL.GenBuffers(2, VBOid);

            GL.BindBuffer(BufferTarget.ArrayBuffer, VBOid[0]);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, VBOid[1]);

            GL.EnableClientState(ArrayCap.VertexArray);
            GL.EnableClientState(ArrayCap.NormalArray);

            worker.ReportProgress(20, "Reading model indices..");

            List <uint> indicelist = new List <uint>();

            for (int i = 0; i < reader.model.skins[0].triangles.Count(); i++)
            {
                indicelist.Add(reader.model.skins[0].triangles[i].pt1);
                indicelist.Add(reader.model.skins[0].triangles[i].pt2);
                indicelist.Add(reader.model.skins[0].triangles[i].pt3);
            }

            uint[] indices = indicelist.ToArray();

            GL.BindBuffer(BufferTarget.ElementArrayBuffer, VBOid[1]);
            GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(indices.Length * sizeof(uint)), indices, BufferUsageHint.StaticDraw);

            worker.ReportProgress(30, "Reading model vertices..");

            Vertex[] vertices = new Vertex[reader.model.vertices.Count()];

            for (int i = 0; i < reader.model.vertices.Count(); i++)
            {
                vertices[i].Position = new Vector3(reader.model.vertices[i].position.X, reader.model.vertices[i].position.Z, reader.model.vertices[i].position.Y * -1);
                vertices[i].Normal   = new Vector3(reader.model.vertices[i].normal.X, reader.model.vertices[i].normal.Z, reader.model.vertices[i].normal.Y);
                vertices[i].TexCoord = new Vector2(reader.model.vertices[i].textureCoordX, reader.model.vertices[i].textureCoordY);
            }
            GL.BindBuffer(BufferTarget.ArrayBuffer, VBOid[0]);
            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * 8 * sizeof(float)), vertices, BufferUsageHint.StaticDraw);

            GL.Enable(EnableCap.Texture2D);

            worker.ReportProgress(40, "Loading textures..");

            materials = new Material[reader.model.textures.Count()];
            for (int i = 0; i < reader.model.textures.Count(); i++)
            {
                Console.WriteLine("Loading texture " + i);
                string texturefilename = @"dungeons\textures\testing\color_13.blp";
                materials[i].flags = reader.model.textures[i].flags;
                Console.WriteLine("      Requires type " + reader.model.textures[i].type + " texture");
                switch (reader.model.textures[i].type)
                {
                case 0:
                    Console.WriteLine("      Texture given in file!");
                    texturefilename = reader.model.textures[i].filename;
                    break;

                case 1:
                    string[] csfilenames = WoWFormatLib.DBC.DBCHelper.getTexturesByModelFilename(filename, (int)reader.model.textures[i].type, i);
                    if (csfilenames.Count() > 0)
                    {
                        texturefilename = csfilenames[0];
                    }
                    else
                    {
                        Console.WriteLine("      No type 1 texture found, falling back to placeholder texture");
                    }
                    break;

                case 2:
                    if (WoWFormatLib.Utils.CASC.FileExists(Path.ChangeExtension(modelpath, ".blp")))
                    {
                        Console.WriteLine("      BLP exists!");
                        texturefilename = Path.ChangeExtension(modelpath, ".blp");
                    }
                    else
                    {
                        Console.WriteLine("      Type 2 does not exist!");
                        //needs lookup?
                    }
                    break;

                case 11:
                    string[] cdifilenames = WoWFormatLib.DBC.DBCHelper.getTexturesByModelFilename(filename, (int)reader.model.textures[i].type);
                    for (int ti = 0; ti < cdifilenames.Count(); ti++)
                    {
                        if (WoWFormatLib.Utils.CASC.FileExists(modelpath.Replace(reader.model.name + ".M2", cdifilenames[ti] + ".blp")))
                        {
                            texturefilename = modelpath.Replace(reader.model.name + ".M2", cdifilenames[ti] + ".blp");
                        }
                    }
                    break;

                default:
                    Console.WriteLine("      Falling back to placeholder texture");
                    break;
                }

                Console.WriteLine("      Eventual filename is " + texturefilename);
                materials[i].textureID = BLPLoader.LoadTexture(texturefilename, cache);
                materials[i].filename  = texturefilename;
            }

            worker.ReportProgress(60, "Loading renderbatches..");
            renderbatches = new RenderBatch[reader.model.skins[0].submeshes.Count()];
            for (int i = 0; i < reader.model.skins[0].submeshes.Count(); i++)
            {
                if (filename.StartsWith("character", StringComparison.CurrentCultureIgnoreCase))
                {
                    if (reader.model.skins[0].submeshes[i].submeshID != 0)
                    {
                        if (!reader.model.skins[0].submeshes[i].submeshID.ToString().EndsWith("01"))
                        {
                            continue;
                        }
                    }

                    Console.WriteLine("Loading submesh " + reader.model.skins[0].submeshes[i].submeshID + "(" + reader.model.skins[0].submeshes[i].unk2 + ")");
                }

                renderbatches[i].firstFace = reader.model.skins[0].submeshes[i].startTriangle;
                renderbatches[i].numFaces  = reader.model.skins[0].submeshes[i].nTriangles;
                for (int tu = 0; tu < reader.model.skins[0].textureunit.Count(); tu++)
                {
                    if (reader.model.skins[0].textureunit[tu].submeshIndex == i)
                    {
                        renderbatches[i].blendType  = reader.model.renderflags[reader.model.skins[0].textureunit[tu].renderFlags].blendingMode;
                        renderbatches[i].materialID = reader.model.texlookup[reader.model.skins[0].textureunit[tu].texture].textureID;
                    }
                }
            }

            worker.ReportProgress(100, "Done.");

            gLoaded = true;
        }
Пример #11
0
        public static void ExportM2(string filename, string outdir, string destinationOverride = null)
        {
            filename = filename.ToLower();

            var customCulture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();

            customCulture.NumberFormat.NumberDecimalSeparator    = ".";
            System.Threading.Thread.CurrentThread.CurrentCulture = customCulture;

            var reader = new M2Reader();

            //If the missing file is an ".mdx", try to look for a ".m2" alternative
            if (!Managers.ArchiveManager.FileExists(filename))
            {
                if (Path.GetExtension(filename) == ".mdx")
                {
                    if (!Managers.ArchiveManager.FileExists(filename.Replace(".mdx", ".m2")))
                    {
                        throw new Exception("404 M2 not found!");
                    }
                    else
                    {
                        filename = filename.Replace(".mdx", ".m2");
                    }
                }
                else
                {
                    throw new Exception("404 M2 not found!");
                }
            }

            reader.LoadM2(filename);

            //Bail if the model has no vertices
            if (reader.model.vertices.Count() == 0)
            {
                return;
            }

            //Export individual geosets...
            var indicelist = new List <uint>();

            for (var i = 0; i < reader.model.skins[0].triangles.Count(); i++)
            {
                var t = reader.model.skins[0].triangles[i];
                indicelist.Add(t.pt1);
                indicelist.Add(t.pt2);
                indicelist.Add(t.pt3);
            }

            var indices = indicelist.ToArray();

            var renderbatches = new Structs.RenderBatch[reader.model.skins[0].submeshes.Count()];

            for (var i = 0; i < reader.model.skins[0].submeshes.Count(); i++)
            {
                renderbatches[i].firstFace = reader.model.skins[0].submeshes[i].startTriangle;
                renderbatches[i].numFaces  = reader.model.skins[0].submeshes[i].nTriangles;
                renderbatches[i].groupID   = (uint)i;
                for (var tu = 0; tu < reader.model.skins[0].textureunit.Count(); tu++)
                {
                    if (reader.model.skins[0].textureunit[tu].submeshIndex == i)
                    {
                        renderbatches[i].blendType  = reader.model.renderflags[reader.model.skins[0].textureunit[tu].renderFlags].blendingMode;
                        renderbatches[i].materialID = reader.model.texlookup[reader.model.skins[0].textureunit[tu].texture].textureID;
                    }
                }
            }

            //----------------------------------------------------------------------------------------------------------
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////
            ///REFERENCE SMD(s)
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //----------------------------------------------------------------------------------------------------------
            int sMeshIndex = 0; // to be used for submeshes names

            foreach (var renderbatch in renderbatches)
            {
                var j = renderbatch.firstFace;

                StreamWriter smdsw;
                if (destinationOverride == null)
                {
                    if (!string.IsNullOrEmpty(filename))
                    {
                        if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(filename))))
                        {
                            Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(filename)));
                        }
                        smdsw = new StreamWriter(Path.Combine(outdir, filename.Replace(".m2", sMeshIndex + ".smd")));
                    }
                    else
                    {
                        if (!Directory.Exists(outdir))
                        {
                            Directory.CreateDirectory(outdir);
                        }
                        smdsw = new StreamWriter(Path.Combine(outdir, filename + sMeshIndex + ".smd"));
                    }
                }
                else
                {
                    if (!string.IsNullOrEmpty(filename))
                    {
                        smdsw = new StreamWriter(Path.Combine(outdir, destinationOverride, Path.GetFileName(filename.ToLower()).Replace(".m2", sMeshIndex + ".smd")));
                    }
                    else
                    {
                        smdsw = new StreamWriter(Path.Combine(outdir, destinationOverride, filename + sMeshIndex + ".smd"));
                    }
                }
                smdsw.WriteLine("// Written by izzy's SMD Export module. Original file: " + filename);

                //Version
                smdsw.WriteLine("version 1");

                //Bones block start
                smdsw.WriteLine("nodes");

                //Root bone
                smdsw.WriteLine("  0 \"" + reader.model.name + "\"  -1");
                for (int i = 0; i < reader.model.bones.Count(); i++)
                {
                    smdsw.WriteLine("  " + (i + 1) + " \"" + reader.model.name + "_bone" + i + "\"  " + (reader.model.bones[i].parentBone + 1));
                }
                smdsw.WriteLine("end");
                //Bones block end

                //Skeleton block start
                smdsw.WriteLine("skeleton");
                smdsw.WriteLine("time 0");
                smdsw.WriteLine("  0 0.000000 0.000000 0.000000 0.000000 -0.000000 0.000000");
                for (int i = 0; i < reader.model.bones.Count(); i++)
                {
                    var currentBone          = reader.model.bones[i];
                    var currentBoneParentPos = new WoWFormatLib.Utils.Vector3();

                    if (currentBone.parentBone != -1)
                    {
                        currentBoneParentPos.X = reader.model.bones[reader.model.bones[i].parentBone].pivot.X;
                        currentBoneParentPos.Y = reader.model.bones[reader.model.bones[i].parentBone].pivot.Y;
                        currentBoneParentPos.Z = reader.model.bones[reader.model.bones[i].parentBone].pivot.Z;
                    }
                    else
                    {
                        currentBoneParentPos.X = 0;
                        currentBoneParentPos.Y = 0;
                        currentBoneParentPos.Z = 0;
                    }
                    smdsw.WriteLine("  " + (i + 1) + " " + (currentBone.pivot.X - currentBoneParentPos.X) + " " + (currentBone.pivot.Z - currentBoneParentPos.Z) + " " + -(currentBone.pivot.Y - currentBoneParentPos.Y) + " " + "0.000000" + " " + "-0.000000" + " " + "0.000000");
                }
                smdsw.WriteLine("end");
                //Skeleton block end

                //Triangles block start
                smdsw.WriteLine("triangles");
                while (j < (renderbatch.firstFace + renderbatch.numFaces))
                {
                    var vert1 = reader.model.vertices[indices[j]];
                    var vert2 = reader.model.vertices[indices[j + 1]];
                    var vert3 = reader.model.vertices[indices[j + 2]];
                    smdsw.WriteLine(Path.GetFileNameWithoutExtension(reader.model.textures[0].filename));
                    string vert1line  = "  " + (vert1.boneIndices_0 + 1) + " " + vert1.position.X + " " + vert1.position.Z + " " + -vert1.position.Y + " " + vert1.normal.X + " " + vert1.normal.Y + " " + vert1.normal.Z + " " + vert1.textureCoordX + " " + (vert1.textureCoordY - 1) * -1;
                    string vert2line  = "  " + (vert2.boneIndices_0 + 1) + " " + vert2.position.X + " " + vert2.position.Z + " " + -vert2.position.Y + " " + vert2.normal.X + " " + vert2.normal.Y + " " + vert2.normal.Z + " " + vert2.textureCoordX + " " + (vert2.textureCoordY - 1) * -1;
                    string vert3line  = "  " + (vert3.boneIndices_0 + 1) + " " + vert3.position.X + " " + vert3.position.Z + " " + -vert3.position.Y + " " + vert3.normal.X + " " + vert3.normal.Y + " " + vert3.normal.Z + " " + vert3.textureCoordX + " " + (vert3.textureCoordY - 1) * -1;
                    int    linksVert1 = 1;
                    int    linksVert2 = 1;
                    int    linksVert3 = 1;
                    string addlink1;
                    string addlink2;
                    string addlink3;
                    addlink1 = (vert1.boneIndices_0 + 1) + " " + vert1.boneWeight_0 / 255f;
                    addlink2 = (vert2.boneIndices_0 + 1) + " " + vert2.boneWeight_0 / 255f;
                    addlink3 = (vert3.boneIndices_0 + 1) + " " + vert3.boneWeight_0 / 255f;
                    //-------------------------------------
                    if (vert1.boneWeight_1 > 0)
                    {
                        addlink1 = addlink1 + " " + (vert1.boneIndices_1 + 1) + " " + vert1.boneWeight_1 / 255f;
                        linksVert1++;
                    }
                    if (vert1.boneWeight_2 > 0)
                    {
                        addlink1 = addlink1 + " " + (vert1.boneIndices_2 + 1) + " " + vert1.boneWeight_2 / 255f;
                        linksVert1++;
                    }
                    if (vert1.boneWeight_3 > 0)
                    {
                        addlink1 = addlink1 + " " + (vert1.boneIndices_3 + 1) + " " + vert1.boneWeight_3 / 255f;
                        linksVert1++;
                    }
                    //-------------------------------------
                    if (vert2.boneWeight_1 > 0)
                    {
                        addlink2 = addlink2 + " " + (vert2.boneIndices_1 + 1) + " " + vert2.boneWeight_1 / 255f;
                        linksVert2++;
                    }
                    if (vert2.boneWeight_2 > 0)
                    {
                        addlink2 = addlink2 + " " + (vert2.boneIndices_2 + 1) + " " + vert2.boneWeight_2 / 255f;
                        linksVert2++;
                    }
                    if (vert2.boneWeight_3 > 0)
                    {
                        addlink2 = addlink2 + " " + (vert2.boneIndices_3 + 1) + " " + vert2.boneWeight_3 / 255f;
                        linksVert2++;
                    }
                    //-------------------------------------
                    if (vert3.boneWeight_1 > 0)
                    {
                        addlink3 = addlink3 + " " + (vert3.boneIndices_1 + 1) + " " + vert3.boneWeight_1 / 255f;
                        linksVert3++;
                    }
                    if (vert3.boneWeight_2 > 0)
                    {
                        addlink3 = addlink3 + " " + (vert3.boneIndices_2 + 1) + " " + vert3.boneWeight_2 / 255f;
                        linksVert3++;
                    }
                    if (vert3.boneWeight_3 > 0)
                    {
                        addlink3 = addlink3 + " " + (vert3.boneIndices_3 + 1) + " " + vert3.boneWeight_3 / 255f;
                        linksVert3++;
                    }
                    //-------------------------------------
                    vert1line = vert1line + " " + linksVert1 + " " + addlink1;
                    vert2line = vert2line + " " + linksVert2 + " " + addlink2;
                    vert3line = vert3line + " " + linksVert3 + " " + addlink3;
                    smdsw.WriteLine(vert1line);
                    smdsw.WriteLine(vert2line);
                    smdsw.WriteLine(vert3line);
                    j += 3;
                }
                smdsw.WriteLine("end");
                //Triangles block end
                smdsw.Close();
                sMeshIndex++;
            }
        }
Пример #12
0
        public static void exportM2(string file, BackgroundWorker exportworker = null)
        {
            if (exportworker == null)
            {
                exportworker = new BackgroundWorker();
            }

            var outdir = ConfigurationManager.AppSettings["outdir"];
            var reader = new M2Reader();

            exportworker.ReportProgress(15, "Reading M2..");

            if (!CASC.FileExists(file))
            {
                throw new Exception("404 M2 not found!");
            }

            reader.LoadM2(file);

            Structs.Vertex[] vertices = new Structs.Vertex[reader.model.vertices.Count()];

            for (int i = 0; i < reader.model.vertices.Count(); i++)
            {
                vertices[i].Position = new OpenTK.Vector3(reader.model.vertices[i].position.X, reader.model.vertices[i].position.Z, reader.model.vertices[i].position.Y * -1);
                vertices[i].Normal   = new OpenTK.Vector3(reader.model.vertices[i].normal.X, reader.model.vertices[i].normal.Z, reader.model.vertices[i].normal.Y);
                vertices[i].TexCoord = new Vector2(reader.model.vertices[i].textureCoordX, reader.model.vertices[i].textureCoordY);
            }

            // Create output directory
            if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(file))))
            {
                Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file)));
            }

            var objsw = new StreamWriter(Path.Combine(outdir, file.Replace(".m2", ".obj")));

            objsw.WriteLine("# Written by Marlamin's WoW OBJExporter. Original file: " + file);
            objsw.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(file) + ".mtl");

            foreach (var vertex in vertices)
            {
                objsw.WriteLine("v " + vertex.Position.X + " " + vertex.Position.Y + " " + vertex.Position.Z);
                objsw.WriteLine("vt " + vertex.TexCoord.X + " " + -vertex.TexCoord.Y);
                objsw.WriteLine("vn " + vertex.Position.X + " " + vertex.Position.Y + " " + vertex.Normal.Z);
            }

            List <uint> indicelist = new List <uint>();

            for (int i = 0; i < reader.model.skins[0].triangles.Count(); i++)
            {
                var t = reader.model.skins[0].triangles[i];
                indicelist.Add(t.pt1);
                indicelist.Add(t.pt2);
                indicelist.Add(t.pt3);
            }

            var indices = indicelist.ToArray();

            exportworker.ReportProgress(35, "Writing files..");

            var renderbatches = new Structs.RenderBatch[reader.model.skins[0].submeshes.Count()];

            for (int i = 0; i < reader.model.skins[0].submeshes.Count(); i++)
            {
                if (file.StartsWith("character", StringComparison.CurrentCultureIgnoreCase))
                {
                    if (reader.model.skins[0].submeshes[i].submeshID != 0)
                    {
                        if (!reader.model.skins[0].submeshes[i].submeshID.ToString().EndsWith("01"))
                        {
                            continue;
                        }
                    }
                }

                renderbatches[i].firstFace = reader.model.skins[0].submeshes[i].startTriangle;
                renderbatches[i].numFaces  = reader.model.skins[0].submeshes[i].nTriangles;
                renderbatches[i].groupID   = (uint)i;
                for (int tu = 0; tu < reader.model.skins[0].textureunit.Count(); tu++)
                {
                    if (reader.model.skins[0].textureunit[tu].submeshIndex == i)
                    {
                        renderbatches[i].blendType  = reader.model.renderflags[reader.model.skins[0].textureunit[tu].renderFlags].blendingMode;
                        renderbatches[i].materialID = reader.model.texlookup[reader.model.skins[0].textureunit[tu].texture].textureID;
                    }
                }
            }

            exportworker.ReportProgress(65, "Exporting textures..");

            var mtlsb     = new StreamWriter(Path.Combine(outdir, file.Replace(".m2", ".mtl")));
            var textureID = 0;
            var materials = new Structs.Material[reader.model.textures.Count()];

            for (int i = 0; i < reader.model.textures.Count(); i++)
            {
                string texturefilename = "Dungeons\\Textures\\testing\\COLOR_13.blp";
                materials[i].flags = reader.model.textures[i].flags;
                switch (reader.model.textures[i].type)
                {
                case 0:
                    //Console.WriteLine("      Texture given in file!");
                    texturefilename = reader.model.textures[i].filename;
                    break;

                case 1:
                    string[] csfilenames = WoWFormatLib.DBC.DBCHelper.getTexturesByModelFilename(file, (int)reader.model.textures[i].type, i);
                    if (csfilenames.Count() > 0)
                    {
                        texturefilename = csfilenames[0];
                    }
                    else
                    {
                        //Console.WriteLine("      No type 1 texture found, falling back to placeholder texture");
                    }
                    break;

                case 2:
                    if (WoWFormatLib.Utils.CASC.FileExists(Path.ChangeExtension(file, ".blp")))
                    {
                        //Console.WriteLine("      BLP exists!");
                        texturefilename = Path.ChangeExtension(file, ".blp");
                    }
                    else
                    {
                        //Console.WriteLine("      Type 2 does not exist!");
                        //needs lookup?
                    }
                    break;

                case 11:
                    string[] cdifilenames = WoWFormatLib.DBC.DBCHelper.getTexturesByModelFilename(file, (int)reader.model.textures[i].type);
                    for (int ti = 0; ti < cdifilenames.Count(); ti++)
                    {
                        if (WoWFormatLib.Utils.CASC.FileExists(file.Replace(reader.model.name + ".M2", cdifilenames[ti] + ".blp")))
                        {
                            texturefilename = file.Replace(reader.model.name + ".M2", cdifilenames[ti] + ".blp");
                        }
                    }
                    break;

                default:
                    // Console.WriteLine("      Falling back to placeholder texture");
                    break;
                }

                //Console.WriteLine("      Eventual filename is " + texturefilename);

                materials[i].textureID = textureID + i;
                materials[i].filename  = Path.GetFileNameWithoutExtension(texturefilename);

                var blpreader = new BLPReader();

                blpreader.LoadBLP(texturefilename);

                try
                {
                    blpreader.bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(file), materials[i].filename + ".png"));
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
            }

            exportworker.ReportProgress(85, "Writing files..");

            foreach (var material in materials)
            {
                mtlsb.WriteLine("newmtl " + material.filename);
                mtlsb.WriteLine("illum 2");
                mtlsb.WriteLine("map_Ka " + material.filename + ".png");
                mtlsb.WriteLine("map_Kd " + material.filename + ".png");
            }

            mtlsb.Close();

            objsw.WriteLine("g " + Path.GetFileNameWithoutExtension(file));

            foreach (var renderbatch in renderbatches)
            {
                var i = renderbatch.firstFace;
                objsw.WriteLine("o " + Path.GetFileNameWithoutExtension(file) + renderbatch.groupID);
                objsw.WriteLine("usemtl " + materials[renderbatch.materialID].filename);
                objsw.WriteLine("s 1");
                while (i < (renderbatch.firstFace + renderbatch.numFaces))
                {
                    objsw.WriteLine("f " + (indices[i] + 1) + "/" + (indices[i] + 1) + "/" + (indices[i] + 1) + " " + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + " " + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1));
                    i = i + 3;
                }
            }

            objsw.Close();
            // https://en.wikipedia.org/wiki/Wavefront_.obj_file#Basic_materials
            // http://wiki.unity3d.com/index.php?title=ExportOBJ
            // http://web.cse.ohio-state.edu/~hwshen/581/Site/Lab3_files/Labhelp_Obj_parser.htm

            Console.WriteLine("Done loading model!");
        }
Пример #13
0
        static void Main(string[] args)
        {
            if (args.Length < 2)
            {
                throw new Exception("Require buildconfig and cdnconfig (and yes for fullrun)");
            }

            var fullrun = false;

            if (args.Length == 3 && args[2] == "1")
            {
                Console.WriteLine("Doing full run!");
                fullrun = true;
            }

            // TODO: Use configuration stuff instead, but I don't want to figure that out right now. :)
            if (!File.Exists("connectionstring.txt"))
            {
                throw new Exception("connectionstring.txt not found!");
            }

            var dbConn = new MySqlConnection(File.ReadAllText("connectionstring.txt"));

            dbConn.Open();

            CASCLib.Logger.Init();

            CASC.InitCasc("wow.tools", args[0], args[1]);

            var insertCmd = new MySqlCommand("INSERT INTO wow_rootfiles_links VALUES (@parent, @child, @type)", dbConn);

            insertCmd.Parameters.AddWithValue("@parent", 0);
            insertCmd.Parameters.AddWithValue("@child", 0);
            insertCmd.Parameters.AddWithValue("@type", "");
            insertCmd.Prepare();

            var insertUVFNCmd = new MySqlCommand("INSERT INTO wow_communityfiles VALUES (@id, @filename)", dbConn);

            insertUVFNCmd.Parameters.AddWithValue("@id", 0);
            insertUVFNCmd.Parameters.AddWithValue("@filename", 0);
            insertCmd.Prepare();

            #region M2
            var m2ids = new List <uint>();

            using (var cmd = dbConn.CreateCommand())
            {
                if (fullrun)
                {
                    cmd.CommandText = "SELECT id from wow_rootfiles WHERE type = 'm2' ORDER BY id DESC";
                }
                else
                {
                    Console.WriteLine("[M2] Generating list of files to process..");
                    cmd.CommandText = "SELECT id from wow_rootfiles WHERE type = 'm2' AND id NOT IN (SELECT parent FROM wow_rootfiles_links) ORDER BY id DESC";
                }

                var reader = cmd.ExecuteReader();

                while (reader.Read())
                {
                    m2ids.Add(uint.Parse(reader["id"].ToString()));
                }

                reader.Close();
            }

            foreach (var m2 in m2ids)
            {
                if (CASC.FileExists(m2))
                {
                    Console.WriteLine("[M2] Loading " + m2);
                    try
                    {
                        var reader = new M2Reader();
                        reader.LoadM2(m2, false);

                        insertCmd.Parameters[0].Value = m2;

                        if (reader.model.textureFileDataIDs != null)
                        {
                            foreach (var textureID in reader.model.textureFileDataIDs)
                            {
                                insertEntry(insertCmd, textureID, "m2 texture");
                            }
                        }

                        if (reader.model.animFileDataIDs != null)
                        {
                            foreach (var animFileID in reader.model.animFileDataIDs)
                            {
                                insertEntry(insertCmd, animFileID.fileDataID, "m2 anim");
                            }
                        }

                        if (reader.model.skinFileDataIDs != null)
                        {
                            foreach (var skinFileID in reader.model.skinFileDataIDs)
                            {
                                insertEntry(insertCmd, skinFileID, "m2 skin");
                            }
                        }

                        if (reader.model.boneFileDataIDs != null)
                        {
                            foreach (var boneFileID in reader.model.boneFileDataIDs)
                            {
                                insertEntry(insertCmd, boneFileID, "m2 bone");
                            }
                        }

                        if (reader.model.recursiveParticleModelFileIDs != null)
                        {
                            foreach (var rpID in reader.model.recursiveParticleModelFileIDs)
                            {
                                insertEntry(insertCmd, rpID, "m2 recursive particle");
                            }
                        }

                        if (reader.model.geometryParticleModelFileIDs != null)
                        {
                            foreach (var gpID in reader.model.geometryParticleModelFileIDs)
                            {
                                insertEntry(insertCmd, gpID, "m2 geometry particle");
                            }
                        }

                        insertEntry(insertCmd, reader.model.skelFileID, "m2 skel");
                        insertEntry(insertCmd, reader.model.physFileID, "m2 phys");
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                    }
                }
            }
            #endregion

            #region WMO
            var wmoids = new List <uint>();

            var groupFixCMD = new MySqlCommand("UPDATE wow_rootfiles SET type = '_xxxwmo' WHERE id = @id LIMIT 1", dbConn);
            groupFixCMD.Parameters.AddWithValue("@id", 0);
            groupFixCMD.Prepare();

            using (var cmd = dbConn.CreateCommand())
            {
                if (fullrun)
                {
                    cmd.CommandText = "SELECT id from wow_rootfiles WHERE type = 'wmo' ORDER BY id DESC";
                }
                else
                {
                    Console.WriteLine("[WMO] Generating list of files to process..");
                    cmd.CommandText = "SELECT id from wow_rootfiles WHERE type = 'wmo' AND id NOT IN (SELECT parent FROM wow_rootfiles_links) ORDER BY id DESC";
                }
                var reader = cmd.ExecuteReader();

                while (reader.Read())
                {
                    wmoids.Add(uint.Parse(reader["id"].ToString()));
                }

                reader.Close();
            }

            foreach (var wmoid in wmoids)
            {
                if (CASC.FileExists(wmoid))
                {
                    Console.WriteLine("[WMO] Loading " + wmoid);
                    try
                    {
                        var reader = new WMOReader();
                        var wmo    = new WoWFormatLib.Structs.WMO.WMO();
                        try
                        {
                            wmo = reader.LoadWMO(wmoid);
                        }
                        catch (NotSupportedException e)
                        {
                            Console.WriteLine("[WMO] " + wmoid + " is a group WMO, fixing type and skipping..");
                            groupFixCMD.Parameters[0].Value = wmoid;
                            groupFixCMD.ExecuteNonQuery();
                            continue;
                        }

                        insertCmd.Parameters[0].Value = wmoid;

                        var inserted = new List <uint>();

                        if (wmo.groupFileDataIDs != null)
                        {
                            foreach (var groupFileDataID in wmo.groupFileDataIDs)
                            {
                                insertEntry(insertCmd, groupFileDataID, "wmo group");
                            }
                        }

                        if (wmo.doodadIds != null)
                        {
                            foreach (var doodadID in wmo.doodadIds)
                            {
                                if (inserted.Contains(doodadID))
                                {
                                    continue;
                                }

                                inserted.Add(doodadID);

                                insertEntry(insertCmd, doodadID, "wmo doodad");
                            }
                        }

                        if (wmo.textures == null && wmo.materials != null)
                        {
                            foreach (var material in wmo.materials)
                            {
                                if (material.texture1 == 0 || inserted.Contains(material.texture1))
                                {
                                    continue;
                                }

                                inserted.Add(material.texture1);
                                insertEntry(insertCmd, material.texture1, "wmo texture");

                                if (material.texture2 == 0 || inserted.Contains(material.texture2))
                                {
                                    continue;
                                }

                                inserted.Add(material.texture2);
                                insertEntry(insertCmd, material.texture2, "wmo texture");
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                    }
                }
            }
            #endregion

            #region WDT
            var wdtids         = new List <uint>();
            var wdtfullnamemap = new Dictionary <string, uint>();
            using (var cmd = dbConn.CreateCommand())
            {
                Console.WriteLine("[WDT] Generating list of WDT files..");
                cmd.CommandText = "SELECT id, filename from wow_rootfiles WHERE type = 'wdt' AND filename IS NOT NULL ORDER BY id DESC";
                var reader = cmd.ExecuteReader();

                while (reader.Read())
                {
                    var filename = (string)reader["filename"];
                    var wdtid    = uint.Parse(reader["id"].ToString());
                    if (filename.Contains("_mpv") || filename.Contains("_lgt") || filename.Contains("_occ") || filename.Contains("_fogs"))
                    {
                        continue;
                    }
                    wdtfullnamemap.Add(filename, wdtid);
                }
            }

            using (var cmd = dbConn.CreateCommand())
            {
                if (fullrun)
                {
                    cmd.CommandText = "SELECT id, filename from wow_rootfiles WHERE type = 'wdt' ORDER BY id DESC";
                }
                else
                {
                    Console.WriteLine("[WDT] Generating list of files to process..");
                    cmd.CommandText = "SELECT id, filename from wow_rootfiles WHERE type = 'wdt' AND id NOT IN (SELECT parent FROM wow_rootfiles_links) ORDER BY id DESC";
                }
                var reader = cmd.ExecuteReader();

                while (reader.Read())
                {
                    //var filename = (string)reader["filename"];
                    var wdtid = uint.Parse(reader["id"].ToString());
                    //if (filename.Contains("_mpv") || filename.Contains("_lgt") || filename.Contains("_occ") || filename.Contains("_fogs"))
                    //   continue;
                    wdtids.Add(wdtid);
                }

                reader.Close();

                foreach (var wdtid in wdtids)
                {
                    Console.WriteLine("[WDT] Loading " + wdtid);

                    insertCmd.Parameters[0].Value = wdtid;
                    try
                    {
                        var wdtreader = new WDTReader();
                        wdtreader.LoadWDT(wdtid);

                        if (wdtreader.wdtfile.modf.id != 0)
                        {
                            Console.WriteLine("WDT has WMO ID: " + wdtreader.wdtfile.modf.id);
                            insertEntry(insertCmd, wdtreader.wdtfile.modf.id, "wdt wmo");
                        }

                        foreach (var records in wdtreader.stringTileFiles)
                        {
                            insertEntry(insertCmd, records.Value.rootADT, "root adt");
                            insertEntry(insertCmd, records.Value.tex0ADT, "tex0 adt");
                            insertEntry(insertCmd, records.Value.lodADT, "lod adt");
                            insertEntry(insertCmd, records.Value.obj0ADT, "obj0 adt");
                            insertEntry(insertCmd, records.Value.obj1ADT, "obj1 adt");
                            insertEntry(insertCmd, records.Value.mapTexture, "map texture");
                            insertEntry(insertCmd, records.Value.mapTextureN, "mapn texture");
                            insertEntry(insertCmd, records.Value.minimapTexture, "minimap texture");
                        }
                    }catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                    }
                }
            }
            #endregion

            #region ADT
            var adtids     = new Dictionary <uint, Dictionary <(byte, byte), uint> >();
            var wdtmapping = new Dictionary <string, uint>();

            using (var cmd = dbConn.CreateCommand())
            {
                if (fullrun)
                {
                    cmd.CommandText = " SELECT id, filename from wow_rootfiles WHERE filename LIKE '%adt' AND filename NOT LIKE '%_obj0.adt' AND filename NOT LIKE '%_obj1.adt' AND filename NOT LIKE '%_lod.adt' AND filename NOT LIKE '%tex0.adt' AND filename NOT LIKE '%tex1.adt' ORDER BY id DESC ";
                }
                else
                {
                    Console.WriteLine("[ADT] Generating list of files to process..");
                    cmd.CommandText = " SELECT id, filename from wow_rootfiles WHERE filename LIKE '%adt' AND filename NOT LIKE '%_obj0.adt' AND filename NOT LIKE '%_obj1.adt' AND filename NOT LIKE '%_lod.adt' AND filename NOT LIKE '%tex0.adt' AND filename NOT LIKE '%tex1.adt' AND id NOT IN (SELECT parent FROM wow_rootfiles_links) ORDER BY id DESC";
                }
                var reader = cmd.ExecuteReader();

                while (reader.Read())
                {
                    var filename = (string)reader["filename"];
                    var mapname  = filename.Replace("world/maps/", "").Substring(0, filename.Replace("world/maps/", "").IndexOf("/"));
                    var exploded = Path.GetFileNameWithoutExtension(filename).Split('_');

                    for (var i = 0; i < exploded.Length; i++)
                    {
                        //Console.WriteLine(i + ": " + exploded[i]);
                    }

                    byte tileX = 0;
                    byte tileY = 0;

                    if (!byte.TryParse(exploded[exploded.Length - 2], out tileX) || !byte.TryParse(exploded[exploded.Length - 1], out tileY))
                    {
                        throw new FormatException("An error occured converting coordinates from " + filename + " to bytes");
                    }

                    if (!wdtmapping.ContainsKey(mapname))
                    {
                        var wdtname = "world/maps/" + mapname + "/" + mapname + ".wdt";
                        if (!wdtfullnamemap.ContainsKey(wdtname))
                        {
                            Console.WriteLine("Unable to get filedataid for " + mapname + ", skipping...");
                            wdtmapping.Remove(mapname);
                            continue;
                        }
                        wdtmapping.Add(mapname, wdtfullnamemap[wdtname]);
                        if (wdtmapping[mapname] == 0)
                        {
                            // TODO: Support WDTs removed in current build
                            Console.WriteLine("Unable to get filedataid for " + mapname + ", skipping...");
                            wdtmapping.Remove(mapname);
                            continue;

                            /*
                             * var wdtconn = new MySqlConnection(File.ReadAllText("connectionstring.txt"));
                             * wdtconn.Open();
                             * using (var wdtcmd = wdtconn.CreateCommand())
                             * {
                             *  wdtcmd.CommandText = "SELECT id from wow_rootfiles WHERE filename = '" + wdtname + "'";
                             *  var wdtread = wdtcmd.ExecuteReader();
                             *  while (wdtread.Read())
                             *  {
                             *      wdtmapping[mapname] = uint.Parse(wdtread["id"].ToString());
                             *  }
                             * }
                             * wdtconn.Close();*/
                        }

                        adtids.Add(wdtmapping[mapname], new Dictionary <(byte, byte), uint>());
                    }

                    var id = uint.Parse(reader["id"].ToString());

                    if (id == 0)
                    {
                        Console.WriteLine("Root ADT " + tileX + ", " + tileY + " with ID 0 on WDT " + wdtmapping[mapname]);
                        continue;
                    }

                    if (wdtmapping.ContainsKey(mapname))
                    {
                        adtids[wdtmapping[mapname]].Add((tileX, tileY), id);
                    }
                }

                reader.Close();

                foreach (var wdtid in adtids)
                {
                    foreach (var adtid in wdtid.Value)
                    {
                        var inserted = new List <uint>();
                        Console.WriteLine("[ADT] Loading " + adtid.Key.Item1 + ", " + adtid.Key.Item2 + "(" + adtid.Value + ")");

                        insertCmd.Parameters[0].Value = adtid.Value;

                        var adtreader = new ADTReader();
                        try
                        {
                            adtreader.LoadADT(wdtid.Key, adtid.Key.Item1, adtid.Key.Item2);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.Message);
                            continue;
                        }

                        if (adtreader.adtfile.objects.m2Names.filenames != null)
                        {
                            Console.WriteLine(adtid + " is still using old filenames, skipping!");
                        }
                        else
                        {
                            foreach (var worldmodel in adtreader.adtfile.objects.worldModels.entries)
                            {
                                if (inserted.Contains(worldmodel.mwidEntry))
                                {
                                    continue;
                                }

                                inserted.Add(worldmodel.mwidEntry);
                                insertEntry(insertCmd, worldmodel.mwidEntry, "adt worldmodel");
                            }

                            foreach (var doodad in adtreader.adtfile.objects.models.entries)
                            {
                                if (inserted.Contains(doodad.mmidEntry))
                                {
                                    continue;
                                }

                                insertEntry(insertCmd, doodad.mmidEntry, "adt doodad");
                                inserted.Add(doodad.mmidEntry);
                            }
                        }
                    }
                }
            }
            #endregion
        }
Пример #14
0
        public static void LoadM2(string filename, CacheStorage cache, int shaderProgram)
        {
            filename = filename.ToLower().Replace(".mdx", ".m2");
            filename = filename.ToLower().Replace(".mdl", ".m2");

            if (cache.doodadBatches.ContainsKey(filename))
            {
                return;
            }

            var model = new WoWFormatLib.Structs.M2.M2Model();

            if (cache.models.ContainsKey(filename))
            {
                model = cache.models[filename];
            }
            else
            {
                if (Listfile.TryGetFileDataID(filename, out var filedataid))
                {
                    if (WoWFormatLib.Utils.CASC.FileExists(filedataid))
                    {
                        var modelreader = new M2Reader();
                        modelreader.LoadM2(filedataid);
                        cache.models.Add(filename, modelreader.model);
                        model = modelreader.model;
                    }
                    else
                    {
                        throw new Exception("Model " + filename + " does not exist!");
                    }
                }
                else
                {
                    throw new Exception("Filename " + filename + " does not exist in listfile!");
                }
            }

            if (model.boundingbox == null)
            {
                CASCLib.Logger.WriteLine("Error during loading file: {0}, bounding box is not defined", filename);
                return;
            }

            var ddBatch = new Renderer.Structs.DoodadBatch()
            {
                boundingBox = new Renderer.Structs.BoundingBox()
                {
                    min = new Vector3(model.boundingbox[0].X, model.boundingbox[0].Y, model.boundingbox[0].Z),
                    max = new Vector3(model.boundingbox[1].X, model.boundingbox[1].Y, model.boundingbox[1].Z)
                }
            };

            if (model.textures == null)
            {
                CASCLib.Logger.WriteLine("Error during loading file: {0}, model has no textures", filename);
                return;
            }

            if (model.skins == null)
            {
                CASCLib.Logger.WriteLine("Error during loading file: {0}, model has no skins", filename);
                return;
            }

            // Textures
            ddBatch.mats = new Renderer.Structs.Material[model.textures.Count()];

            for (var i = 0; i < model.textures.Count(); i++)
            {
                uint textureFileDataID = 528732;
                ddBatch.mats[i].flags = model.textures[i].flags;

                switch (model.textures[i].type)
                {
                case 0:
                    if (model.textureFileDataIDs != null && model.textureFileDataIDs.Length > 0 && model.textureFileDataIDs[i] != 0)
                    {
                        textureFileDataID = model.textureFileDataIDs[i];
                    }
                    else
                    {
                        textureFileDataID = WoWFormatLib.Utils.CASC.getFileDataIdByName(model.textures[i].filename);
                    }
                    break;

                case 1:
                case 2:
                case 11:
                default:
                    textureFileDataID = 528732;
                    break;
                }

                // Not set in TXID
                if (textureFileDataID == 0)
                {
                    textureFileDataID = 528732;
                }

                ddBatch.mats[i].textureID = BLPLoader.LoadTexture(textureFileDataID, cache);
                ddBatch.mats[i].filename  = textureFileDataID.ToString();
            }

            // Submeshes
            ddBatch.submeshes = new Renderer.Structs.Submesh[model.skins[0].submeshes.Count()];
            for (var i = 0; i < model.skins[0].submeshes.Count(); i++)
            {
                if (filename.StartsWith("character"))
                {
                    if (model.skins[0].submeshes[i].submeshID != 0)
                    {
                        if (!model.skins[0].submeshes[i].submeshID.ToString().EndsWith("01"))
                        {
                            continue;
                        }
                    }
                }

                ddBatch.submeshes[i].firstFace = model.skins[0].submeshes[i].startTriangle;
                ddBatch.submeshes[i].numFaces  = model.skins[0].submeshes[i].nTriangles;
                for (var tu = 0; tu < model.skins[0].textureunit.Count(); tu++)
                {
                    if (model.skins[0].textureunit[tu].submeshIndex == i)
                    {
                        ddBatch.submeshes[i].blendType = model.renderflags[model.skins[0].textureunit[tu].renderFlags].blendingMode;

                        uint textureFileDataID = 528732;

                        if (model.textureFileDataIDs != null && model.textureFileDataIDs.Length > 0 && model.textureFileDataIDs[model.texlookup[model.skins[0].textureunit[tu].texture].textureID] != 0)
                        {
                            textureFileDataID = model.textureFileDataIDs[model.texlookup[model.skins[0].textureunit[tu].texture].textureID];
                        }
                        else
                        {
                            if (Listfile.FilenameToFDID.TryGetValue(model.textures[model.texlookup[model.skins[0].textureunit[tu].texture].textureID].filename.Replace('\\', '/').ToLower(), out var filedataid))
                            {
                                textureFileDataID = filedataid;
                            }
                            else
                            {
                                textureFileDataID = 528732;
                            }
                        }

                        if (!cache.materials.ContainsKey(textureFileDataID))
                        {
                            throw new Exception("MaterialCache does not have texture " + textureFileDataID);
                        }

                        ddBatch.submeshes[i].material = (uint)cache.materials[textureFileDataID];
                    }
                }
            }

            ddBatch.vao = GL.GenVertexArray();
            GL.BindVertexArray(ddBatch.vao);

            // Vertices & indices
            ddBatch.vertexBuffer = GL.GenBuffer();
            ddBatch.indiceBuffer = GL.GenBuffer();

            GL.BindBuffer(BufferTarget.ArrayBuffer, ddBatch.vertexBuffer);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, ddBatch.indiceBuffer);

            var modelindicelist = new List <uint>();

            for (var i = 0; i < model.skins[0].triangles.Count(); i++)
            {
                modelindicelist.Add(model.skins[0].triangles[i].pt1);
                modelindicelist.Add(model.skins[0].triangles[i].pt2);
                modelindicelist.Add(model.skins[0].triangles[i].pt3);
            }

            var modelindices = modelindicelist.ToArray();

            ddBatch.indices = modelindices;

            GL.BindBuffer(BufferTarget.ElementArrayBuffer, ddBatch.indiceBuffer);
            GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(ddBatch.indices.Length * sizeof(uint)), ddBatch.indices, BufferUsageHint.StaticDraw);

            var modelvertices = new Renderer.Structs.M2Vertex[model.vertices.Count()];

            for (var i = 0; i < model.vertices.Count(); i++)
            {
                modelvertices[i].Position = new Vector3(model.vertices[i].position.X, model.vertices[i].position.Y, model.vertices[i].position.Z);
                modelvertices[i].Normal   = new Vector3(model.vertices[i].normal.X, model.vertices[i].normal.Y, model.vertices[i].normal.Z);
                modelvertices[i].TexCoord = new Vector2(model.vertices[i].textureCoordX, model.vertices[i].textureCoordY);
            }
            GL.BindBuffer(BufferTarget.ArrayBuffer, ddBatch.vertexBuffer);
            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(modelvertices.Length * 8 * sizeof(float)), modelvertices, BufferUsageHint.StaticDraw);

            //Set pointers in buffer
            //var normalAttrib = GL.GetAttribLocation(shaderProgram, "normal");
            //GL.EnableVertexAttribArray(normalAttrib);
            //GL.VertexAttribPointer(normalAttrib, 3, VertexAttribPointerType.Float, false, sizeof(float) * 8, sizeof(float) * 0);

            var texCoordAttrib = GL.GetAttribLocation(shaderProgram, "texCoord");

            GL.EnableVertexAttribArray(texCoordAttrib);
            GL.VertexAttribPointer(texCoordAttrib, 2, VertexAttribPointerType.Float, false, sizeof(float) * 8, sizeof(float) * 3);

            var posAttrib = GL.GetAttribLocation(shaderProgram, "position");

            GL.EnableVertexAttribArray(posAttrib);
            GL.VertexAttribPointer(posAttrib, 3, VertexAttribPointerType.Float, false, sizeof(float) * 8, sizeof(float) * 5);
            cache.doodadBatches.Add(filename, ddBatch);
        }
Пример #15
0
        private static uint MISSING_TEXTURE_ID = 186184; // textures/shanecube.blp

        public static Renderer.Structs.DoodadBatch LoadM2(string fileName, int shaderProgram)
        {
            fileName = fileName.ToLower().Replace(".mdx", ".m2");
            fileName = fileName.ToLower().Replace(".mdl", ".m2");

            M2Model model = new M2Model();

            if (Listfile.TryGetFileDataID(fileName, out var fileDataID))
            {
                if (WoWFormatLib.Utils.CASC.FileExists(fileDataID))
                {
                    var modelReader = new M2Reader();
                    modelReader.LoadM2(fileDataID);
                    model = modelReader.model;
                }
                else
                {
                    throw new Exception("Model " + fileName + " does not exist!");
                }
            }
            else
            {
                throw new Exception("Filename " + fileName + " does not exist in listfile!");
            }

            if (model.boundingbox == null)
            {
                throw new Exception("Model does not contain bounding box: " + fileName);
            }

            var doodadBatch = new Renderer.Structs.DoodadBatch()
            {
                boundingBox = new Renderer.Structs.BoundingBox()
                {
                    min = new Vector3(model.boundingbox[0].X, model.boundingbox[0].Y, model.boundingbox[0].Z),
                    max = new Vector3(model.boundingbox[1].X, model.boundingbox[1].Y, model.boundingbox[1].Z)
                }
            };

            if (model.textures == null)
            {
                throw new Exception("Model does not contain textures: " + fileName);
            }

            if (model.skins == null)
            {
                throw new Exception("Model does not contain skins: " + fileName);
            }

            // Textures
            doodadBatch.mats = new Renderer.Structs.Material[model.textures.Count()];
            for (var i = 0; i < model.textures.Count(); i++)
            {
                uint textureFileDataID = DEFAULT_TEXTURE_ID;
                doodadBatch.mats[i].flags = model.textures[i].flags;

                switch (model.textures[i].type)
                {
                case 0:     // NONE
                    if (model.textureFileDataIDs != null && model.textureFileDataIDs.Length > 0 && model.textureFileDataIDs[i] != 0)
                    {
                        textureFileDataID = model.textureFileDataIDs[i];
                    }
                    else
                    {
                        textureFileDataID = WoWFormatLib.Utils.CASC.getFileDataIdByName(model.textures[i].filename);
                    }
                    break;

                case 1:     // TEX_COMPONENT_SKIN
                case 2:     // TEX_COMPONENT_OBJECT_SKIN
                case 11:    // TEX_COMPONENT_MONSTER_1
                    break;
                }

                // Not set in TXID
                if (textureFileDataID == 0)
                {
                    textureFileDataID = DEFAULT_TEXTURE_ID;
                }

                if (!WoWFormatLib.Utils.CASC.FileExists(textureFileDataID))
                {
                    textureFileDataID = MISSING_TEXTURE_ID;
                }

                doodadBatch.mats[i].textureID = BLPLoader.LoadTexture(textureFileDataID);
                doodadBatch.mats[i].filename  = textureFileDataID.ToString();
            }

            // Submeshes
            doodadBatch.submeshes = new Renderer.Structs.Submesh[model.skins[0].submeshes.Count()];
            for (var i = 0; i < model.skins[0].submeshes.Count(); i++)
            {
                doodadBatch.submeshes[i].firstFace = model.skins[0].submeshes[i].startTriangle;
                doodadBatch.submeshes[i].numFaces  = model.skins[0].submeshes[i].nTriangles;
                for (var tu = 0; tu < model.skins[0].textureunit.Count(); tu++)
                {
                    if (model.skins[0].textureunit[tu].submeshIndex == i)
                    {
                        doodadBatch.submeshes[i].blendType = model.renderflags[model.skins[0].textureunit[tu].renderFlags].blendingMode;

                        uint textureFileDataID = DEFAULT_TEXTURE_ID;
                        if (!WoWFormatLib.Utils.CASC.FileExists(textureFileDataID))
                        {
                            textureFileDataID = MISSING_TEXTURE_ID;
                        }

                        if (model.textureFileDataIDs != null && model.textureFileDataIDs.Length > 0 && model.textureFileDataIDs[model.texlookup[model.skins[0].textureunit[tu].texture].textureID] != 0)
                        {
                            textureFileDataID = model.textureFileDataIDs[model.texlookup[model.skins[0].textureunit[tu].texture].textureID];
                        }
                        else
                        {
                            if (Listfile.FilenameToFDID.TryGetValue(model.textures[model.texlookup[model.skins[0].textureunit[tu].texture].textureID].filename.Replace('\\', '/').ToLower(), out var filedataid))
                            {
                                textureFileDataID = filedataid;
                            }
                            else
                            {
                                textureFileDataID = DEFAULT_TEXTURE_ID;
                                if (!WoWFormatLib.Utils.CASC.FileExists(textureFileDataID))
                                {
                                    textureFileDataID = MISSING_TEXTURE_ID;
                                }
                            }
                        }

                        if (!WoWFormatLib.Utils.CASC.FileExists(textureFileDataID))
                        {
                            textureFileDataID = MISSING_TEXTURE_ID;
                        }

                        doodadBatch.submeshes[i].material = (uint)BLPLoader.LoadTexture(textureFileDataID);
                    }
                }
            }

            doodadBatch.vao = GL.GenVertexArray();
            GL.BindVertexArray(doodadBatch.vao);

            // Vertices & indices
            doodadBatch.vertexBuffer = GL.GenBuffer();
            doodadBatch.indiceBuffer = GL.GenBuffer();

            GL.BindBuffer(BufferTarget.ArrayBuffer, doodadBatch.vertexBuffer);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, doodadBatch.indiceBuffer);

            var modelindicelist = new List <uint>();

            for (var i = 0; i < model.skins[0].triangles.Count(); i++)
            {
                modelindicelist.Add(model.skins[0].triangles[i].pt1);
                modelindicelist.Add(model.skins[0].triangles[i].pt2);
                modelindicelist.Add(model.skins[0].triangles[i].pt3);
            }

            var modelindices = modelindicelist.ToArray();

            doodadBatch.indices = modelindices;

            GL.BindBuffer(BufferTarget.ElementArrayBuffer, doodadBatch.indiceBuffer);
            GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(doodadBatch.indices.Length * sizeof(uint)), doodadBatch.indices, BufferUsageHint.StaticDraw);

            var modelvertices = new Renderer.Structs.M2Vertex[model.vertices.Count()];

            for (var i = 0; i < model.vertices.Count(); i++)
            {
                modelvertices[i].Position = new Vector3(model.vertices[i].position.X, model.vertices[i].position.Y, model.vertices[i].position.Z);
                modelvertices[i].Normal   = new Vector3(model.vertices[i].normal.X, model.vertices[i].normal.Y, model.vertices[i].normal.Z);
                modelvertices[i].TexCoord = new Vector2(model.vertices[i].textureCoordX, model.vertices[i].textureCoordY);
            }
            GL.BindBuffer(BufferTarget.ArrayBuffer, doodadBatch.vertexBuffer);
            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(modelvertices.Length * 8 * sizeof(float)), modelvertices, BufferUsageHint.StaticDraw);

            //Set pointers in buffer
            //var normalAttrib = GL.GetAttribLocation(shaderProgram, "normal");
            //GL.EnableVertexAttribArray(normalAttrib);
            //GL.VertexAttribPointer(normalAttrib, 3, VertexAttribPointerType.Float, false, sizeof(float) * 8, sizeof(float) * 0);

            var texCoordAttrib = GL.GetAttribLocation(shaderProgram, "texCoord");

            GL.EnableVertexAttribArray(texCoordAttrib);
            GL.VertexAttribPointer(texCoordAttrib, 2, VertexAttribPointerType.Float, false, sizeof(float) * 8, sizeof(float) * 3);

            var posAttrib = GL.GetAttribLocation(shaderProgram, "position");

            GL.EnableVertexAttribArray(posAttrib);
            GL.VertexAttribPointer(posAttrib, 3, VertexAttribPointerType.Float, false, sizeof(float) * 8, sizeof(float) * 5);

            return(doodadBatch);
        }
Пример #16
0
        public static void ExportM2(string file, BackgroundWorker exportworker = null, string destinationOverride = null, string outdir = "", uint filedataid = 0)
        {
            if (exportworker == null)
            {
                exportworker = new BackgroundWorker();
                exportworker.WorkerReportsProgress = true;
            }

            Console.WriteLine("M2 glTF Exporter: Loading file {0}...", file);

            exportworker.ReportProgress(5, "Reading M2..");

            var reader = new M2Reader();

            if (filedataid != 0)
            {
                reader.LoadM2(filedataid);
            }
            else
            {
                reader.LoadM2(file);
            }

            var customCulture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();

            customCulture.NumberFormat.NumberDecimalSeparator    = ".";
            System.Threading.Thread.CurrentThread.CurrentCulture = customCulture;

            if (destinationOverride == null)
            {
                if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(file))))
                {
                    Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file)));
                }
            }

            file = file.ToLower();

            if (reader.model.vertices.Count() == 0)
            {
                Console.WriteLine("M2 glTF Exporter: File {0} has no vertices, skipping export!", file);
                return;
            }

            exportworker.ReportProgress(25, "Generating glTF..");

            var glTF = new glTF()
            {
                asset = new Asset()
                {
                    version    = "2.0",
                    generator  = "Marlamin's WoW Exporter " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(),
                    copyright  = "Contents are owned by Blizzard Entertainment",
                    minVersion = "2.0"
                }
            };

            FileStream stream;

            if (destinationOverride == null)
            {
                stream = new FileStream(Path.Combine(outdir, file.Replace(".m2", ".bin")), FileMode.OpenOrCreate);
            }
            else
            {
                stream = new FileStream(Path.Combine(destinationOverride, Path.GetFileNameWithoutExtension(file).ToLower() + ".bin"), FileMode.OpenOrCreate);
            }

            var writer       = new BinaryWriter(stream);
            var bufferViews  = new List <BufferView>();
            var accessorInfo = new List <Accessor>();
            var meshes       = new List <Mesh>();

            // Position bufferview
            var vPosBuffer = new BufferView()
            {
                buffer     = 0,
                byteOffset = (uint)writer.BaseStream.Position,
                target     = 34962
            };

            var minPosX = float.MaxValue;
            var minPosY = float.MaxValue;
            var minPosZ = float.MaxValue;

            var maxPosX = float.MinValue;
            var maxPosY = float.MinValue;
            var maxPosZ = float.MinValue;

            for (var i = 0; i < reader.model.vertices.Count(); i++)
            {
                writer.Write(reader.model.vertices[i].position.X);
                writer.Write(reader.model.vertices[i].position.Z);
                writer.Write(reader.model.vertices[i].position.Y * -1);

                if (reader.model.vertices[i].position.X < minPosX)
                {
                    minPosX = reader.model.vertices[i].position.X;
                }
                if (reader.model.vertices[i].position.Z < minPosY)
                {
                    minPosY = reader.model.vertices[i].position.Z;
                }
                if (reader.model.vertices[i].position.Y * -1 < minPosZ)
                {
                    minPosZ = reader.model.vertices[i].position.Y * -1;
                }

                if (reader.model.vertices[i].position.X > maxPosX)
                {
                    maxPosX = reader.model.vertices[i].position.X;
                }
                if (reader.model.vertices[i].position.Z > maxPosY)
                {
                    maxPosY = reader.model.vertices[i].position.Z;
                }
                if (reader.model.vertices[i].position.Y * -1 > maxPosZ)
                {
                    maxPosZ = reader.model.vertices[i].position.Y * -1;
                }
            }

            vPosBuffer.byteLength = (uint)writer.BaseStream.Position - vPosBuffer.byteOffset;

            var posLoc = accessorInfo.Count();

            accessorInfo.Add(new Accessor()
            {
                name          = "vPos",
                bufferView    = bufferViews.Count(),
                byteOffset    = 0,
                componentType = 5126,
                count         = (uint)reader.model.vertices.Count(),
                type          = "VEC3",
                min           = new float[] { minPosX, minPosY, minPosZ },
                max           = new float[] { maxPosX, maxPosY, maxPosZ }
            });

            bufferViews.Add(vPosBuffer);

            // Normal bufferview
            var normalBuffer = new BufferView()
            {
                buffer     = 0,
                byteOffset = (uint)writer.BaseStream.Position,
                target     = 34962
            };

            for (var i = 0; i < reader.model.vertices.Count(); i++)
            {
                writer.Write(reader.model.vertices[i].normal.X);
                writer.Write(reader.model.vertices[i].normal.Z);
                writer.Write(reader.model.vertices[i].normal.Y);
            }

            normalBuffer.byteLength = (uint)writer.BaseStream.Position - normalBuffer.byteOffset;

            var normalLoc = accessorInfo.Count();

            accessorInfo.Add(new Accessor()
            {
                name          = "vNormal",
                bufferView    = bufferViews.Count(),
                byteOffset    = 0,
                componentType = 5126,
                count         = (uint)reader.model.vertices.Count(),
                type          = "VEC3"
            });

            bufferViews.Add(normalBuffer);

            // TexCoord bufferview
            var texCoordBuffer = new BufferView()
            {
                buffer     = 0,
                byteOffset = (uint)writer.BaseStream.Position,
                target     = 34962
            };

            for (var i = 0; i < reader.model.vertices.Count(); i++)
            {
                writer.Write(reader.model.vertices[i].textureCoordX);
                writer.Write(reader.model.vertices[i].textureCoordY);
            }

            texCoordBuffer.byteLength = (uint)writer.BaseStream.Position - texCoordBuffer.byteOffset;

            var texLoc = accessorInfo.Count();

            accessorInfo.Add(new Accessor()
            {
                name          = "vTex",
                bufferView    = bufferViews.Count(),
                byteOffset    = 0,
                componentType = 5126,
                count         = (uint)reader.model.vertices.Count(),
                type          = "VEC2"
            });

            bufferViews.Add(texCoordBuffer);

            // Joints bufferview
            var jointBuffer = new BufferView()
            {
                buffer     = 0,
                byteOffset = (uint)writer.BaseStream.Position,
                target     = 34962
            };

            for (var i = 0; i < reader.model.vertices.Count(); i++)
            {
                writer.Write(reader.model.vertices[i].boneIndices_0);
                writer.Write(reader.model.vertices[i].boneIndices_1);
                writer.Write(reader.model.vertices[i].boneIndices_2);
                writer.Write(reader.model.vertices[i].boneIndices_3);
            }

            jointBuffer.byteOffset = (uint)writer.BaseStream.Position - jointBuffer.byteOffset;

            var jointLoc = accessorInfo.Count();

            accessorInfo.Add(new Accessor()
            {
                name          = "vJoint",
                bufferView    = bufferViews.Count(),
                byteOffset    = 0,
                componentType = 5121,
                count         = (uint)reader.model.vertices.Count(),
                type          = "VEC4"
            });

            bufferViews.Add(jointBuffer);

            // Weight bufferview
            var weightBuffer = new BufferView()
            {
                buffer     = 0,
                byteOffset = (uint)writer.BaseStream.Position,
                target     = 34962
            };

            for (var i = 0; i < reader.model.vertices.Count(); i++)
            {
                writer.Write(reader.model.vertices[i].boneWeight_0);
                writer.Write(reader.model.vertices[i].boneWeight_1);
                writer.Write(reader.model.vertices[i].boneWeight_2);
                writer.Write(reader.model.vertices[i].boneWeight_3);
            }

            weightBuffer.byteOffset = (uint)writer.BaseStream.Position - weightBuffer.byteOffset;

            var weightLoc = accessorInfo.Count();

            accessorInfo.Add(new Accessor()
            {
                name          = "vWeight",
                bufferView    = bufferViews.Count(),
                byteOffset    = 0,
                componentType = 5121,
                count         = (uint)reader.model.vertices.Count(),
                type          = "VEC4"
            });

            bufferViews.Add(weightBuffer);

            // End of element bufferviews
            var indexBufferPos = bufferViews.Count();
            var materialBlends = new Dictionary <int, ushort>();

            for (var i = 0; i < reader.model.skins[0].submeshes.Count(); i++)
            {
                var batch = reader.model.skins[0].submeshes[i];

                accessorInfo.Add(new Accessor()
                {
                    name          = "indices",
                    bufferView    = indexBufferPos,
                    byteOffset    = reader.model.skins[0].submeshes[i].startTriangle * 2,
                    componentType = 5123,
                    count         = reader.model.skins[0].submeshes[i].nTriangles,
                    type          = "SCALAR"
                });

                var mesh = new Mesh();
                mesh.name       = "Group #" + i;
                mesh.primitives = new Primitive[1];
                mesh.primitives[0].attributes = new Dictionary <string, int>
                {
                    { "POSITION", posLoc },
                    { "NORMAL", normalLoc },
                    { "TEXCOORD_0", texLoc },
                    { "JOINTS_0", jointLoc },
                    { "WEIGHTS_0", weightLoc }
                };

                mesh.primitives[0].indices = (uint)accessorInfo.Count() - 1;
                mesh.primitives[0].mode    = 4;

                meshes.Add(mesh);
                // Texture stuff
                for (var tu = 0; tu < reader.model.skins[0].textureunit.Count(); tu++)
                {
                    if (reader.model.skins[0].textureunit[tu].submeshIndex == i)
                    {
                        mesh.primitives[0].material = reader.model.texlookup[reader.model.skins[0].textureunit[tu].texture].textureID;

                        // todo
                        if (!materialBlends.ContainsKey(i))
                        {
                            // add texture
                            materialBlends.Add(i, reader.model.renderflags[reader.model.skins[0].textureunit[tu].renderFlags].blendingMode);
                        }
                        else
                        {
                            // already exists
                            Console.WriteLine("Material " + mesh.primitives[0].material + " already exists in blend map with value " + materialBlends[i]);
                        }
                    }
                }
            }

            var indiceBuffer = new BufferView()
            {
                buffer     = 0,
                byteOffset = (uint)writer.BaseStream.Position,
                target     = 34963
            };

            for (var i = 0; i < reader.model.skins[0].triangles.Count(); i++)
            {
                var t = reader.model.skins[0].triangles[i];
                writer.Write(t.pt1);
                writer.Write(t.pt2);
                writer.Write(t.pt3);
            }

            indiceBuffer.byteLength = (uint)writer.BaseStream.Position - indiceBuffer.byteOffset;
            bufferViews.Add(indiceBuffer);

            glTF.bufferViews = bufferViews.ToArray();
            glTF.accessors   = accessorInfo.ToArray();

            glTF.buffers = new Buffer[1];
            glTF.buffers[0].byteLength = (uint)writer.BaseStream.Length;
            glTF.buffers[0].uri        = Path.GetFileNameWithoutExtension(file) + ".bin";

            writer.Close();
            writer.Dispose();

            exportworker.ReportProgress(65, "Exporting textures..");

            var materialCount = reader.model.textures.Count();

            glTF.images    = new Image[materialCount];
            glTF.textures  = new Texture[materialCount];
            glTF.materials = new Material[materialCount];

            var textureID = 0;
            var materials = new Structs.Material[reader.model.textures.Count()];

            for (var i = 0; i < reader.model.textures.Count(); i++)
            {
                uint textureFileDataID = 903224;
                materials[i].flags = reader.model.textures[i].flags;
                switch (reader.model.textures[i].type)
                {
                case 0:
                    textureFileDataID = reader.model.textureFileDataIDs[i];
                    break;

                case 1:
                case 2:
                case 11:
                default:
                    Console.WriteLine("      Falling back to placeholder texture");
                    break;
                }

                // Check if texture is a replacable texture, return test texture for now
                if (textureFileDataID == 0)
                {
                    textureFileDataID = 903224;
                }
                materials[i].textureID = textureID + i;

                materials[i].filename = textureFileDataID.ToString();

                glTF.materials[i].name = materials[i].filename;
                glTF.materials[i].pbrMetallicRoughness = new PBRMetallicRoughness();
                glTF.materials[i].pbrMetallicRoughness.baseColorTexture       = new TextureIndex();
                glTF.materials[i].pbrMetallicRoughness.baseColorTexture.index = i;
                glTF.materials[i].pbrMetallicRoughness.metallicFactor         = 0.0f;

                glTF.materials[i].alphaMode   = "MASK";
                glTF.materials[i].alphaCutoff = 0.5f;

                glTF.images[i].uri       = "tex_" + materials[i].filename + ".png";
                glTF.textures[i].sampler = 0;
                glTF.textures[i].source  = i;

                var blpreader = new BLPReader();
                blpreader.LoadBLP(textureFileDataID);

                try
                {
                    if (destinationOverride == null)
                    {
                        blpreader.bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(file), glTF.images[i].uri));
                    }
                    else
                    {
                        blpreader.bmp.Save(Path.Combine(outdir, destinationOverride, glTF.images[i].uri));
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
            }

            exportworker.ReportProgress(85, "Writing files..");

            glTF.samplers              = new Sampler[1];
            glTF.samplers[0].name      = "Default Sampler";
            glTF.samplers[0].minFilter = 9986;
            glTF.samplers[0].magFilter = 9729;
            glTF.samplers[0].wrapS     = 10497;
            glTF.samplers[0].wrapT     = 10497;

            glTF.scenes         = new Scene[1];
            glTF.scenes[0].name = Path.GetFileNameWithoutExtension(file);

            glTF.nodes = new Node[meshes.Count()];
            var meshIDs = new List <int>();

            for (var i = 0; i < meshes.Count(); i++)
            {
                glTF.nodes[i].name = meshes[i].name;
                glTF.nodes[i].mesh = i;
                meshIDs.Add(i);
            }

            glTF.scenes[0].nodes = meshIDs.ToArray();

            glTF.meshes = meshes.ToArray();

            glTF.scene = 0;

            exportworker.ReportProgress(95, "Writing to file..");

            if (destinationOverride == null)
            {
                File.WriteAllText(Path.Combine(outdir, file.Replace(".m2", ".gltf")), JsonConvert.SerializeObject(glTF, Formatting.Indented, new JsonSerializerSettings
                {
                    NullValueHandling = NullValueHandling.Ignore
                }));
            }
            else
            {
                File.WriteAllText(Path.Combine(destinationOverride, Path.GetFileName(file.ToLower()).Replace(".m2", ".gltf")), JsonConvert.SerializeObject(glTF, Formatting.Indented, new JsonSerializerSettings
                {
                    NullValueHandling = NullValueHandling.Ignore
                }));
            }

            /*
             * objsw.WriteLine("g " + Path.GetFileNameWithoutExtension(file));
             *
             * foreach (var renderbatch in renderbatches)
             * {
             *  var i = renderbatch.firstFace;
             *  objsw.WriteLine("o " + Path.GetFileNameWithoutExtension(file) + renderbatch.groupID);
             *  objsw.WriteLine("usemtl tex_" + materials[renderbatch.materialID].filename);
             *  objsw.WriteLine("s 1");
             *  while (i < (renderbatch.firstFace + renderbatch.numFaces))
             *  {
             *      objsw.WriteLine("f " + (indices[i] + 1) + "/" + (indices[i] + 1) + "/" + (indices[i] + 1) + " " + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + " " + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1));
             *      i = i + 3;
             *  }
             * }
             *
             * objsw.Close();
             *
             * // Only export phys when exporting a single M2, causes issues for some users when combined with WMO/ADT
             * if (destinationOverride == null)
             * {
             *  exportworker.ReportProgress(90, "Exporting collision..");
             *
             *  objsw = new StreamWriter(Path.Combine(outdir, file.Replace(".m2", ".phys.obj")));
             *
             *  objsw.WriteLine("# Written by Marlamin's WoW Exporter. Original file: " + file);
             *
             *  for (int i = 0; i < reader.model.boundingvertices.Count(); i++)
             *  {
             *      objsw.WriteLine("v " +
             *           reader.model.boundingvertices[i].vertex.X + " " +
             *           reader.model.boundingvertices[i].vertex.Z + " " +
             *          -reader.model.boundingvertices[i].vertex.Y);
             *  }
             *
             *  for (int i = 0; i < reader.model.boundingtriangles.Count(); i++)
             *  {
             *      var t = reader.model.boundingtriangles[i];
             *      objsw.WriteLine("f " + (t.index_0 + 1) + " " + (t.index_1 + 1) + " " + (t.index_2 + 1));
             *  }
             *
             *  objsw.Close();
             * }
             *
             * // https://en.wikipedia.org/wiki/Wavefront_.obj_file#Basic_materials
             * // http://wiki.unity3d.com/index.php?title=ExportOBJ
             * // http://web.cse.ohio-state.edu/~hwshen/581/Site/Lab3_files/Labhelp_Obj_parser.htm
             */
        }
Пример #17
0
        public Render()
        {
            using (var dg = new DisposeGroup())
            {
                //Load Shaders
                var pVSBlob        = dg.Add(ShaderBytecode.CompileFromFile("RenderWithCam.fx", "VS", "vs_4_0"));
                var inputSignature = dg.Add(ShaderSignature.GetInputSignature(pVSBlob));
                m_pVertexShader = new VertexShader(Device, pVSBlob);

                var pPSBlob = dg.Add(ShaderBytecode.CompileFromFile("RenderWithCam.fx", "PS", "ps_4_0"));
                m_pPixelShader = new PixelShader(Device, pPSBlob);

                //Define layout
                var layout = dg.Add(new InputLayout(Device, inputSignature, new[] {
                    new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
                    new InputElement("TEXCOORD", 0, Format.R32G32_Float, 16, 0)
                }));

                //Load model
                M2Reader reader = new M2Reader("Z:\\18566_full\\");
                reader.LoadM2(@"World\ArtTest\Boxtest\xyz.m2");

                //Load vertices
                List <float> verticelist = new List <float>();
                for (int i = 0; i < reader.model.vertices.Count(); i++)
                {
                    verticelist.Add(reader.model.vertices[i].position.X);
                    verticelist.Add(reader.model.vertices[i].position.Z * -1);
                    verticelist.Add(reader.model.vertices[i].position.Y);
                    verticelist.Add(1.0f);
                    verticelist.Add(reader.model.vertices[i].textureCoordX);
                    verticelist.Add(reader.model.vertices[i].textureCoordY);
                }

                //Load indices
                List <ushort> indicelist = new List <ushort>();
                for (int i = 0; i < reader.model.skins[0].triangles.Count(); i++)
                {
                    indicelist.Add(reader.model.skins[0].triangles[i].pt1);
                    indicelist.Add(reader.model.skins[0].triangles[i].pt2);
                    indicelist.Add(reader.model.skins[0].triangles[i].pt3);
                }

                //Convert to array
                ushort[] indices  = indicelist.ToArray();
                float[]  vertices = verticelist.ToArray();

                //Set count for use in draw later on
                indicecount = indices.Count();

                //Create buffers
                var vertexBuffer        = dg.Add(Buffer.Create(Device, BindFlags.VertexBuffer, vertices));
                var vertexBufferBinding = new VertexBufferBinding(vertexBuffer, Utilities.SizeOf <Vector4>() + Utilities.SizeOf <Vector2>(), 0);
                var indexBuffer         = dg.Add(Buffer.Create(Device, BindFlags.IndexBuffer, indices));

                Device.ImmediateContext.InputAssembler.InputLayout = (layout);
                Device.ImmediateContext.InputAssembler.SetVertexBuffers(0, vertexBufferBinding);
                Device.ImmediateContext.InputAssembler.SetIndexBuffer(indexBuffer, Format.R16_UInt, 0);
                Device.ImmediateContext.InputAssembler.PrimitiveTopology = (PrimitiveTopology.TriangleList);

                //Get texture, what a mess this could be much better
                var blp = new BLPReader("Z:\\18566_full\\");
                if (File.Exists(Path.Combine("Z:\\18566_full\\", reader.model.filename.Replace("M2", "blp"))))
                {
                    blp.LoadBLP(reader.model.filename.Replace("M2", "blp"));
                }
                else
                {
                    if (reader.model.textures.Count() > 0)
                    {
                        blp.LoadBLP(reader.model.textures[0]);
                    }
                    else
                    {
                        throw new Exception("No forking textures, mate.");
                    }
                }

                MemoryStream s = new MemoryStream();
                blp.bmp.Save(s, System.Drawing.Imaging.ImageFormat.Png);
                s.Seek(0, SeekOrigin.Begin);
                Texture2D texture = Texture2D.FromMemory <Texture2D>(Device, s.ToArray());

                var textureView = new ShaderResourceView(Device, texture);

                var sampler = new SamplerState(Device, new SamplerStateDescription()
                {
                    Filter             = Filter.MinMagMipLinear,
                    AddressU           = TextureAddressMode.Wrap,
                    AddressV           = TextureAddressMode.Wrap,
                    AddressW           = TextureAddressMode.Wrap,
                    BorderColor        = SharpDX.Color.Black,
                    ComparisonFunction = Comparison.Never,
                    MaximumAnisotropy  = 16,
                    MipLodBias         = 0,
                    MinimumLod         = 0,
                    MaximumLod         = 16,
                });

                Device.ImmediateContext.PixelShader.SetSampler(0, sampler);
                Device.ImmediateContext.PixelShader.SetShaderResource(0, textureView);
                //End of texture stuff,

                Set(ref m_pConstantBuffer, new ConstantBuffer <Projections>(Device));
                Device.ImmediateContext.VertexShader.SetConstantBuffer(0, m_pConstantBuffer.Buffer);
            }

            //Make camera
            Camera = new FirstPersonCamera();
            Camera.SetProjParams((float)Math.PI / 2, 1, 0.01f, 100.0f);
            Camera.SetViewParams(new Vector3(0.0f, 0.0f, -5.0f), new Vector3(0.0f, 1.0f, 0.0f));
        }