Ejemplo n.º 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();
        }
Ejemplo n.º 2
0
        private void LoadTile(int[] tile)
        {
            var       x = tile[0];
            var       y = tile[1];
            string    _SelectedMapName = _map;
            Rectangle rect             = new Rectangle();

            rect.Name                = _SelectedMapName.Replace("'", string.Empty).Replace(" ", string.Empty) + "_" + x.ToString("D2") + "_" + y.ToString("D2"); //leading zeros just like adts (TODO: NOT REALLY), this breaks when the mapname has special characters (zg)D:
            rect.Width               = WDTGrid.Width / 64;
            rect.Height              = WDTGrid.Height / 64;
            rect.VerticalAlignment   = VerticalAlignment.Top;
            rect.HorizontalAlignment = HorizontalAlignment.Left;
            rect.MouseEnter         += Rect_MouseEnter;
            rect.MouseLeave         += Rect_MouseLeave;
            if (CASC.cascHandler.FileExists(System.IO.Path.Combine(@"world\minimaps\" + _SelectedMapName + "\\map" + x.ToString("D2") + "_" + y.ToString("D2") + ".blp")))
            {
                rect.MouseLeftButtonDown += new MouseButtonEventHandler(Rectangle_Mousedown);
                var xmargin = (x * rect.Width) - (min_x * rect.Width);
                var ymargin = (y * rect.Height) - (min_y * rect.Height);
                rect.Margin = new Thickness(xmargin, ymargin, 0, 0);

                var blp = new BLPReader();
                blp.LoadBLP(@"world\minimaps\" + _SelectedMapName + "\\map" + x.ToString("D2") + "_" + y.ToString("D2") + ".blp");
                BitmapImage bitmapImage = new BitmapImage();

                using (MemoryStream bitmap = blp.asBitmapStream())
                {
                    bitmapImage.BeginInit();
                    bitmapImage.StreamSource      = bitmap;
                    bitmapImage.DecodePixelHeight = Convert.ToInt32(rect.Width);
                    bitmapImage.DecodePixelWidth  = Convert.ToInt32(rect.Height);
                    bitmapImage.CacheOption       = BitmapCacheOption.OnLoad;
                    bitmapImage.EndInit();
                }

                ImageBrush imgBrush = new ImageBrush(bitmapImage);
                rect.Fill = imgBrush;
            }
            else
            {
                var xmargin = (x * rect.Width) - (min_x * rect.Width);
                var ymargin = (y * rect.Height) - (min_y * rect.Height);
                rect.Margin = new Thickness(xmargin, ymargin, 0, 0);
                rect.Fill   = new SolidColorBrush(Color.FromRgb(0, 0, 0));
            }
            WDTGrid.Children.Add(rect);
        }
Ejemplo n.º 3
0
        public static void ExportBLP(string filename, string outdir)
        {
            BLPReader reader = new BLPReader();

            if (!File.Exists(Path.Combine(outdir, filename.Replace(".blp", ".png"))))
            {
                if (!string.IsNullOrEmpty(filename))
                {
                    if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(filename))))
                    {
                        Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(filename)));
                    }
                    reader.LoadBLP(Managers.ArchiveManager.ReadThisFile(filename));
                    reader.bmp.Save(Path.Combine(outdir, filename.Replace(".blp", ".png")));
                }
            }
        }
Ejemplo n.º 4
0
        public void LoadWMO()
        {
            WMOReader reader = new WMOReader(basedir);

            reader.LoadWMO(modelPath);

            WMOMaterial[] materials = new WMOMaterial[reader.wmofile.materials.Count()];
            for (int i = 0; i < reader.wmofile.materials.Count(); i++)
            {
                for (int ti = 0; ti < reader.wmofile.textures.Count(); ti++)
                {
                    if (reader.wmofile.textures[ti].startOffset == reader.wmofile.materials[i].texture1)
                    {
                        Texture2D texture;
                        var       blp = new BLPReader(basedir);
                        blp.LoadBLP(reader.wmofile.textures[ti].filename);
                        if (blp.bmp == null)
                        {
                            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);
                            texture = Texture2D.FromMemory <Texture2D>(device, s.ToArray());
                            s.Dispose();
                        }
                        materials[i].materialID = (uint)i;
                        materials[i].filename   = reader.wmofile.textures[ti].filename;
                        materials[i].texture    = texture;
                    }
                }
            }

            WoWWMOGroup[] groups = new WoWWMOGroup[reader.wmofile.header.nGroups];

            for (int i = 0; i < reader.wmofile.header.nGroups; i++)
            {
                groups[i] = LoadGroupWMO(reader.wmofile.group[i]);
            }

            wmo.materials = materials;
            wmo.groups    = groups;
        }
Ejemplo n.º 5
0
        public static int LoadTexture(string filename, CacheStorage cache)
        {
            GL.ActiveTexture(TextureUnit.Texture0);

            filename = filename.ToLower();

            if (cache.materials.ContainsKey(filename))
            {
                // Console.WriteLine("[CACHE HIT] " + filename);
                return(cache.materials[filename]);
            }

            //Console.WriteLine("[CACHE MISS] " + filename);

            int textureId = GL.GenTexture();

            var blp = new BLPReader();

            blp.LoadBLP(filename);

            if (blp.bmp == null)
            {
                throw new Exception("BMP is null!");
            }
            else
            {
                GL.BindTexture(TextureTarget.Texture2D, textureId);
                cache.materials.Add(filename, textureId);
                System.Drawing.Imaging.BitmapData bmp_data = blp.bmp.LockBits(new System.Drawing.Rectangle(0, 0, blp.bmp.Width, blp.bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmp_data.Width, bmp_data.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bmp_data.Scan0);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
                GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);

                blp.bmp.UnlockBits(bmp_data);
            }

            // Console.WriteLine("[CACHE ADD] " + filename);

            return(textureId);
        }
Ejemplo n.º 6
0
        private void LoadTile(string basedir, int[] tile)
        {
            var       x = tile[0];
            var       y = tile[1];
            string    _SelectedMapName = ((KeyValuePair <int, string>)MapListBox.SelectedValue).Value;
            Rectangle rect             = new Rectangle();

            rect.Name                = _SelectedMapName.Replace("'", string.Empty).Replace(" ", string.Empty) + x.ToString("D2") + "_" + y.ToString("D2"); //leading zeros just like adts, this breaks when the mapname has special characters (zg)D:
            rect.Width               = WDTGrid.Width / 64;
            rect.Height              = WDTGrid.Height / 64;
            rect.VerticalAlignment   = VerticalAlignment.Top;
            rect.HorizontalAlignment = HorizontalAlignment.Left;

            if (File.Exists(basedir + "World\\Minimaps\\" + _SelectedMapName + "\\map" + x.ToString("D2") + "_" + y.ToString("D2") + ".blp"))
            {
                rect.MouseLeftButtonDown += new MouseButtonEventHandler(Rectangle_Mousedown);
                var xmargin = x * rect.Width;
                var ymargin = y * rect.Height;
                rect.Margin = new Thickness(xmargin, ymargin, 0, 0);
                var blp = new BLPReader(basedir);

                //Kalimdor takes a few seconds to load, and takes up about ~4xxMB of memory after its loaded, this can be much improved
                blp.LoadBLP("World\\Minimaps\\" + _SelectedMapName + "\\map" + x.ToString("D2") + "_" + y.ToString("D2") + ".blp");
                BitmapImage bitmapImage = new BitmapImage();
                using (MemoryStream bitmap = blp.asBitmapStream())
                {
                    bitmapImage.BeginInit();
                    bitmapImage.StreamSource      = bitmap;
                    bitmapImage.DecodePixelHeight = Convert.ToInt32(rect.Width);
                    bitmapImage.DecodePixelWidth  = Convert.ToInt32(rect.Height);
                    bitmapImage.CacheOption       = BitmapCacheOption.OnLoad;
                    bitmapImage.EndInit();
                }
                ImageBrush imgBrush = new ImageBrush(bitmapImage);
                rect.Fill = imgBrush;
            }
            else
            {
                rect.Fill = new SolidColorBrush(Color.FromRgb(0, 111, 0));
                Console.WriteLine(basedir + "World\\Minimaps\\" + _SelectedMapName + "\\map" + x.ToString("D2") + "_" + y.ToString("D2") + ".blp");
            }
            WDTGrid.Children.Add(rect);
        }
Ejemplo n.º 7
0
        private Bitmap CompileGroup(string filename, string groupid)
        {
            //Console.WriteLine("  group " + groupid);
            int min_x = 64;
            int min_y = 64;

            int max_x = 0;
            int max_y = 0;

            int x = 0;
            int y = 0;

            var  wmoonlyname = Path.GetFileNameWithoutExtension(filename);
            var  wmodir      = filename.Replace("world/", "world/minimaps/").Replace(wmoonlyname + ".wmo", "");
            var  filePaths   = new List <(uint FileDataID, string GroupFileName)>();
            uint lastpath    = 0;

            var hasMinimaps = false;

            for (int cur_x = 0; cur_x < 64; cur_x++)
            {
                for (int cur_y = 0; cur_y < 64; cur_y++)
                {
                    string wmogroupfilename = wmodir + wmoonlyname + "_" + groupid + "_" + cur_x.ToString().PadLeft(2, '0') + "_" + cur_y.ToString().PadLeft(2, '0') + ".blp";
                    if (wmogroupfilename.Contains("000_00_00"))
                    {
                        //Console.WriteLine("CHECKING " + wmogroupfilename);
                    }

                    if (Listfile.nameToFDIDMap.TryGetValue(wmogroupfilename, out var groupFileDataID))
                    {
                        if (CASC.FileExists(groupFileDataID))
                        {
                            //Console.WriteLine(wmogroupfilename + " exists!");
                            filePaths.Add((groupFileDataID, wmogroupfilename));
                            hasMinimaps = true;
                        }
                    }
                    else
                    {
                        //Console.WriteLine("Group filename " + wmogroupfilename + " could not be found in the listfile");
                    }
                }
            }

            foreach ((uint fdid, string path) in filePaths)
            {
                Console.WriteLine(path);
                x = int.Parse(path.Substring(path.Length - 9, 2));
                y = int.Parse(path.Substring(path.Length - 6, 2));

                if (x > max_x)
                {
                    max_x = x;
                }
                if (y > max_y)
                {
                    max_y = y;
                }

                if (x < min_x)
                {
                    min_x = x;
                }
                if (y < min_y)
                {
                    min_y = y;
                }

                // Console.WriteLine("[" + groupid + "] MIN: " + min_x + " " + min_y);
                // Console.WriteLine("[" + groupid + "] MAX: " + max_x + " " + max_y);

                lastpath = fdid;
            }

            var res_x = 0;
            var res_y = 0;

            if (min_x == 0 && max_x == 0 && min_y == 0 && max_y == 0)
            {
                var blpreader = new BLPReader();
                blpreader.LoadBLP(lastpath);
                res_x = blpreader.bmp.Width;
                res_y = blpreader.bmp.Height;
            }
            else
            {
                res_x = (((max_x - min_x) * 256) + 256);
                res_y = (((max_y - min_y) * 256) + 256);
            }

            //Console.WriteLine("[" + groupid + "] " + "Creating new image of " + res_x + "x" + res_y + " for " + wmoname);

            if (res_x < 0)
            {
                res_x = 1;
            }
            if (res_y < 0)
            {
                res_y = 1;
            }

            if (!hasMinimaps)
            {
                throw new FileNotFoundException("No minimaps found for this WMO");
            }

            var bmp = new Bitmap(res_x, res_y);
            var g   = Graphics.FromImage(bmp);

            foreach ((uint fdid, string path) in filePaths)
            {
                x = int.Parse(path.Substring(path.Length - 9, 2));
                y = int.Parse(path.Substring(path.Length - 6, 2));
                var blpreader = new BLPReader();
                blpreader.LoadBLP(fdid);
                //  Console.WriteLine("BLP Width: " + blpreader.bmp.Width);
                //  Console.WriteLine("BLP Height: " + blpreader.bmp.Height);
                var draw_x = (x - min_x) * 256;
                var draw_y = (max_y - (y - min_y)) * 256;
                //Console.WriteLine("Drawing tile at " + draw_x + " & " + draw_y);
                g.DrawImage(blpreader.bmp, draw_x, draw_y, new Rectangle(0, 0, blpreader.bmp.Width, blpreader.bmp.Height), GraphicsUnit.Pixel);
            }

            g.Dispose();
            return(bmp);
        }
Ejemplo n.º 8
0
        public static void exportWMO(string file, BackgroundWorker exportworker = null)
        {
            if (exportworker == null)
            {
                exportworker = new BackgroundWorker();
            }

            Console.WriteLine("Loading WMO file..");

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

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

            reader.LoadWMO(file);

            // TODO: Support doodads!

            /*
             * for (int i = 0; i < reader.wmofile.doodadNames.Count(); i++)
             * {
             *  //Console.WriteLine(reader.wmofile.doodadNames[i].filename);
             *  //reader.wmofile.doodadDefinitions[i].
             *  //reader.wmofile.doodadDefinitions[i].
             * }
             */

            exportworker.ReportProgress(30, "Reading WMO..");

            uint totalVertices = 0;

            var groups = new Structs.WMOGroup[reader.wmofile.group.Count()];

            for (int g = 0; g < reader.wmofile.group.Count(); g++)
            {
                Console.WriteLine("Loading group #" + g);
                if (reader.wmofile.group[g].mogp.vertices == null)
                {
                    Console.WriteLine("Group has no vertices!");  continue;
                }
                for (int i = 0; i < reader.wmofile.groupNames.Count(); i++)
                {
                    if (reader.wmofile.group[g].mogp.nameOffset == reader.wmofile.groupNames[i].offset)
                    {
                        groups[g].name = reader.wmofile.groupNames[i].name.Replace(" ", "_");
                    }
                }

                if (groups[g].name == "antiportal")
                {
                    Console.WriteLine("Group is antiportal"); continue;
                }

                groups[g].verticeOffset = totalVertices;
                groups[g].vertices      = new Structs.Vertex[reader.wmofile.group[g].mogp.vertices.Count()];

                for (int i = 0; i < reader.wmofile.group[g].mogp.vertices.Count(); i++)
                {
                    groups[g].vertices[i].Position = new Vector3(reader.wmofile.group[g].mogp.vertices[i].vector.X * -1, reader.wmofile.group[g].mogp.vertices[i].vector.Z, reader.wmofile.group[g].mogp.vertices[i].vector.Y);
                    groups[g].vertices[i].Normal   = new Vector3(reader.wmofile.group[g].mogp.normals[i].normal.X, reader.wmofile.group[g].mogp.normals[i].normal.Z, reader.wmofile.group[g].mogp.normals[i].normal.Y);
                    groups[g].vertices[i].TexCoord = new Vector2(reader.wmofile.group[g].mogp.textureCoords[0][i].X, reader.wmofile.group[g].mogp.textureCoords[0][i].Y);
                    totalVertices++;
                }

                var indicelist = new List <uint>();

                for (int i = 0; i < reader.wmofile.group[g].mogp.indices.Count(); i++)
                {
                    indicelist.Add(reader.wmofile.group[g].mogp.indices[i].indice);
                }

                groups[g].indices = indicelist.ToArray();
            }

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

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

            var mtlsb     = new StringBuilder();
            var textureID = 0;

            if (reader.wmofile.materials == null)
            {
                Console.WriteLine("Materials empty"); return;
            }
            var materials = new Structs.Material[reader.wmofile.materials.Count()];

            for (int i = 0; i < reader.wmofile.materials.Count(); i++)
            {
                for (int ti = 0; ti < reader.wmofile.textures.Count(); ti++)
                {
                    if (reader.wmofile.textures[ti].startOffset == reader.wmofile.materials[i].texture1)
                    {
                        //materials[i].textureID = BLPLoader.LoadTexture(reader.wmofile.textures[ti].filename, cache);
                        materials[i].textureID = textureID + i;
                        materials[i].filename  = Path.GetFileNameWithoutExtension(reader.wmofile.textures[ti].filename);

                        if (reader.wmofile.materials[i].blendMode == 0)
                        {
                            materials[i].transparent = false;
                        }
                        else
                        {
                            materials[i].transparent = true;
                        }

                        if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), materials[i].filename + ".png")))
                        {
                            var blpreader = new BLPReader();

                            blpreader.LoadBLP(reader.wmofile.textures[ti].filename);

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

                        textureID++;
                    }
                }
            }

            //No idea how MTL files really work yet. Needs more investigation.
            foreach (var material in materials)
            {
                mtlsb.Append("newmtl " + material.filename + "\n");
                mtlsb.Append("Ns 96.078431\n");
                mtlsb.Append("Ka 1.000000 1.000000 1.000000\n");
                mtlsb.Append("Kd 0.640000 0.640000 0.640000\n");
                mtlsb.Append("Ks 0.000000 0.000000 0.000000\n");
                mtlsb.Append("Ke 0.000000 0.000000 0.000000\n");
                mtlsb.Append("Ni 1.000000\n");
                mtlsb.Append("d 1.000000\n");
                mtlsb.Append("illum 2\n");
                mtlsb.Append("map_Kd " + material.filename + ".png\n");
                if (material.transparent)
                {
                    mtlsb.Append("map_d " + material.filename + ".png\n");
                }
            }

            File.WriteAllText(Path.Combine(outdir, file.Replace(".wmo", ".mtl")), mtlsb.ToString());

            exportworker.ReportProgress(75, "Exporting model..");

            int numRenderbatches = 0;

            //Get total amount of render batches
            for (int i = 0; i < reader.wmofile.group.Count(); i++)
            {
                if (reader.wmofile.group[i].mogp.renderBatches == null)
                {
                    continue;
                }
                numRenderbatches = numRenderbatches + reader.wmofile.group[i].mogp.renderBatches.Count();
            }


            int rb = 0;

            for (int g = 0; g < reader.wmofile.group.Count(); g++)
            {
                groups[g].renderBatches = new Structs.RenderBatch[numRenderbatches];

                var group = reader.wmofile.group[g];
                if (group.mogp.renderBatches == null)
                {
                    continue;
                }
                for (int i = 0; i < group.mogp.renderBatches.Count(); i++)
                {
                    var batch = group.mogp.renderBatches[i];

                    groups[g].renderBatches[rb].firstFace = batch.firstFace;
                    groups[g].renderBatches[rb].numFaces  = batch.numFaces;

                    if (batch.flags == 2)
                    {
                        groups[g].renderBatches[rb].materialID = (uint)batch.possibleBox2_3;
                    }
                    else
                    {
                        groups[g].renderBatches[rb].materialID = batch.materialID;
                    }
                    groups[g].renderBatches[rb].blendType = reader.wmofile.materials[batch.materialID].blendMode;
                    groups[g].renderBatches[rb].groupID   = (uint)g;
                    rb++;
                }
            }

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

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

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

            foreach (var group in groups)
            {
                if (group.vertices == null)
                {
                    continue;
                }
                Console.WriteLine("Writing " + group.name);
                objsw.WriteLine("g " + group.name);

                foreach (var vertex in group.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 + " " + vertex.Normal.Y + " " + vertex.Normal.Z);
                }

                var indices = group.indices;

                foreach (var renderbatch in group.renderBatches)
                {
                    var i = renderbatch.firstFace;
                    if (renderbatch.numFaces > 0)
                    {
                        objsw.WriteLine("usemtl " + materials[renderbatch.materialID].filename);
                        objsw.WriteLine("s 1");
                        while (i < (renderbatch.firstFace + renderbatch.numFaces))
                        {
                            objsw.WriteLine("f " + (indices[i] + group.verticeOffset + 1) + "/" + (indices[i] + group.verticeOffset + 1) + "/" + (indices[i] + group.verticeOffset + 1) + " " + (indices[i + 1] + group.verticeOffset + 1) + "/" + (indices[i + 1] + group.verticeOffset + 1) + "/" + (indices[i + 1] + group.verticeOffset + 1) + " " + (indices[i + 2] + group.verticeOffset + 1) + "/" + (indices[i + 2] + group.verticeOffset + 1) + "/" + (indices[i + 2] + group.verticeOffset + 1));
                            i = i + 3;
                        }
                    }
                }
            }
            objsw.Close();
            Console.WriteLine("Done loading WMO file!");
        }
Ejemplo n.º 9
0
        public static void exportADT(string file, BackgroundWorker exportworker = null)
        {
            //if (exportworker == null)
            //{
            //   exportworker = new BackgroundWorker();
            // }

            //CASC.InitCasc(null, @"C:\World of Warcraft Beta", "wow_beta");
            var outdir = ConfigurationManager.AppSettings["outdir"];

            float TileSize    = 1600.0f / 3.0f;   //533.333
            float ChunkSize   = TileSize / 16.0f; //33.333
            float UnitSize    = ChunkSize / 8.0f; //4.166666 // ~~fun fact time with marlamin~~ this /2 ends up being pixelspercoord on minimap
            float MapMidPoint = 32.0f / ChunkSize;

            var mapname = file.Replace("world/maps/", "").Substring(0, file.Replace("world/maps/", "").IndexOf("/"));
            var coord   = file.Replace("world/maps/" + mapname + "/" + mapname, "").Replace(".adt", "").Split('_');

            var centerx = int.Parse(coord[1]);
            var centery = int.Parse(coord[2]);

            List <Structs.RenderBatch> renderBatches = new List <Structs.RenderBatch>();
            List <Structs.Vertex>      verticelist   = new List <Structs.Vertex>();
            List <int> indicelist = new List <Int32>();
            Dictionary <int, string> materials = new Dictionary <int, string>();

            var distance = 1;

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

            for (int y = centery; y < centery + distance; y++)
            {
                for (int x = centerx; x < centerx + distance; x++)
                {
                    var curfile = "world\\maps\\" + mapname + "\\" + mapname + "_" + x + "_" + y + ".adt";

                    if (!CASC.FileExists(file))
                    {
                        Console.WriteLine("File " + file + " does not exist");
                        continue;
                    }

                    //exportworker.ReportProgress(0, "Loading ADT " + curfile);

                    ADTReader reader = new ADTReader();
                    reader.LoadADT(curfile);

                    // No chunks? Let's get the hell out of here
                    if (reader.adtfile.chunks == null)
                    {
                        continue;
                    }
                    if (CASC.FileExists("world\\maptextures\\" + mapname + "\\" + mapname + "_" + x + "_" + y + ".blp"))
                    {
                        materials.Add(materials.Count() + 1, "mat" + y.ToString() + x.ToString());

                        var blpreader = new BLPReader();

                        blpreader.LoadBLP(curfile.Replace("maps", "maptextures").Replace(".adt", ".blp"));

                        try
                        {
                            blpreader.bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(file), "mat" + y.ToString() + x.ToString() + ".png"));
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.Message);
                        }
                    }
                    else
                    {
                        throw new Exception("This map has no maptextures. Try a different map.");
                    }

                    //List<Material> materials = new List<Material>();

                    //for (int ti = 0; ti < reader.adtfile.textures.filenames.Count(); ti++)
                    //{
                    //    Material material = new Material();
                    //    material.filename = reader.adtfile.textures.filenames[ti];

                    //    //if (!WoWFormatLib.Utils.CASC.FileExists(material.filename)) { continue; }

                    //    material.textureID = BLPLoader.LoadTexture(reader.adtfile.textures.filenames[ti], cache);

                    //    materials.Add(material);
                    //}

                    var initialChunkY = reader.adtfile.chunks[0].header.position.Y;
                    var initialChunkX = reader.adtfile.chunks[0].header.position.X;

                    for (uint c = 0; c < reader.adtfile.chunks.Count(); c++)
                    {
                        var chunk = reader.adtfile.chunks[c];

                        int off = verticelist.Count();

                        Structs.RenderBatch batch = new Structs.RenderBatch();

                        for (int i = 0, idx = 0; i < 17; i++)
                        {
                            for (int j = 0; j < (((i % 2) != 0) ? 8 : 9); j++)
                            {
                                Structs.Vertex v = new Structs.Vertex();
                                v.Normal   = new OpenTK.Vector3(chunk.normals.normal_2[idx] / 127f, chunk.normals.normal_0[idx] / 127f, chunk.normals.normal_1[idx] / 127f);
                                v.Position = new OpenTK.Vector3(chunk.header.position.Y - (j * UnitSize), chunk.vertices.vertices[idx++] + chunk.header.position.Z, chunk.header.position.X - (i * UnitSize * 0.5f));
                                if ((i % 2) != 0)
                                {
                                    v.Position.X -= 0.5f * UnitSize;
                                }
                                v.TexCoord = new Vector2(-(v.Position.X - initialChunkX) / TileSize, -(v.Position.Z - initialChunkY) / TileSize);
                                verticelist.Add(v);
                            }
                        }

                        batch.firstFace = (uint)indicelist.Count();

                        for (int j = 9; j < 145; j++)
                        {
                            indicelist.AddRange(new Int32[] { off + j + 8, off + j - 9, off + j });
                            indicelist.AddRange(new Int32[] { off + j - 9, off + j - 8, off + j });
                            indicelist.AddRange(new Int32[] { off + j - 8, off + j + 9, off + j });
                            indicelist.AddRange(new Int32[] { off + j + 9, off + j + 8, off + j });
                            if ((j + 1) % (9 + 8) == 0)
                            {
                                j += 9;
                            }
                        }

                        batch.materialID = (uint)materials.Count();

                        batch.numFaces = (uint)(indicelist.Count()) - batch.firstFace;

                        //var layermats = new List<uint>();
                        //var alphalayermats = new List<int>();

                        //for (int li = 0; li < reader.adtfile.texChunks[c].layers.Count(); li++)
                        //{
                        //    if (reader.adtfile.texChunks[c].alphaLayer != null)
                        //    {
                        //        alphalayermats.Add(BLPLoader.GenerateAlphaTexture(reader.adtfile.texChunks[c].alphaLayer[li].layer));
                        //    }
                        //    layermats.Add((uint)cache.materials[reader.adtfile.textures.filenames[reader.adtfile.texChunks[c].layers[li].textureId].ToLower()]);
                        //}

                        //batch.materialID = layermats.ToArray();
                        //batch.alphaMaterialID = alphalayermats.ToArray();

                        renderBatches.Add(batch);
                    }
                }
            }

            var mtlsw = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file).Replace(" ", "") + ".mtl"));

            //No idea how MTL files really work yet. Needs more investigation.
            foreach (var material in materials)
            {
                mtlsw.WriteLine("newmtl " + material.Value);
                mtlsw.WriteLine("Ka 1.000000 1.000000 1.000000");
                mtlsw.WriteLine("Kd 0.640000 0.640000 0.640000");
                mtlsw.WriteLine("map_Ka " + material.Value + ".png");
                mtlsw.WriteLine("map_Kd " + material.Value + ".png");
            }

            mtlsw.Close();

            var indices = indicelist.ToArray();

            var adtname = Path.GetFileNameWithoutExtension(file);

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

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

            foreach (var vertex in verticelist)
            {
                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 + " " + vertex.Normal.Y + " " + vertex.Normal.Z);
            }

            foreach (var renderBatch in renderBatches)
            {
                var i = renderBatch.firstFace;
                if (materials.ContainsKey((int)renderBatch.materialID))
                {
                    objsw.WriteLine("usemtl " + materials[(int)renderBatch.materialID]); objsw.WriteLine("s 1");
                }
                while (i < (renderBatch.firstFace + renderBatch.numFaces))
                {
                    objsw.WriteLine("f " + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + " " + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + " " + (indices[i] + 1) + "/" + (indices[i] + 1) + "/" + (indices[i] + 1));
                    i = i + 3;
                }
            }

            objsw.Close();
        }
Ejemplo n.º 10
0
        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (treeView1.SelectedNode.FullPath.EndsWith(".blp"))
            {
                try
                {
                    BLPReader reader = new BLPReader();
                    reader.LoadBLP(Managers.ArchiveManager.ReadThisFile(treeView1.SelectedNode.FullPath.Replace(@"root\", "")));
                    pictureBox1.Image = reader.bmp;
                }
                catch
                {
                    //Console.WriteLine("Error occured while trying to read " + treeView1.SelectedNode.FullPath.Replace(@"root\", ""));
                }
            }

            if (treeView1.SelectedNode.FullPath.EndsWith(".adt"))
            {
                try
                {
                    if (Managers.ConfigurationManager.Profile >= 4) // Cata and above
                    {
                        string filedirectory = treeView1.SelectedNode.FullPath.Replace("\\maps\\", "\\minimaps\\");
                        filedirectory = filedirectory.Substring(0, filedirectory.LastIndexOf("\\") + 1);
                        filedirectory = filedirectory.Substring(5, filedirectory.Length - 5);

                        string filename = Path.GetFileNameWithoutExtension(treeView1.SelectedNode.FullPath);
                        filename = filename.Replace(filename.Substring(0, filename.IndexOf("_") + 1), "map") + ".blp";
                        //Console.WriteLine(filedirectory + filename);
                        try
                        {
                            BLPReader reader = new BLPReader();
                            if (Managers.ArchiveManager.FileExists(filedirectory + filename))
                            {
                                reader.LoadBLP(Managers.ArchiveManager.ReadThisFile(filedirectory + filename));
                                pictureBox1.Image = reader.bmp;
                            }
                        }
                        catch
                        {
                        }
                    }
                    else
                    {
                        string filename = treeView1.SelectedNode.FullPath;
                        try
                        {
                            BLPReader reader = new BLPReader();
                            if (Managers.ArchiveManager.FileExists(Managers.md5Manager.TranslateThisMap(filename)))
                            {
                                reader.LoadBLP(Managers.ArchiveManager.ReadThisFile(Managers.md5Manager.TranslateThisMap(filename)));
                                pictureBox1.Image = reader.bmp;
                            }
                        }
                        catch
                        {
                        }
                    }
                }
                catch
                {
                }
            }
        }
Ejemplo n.º 11
0
        public static void exportADT(string file, BackgroundWorker exportworker = null)
        {
            if (exportworker == null)
            {
                exportworker = new BackgroundWorker();
                exportworker.WorkerReportsProgress = true;
            }

            //CASC.InitCasc(null, @"C:\World of Warcraft Beta", "wow_beta");
            var outdir = ConfigurationManager.AppSettings["outdir"];

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

            float TileSize    = 1600.0f / 3.0f;   //533.333
            float ChunkSize   = TileSize / 16.0f; //33.333
            float UnitSize    = ChunkSize / 8.0f; //4.166666 // ~~fun fact time with marlamin~~ this /2 ends up being pixelspercoord on minimap
            float MapMidPoint = 32.0f / ChunkSize;

            var mapname = file.Replace("world/maps/", "").Substring(0, file.Replace("world/maps/", "").IndexOf("/"));
            var coord   = file.Replace("world/maps/" + mapname + "/" + mapname, "").Replace(".adt", "").Split('_');

            var centerx = int.Parse(coord[1]);
            var centery = int.Parse(coord[2]);

            List <Structs.RenderBatch> renderBatches = new List <Structs.RenderBatch>();
            List <Structs.Vertex>      verticelist   = new List <Structs.Vertex>();
            List <int> indicelist = new List <Int32>();
            Dictionary <int, string> materials = new Dictionary <int, string>();

            var distance = 1;

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

            for (int y = centery; y < centery + distance; y++)
            {
                for (int x = centerx; x < centerx + distance; x++)
                {
                    var curfile = "world\\maps\\" + mapname + "\\" + mapname + "_" + x + "_" + y + ".adt";

                    if (!CASC.FileExists(file))
                    {
                        Console.WriteLine("File " + file + " does not exist");
                        continue;
                    }

                    exportworker.ReportProgress(0, "Loading ADT " + curfile);

                    ADTReader reader = new ADTReader();
                    reader.LoadADT(curfile);

                    // No chunks? Let's get the hell out of here
                    if (reader.adtfile.chunks == null)
                    {
                        continue;
                    }

                    if (CASC.FileExists("world\\maptextures\\" + mapname + "\\" + mapname + "_" + x + "_" + y + ".blp"))
                    {
                        materials.Add(materials.Count() + 1, "mat" + y.ToString() + x.ToString());

                        var blpreader = new BLPReader();

                        blpreader.LoadBLP(curfile.Replace("maps", "maptextures").Replace(".adt", ".blp"));

                        try
                        {
                            blpreader.bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(file), "mat" + y.ToString() + x.ToString() + ".png"));
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.Message);
                        }
                    }
                    else
                    {
                        Console.WriteLine("No maptextures, this map will have missing textures.");
                    }

                    //List<Material> materials = new List<Material>();

                    //for (int ti = 0; ti < reader.adtfile.textures.filenames.Count(); ti++)

                    //{

                    //    Material material = new Material();

                    //    material.filename = reader.adtfile.textures.filenames[ti];

                    //    //if (!WoWFormatLib.Utils.CASC.FileExists(material.filename)) { continue; }

                    //    material.textureID = BLPLoader.LoadTexture(reader.adtfile.textures.filenames[ti], cache);

                    //    materials.Add(material);

                    //}

                    var initialChunkY = reader.adtfile.chunks[0].header.position.Y;
                    var initialChunkX = reader.adtfile.chunks[0].header.position.X;

                    for (uint c = 0; c < reader.adtfile.chunks.Count(); c++)
                    {
                        var chunk = reader.adtfile.chunks[c];

                        int off = verticelist.Count();

                        Structs.RenderBatch batch = new Structs.RenderBatch();

                        for (int i = 0, idx = 0; i < 17; i++)
                        {
                            for (int j = 0; j < (((i % 2) != 0) ? 8 : 9); j++)
                            {
                                Structs.Vertex v = new Structs.Vertex();
                                v.Normal   = new OpenTK.Vector3(chunk.normals.normal_2[idx] / 127f, chunk.normals.normal_0[idx] / 127f, chunk.normals.normal_1[idx] / 127f);
                                v.Position = new OpenTK.Vector3(chunk.header.position.Y - (j * UnitSize), chunk.vertices.vertices[idx++] + chunk.header.position.Z, chunk.header.position.X - (i * UnitSize * 0.5f));
                                if ((i % 2) != 0)
                                {
                                    v.Position.X -= 0.5f * UnitSize;
                                }
                                v.TexCoord = new Vector2(-(v.Position.X - initialChunkX) / TileSize, -(v.Position.Z - initialChunkY) / TileSize);
                                verticelist.Add(v);
                            }
                        }

                        batch.firstFace = (uint)indicelist.Count();

                        for (int j = 9; j < 145; j++)
                        {
                            indicelist.AddRange(new Int32[] { off + j + 8, off + j - 9, off + j });
                            indicelist.AddRange(new Int32[] { off + j - 9, off + j - 8, off + j });
                            indicelist.AddRange(new Int32[] { off + j - 8, off + j + 9, off + j });
                            indicelist.AddRange(new Int32[] { off + j + 9, off + j + 8, off + j });
                            if ((j + 1) % (9 + 8) == 0)
                            {
                                j += 9;
                            }
                        }

                        batch.materialID = (uint)materials.Count();

                        batch.numFaces = (uint)(indicelist.Count()) - batch.firstFace;

                        var layermats      = new List <uint>();
                        var alphalayermats = new List <int>();

                        for (int li = 0; li < reader.adtfile.texChunks[c].layers.Count(); li++)
                        {
                            //if (reader.adtfile.texChunks[c].alphaLayer != null)
                            //{
                            //    //alphalayermats.Add(BLPLoader.GenerateAlphaTexture(reader.adtfile.texChunks[c].alphaLayer[li].layer));
                            //    var bmp = new System.Drawing.Bitmap(64, 64);
                            //    var data = bmp.LockBits(new System.Drawing.Rectangle(0, 0, 64, 64), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                            //    int stride = data.Stride;
                            //    var values = reader.adtfile.texChunks[c].alphaLayer[li].layer;
                            //    unsafe
                            //    {
                            //        byte* ptr = (byte*)data.Scan0;
                            //        for (int ax = 0; ax < 64; ax++)
                            //        {
                            //            for (int ay = 0; ay < 64; ay++)
                            //            {
                            //                var color = System.Drawing.Color.FromArgb(values[ax * 64 + ay], values[ax * 64 + ay], values[ax * 64 + ay], values[ax * 64 + ay]);
                            //                ptr[(y * 4) + x * stride] = color.B;
                            //                ptr[(y * 4) + x * stride + 1] = color.G;
                            //                ptr[(y * 4) + x * stride + 2] = color.R;
                            //                ptr[(y * 4) + x * stride + 3] = color.A;
                            //            }
                            //        }
                            //    }
                            //    bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file).Replace(" ", "") + "_" + c + "_" + li + ".png"));
                            //}
                        }

                        renderBatches.Add(batch);
                    }

                    var doodadSW = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file).Replace(" ", "") + "_ModelPlacementInformation.csv"));
                    doodadSW.WriteLine("ModelFile;PositionX;PositionY;PositionZ;RotationX;RotationY;RotationZ;ScaleFactor;ModelId");

                    exportworker.ReportProgress(25, "Exporting WMOs");

                    for (int mi = 0; mi < reader.adtfile.objects.worldModels.entries.Count(); mi++)
                    {
                        var wmo = reader.adtfile.objects.worldModels.entries[mi];

                        var filename = reader.adtfile.objects.wmoNames.filenames[wmo.mwidEntry];

                        if (!File.Exists(Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj"))
                        {
                            WMOExporter.exportWMO(filename, null, Path.Combine(outdir, Path.GetDirectoryName(file)));
                        }

                        doodadSW.WriteLine(Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj;" + wmo.position.X + ";" + wmo.position.Y + ";" + wmo.position.Z + ";" + wmo.rotation.X + ";" + wmo.rotation.Y + ";" + wmo.rotation.Z + ";;" + wmo.uniqueId);
                    }

                    exportworker.ReportProgress(50, "Exporting M2s");

                    for (int mi = 0; mi < reader.adtfile.objects.models.entries.Count(); mi++)
                    {
                        var doodad = reader.adtfile.objects.models.entries[mi];

                        var filename = reader.adtfile.objects.m2Names.filenames[doodad.mmidEntry];

                        if (!File.Exists(Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj"))
                        {
                            M2Exporter.exportM2(filename, null, Path.Combine(outdir, Path.GetDirectoryName(file)));
                        }

                        doodadSW.WriteLine(Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj;" + doodad.position.X + ";" + doodad.position.Y + ";" + doodad.position.Z + ";" + doodad.rotation.X + ";" + doodad.rotation.Y + ";" + doodad.rotation.Z + ";" + doodad.scale / 1024f + ";" + doodad.uniqueId);
                    }

                    doodadSW.Close();
                }
            }

            exportworker.ReportProgress(75, "Exporting terrain textures..");

            var mtlsw = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file).Replace(" ", "") + ".mtl"));

            //No idea how MTL files really work yet. Needs more investigation.
            foreach (var material in materials)
            {
                mtlsw.WriteLine("newmtl " + material.Value);
                mtlsw.WriteLine("Ka 1.000000 1.000000 1.000000");
                mtlsw.WriteLine("Kd 0.640000 0.640000 0.640000");
                mtlsw.WriteLine("map_Ka " + material.Value + ".png");
                mtlsw.WriteLine("map_Kd " + material.Value + ".png");
            }

            mtlsw.Close();

            exportworker.ReportProgress(85, "Exporting terrain geometry..");

            var indices = indicelist.ToArray();

            var adtname = Path.GetFileNameWithoutExtension(file);

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

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

            foreach (var vertex in verticelist)
            {
                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 + " " + vertex.Normal.Y + " " + vertex.Normal.Z);
            }

            foreach (var renderBatch in renderBatches)
            {
                var i = renderBatch.firstFace;
                if (materials.ContainsKey((int)renderBatch.materialID))
                {
                    objsw.WriteLine("usemtl " + materials[(int)renderBatch.materialID]); objsw.WriteLine("s 1");
                }
                while (i < (renderBatch.firstFace + renderBatch.numFaces))
                {
                    objsw.WriteLine("f " + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + " " + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + " " + (indices[i] + 1) + "/" + (indices[i] + 1) + "/" + (indices[i] + 1));
                    i = i + 3;
                }
            }

            objsw.Close();
        }
Ejemplo n.º 12
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
        }
Ejemplo n.º 13
0
        public static void ExportWMO(uint filedataid, BackgroundWorker exportworker = null, string destinationOverride = null, ushort doodadSetExportID = ushort.MaxValue, string filename = "")
        {
            if (exportworker == null)
            {
                exportworker = new BackgroundWorker();
                exportworker.WorkerReportsProgress = true;
            }

            if (string.IsNullOrEmpty(filename))
            {
                if (!Listfile.TryGetFilename(filedataid, out filename))
                {
                    CASCLib.Logger.WriteLine("Warning! Could not find filename for " + filedataid + "!");
                }
            }

            Console.WriteLine("Loading WMO file..");

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

            var outdir = ConfigurationManager.AppSettings["outdir"];
            var wmo    = new WMOReader().LoadWMO(filedataid);

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

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

            exportworker.ReportProgress(30, "Reading WMO..");

            uint totalVertices = 0;

            var groups = new Structs.WMOGroup[wmo.group.Count()];

            for (var g = 0; g < wmo.group.Count(); g++)
            {
                Console.WriteLine("Loading group #" + g);
                if (wmo.group[g].mogp.vertices == null)
                {
                    Console.WriteLine("Group has no vertices!"); continue;
                }
                for (var i = 0; i < wmo.groupNames.Count(); i++)
                {
                    if (wmo.group[g].mogp.nameOffset == wmo.groupNames[i].offset)
                    {
                        groups[g].name = wmo.groupNames[i].name.Replace(" ", "_");
                    }
                }

                if (groups[g].name == "antiportal")
                {
                    Console.WriteLine("Group is antiportal"); continue;
                }

                groups[g].verticeOffset = totalVertices;
                groups[g].vertices      = new Structs.Vertex[wmo.group[g].mogp.vertices.Count()];

                for (var i = 0; i < wmo.group[g].mogp.vertices.Count(); i++)
                {
                    groups[g].vertices[i].Position = new Structs.Vector3D()
                    {
                        X = wmo.group[g].mogp.vertices[i].vector.X * -1,
                        Y = wmo.group[g].mogp.vertices[i].vector.Z,
                        Z = wmo.group[g].mogp.vertices[i].vector.Y
                    };

                    groups[g].vertices[i].Normal = new Structs.Vector3D()
                    {
                        X = wmo.group[g].mogp.normals[i].normal.X,
                        Y = wmo.group[g].mogp.normals[i].normal.Z,
                        Z = wmo.group[g].mogp.normals[i].normal.Y
                    };

                    groups[g].vertices[i].TexCoord = new Structs.Vector2D()
                    {
                        X = wmo.group[g].mogp.textureCoords[0][i].X,
                        Y = wmo.group[g].mogp.textureCoords[0][i].Y
                    };

                    totalVertices++;
                }

                var indicelist = new List <uint>();

                for (var i = 0; i < wmo.group[g].mogp.indices.Count(); i++)
                {
                    indicelist.Add(wmo.group[g].mogp.indices[i].indice);
                }

                groups[g].indices = indicelist.ToArray();
            }

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

            StreamWriter doodadSW;

            if (destinationOverride == null)
            {
                if (!string.IsNullOrEmpty(filename))
                {
                    doodadSW = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename.Replace(" ", "")) + "_ModelPlacementInformation.csv"));
                }
                else
                {
                    doodadSW = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(filename), filedataid + "_ModelPlacementInformation.csv"));
                }
            }
            else
            {
                if (!string.IsNullOrEmpty(filename))
                {
                    doodadSW = new StreamWriter(Path.Combine(outdir, destinationOverride, Path.GetFileNameWithoutExtension(filename).Replace(" ", "") + "_ModelPlacementInformation.csv"));
                }
                else
                {
                    doodadSW = new StreamWriter(Path.Combine(outdir, destinationOverride, filedataid + "_ModelPlacementInformation.csv"));
                }
            }

            exportworker.ReportProgress(55, "Exporting doodads..");

            doodadSW.WriteLine("ModelFile;PositionX;PositionY;PositionZ;RotationW;RotationX;RotationY;RotationZ;ScaleFactor;DoodadSet");

            for (var i = 0; i < wmo.doodadSets.Count(); i++)
            {
                var doodadSet = wmo.doodadSets[i];

                var currentDoodadSetName = doodadSet.setName.Replace("Set_", "").Replace("SET_", "").Replace("$DefaultGlobal", "Default");

                if (doodadSetExportID != ushort.MaxValue)
                {
                    if (i != 0 && i != doodadSetExportID)
                    {
                        Console.WriteLine("Skipping doodadset with ID " + i + " (" + currentDoodadSetName + ") because export filter is set to " + doodadSetExportID);
                        continue;
                    }
                }

                Console.WriteLine("At doodadset " + i + " (" + currentDoodadSetName + ")");

                for (var j = doodadSet.firstInstanceIndex; j < (doodadSet.firstInstanceIndex + doodadSet.numDoodads); j++)
                {
                    var doodadDefinition = wmo.doodadDefinitions[j];

                    var  doodadFilename   = "";
                    uint doodadFileDataID = 0;

                    if (wmo.doodadIds != null)
                    {
                        doodadFileDataID = wmo.doodadIds[doodadDefinition.offset];
                        if (!Listfile.TryGetFilename(doodadFileDataID, out doodadFilename))
                        {
                            CASCLib.Logger.WriteLine("Could not find filename for " + doodadFileDataID + ", setting filename to filedataid..");
                            doodadFilename = doodadFileDataID.ToString();
                        }
                    }
                    else
                    {
                        CASCLib.Logger.WriteLine("Warning!! File " + filename + " ID: " + filedataid + " still has filenames!");
                        foreach (var doodadNameEntry in wmo.doodadNames)
                        {
                            if (doodadNameEntry.startOffset == doodadDefinition.offset)
                            {
                                doodadFilename = doodadNameEntry.filename.Replace(".MDX", ".M2").Replace(".MDL", ".M2").ToLower();
                                if (!Listfile.TryGetFileDataID(doodadFilename, out doodadFileDataID))
                                {
                                    CASCLib.Logger.WriteLine("Error! Could not find filedataid for " + doodadFilename + "!");
                                    continue;
                                }
                            }
                        }
                    }

                    if (destinationOverride == null)
                    {
                        if (!string.IsNullOrEmpty(doodadFilename))
                        {
                            if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(doodadFilename) + ".obj")))
                            {
                                M2Exporter.ExportM2(doodadFileDataID, null, Path.Combine(outdir, Path.GetDirectoryName(filename)), doodadFilename);
                            }

                            if (File.Exists(Path.Combine(outdir, Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(doodadFilename) + ".obj")))
                            {
                                doodadSW.WriteLine(Path.GetFileNameWithoutExtension(doodadFilename) + ".obj;" + doodadDefinition.position.X.ToString("F09") + ";" + doodadDefinition.position.Y.ToString("F09") + ";" + doodadDefinition.position.Z.ToString("F09") + ";" + doodadDefinition.rotation.W.ToString("F15") + ";" + doodadDefinition.rotation.X.ToString("F15") + ";" + doodadDefinition.rotation.Y.ToString("F15") + ";" + doodadDefinition.rotation.Z.ToString("F15") + ";" + doodadDefinition.scale + ";" + currentDoodadSetName);
                            }
                        }
                        else
                        {
                            if (!File.Exists(Path.Combine(outdir, doodadFileDataID + ".obj")))
                            {
                                M2Exporter.ExportM2(doodadFileDataID, null, outdir, doodadFilename);
                            }

                            if (File.Exists(Path.Combine(outdir, doodadFileDataID + ".obj")))
                            {
                                doodadSW.WriteLine(doodadFileDataID + ".obj;" + doodadDefinition.position.X.ToString("F09") + ";" + doodadDefinition.position.Y.ToString("F09") + ";" + doodadDefinition.position.Z.ToString("F09") + ";" + doodadDefinition.rotation.W.ToString("F15") + ";" + doodadDefinition.rotation.X.ToString("F15") + ";" + doodadDefinition.rotation.Y.ToString("F15") + ";" + doodadDefinition.rotation.Z.ToString("F15") + ";" + doodadDefinition.scale + ";" + currentDoodadSetName);
                            }
                        }
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(doodadFilename))
                        {
                            if (!File.Exists(Path.Combine(destinationOverride, Path.GetFileNameWithoutExtension(doodadFilename) + ".obj")))
                            {
                                M2Exporter.ExportM2(doodadFileDataID, null, destinationOverride, doodadFilename);
                            }

                            if (File.Exists(Path.Combine(destinationOverride, Path.GetFileNameWithoutExtension(doodadFilename) + ".obj")))
                            {
                                doodadSW.WriteLine(Path.GetFileNameWithoutExtension(doodadFilename) + ".obj;" + doodadDefinition.position.X.ToString("F09") + ";" + doodadDefinition.position.Y.ToString("F09") + ";" + doodadDefinition.position.Z.ToString("F09") + ";" + doodadDefinition.rotation.W.ToString("F15") + ";" + doodadDefinition.rotation.X.ToString("F15") + ";" + doodadDefinition.rotation.Y.ToString("F15") + ";" + doodadDefinition.rotation.Z.ToString("F15") + ";" + doodadDefinition.scale + ";" + currentDoodadSetName);
                            }
                        }
                        else
                        {
                            if (!File.Exists(Path.Combine(destinationOverride, doodadFileDataID + ".obj")))
                            {
                                M2Exporter.ExportM2(doodadFileDataID, null, destinationOverride, doodadFilename);
                            }

                            if (File.Exists(Path.Combine(destinationOverride, doodadFileDataID + ".obj")))
                            {
                                doodadSW.WriteLine(doodadFileDataID + ".obj;" + doodadDefinition.position.X.ToString("F09") + ";" + doodadDefinition.position.Y.ToString("F09") + ";" + doodadDefinition.position.Z.ToString("F09") + ";" + doodadDefinition.rotation.W.ToString("F15") + ";" + doodadDefinition.rotation.X.ToString("F15") + ";" + doodadDefinition.rotation.Y.ToString("F15") + ";" + doodadDefinition.rotation.Z.ToString("F15") + ";" + doodadDefinition.scale + ";" + currentDoodadSetName);
                            }
                        }
                    }
                }
            }

            doodadSW.Close();

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

            var mtlsb     = new StringBuilder();
            var textureID = 0;

            if (wmo.materials == null)
            {
                CASCLib.Logger.WriteLine("Unable to find materials for WMO " + filedataid + ", not exporting!");
                return;
            }

            var materials      = new Structs.Material[wmo.materials.Count()];
            var extraMaterials = new List <Structs.Material>();

            for (var i = 0; i < wmo.materials.Count(); i++)
            {
                var blpreader = new BLPReader();

                if (wmo.textures == null)
                {
                    if (Listfile.TryGetFilename(wmo.materials[i].texture1, out var textureFilename))
                    {
                        materials[i].filename = Path.GetFileNameWithoutExtension(textureFilename);
                    }
                    else
                    {
                        materials[i].filename = wmo.materials[i].texture1.ToString();
                    }

                    blpreader.LoadBLP(wmo.materials[i].texture1);
                }
                else
                {
                    for (var ti = 0; ti < wmo.textures.Count(); ti++)
                    {
                        if (wmo.textures[ti].startOffset == wmo.materials[i].texture1)
                        {
                            materials[i].filename = Path.GetFileNameWithoutExtension(wmo.textures[ti].filename);
                            blpreader.LoadBLP(wmo.textures[ti].filename);
                        }
                    }
                }

                materials[i].textureID = textureID + i;

                if (wmo.materials[i].blendMode == 0)
                {
                    materials[i].transparent = false;
                }
                else
                {
                    materials[i].transparent = true;
                }

                materials[i].blendMode   = wmo.materials[i].blendMode;
                materials[i].shaderID    = wmo.materials[i].shader;
                materials[i].terrainType = wmo.materials[i].groundType;

                var saveLocation = "";

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

                if (!File.Exists(saveLocation))
                {
                    try
                    {
                        if (materials[i].transparent)
                        {
                            blpreader.bmp.Save(saveLocation);
                        }
                        else
                        {
                            blpreader.bmp.Clone(new Rectangle(0, 0, blpreader.bmp.Width, blpreader.bmp.Height), PixelFormat.Format32bppRgb).Save(saveLocation);
                        }
                    }
                    catch (Exception e)
                    {
                        CASCLib.Logger.WriteLine("Exception while saving BLP " + materials[i].filename + ": " + e.Message);
                    }
                }

                textureID++;

                // Extra materials
                // Texture 2
                if (CASC.FileExists(wmo.materials[i].texture2))
                {
                    var tex2mat = new Structs.Material();
                    if (wmo.textures == null)
                    {
                        if (Listfile.TryGetFilename(wmo.materials[i].texture2, out var textureFilename))
                        {
                            tex2mat.filename = Path.GetFileNameWithoutExtension(textureFilename);
                        }
                        else
                        {
                            tex2mat.filename = wmo.materials[i].texture2.ToString();
                        }

                        blpreader.LoadBLP(wmo.materials[i].texture2);
                    }
                    else
                    {
                        for (var ti = 0; ti < wmo.textures.Count(); ti++)
                        {
                            if (wmo.textures[ti].startOffset == wmo.materials[i].texture2)
                            {
                                tex2mat.filename = Path.GetFileNameWithoutExtension(wmo.textures[ti].filename);
                                blpreader.LoadBLP(wmo.textures[ti].filename);
                            }
                        }
                    }

                    if (destinationOverride == null)
                    {
                        if (!string.IsNullOrEmpty(filename))
                        {
                            saveLocation = Path.Combine(outdir, Path.GetDirectoryName(filename), tex2mat.filename + ".png");
                        }
                        else
                        {
                            saveLocation = Path.Combine(outdir, tex2mat.filename + ".png");
                        }
                    }
                    else
                    {
                        saveLocation = Path.Combine(outdir, destinationOverride, tex2mat.filename + ".png");
                    }

                    if (!File.Exists(saveLocation))
                    {
                        try
                        {
                            blpreader.bmp.Save(saveLocation);
                        }
                        catch (Exception e)
                        {
                            CASCLib.Logger.WriteLine("Exception while saving BLP " + tex2mat.filename + ": " + e.Message);
                        }
                    }

                    extraMaterials.Add(tex2mat);
                }

                // Texture 3
                if (CASC.FileExists(wmo.materials[i].texture3))
                {
                    var tex3mat = new Structs.Material();
                    if (wmo.textures == null)
                    {
                        if (Listfile.TryGetFilename(wmo.materials[i].texture3, out var textureFilename))
                        {
                            tex3mat.filename = Path.GetFileNameWithoutExtension(textureFilename);
                        }
                        else
                        {
                            tex3mat.filename = wmo.materials[i].texture3.ToString();
                        }

                        blpreader.LoadBLP(wmo.materials[i].texture3);
                    }
                    else
                    {
                        for (var ti = 0; ti < wmo.textures.Count(); ti++)
                        {
                            if (wmo.textures[ti].startOffset == wmo.materials[i].texture3)
                            {
                                tex3mat.filename = Path.GetFileNameWithoutExtension(wmo.textures[ti].filename);
                                blpreader.LoadBLP(wmo.textures[ti].filename);
                            }
                        }
                    }

                    if (destinationOverride == null)
                    {
                        if (!string.IsNullOrEmpty(filename))
                        {
                            saveLocation = Path.Combine(outdir, Path.GetDirectoryName(filename), tex3mat.filename + ".png");
                        }
                        else
                        {
                            saveLocation = Path.Combine(outdir, tex3mat.filename + ".png");
                        }
                    }
                    else
                    {
                        saveLocation = Path.Combine(outdir, destinationOverride, tex3mat.filename + ".png");
                    }

                    if (!File.Exists(saveLocation))
                    {
                        try
                        {
                            blpreader.bmp.Save(saveLocation);
                        }
                        catch (Exception e)
                        {
                            CASCLib.Logger.WriteLine("Exception while saving BLP " + tex3mat.filename + ": " + e.Message);
                        }
                    }

                    extraMaterials.Add(tex3mat);
                }
            }

            //No idea how MTL files really work yet. Needs more investigation.
            foreach (var material in materials)
            {
                mtlsb.Append("newmtl " + material.filename + "\n");
                mtlsb.Append("Ns 96.078431\n");
                mtlsb.Append("Ka 1.000000 1.000000 1.000000\n");
                mtlsb.Append("Kd 0.640000 0.640000 0.640000\n");
                mtlsb.Append("Ks 0.000000 0.000000 0.000000\n");
                mtlsb.Append("Ke 0.000000 0.000000 0.000000\n");
                mtlsb.Append("Ni 1.000000\n");
                mtlsb.Append("d 1.000000\n");
                mtlsb.Append("illum 1\n");
                mtlsb.Append("map_Kd " + material.filename + ".png\n");
                if (material.transparent)
                {
                    mtlsb.Append("map_d " + material.filename + ".png\n");
                }

                if (ConfigurationManager.AppSettings["textureMetadata"] == "True")
                {
                    mtlsb.Append("blend " + material.blendMode + "\n");
                    mtlsb.Append("shader " + material.shaderID + "\n");
                    mtlsb.Append("terrain " + material.terrainType + "\n");
                }
            }

            foreach (var material in extraMaterials)
            {
                mtlsb.Append("newmtl " + material.filename + "\n");
                mtlsb.Append("Ns 96.078431\n");
                mtlsb.Append("Ka 1.000000 1.000000 1.000000\n");
                mtlsb.Append("Kd 0.640000 0.640000 0.640000\n");
                mtlsb.Append("Ks 0.000000 0.000000 0.000000\n");
                mtlsb.Append("Ke 0.000000 0.000000 0.000000\n");
                mtlsb.Append("Ni 1.000000\n");
                mtlsb.Append("d 1.000000\n");
                mtlsb.Append("illum 1\n");
                mtlsb.Append("map_Kd " + material.filename + ".png\n");
                if (material.transparent)
                {
                    mtlsb.Append("map_d " + material.filename + ".png\n");
                }
            }


            if (!string.IsNullOrEmpty(filename))
            {
                if (destinationOverride == null)
                {
                    File.WriteAllText(Path.Combine(outdir, filename.Replace(".wmo", ".mtl")), mtlsb.ToString());
                }
                else
                {
                    File.WriteAllText(Path.Combine(outdir, destinationOverride, Path.GetFileName(filename.ToLower()).Replace(".wmo", ".mtl")), mtlsb.ToString());
                }
            }
            else
            {
                if (destinationOverride == null)
                {
                    File.WriteAllText(Path.Combine(outdir, filedataid + ".mtl"), mtlsb.ToString());
                }
                else
                {
                    File.WriteAllText(Path.Combine(outdir, destinationOverride, filedataid + ".mtl"), mtlsb.ToString());
                }
            }

            exportworker.ReportProgress(75, "Exporting model..");

            var numRenderbatches = 0;

            //Get total amount of render batches
            for (var i = 0; i < wmo.group.Count(); i++)
            {
                if (wmo.group[i].mogp.renderBatches == null)
                {
                    continue;
                }
                numRenderbatches = numRenderbatches + wmo.group[i].mogp.renderBatches.Count();
            }


            var rb = 0;

            for (var g = 0; g < wmo.group.Count(); g++)
            {
                groups[g].renderBatches = new Structs.RenderBatch[numRenderbatches];

                var group = wmo.group[g];
                if (group.mogp.renderBatches == null)
                {
                    continue;
                }

                for (var i = 0; i < group.mogp.renderBatches.Count(); i++)
                {
                    var batch = group.mogp.renderBatches[i];

                    groups[g].renderBatches[rb].firstFace = batch.firstFace;
                    groups[g].renderBatches[rb].numFaces  = batch.numFaces;

                    if (batch.flags == 2)
                    {
                        groups[g].renderBatches[rb].materialID = (uint)batch.possibleBox2_3;
                    }
                    else
                    {
                        groups[g].renderBatches[rb].materialID = batch.materialID;
                    }
                    groups[g].renderBatches[rb].blendType = wmo.materials[batch.materialID].blendMode;
                    groups[g].renderBatches[rb].groupID   = (uint)g;
                    rb++;
                }
            }

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

            StreamWriter objsw;

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

                objsw.WriteLine("# Written by Marlamin's WoW Export Tools. Original file: " + filename);
                objsw.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(filename) + ".mtl");
            }
            else
            {
                if (destinationOverride == null)
                {
                    objsw = new StreamWriter(Path.Combine(outdir, filedataid + ".obj"));
                }
                else
                {
                    objsw = new StreamWriter(Path.Combine(outdir, destinationOverride, filedataid + ".obj"));
                }

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

            foreach (var group in groups)
            {
                if (group.vertices == null)
                {
                    continue;
                }
                Console.WriteLine("Writing " + group.name);
                objsw.WriteLine("g " + group.name);

                foreach (var vertex in group.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 indices = group.indices;

                foreach (var renderbatch in group.renderBatches)
                {
                    var i = renderbatch.firstFace;
                    if (renderbatch.numFaces > 0)
                    {
                        objsw.WriteLine("usemtl " + materials[renderbatch.materialID].filename);
                        objsw.WriteLine("s 1");
                        while (i < (renderbatch.firstFace + renderbatch.numFaces))
                        {
                            objsw.WriteLine("f " + (indices[i] + group.verticeOffset + 1) + "/" + (indices[i] + group.verticeOffset + 1) + "/" + (indices[i] + group.verticeOffset + 1) + " " + (indices[i + 1] + group.verticeOffset + 1) + "/" + (indices[i + 1] + group.verticeOffset + 1) + "/" + (indices[i + 1] + group.verticeOffset + 1) + " " + (indices[i + 2] + group.verticeOffset + 1) + "/" + (indices[i + 2] + group.verticeOffset + 1) + "/" + (indices[i + 2] + group.verticeOffset + 1));
                            i = i + 3;
                        }
                    }
                }
            }
            objsw.Close();
            Console.WriteLine("Done loading WMO file!");
        }
Ejemplo n.º 14
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!");
        }
Ejemplo n.º 15
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
        }
Ejemplo n.º 16
0
        public static void exportWMO(string file, BackgroundWorker exportworker = null, string destinationOverride = null, ushort doodadSetExportID = ushort.MaxValue)
        {
            if (exportworker == null)
            {
                exportworker = new BackgroundWorker();
                exportworker.WorkerReportsProgress = true;
            }

            Console.WriteLine("Loading WMO file..");

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

            var outdir = ConfigurationManager.AppSettings["outdir"];
            var wmo    = new WMOReader().LoadWMO(file);

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

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

            exportworker.ReportProgress(30, "Reading WMO..");

            uint totalVertices = 0;

            var groups = new Structs.WMOGroup[wmo.group.Count()];

            for (var g = 0; g < wmo.group.Count(); g++)
            {
                Console.WriteLine("Loading group #" + g);
                if (wmo.group[g].mogp.vertices == null)
                {
                    Console.WriteLine("Group has no vertices!"); continue;
                }
                for (var i = 0; i < wmo.groupNames.Count(); i++)
                {
                    if (wmo.group[g].mogp.nameOffset == wmo.groupNames[i].offset)
                    {
                        groups[g].name = wmo.groupNames[i].name.Replace(" ", "_");
                    }
                }

                if (groups[g].name == "antiportal")
                {
                    Console.WriteLine("Group is antiportal"); continue;
                }

                groups[g].verticeOffset = totalVertices;
                groups[g].vertices      = new Structs.Vertex[wmo.group[g].mogp.vertices.Count()];

                for (var i = 0; i < wmo.group[g].mogp.vertices.Count(); i++)
                {
                    groups[g].vertices[i].Position = new Vector3(wmo.group[g].mogp.vertices[i].vector.X * -1, wmo.group[g].mogp.vertices[i].vector.Z, wmo.group[g].mogp.vertices[i].vector.Y);
                    groups[g].vertices[i].Normal   = new Vector3(wmo.group[g].mogp.normals[i].normal.X, wmo.group[g].mogp.normals[i].normal.Z, wmo.group[g].mogp.normals[i].normal.Y);
                    groups[g].vertices[i].TexCoord = new Vector2(wmo.group[g].mogp.textureCoords[0][i].X, wmo.group[g].mogp.textureCoords[0][i].Y);
                    totalVertices++;
                }

                var indicelist = new List <uint>();

                for (var i = 0; i < wmo.group[g].mogp.indices.Count(); i++)
                {
                    indicelist.Add(wmo.group[g].mogp.indices[i].indice);
                }

                groups[g].indices = indicelist.ToArray();
            }

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

            StreamWriter doodadSW;

            if (destinationOverride == null)
            {
                doodadSW = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file).Replace(" ", "") + "_ModelPlacementInformation.csv"));
            }
            else
            {
                doodadSW = new StreamWriter(Path.Combine(outdir, destinationOverride, Path.GetFileNameWithoutExtension(file).Replace(" ", "") + "_ModelPlacementInformation.csv"));
            }

            exportworker.ReportProgress(55, "Exporting doodads..");

            doodadSW.WriteLine("ModelFile;PositionX;PositionY;PositionZ;RotationW;RotationX;RotationY;RotationZ;ScaleFactor;DoodadSet");

            for (var i = 0; i < wmo.doodadSets.Count(); i++)
            {
                var doodadSet = wmo.doodadSets[i];

                var currentDoodadSetName = doodadSet.setName.Replace("Set_", "").Replace("SET_", "").Replace("$DefaultGlobal", "Default");

                if (doodadSetExportID != ushort.MaxValue)
                {
                    //if (i != 0 && i != doodadSetExportID) // Is 0 always exported? Double check?
                    if (i != doodadSetExportID)
                    {
                        Console.WriteLine("Skipping doodadset with ID " + i + " (" + currentDoodadSetName + ") because export filter is set to " + doodadSetExportID);
                        continue;
                    }
                }

                Console.WriteLine("At doodadset " + i + " (" + currentDoodadSetName + ")");

                for (var j = doodadSet.firstInstanceIndex; j < (doodadSet.firstInstanceIndex + doodadSet.numDoodads); j++)
                {
                    var doodadDefinition = wmo.doodadDefinitions[j];

                    if (wmo.doodadIds != null)
                    {
                        var doodadFileDataID = wmo.doodadIds[doodadDefinition.offset];

                        if (destinationOverride == null)
                        {
                            if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), doodadFileDataID + ".obj")))
                            {
                                M2Exporter.ExportM2(doodadFileDataID, null, Path.Combine(outdir, Path.GetDirectoryName(file)));
                            }

                            if (File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), doodadFileDataID + ".obj")))
                            {
                                doodadSW.WriteLine(doodadFileDataID + ".obj;" + doodadDefinition.position.X.ToString("F09") + ";" + doodadDefinition.position.Y.ToString("F09") + ";" + doodadDefinition.position.Z.ToString("F09") + ";" + doodadDefinition.rotation.W.ToString("F15") + ";" + doodadDefinition.rotation.X.ToString("F15") + ";" + doodadDefinition.rotation.Y.ToString("F15") + ";" + doodadDefinition.rotation.Z.ToString("F15") + ";" + doodadDefinition.scale + ";" + currentDoodadSetName);
                            }
                        }
                        else
                        {
                            if (!File.Exists(Path.Combine(destinationOverride, doodadFileDataID + ".obj")))
                            {
                                M2Exporter.ExportM2(doodadFileDataID, null, destinationOverride);
                            }

                            if (File.Exists(Path.Combine(destinationOverride, doodadFileDataID + ".obj")))
                            {
                                doodadSW.WriteLine(doodadFileDataID + ".obj;" + doodadDefinition.position.X.ToString("F09") + ";" + doodadDefinition.position.Y.ToString("F09") + ";" + doodadDefinition.position.Z.ToString("F09") + ";" + doodadDefinition.rotation.W.ToString("F15") + ";" + doodadDefinition.rotation.X.ToString("F15") + ";" + doodadDefinition.rotation.Y.ToString("F15") + ";" + doodadDefinition.rotation.Z.ToString("F15") + ";" + doodadDefinition.scale + ";" + currentDoodadSetName);
                            }
                        }
                    }
                    else
                    {
                        foreach (var doodadNameEntry in wmo.doodadNames)
                        {
                            if (doodadNameEntry.startOffset == doodadDefinition.offset)
                            {
                                var doodadFileName = doodadNameEntry.filename.Replace(".MDX", ".M2").Replace(".MDL", ".M2");

                                if (destinationOverride == null)
                                {
                                    if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileName(doodadFileName.ToLower()).Replace(".m2", ".obj"))))
                                    {
                                        M2Exporter.ExportM2(doodadFileName, null, Path.Combine(outdir, Path.GetDirectoryName(file)));
                                    }

                                    if (File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileName(doodadFileName.ToLower()).Replace(".m2", ".obj"))))
                                    {
                                        doodadSW.WriteLine(Path.GetFileNameWithoutExtension(doodadNameEntry.filename).ToLower() + ".obj;" + doodadDefinition.position.X.ToString("F09") + ";" + doodadDefinition.position.Y.ToString("F09") + ";" + doodadDefinition.position.Z.ToString("F09") + ";" + doodadDefinition.rotation.W.ToString("F15") + ";" + doodadDefinition.rotation.X.ToString("F15") + ";" + doodadDefinition.rotation.Y.ToString("F15") + ";" + doodadDefinition.rotation.Z.ToString("F15") + ";" + doodadDefinition.scale + ";" + currentDoodadSetName);
                                    }
                                }
                                else
                                {
                                    if (!File.Exists(Path.Combine(destinationOverride, Path.GetFileName(doodadFileName.ToLower()).Replace(".m2", ".obj"))))
                                    {
                                        M2Exporter.ExportM2(doodadNameEntry.filename.Replace(".MDX", ".M2").Replace(".MDL", ".M2"), null, destinationOverride);
                                    }

                                    if (File.Exists(Path.Combine(destinationOverride, Path.GetFileName(doodadFileName.ToLower()).Replace(".m2", ".obj"))))
                                    {
                                        doodadSW.WriteLine(Path.GetFileNameWithoutExtension(doodadNameEntry.filename).ToLower() + ".obj;" + doodadDefinition.position.X.ToString("F09") + ";" + doodadDefinition.position.Y.ToString("F09") + ";" + doodadDefinition.position.Z.ToString("F09") + ";" + doodadDefinition.rotation.W.ToString("F15") + ";" + doodadDefinition.rotation.X.ToString("F15") + ";" + doodadDefinition.rotation.Y.ToString("F15") + ";" + doodadDefinition.rotation.Z.ToString("F15") + ";" + doodadDefinition.scale + ";" + currentDoodadSetName);
                                    }
                                }

                                break;
                            }
                        }
                    }
                }
            }

            doodadSW.Close();

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

            var mtlsb     = new StringBuilder();
            var textureID = 0;

            if (wmo.materials == null)
            {
                Console.WriteLine("Materials empty");
                return;
            }

            var materials = new Structs.Material[wmo.materials.Count()];

            for (var i = 0; i < wmo.materials.Count(); i++)
            {
                if (wmo.textures == null)
                {
                    materials[i].textureID = textureID + i;
                    materials[i].filename  = wmo.materials[i].texture1.ToString();

                    if (wmo.materials[i].blendMode == 0)
                    {
                        materials[i].transparent = false;
                    }
                    else
                    {
                        materials[i].transparent = true;
                    }

                    if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), materials[i].filename + ".png")))
                    {
                        var blpreader = new BLPReader();

                        blpreader.LoadBLP(wmo.materials[i].texture1);

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

                    textureID++;
                }
                else
                {
                    for (var ti = 0; ti < wmo.textures.Count(); ti++)
                    {
                        if (wmo.textures[ti].startOffset == wmo.materials[i].texture1)
                        {
                            materials[i].textureID = textureID + i;
                            materials[i].filename  = Path.GetFileNameWithoutExtension(wmo.textures[ti].filename);

                            if (wmo.materials[i].blendMode == 0)
                            {
                                materials[i].transparent = false;
                            }
                            else
                            {
                                materials[i].transparent = true;
                            }

                            if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), materials[i].filename + ".png")))
                            {
                                var blpreader = new BLPReader();

                                blpreader.LoadBLP(wmo.textures[ti].filename);

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

                            textureID++;
                        }
                    }
                }
            }

            //No idea how MTL files really work yet. Needs more investigation.
            foreach (var material in materials)
            {
                mtlsb.Append("newmtl " + material.filename + "\n");
                mtlsb.Append("Ns 96.078431\n");
                mtlsb.Append("Ka 1.000000 1.000000 1.000000\n");
                mtlsb.Append("Kd 0.640000 0.640000 0.640000\n");
                mtlsb.Append("Ks 0.000000 0.000000 0.000000\n");
                mtlsb.Append("Ke 0.000000 0.000000 0.000000\n");
                mtlsb.Append("Ni 1.000000\n");
                mtlsb.Append("d 1.000000\n");
                mtlsb.Append("illum 2\n");
                mtlsb.Append("map_Kd " + material.filename + ".png\n");
                if (material.transparent)
                {
                    mtlsb.Append("map_d " + material.filename + ".png\n");
                }
            }

            if (destinationOverride == null)
            {
                File.WriteAllText(Path.Combine(outdir, file.Replace(".wmo", ".mtl")), mtlsb.ToString());
            }
            else
            {
                File.WriteAllText(Path.Combine(outdir, destinationOverride, Path.GetFileName(file.ToLower()).Replace(".wmo", ".mtl")), mtlsb.ToString());
            }

            exportworker.ReportProgress(75, "Exporting model..");

            var numRenderbatches = 0;

            //Get total amount of render batches
            for (var i = 0; i < wmo.group.Count(); i++)
            {
                if (wmo.group[i].mogp.renderBatches == null)
                {
                    continue;
                }
                numRenderbatches = numRenderbatches + wmo.group[i].mogp.renderBatches.Count();
            }


            var rb = 0;

            for (var g = 0; g < wmo.group.Count(); g++)
            {
                groups[g].renderBatches = new Structs.RenderBatch[numRenderbatches];

                var group = wmo.group[g];
                if (group.mogp.renderBatches == null)
                {
                    continue;
                }

                for (var i = 0; i < group.mogp.renderBatches.Count(); i++)
                {
                    var batch = group.mogp.renderBatches[i];

                    groups[g].renderBatches[rb].firstFace = batch.firstFace;
                    groups[g].renderBatches[rb].numFaces  = batch.numFaces;

                    if (batch.flags == 2)
                    {
                        groups[g].renderBatches[rb].materialID = (uint)batch.possibleBox2_3;
                    }
                    else
                    {
                        groups[g].renderBatches[rb].materialID = batch.materialID;
                    }
                    groups[g].renderBatches[rb].blendType = wmo.materials[batch.materialID].blendMode;
                    groups[g].renderBatches[rb].groupID   = (uint)g;
                    rb++;
                }
            }

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

            StreamWriter objsw;

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

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

            foreach (var group in groups)
            {
                if (group.vertices == null)
                {
                    continue;
                }
                Console.WriteLine("Writing " + group.name);
                objsw.WriteLine("g " + group.name);

                foreach (var vertex in group.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"));
                }

                var indices = group.indices;

                foreach (var renderbatch in group.renderBatches)
                {
                    var i = renderbatch.firstFace;
                    if (renderbatch.numFaces > 0)
                    {
                        objsw.WriteLine("usemtl " + materials[renderbatch.materialID].filename);
                        objsw.WriteLine("s 1");
                        while (i < (renderbatch.firstFace + renderbatch.numFaces))
                        {
                            objsw.WriteLine("f " + (indices[i] + group.verticeOffset + 1) + "/" + (indices[i] + group.verticeOffset + 1) + "/" + (indices[i] + group.verticeOffset + 1) + " " + (indices[i + 1] + group.verticeOffset + 1) + "/" + (indices[i + 1] + group.verticeOffset + 1) + "/" + (indices[i + 1] + group.verticeOffset + 1) + " " + (indices[i + 2] + group.verticeOffset + 1) + "/" + (indices[i + 2] + group.verticeOffset + 1) + "/" + (indices[i + 2] + group.verticeOffset + 1));
                            i = i + 3;
                        }
                    }
                }
            }
            objsw.Close();
            Console.WriteLine("Done loading WMO file!");
        }
Ejemplo n.º 17
0
        public static void ExportWMO(string filename, string outdir, BackgroundWorker exportworker = null, string destinationOverride = null, ushort doodadSetExportID = ushort.MaxValue)
        {
            filename = filename.ToLower();


            if (exportworker == null)
            {
                exportworker = new BackgroundWorker();
                exportworker.WorkerReportsProgress = true;
            }

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

            var wmo = new WMOReader();

            wmo.LoadWMO(filename);


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

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

            exportworker.ReportProgress(30, "Reading WMO..");

            uint totalVertices = 0;

            var groups = new Structs.WMOGroup[wmo.wmofile.group.Count()];

            for (var g = 0; g < wmo.wmofile.group.Count(); g++)
            {
                if (wmo.wmofile.group[g].mogp.vertices == null)
                {
                    continue;
                }
                for (var i = 0; i < wmo.wmofile.groupNames.Count(); i++)
                {
                    if (wmo.wmofile.group[g].mogp.nameOffset == wmo.wmofile.groupNames[i].offset)
                    {
                        groups[g].name = wmo.wmofile.groupNames[i].name.Replace(" ", "_");
                    }
                }

                if (groups[g].name == "antiportal")
                {
                    //Console.WriteLine("Group is antiportal");
                    continue;
                }

                groups[g].verticeOffset = totalVertices;
                groups[g].vertices      = new Structs.Vertex[wmo.wmofile.group[g].mogp.vertices.Count()];

                for (var i = 0; i < wmo.wmofile.group[g].mogp.vertices.Count(); i++)
                {
                    groups[g].vertices[i].Position = new Structs.Vector3D()
                    {
                        X = wmo.wmofile.group[g].mogp.vertices[i].vector.X * -1,
                        Y = wmo.wmofile.group[g].mogp.vertices[i].vector.Z,
                        Z = wmo.wmofile.group[g].mogp.vertices[i].vector.Y
                    };

                    groups[g].vertices[i].Normal = new Structs.Vector3D()
                    {
                        X = wmo.wmofile.group[g].mogp.normals[i].normal.X,
                        Y = wmo.wmofile.group[g].mogp.normals[i].normal.Z,
                        Z = wmo.wmofile.group[g].mogp.normals[i].normal.Y
                    };

                    groups[g].vertices[i].TexCoord = new Structs.Vector2D()
                    {
                        X = wmo.wmofile.group[g].mogp.textureCoords[0][i].X,
                        Y = wmo.wmofile.group[g].mogp.textureCoords[0][i].Y
                    };

                    totalVertices++;
                }

                var indicelist = new List <uint>();

                for (var i = 0; i < wmo.wmofile.group[g].mogp.indices.Count(); i++)
                {
                    indicelist.Add(wmo.wmofile.group[g].mogp.indices[i].indice);
                }

                groups[g].indices = indicelist.ToArray();
            }

            if (destinationOverride == null)
            {
                // Create output directory
                if (!string.IsNullOrEmpty(filename))
                {
                    if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(filename))))
                    {
                        Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(filename)));
                    }
                }
                else
                {
                    if (!Directory.Exists(outdir))
                    {
                        Directory.CreateDirectory(outdir);
                    }
                }
            }
            #region M2Export
            bool exportM2 = Managers.ConfigurationManager.WMOExportM2;
            if (exportM2)
            {
                StreamWriter doodadSW;

                if (destinationOverride == null)
                {
                    if (!string.IsNullOrEmpty(filename))
                    {
                        doodadSW = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename.Replace(" ", "")) + "_ModelPlacementInformation.csv"));
                    }
                    else
                    {
                        doodadSW = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(filename), filename + "_ModelPlacementInformation.csv"));
                    }
                }
                else
                {
                    if (!string.IsNullOrEmpty(filename))
                    {
                        doodadSW = new StreamWriter(Path.Combine(outdir, destinationOverride, Path.GetFileNameWithoutExtension(filename).Replace(" ", "") + "_ModelPlacementInformation.csv"));
                    }
                    else
                    {
                        doodadSW = new StreamWriter(Path.Combine(outdir, destinationOverride, filename + "_ModelPlacementInformation.csv"));
                    }
                }

                exportworker.ReportProgress(55, "Exporting doodads..");

                doodadSW.WriteLine("ModelFile;PositionX;PositionY;PositionZ;RotationW;RotationX;RotationY;RotationZ;ScaleFactor;DoodadSet");

                for (var i = 0; i < wmo.wmofile.doodadSets.Count(); i++)
                {
                    var doodadSet = wmo.wmofile.doodadSets[i];

                    var currentDoodadSetName = doodadSet.setName.Replace("Set_", "").Replace("SET_", "").Replace("$DefaultGlobal", "Default");

                    if (doodadSetExportID != ushort.MaxValue)
                    {
                        if (i != 0 && i != doodadSetExportID)
                        {
                            //Console.WriteLine("Skipping doodadset with ID " + i + " (" + currentDoodadSetName + ") because export filter is set to " + doodadSetExportID);
                            continue;
                        }
                    }

                    //Console.WriteLine("At doodadset " + i + " (" + currentDoodadSetName + ")");

                    for (var j = doodadSet.firstInstanceIndex; j < (doodadSet.firstInstanceIndex + doodadSet.numDoodads); j++)
                    {
                        foreach (var doodadNameEntry in wmo.wmofile.doodadNames)
                        {
                            var doodadDefinition = wmo.wmofile.doodadDefinitions[j];

                            if (doodadNameEntry.startOffset == doodadDefinition.offset)
                            {
                                var doodadFileName = doodadNameEntry.filename.Replace(".MDX", ".M2").Replace(".MDL", ".M2");

                                if (destinationOverride == null)
                                {
                                    if (Managers.ConfigurationManager.WMODoodadsGlobalPath)
                                    {
                                        if (!File.Exists(Path.Combine(outdir, Path.GetFileName(doodadFileName.ToLower()).Replace(".m2", ".obj"))))
                                        {
                                            M2Exporter.ExportM2(doodadFileName, outdir, exportworker);
                                        }
                                    }
                                    else
                                    {
                                        if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(filename), Path.GetFileName(doodadFileName.ToLower()).Replace(".m2", ".obj"))))
                                        {
                                            M2Exporter.ExportM2(doodadFileName, Path.Combine(outdir, Path.GetDirectoryName(filename)), exportworker);
                                        }
                                    }
                                }
                                else
                                {
                                    if (!File.Exists(Path.Combine(destinationOverride, Path.GetFileName(doodadFileName.ToLower()).Replace(".m2", ".obj"))))
                                    {
                                        M2Exporter.ExportM2(doodadNameEntry.filename.Replace(".MDX", ".M2").Replace(".MDL", ".M2"), destinationOverride, exportworker);
                                    }
                                }

                                if (Managers.ConfigurationManager.WMODoodadsPlacementGlobalPath)
                                {
                                    doodadSW.WriteLine(doodadNameEntry.filename.ToLower().Replace(".mdx", ".m2").Replace(".mdl", ".m2").Replace(".m2", ".obj;") + doodadDefinition.position.X.ToString("F09") + ";" + doodadDefinition.position.Y.ToString("F09") + ";" + doodadDefinition.position.Z.ToString("F09") + ";" + doodadDefinition.rotation.W.ToString("F15") + ";" + doodadDefinition.rotation.X.ToString("F15") + ";" + doodadDefinition.rotation.Y.ToString("F15") + ";" + doodadDefinition.rotation.Z.ToString("F15") + ";" + doodadDefinition.scale + ";" + currentDoodadSetName);
                                }
                                else
                                {
                                    doodadSW.WriteLine(Path.GetFileNameWithoutExtension(doodadNameEntry.filename).ToLower() + ".obj;" + doodadDefinition.position.X.ToString("F09") + ";" + doodadDefinition.position.Y.ToString("F09") + ";" + doodadDefinition.position.Z.ToString("F09") + ";" + doodadDefinition.rotation.W.ToString("F15") + ";" + doodadDefinition.rotation.X.ToString("F15") + ";" + doodadDefinition.rotation.Y.ToString("F15") + ";" + doodadDefinition.rotation.Z.ToString("F15") + ";" + doodadDefinition.scale + ";" + currentDoodadSetName);
                                }

                                break;
                            }
                        }
                    }
                }
                doodadSW.Close();
            }
            #endregion
            var mtlsb     = new StringBuilder();
            var textureID = 0;

            if (wmo.wmofile.materials == null)
            {
                return;
            }

            var materials = new Structs.Material[wmo.wmofile.materials.Count()];

            for (var i = 0; i < wmo.wmofile.materials.Count(); i++)
            {
                for (var ti = 0; ti < wmo.wmofile.textures.Count(); ti++)
                {
                    if (wmo.wmofile.textures[ti].startOffset == wmo.wmofile.materials[i].texture1)
                    {
                        materials[i].textureID = textureID + i;
                        materials[i].filename  = Path.GetFileNameWithoutExtension(wmo.wmofile.textures[ti].filename);

                        if (wmo.wmofile.materials[i].blendMode == 0)
                        {
                            materials[i].transparent = false;
                        }
                        else
                        {
                            materials[i].transparent = true;
                        }

                        if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(filename), materials[i].filename + ".png")))
                        {
                            var blpreader = new BLPReader();
                            blpreader.LoadBLP(Managers.ArchiveManager.ReadThisFile(wmo.wmofile.textures[ti].filename));

                            try
                            {
                                if (destinationOverride == null)
                                {
                                    blpreader.bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(filename), materials[i].filename + ".png"));
                                }
                                else
                                {
                                    blpreader.bmp.Save(Path.Combine(outdir, destinationOverride, materials[i].filename.ToLower() + ".png"));
                                }
                            }
                            catch
                            {
                                //Error on file save
                            }
                        }

                        textureID++;
                    }
                }
            }

            //No idea how MTL files really work yet. Needs more investigation.
            foreach (var material in materials)
            {
                mtlsb.Append("newmtl " + material.filename + "\n");
                mtlsb.Append("Ns 96.078431\n");
                mtlsb.Append("Ka 1.000000 1.000000 1.000000\n");
                mtlsb.Append("Kd 0.640000 0.640000 0.640000\n");
                mtlsb.Append("Ks 0.000000 0.000000 0.000000\n");
                mtlsb.Append("Ke 0.000000 0.000000 0.000000\n");
                mtlsb.Append("Ni 1.000000\n");
                mtlsb.Append("d 1.000000\n");
                mtlsb.Append("illum 1\n");
                mtlsb.Append("map_Kd " + material.filename + ".png\n");
                if (material.transparent)
                {
                    mtlsb.Append("map_d " + material.filename + ".png\n");
                }

                /* //temporary removed
                 * if (ConfigurationManager.AppSettings["textureMetadata"] == "True")
                 * {
                 *  mtlsb.Append("blend " + material.blendMode + "\n");
                 *  mtlsb.Append("shader " + material.shaderID + "\n");
                 *  mtlsb.Append("terrain " + material.terrainType + "\n");
                 * }
                 */
            }

            if (!string.IsNullOrEmpty(filename))
            {
                if (destinationOverride == null)
                {
                    File.WriteAllText(Path.Combine(outdir, filename.Replace(".wmo", ".mtl")), mtlsb.ToString());
                }
                else
                {
                    File.WriteAllText(Path.Combine(outdir, destinationOverride, Path.GetFileName(filename.ToLower()).Replace(".wmo", ".mtl")), mtlsb.ToString());
                }
            }
            else
            {
                if (destinationOverride == null)
                {
                    File.WriteAllText(Path.Combine(outdir, filename + ".mtl"), mtlsb.ToString());
                }
                else
                {
                    File.WriteAllText(Path.Combine(outdir, destinationOverride, filename + ".mtl"), mtlsb.ToString());
                }
            }

            exportworker.ReportProgress(75, "Exporting model..");

            var numRenderbatches = 0;
            //Get total amount of render batches
            for (var i = 0; i < wmo.wmofile.group.Count(); i++)
            {
                if (wmo.wmofile.group[i].mogp.renderBatches == null)
                {
                    continue;
                }
                numRenderbatches = numRenderbatches + wmo.wmofile.group[i].mogp.renderBatches.Count();
            }


            var rb = 0;
            for (var g = 0; g < wmo.wmofile.group.Count(); g++)
            {
                groups[g].renderBatches = new Structs.RenderBatch[numRenderbatches];

                var group = wmo.wmofile.group[g];
                if (group.mogp.renderBatches == null)
                {
                    continue;
                }

                for (var i = 0; i < group.mogp.renderBatches.Count(); i++)
                {
                    var batch = group.mogp.renderBatches[i];

                    groups[g].renderBatches[rb].firstFace = batch.firstFace;
                    groups[g].renderBatches[rb].numFaces  = batch.numFaces;

                    if (batch.flags == 2)
                    {
                        groups[g].renderBatches[rb].materialID = (uint)batch.possibleBox2_3;
                    }
                    else
                    {
                        groups[g].renderBatches[rb].materialID = batch.materialID;
                    }
                    groups[g].renderBatches[rb].blendType = wmo.wmofile.materials[batch.materialID].blendMode;
                    groups[g].renderBatches[rb].groupID   = (uint)g;
                    rb++;
                }
            }

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

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

                objsw.WriteLine("# Written by Marlamin's WoW Export Tools. Original file: " + filename);
                objsw.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(filename) + ".mtl");
            }
            else
            {
                if (destinationOverride == null)
                {
                    objsw = new StreamWriter(Path.Combine(outdir, filename + ".obj"));
                }
                else
                {
                    objsw = new StreamWriter(Path.Combine(outdir, destinationOverride, filename + ".obj"));
                }
                objsw.WriteLine("# Written by Marlamin's WoW Export Tools. Original file id: " + filename);
                objsw.WriteLine("mtllib " + filename + ".mtl");
            }

            foreach (var group in groups)
            {
                if (group.vertices == null)
                {
                    continue;
                }
                //Console.WriteLine("Writing " + group.name);
                objsw.WriteLine("o " + group.name);

                //Added thunderysteak's adjustment (original commit: ed067c7c6e8321c33ef0f3679d33c9c472dcefc3)
                foreach (var vertex in group.vertices)
                {
                    objsw.WriteLine("v " + vertex.Position.X + " " + vertex.Position.Y + " " + vertex.Position.Z);
                }

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

                var indices = group.indices;

                foreach (var renderbatch in group.renderBatches)
                {
                    var i = renderbatch.firstFace;
                    if (renderbatch.numFaces > 0)
                    {
                        //thunderysteak's adjustment
                        //objsw.WriteLine("o " + group.name); //?
                        objsw.WriteLine("g " + group.name);//3DS Max's OBJ importer fails with invalid normal index without groups being defined
                        //--------------------------
                        objsw.WriteLine("usemtl " + materials[renderbatch.materialID].filename);
                        objsw.WriteLine("s 1");
                        while (i < (renderbatch.firstFace + renderbatch.numFaces))
                        {
                            objsw.WriteLine("f " + (indices[i] + group.verticeOffset + 1) + "/" + (indices[i] + group.verticeOffset + 1) + "/" + (indices[i] + group.verticeOffset + 1) + " " + (indices[i + 1] + group.verticeOffset + 1) + "/" + (indices[i + 1] + group.verticeOffset + 1) + "/" + (indices[i + 1] + group.verticeOffset + 1) + " " + (indices[i + 2] + group.verticeOffset + 1) + "/" + (indices[i + 2] + group.verticeOffset + 1) + "/" + (indices[i + 2] + group.verticeOffset + 1));
                            i += 3;
                        }
                    }
                }
            }
            objsw.Close();
            //Console.WriteLine("Done loading WMO file!");
        }
Ejemplo n.º 18
0
        public static void exportADT(string file, string outdir, string bakeQuality, BackgroundWorker exportworker = null)
        {
            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 MaxSize      = 51200 / 3.0;
            var TileSize     = MaxSize / 32.0;
            var ChunkSize    = TileSize / 16.0;
            var UnitSize     = ChunkSize / 8.0;
            var UnitSizeHalf = UnitSize / 2.0;

            string mapname = file;

            mapname = mapname.Substring(mapname.LastIndexOf("\\", mapname.Length - 2) + 1);
            mapname = mapname.Substring(0, mapname.Length - 4);

            var reader = new ADTReader();

            var ADTfile = file;

            exportworker.ReportProgress(0, "Loading ADT " + file);

            if (Managers.ConfigurationManager.Profile <= 3) //WoTLK and below
            {
                reader.Load335ADT(ADTfile);
            }
            else
            {
                reader.LoadADT(ADTfile);
            }

            if (reader.adtfile.chunks == null)
            {
                throw new Exception("ADT OBJ Exporter: File has no chunks, skipping export!");
            }

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

            var renderBatches = new List <Structs.RenderBatch>();
            var verticelist   = new List <Structs.Vertex>();
            var indicelist    = new List <int>();
            var materials     = new Dictionary <int, string>();

            // Calculate ADT offset in world coordinates
            var adtStartX = reader.adtfile.chunks[0].header.position.X;
            var adtStartY = reader.adtfile.chunks[0].header.position.Y;

            // Calculate first chunk offset in world coordinates
            var initialChunkX = adtStartX + (reader.adtfile.chunks[0].header.indexX * ChunkSize) * -1;
            var initialChunkY = adtStartY + (reader.adtfile.chunks[0].header.indexY * ChunkSize) * -1;

            uint ci = 0;

            for (var x = 0; x < 16; x++)
            {
                for (var y = 0; y < 16; y++)
                {
                    var genx = (initialChunkX + (ChunkSize * x) * -1);
                    var geny = (initialChunkY + (ChunkSize * y) * -1);

                    var chunk = reader.adtfile.chunks[ci];

                    var off = verticelist.Count();

                    var batch = new Structs.RenderBatch();

                    for (int row = 0, idx = 0; row < 17; row++)
                    {
                        bool isSmallRow = (row % 2) != 0;
                        int  rowLength  = isSmallRow ? 8 : 9;

                        for (var col = 0; col < rowLength; col++)
                        {
                            var v = new Structs.Vertex();

                            v.Normal = new Structs.Vector3D
                            {
                                X = (double)chunk.normals.normal_0[idx] / 127,
                                Y = (double)chunk.normals.normal_2[idx] / 127,
                                Z = (double)chunk.normals.normal_1[idx] / 127
                            };

                            var px = geny - (col * UnitSize);
                            var py = chunk.vertices.vertices[idx++] + chunk.header.position.Z;
                            var pz = genx - (row * UnitSizeHalf);

                            v.Position = new Structs.Vector3D
                            {
                                X = px,
                                Y = py,
                                Z = pz
                            };

                            if ((row % 2) != 0)
                            {
                                v.Position.X = (px - UnitSizeHalf);
                            }

                            double ofs = col;
                            if (isSmallRow)
                            {
                                ofs += 0.5;
                            }

                            if (bakeQuality == "high")
                            {
                                double tx = ofs / 8d;
                                double ty = 1 - (row / 16d);
                                v.TexCoord = new Structs.Vector2D {
                                    X = tx, Y = ty
                                };
                            }
                            else
                            {
                                double tx = -(v.Position.X - initialChunkY) / TileSize;
                                double ty = (v.Position.Z - initialChunkX) / TileSize;

                                v.TexCoord = new Structs.Vector2D {
                                    X = tx, Y = ty
                                };
                            }
                            verticelist.Add(v);
                        }
                    }

                    batch.firstFace = (uint)indicelist.Count();

                    // Stupid C# and its structs
                    var holesHighRes = new byte[8];
                    holesHighRes[0] = chunk.header.holesHighRes_0;
                    holesHighRes[1] = chunk.header.holesHighRes_1;
                    holesHighRes[2] = chunk.header.holesHighRes_2;
                    holesHighRes[3] = chunk.header.holesHighRes_3;
                    holesHighRes[4] = chunk.header.holesHighRes_4;
                    holesHighRes[5] = chunk.header.holesHighRes_5;
                    holesHighRes[6] = chunk.header.holesHighRes_6;
                    holesHighRes[7] = chunk.header.holesHighRes_7;

                    for (int j = 9, xx = 0, yy = 0; j < 145; j++, xx++)
                    {
                        if (xx >= 8)
                        {
                            xx = 0; ++yy;
                        }
                        var isHole = true;

                        // Check if chunk is using low-res holes
                        if ((chunk.header.flags & 0x10000) == 0)
                        {
                            // Calculate current hole number
                            var currentHole = (int)Math.Pow(2,
                                                            Math.Floor(xx / 2f) * 1f +
                                                            Math.Floor(yy / 2f) * 4f);

                            // Check if current hole number should be a hole
                            if ((chunk.header.holesLowRes & currentHole) == 0)
                            {
                                isHole = false;
                            }
                        }

                        //Sloppy ignore holes:
                        if (Managers.ConfigurationManager.ADTIgnoreHoles)
                        {
                            isHole = false;
                        }
                        else
                        {
                            // Check if current section is a hole
                            if (((holesHighRes[yy] >> xx) & 1) == 0)
                            {
                                isHole = false;
                            }
                        }

                        if (!isHole)
                        {
                            indicelist.AddRange(new int[] { off + j + 8, off + j - 9, off + j });
                            indicelist.AddRange(new int[] { off + j - 9, off + j - 8, off + j });
                            indicelist.AddRange(new int[] { off + j - 8, off + j + 9, off + j });
                            indicelist.AddRange(new int[] { off + j + 9, off + j + 8, off + j });

                            // Generates quads instead of 4x triangles
                            //indicelist.AddRange(new int[] { off + j + 8, off + j - 9, off + j - 8 });
                            //indicelist.AddRange(new int[] { off + j - 8, off + j + 9, off + j + 8 });
                        }
                        if ((j + 1) % (9 + 8) == 0)
                        {
                            j += 9;
                        }
                    }

                    if (bakeQuality == "high")
                    {
                        materials.Add((int)ci + 1, Path.GetFileNameWithoutExtension(file) + "_" + ci);
                        batch.materialID = ci + 1;
                    }
                    else
                    {
                        if (!materials.ContainsKey(1))
                        {
                            materials.Add(1, Path.GetFileNameWithoutExtension(file));
                        }
                        batch.materialID = (uint)materials.Count();
                    }
                    batch.numFaces = (uint)(indicelist.Count()) - batch.firstFace;

                    renderBatches.Add(batch);
                    ci++;
                }
            }

            bool exportWMO       = Managers.ConfigurationManager.ADTExportWMO;
            bool exportM2        = Managers.ConfigurationManager.ADTExportM2;
            bool exportTextures  = Managers.ConfigurationManager.ADTexportTextures;
            bool exportAlphaMaps = Managers.ConfigurationManager.ADTexportAlphaMaps;
            bool exportHeightmap = Managers.ConfigurationManager.ADTExportHeightmap;
            bool exportFoliage   = Managers.ConfigurationManager.ADTExportFoliage;

            //FOLIAGE
            if (exportFoliage && Managers.ArchiveManager.usingCasc) //ONLY EXPROT IF CASC; PRE CASC NEEDS TO BE IMPLEMEMNTED
            {
                exportworker.ReportProgress(65, "Exporting foliage");

                try
                {
                    var build = Managers.ArchiveManager.cascHandler.Config.VersionName; //TODO: IMPLEMENT PRE CASC BUILDS
                    var dbcd  = new DBCD.DBCD(new WoWExport.DBC.ArchiveDBCProvider(), new WoWExport.DBC.LocalDBCDProvider());
                    var groundEffectTextureDB = dbcd.Load("GroundEffectTexture", build);
                    var groundEffectDoodadDB  = dbcd.Load("GroundEffectDoodad", build);

                    for (var c = 0; c < reader.adtfile.texChunks.Length; c++)
                    {
                        for (var l = 0; l < reader.adtfile.texChunks[c].layers.Length; l++)
                        {
                            var effectID = reader.adtfile.texChunks[c].layers[l].effectId;
                            if (effectID == 0)
                            {
                                continue;
                            }

                            if (!groundEffectTextureDB.ContainsKey(effectID))
                            {
                                continue;
                            }

                            dynamic textureEntry = groundEffectTextureDB[effectID];
                            foreach (int doodad in textureEntry.DoodadID)
                            {
                                if (!groundEffectDoodadDB.ContainsKey(doodad))
                                {
                                    continue;
                                }

                                dynamic doodadEntry = groundEffectDoodadDB[doodad];

                                var filedataid = (uint)doodadEntry.ModelFileID;

                                if (!WoWExport.Listfile.TryGetFilename(filedataid, out var filename))
                                {
                                    Console.WriteLine("Could not find filename for " + filedataid + ", setting filename to filedataid..");
                                    filename = filedataid.ToString();
                                }

                                if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), "foliage")))
                                {
                                    Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file), "foliage"));
                                }

                                if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), "foliage", Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj")))
                                {
                                    M2Exporter.ExportM2(filename, Path.Combine(outdir, Path.GetDirectoryName(file), "foliage"));
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("Error exporting GroundEffects: " + e.Message);
                }
            }

            if (exportWMO || exportM2)
            {
                var doodadSW = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file).Replace(" ", "") + "_ModelPlacementInformation.csv"));
                doodadSW.WriteLine("ModelFile;PositionX;PositionY;PositionZ;RotationX;RotationY;RotationZ;ScaleFactor;ModelId;Type");

                if (exportWMO)
                {
                    exportworker.ReportProgress(25, "Exporting WMOs");

                    for (var mi = 0; mi < reader.adtfile.objects.worldModels.entries.Count(); mi++)
                    {
                        var wmo = reader.adtfile.objects.worldModels.entries[mi];

                        float wmoScale;
                        if (wmo.scale != 0)
                        {
                            wmoScale = wmo.scale / 1024f;
                        }
                        else
                        {
                            wmoScale = 1;
                        }

                        var filename = reader.adtfile.objects.wmoNames.filenames[wmo.mwidEntry];

                        if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj")))
                        {
                            WMOExporter.ExportWMO(filename, Path.Combine(outdir, Path.GetDirectoryName(file)), exportworker, null, wmo.doodadSet);
                        }

                        if (Managers.ConfigurationManager.ADTModelsPlacementGlobalPath)
                        {
                            doodadSW.WriteLine(Path.Combine(Path.GetDirectoryName(filename).ToLower(), Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj") + ";" + wmo.position.X + ";" + wmo.position.Y + ";" + wmo.position.Z + ";" + wmo.rotation.X + ";" + wmo.rotation.Y + ";" + wmo.rotation.Z + ";" + wmoScale + ";" + wmo.uniqueId + ";wmo");
                        }
                        else
                        {
                            doodadSW.WriteLine(Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj;" + wmo.position.X + ";" + wmo.position.Y + ";" + wmo.position.Z + ";" + wmo.rotation.X + ";" + wmo.rotation.Y + ";" + wmo.rotation.Z + ";" + wmoScale + ";" + wmo.uniqueId + ";wmo");
                        }
                    }
                }

                if (exportM2)
                {
                    exportworker.ReportProgress(50, "Exporting M2s");

                    for (var mi = 0; mi < reader.adtfile.objects.models.entries.Count(); mi++)
                    {
                        var doodad = reader.adtfile.objects.models.entries[mi];

                        string filename;
                        filename = reader.adtfile.objects.m2Names.filenames[doodad.mmidEntry];
                        if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj")))
                        {
                            M2Exporter.ExportM2(filename, Path.Combine(outdir, Path.GetDirectoryName(file)), exportworker);
                        }
                        if (Managers.ConfigurationManager.ADTModelsPlacementGlobalPath)
                        {
                            doodadSW.WriteLine(Path.Combine(Path.GetDirectoryName(filename).ToLower(), Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj") + ";" + doodad.position.X + ";" + doodad.position.Y + ";" + doodad.position.Z + ";" + doodad.rotation.X + ";" + doodad.rotation.Y + ";" + doodad.rotation.Z + ";" + doodad.scale / 1024f + ";" + doodad.uniqueId + ";m2");
                        }
                        else
                        {
                            doodadSW.WriteLine(Path.GetFileNameWithoutExtension(filename).ToLower() + ".obj;" + doodad.position.X + ";" + doodad.position.Y + ";" + doodad.position.Z + ";" + doodad.rotation.X + ";" + doodad.rotation.Y + ";" + doodad.rotation.Z + ";" + doodad.scale / 1024f + ";" + doodad.uniqueId + ";m2");
                        }
                    }
                }
                doodadSW.Close();
            }
            #region Alpha&Tex
            //----------------------------------------------------------------------------------------------------------
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////
            ///TEXTURE & ALPHA & HEIGHTMAP RELATED START
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //----------------------------------------------------------------------------------------------------------
            if (exportTextures) //Export ground textures
            {
                {
                    if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures")))
                    {
                        Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures"));
                    }
                }

                List <String> GroundTextures = reader.adtfile.textures.filenames.ToList();

                var blpreader = new BLPReader();
                foreach (string texture in GroundTextures)
                {
                    if (Managers.ConfigurationManager.ADTPreserveTextureStruct)
                    {
                        if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures", Path.GetDirectoryName(texture) + Path.GetFileNameWithoutExtension(texture) + ".png")))
                        {
                            if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures", Path.GetDirectoryName(texture))))
                            {
                                Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures", Path.GetDirectoryName(texture)));
                            }

                            if (Managers.ArchiveManager.FileExists(texture))
                            {
                                try
                                {
                                    blpreader.LoadBLP(Managers.ArchiveManager.ReadThisFile(texture));
                                    blpreader.bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures", Path.GetDirectoryName(texture), Path.GetFileNameWithoutExtension(texture) + ".png"));
                                    if (Managers.ConfigurationManager.ADTExportSpecularTextures)
                                    {
                                        if (Managers.ArchiveManager.FileExists(Path.Combine(Path.GetDirectoryName(texture), Path.GetFileNameWithoutExtension(texture) + "_s.blp")))
                                        {
                                            if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures", Path.GetDirectoryName(texture), Path.GetFileNameWithoutExtension(texture) + "_s.png")))
                                            {
                                                blpreader.LoadBLP(Managers.ArchiveManager.ReadThisFile(Path.Combine(Path.GetDirectoryName(texture), Path.GetFileNameWithoutExtension(texture) + "_s.blp")));
                                                blpreader.bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures", Path.GetDirectoryName(texture), Path.GetFileNameWithoutExtension(texture) + "_s.png"));
                                            }
                                        }
                                    }
                                }
                                catch (Exception e)
                                {
                                    //Error on file save
                                    throw new Exception(e.Message);
                                }
                            }
                            else
                            {
                                //Missing file
                            }
                        }
                    }
                    else
                    {
                        if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures\\", Path.GetFileNameWithoutExtension(texture) + ".png")))
                        {
                            if (Managers.ArchiveManager.FileExists(texture))
                            {
                                try
                                {
                                    blpreader.LoadBLP(Managers.ArchiveManager.ReadThisFile(texture));
                                    blpreader.bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures\\", Path.GetFileNameWithoutExtension(texture) + ".png"));
                                    if (Managers.ConfigurationManager.ADTExportSpecularTextures)
                                    {
                                        if (Managers.ArchiveManager.FileExists(Path.Combine(Path.GetDirectoryName(texture), Path.GetFileNameWithoutExtension(texture) + "_s.blp")))
                                        {
                                            if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures\\", Path.GetFileNameWithoutExtension(texture) + "_s.png")))
                                            {
                                                blpreader.LoadBLP(Managers.ArchiveManager.ReadThisFile(Path.Combine(Path.GetDirectoryName(texture), Path.GetFileNameWithoutExtension(texture) + "_s.blp")));
                                                blpreader.bmp.Save(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\GroundTextures\\", Path.GetFileNameWithoutExtension(texture) + "_s.png"));
                                            }
                                        }
                                    }
                                }
                                catch (Exception e)
                                {
                                    //Error on file save
                                    throw new Exception(e.Message);
                                }
                            }
                            else
                            {
                                //Missing file
                            }
                        }
                    }
                }
            }

            if (exportAlphaMaps)
            {
                Generators.ADT_Alpha.ADT_Alpha AlphaMapsGenerator = new Generators.ADT_Alpha.ADT_Alpha();
                AlphaMapsGenerator.GenerateAlphaMaps(reader.adtfile, Managers.ConfigurationManager.ADTAlphaMode);

                List <System.Drawing.Bitmap> AlphaLayers = new List <System.Drawing.Bitmap>();
                AlphaLayers = AlphaMapsGenerator.AlphaLayers;

                if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps")))
                {
                    Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps"));
                }

                if (AlphaLayers != null)
                {
                    if (Managers.ConfigurationManager.ADTAlphaMode == 0 || Managers.ConfigurationManager.ADTAlphaMode == 1)
                    {
                        for (int m = 0; m < AlphaLayers.ToArray().Length; m++)
                        {
                            if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps\\", mapname + "_" + m + ".png")))
                            {
                                try
                                {
                                    AlphaLayers[m].Save(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps\\", mapname + "_" + m + ".png"));
                                }
                                catch
                                {
                                    //Error on file save
                                }
                            }
                        }
                    }
                    if (Managers.ConfigurationManager.ADTAlphaMode == 2 || Managers.ConfigurationManager.ADTAlphaMode == 3)
                    {
                        List <String> AlphaLayersNames = new List <String>(AlphaMapsGenerator.AlphaLayersNames);
                        for (int m = 0; m < AlphaLayers.ToArray().Length; m++)
                        {
                            if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps\\", mapname + "_" + AlphaLayersNames[m].Replace(";", "_") + ".png")))
                            {
                                try
                                {
                                    AlphaLayers[m].Save(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps\\", mapname + "_" + AlphaLayersNames[m].Replace(";", "_") + ".png"));
                                }
                                catch
                                {
                                    //Error on file save
                                }
                            }
                        }
                    }
                    if (Managers.ConfigurationManager.ADTAlphaMode == 4) //Splatmaps
                    {
                        //Save the splatmaps
                        for (int m = 0; m < AlphaLayers.ToArray().Length; m++)
                        {
                            if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps\\", mapname + "_splatmap_" + m + ".png")))
                            {
                                try
                                {
                                    AlphaLayers[m].Save(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps\\", mapname + "_splatmap_" + m + ".png"));
                                }
                                catch
                                {
                                    //Error on file save
                                }
                            }
                        }
                        //Save the material info JSON
                        if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps\\", mapname + "_MaterialData.json")))
                        {
                            try
                            {
                                File.WriteAllText(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\AlphaMaps\\", mapname + "_MaterialData.json"), AlphaMapsGenerator.SplatmapJSON);
                            }
                            catch
                            {
                                //Error on file save
                            }
                        }
                    }
                }

                //Check if the CSV already exists, if not, create it
                if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\" + mapname + "_" + "layers.csv")))
                {
                    //Generate layer information CSV
                    StreamWriter layerCsvSR = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\" + mapname + "_" + "layers.csv"));
                    //Insert CSV scheme
                    layerCsvSR.WriteLine("chunk;tex0;tex1;tex2;tex3");
                    for (uint c = 0; c < reader.adtfile.chunks.Count(); c++)
                    {
                        string csvLine = c.ToString();
                        for (int li = 0; li < reader.adtfile.texChunks[c].layers.Count(); li++)
                        {
                            var AlphaLayerName = reader.adtfile.textures.filenames[reader.adtfile.texChunks[c].layers[li].textureId].ToLower();
                            if (Managers.ConfigurationManager.ADTPreserveTextureStruct)
                            {
                                csvLine = csvLine + ";" + Path.Combine(Path.GetDirectoryName(AlphaLayerName), Path.GetFileNameWithoutExtension(AlphaLayerName));
                            }
                            else
                            {
                                csvLine = csvLine + ";" + Path.GetFileNameWithoutExtension(AlphaLayerName);
                            }
                        }
                        layerCsvSR.WriteLine(csvLine);
                    }
                    layerCsvSR.Close();
                }
            }

            if (exportHeightmap)
            {
                Generators.ADT_Height.ADT_Height heightmapGenerator = new Generators.ADT_Height.ADT_Height();
                heightmapGenerator.GenerateHeightmap(reader.adtfile);

                if (!Directory.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\HeightMaps")))
                {
                    Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\HeightMaps"));
                }

                try
                {
                    File.WriteAllText(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\HeightMaps\\", mapname + "_HeightData.json"), Newtonsoft.Json.JsonConvert.SerializeObject(heightmapGenerator.heightArray2d));
                    heightmapGenerator.heightMap.Save(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\HeightMaps\\", mapname + "_heightmap.png"));
                }
                catch
                {
                    //Error on save
                }
            }
            //----------------------------------------------------------------------------------------------------------
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////
            ///TEXTURE & ALPHA & HEIGHTMAP RELATED END
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //----------------------------------------------------------------------------------------------------------
            #endregion

            //VERTEX COLORS -- not implemented

            /*
             * //Vertex color data
             * if (!File.Exists(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\" + mapname + "_" + "vertex_colors.csv")))
             * {
             *  StreamWriter vertesColorCSV = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file) + "\\" + mapname + "_" + "vertex_colors.csv"));
             *  vertesColorCSV.WriteLine("chunk;vert;a;r;g;b"); //header
             *  for (uint c = 0; c < reader.adtfile.chunks.Count(); c++)
             *  {
             *      if (reader.adtfile.chunks[c].vertexShading.red != null)
             *      {
             *          for (int i = 0; i < 145; i++)
             *          {
             *              //Console.WriteLine(c + "_" + i + "-" + reader.adtfile.chunks[c].vertexShading.alpha[i] + " " + reader.adtfile.chunks[c].vertexShading.red[i] + " " + reader.adtfile.chunks[c].vertexShading.green[i] + " " + reader.adtfile.chunks[c].vertexShading.blue[i]);
             *              vertesColorCSV.WriteLine(c + ";" + i + ";" + reader.adtfile.chunks[c].vertexShading.alpha[i] + ";" + reader.adtfile.chunks[c].vertexShading.red[i] + ";" + reader.adtfile.chunks[c].vertexShading.green[i] + ";" + reader.adtfile.chunks[c].vertexShading.blue[i]);
             *          }
             *      }
             *      else
             *      {
             *          //Console.WriteLine(c + "- null");
             *          vertesColorCSV.WriteLine(c + ";0;0;0;0;0");
             *      }
             *  }
             *  vertesColorCSV.Close();
             * }
             */

            exportworker.ReportProgress(75, "Exporting terrain textures..");

            if (bakeQuality != "none")
            {
                var mtlsw = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file).Replace(" ", "") + ".mtl"));

                //No idea how MTL files really work yet. Needs more investigation.
                foreach (var material in materials)
                {
                    mtlsw.WriteLine("newmtl " + material.Value.Replace(" ", ""));
                    mtlsw.WriteLine("Ka 1.000000 1.000000 1.000000");
                    mtlsw.WriteLine("Kd 0.640000 0.640000 0.640000");
                    mtlsw.WriteLine("map_Ka " + material.Value.Replace(" ", "") + ".png");
                    mtlsw.WriteLine("map_Kd " + material.Value.Replace(" ", "") + ".png");
                }

                mtlsw.Close();
            }

            exportworker.ReportProgress(85, "Exporting terrain geometry..");

            var indices = indicelist.ToArray();

            var adtname = Path.GetFileNameWithoutExtension(file);

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

            objsw.WriteLine("# Written by Marlamin's WoW OBJExporter. Original file: " + file);
            if (bakeQuality != "none")
            {
                objsw.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(file).Replace(" ", "") + ".mtl");
            }

            objsw.WriteLine("g " + adtname.Replace(" ", ""));
            var verticeCounter = 1;
            var chunkCounter   = 1;
            foreach (var vertex in verticelist)
            {
                objsw.WriteLine("# C" + chunkCounter + ".V" + verticeCounter);
                objsw.WriteLine("v " + vertex.Position.X.ToString("R") + " " + vertex.Position.Y.ToString("R") + " " + vertex.Position.Z.ToString("R"));
                objsw.WriteLine("vt " + vertex.TexCoord.X + " " + vertex.TexCoord.Y);
                objsw.WriteLine("vn " + vertex.Normal.X.ToString("R") + " " + vertex.Normal.Y.ToString("R") + " " + vertex.Normal.Z.ToString("R"));
                verticeCounter++;
                if (verticeCounter == 146)
                {
                    chunkCounter++;
                    verticeCounter = 1;
                }
            }

            if (bakeQuality != "high")
            {
                objsw.WriteLine("usemtl " + materials[1]);
                objsw.WriteLine("s 1");
            }
            int currentChunk = 0;
            foreach (var renderBatch in renderBatches)
            {
                var i = renderBatch.firstFace;
                if (bakeQuality == "high" && materials.ContainsKey((int)renderBatch.materialID))
                {
                    if (Managers.ConfigurationManager.ADTSplitChunks)
                    {
                        objsw.WriteLine("g " + materials[(int)renderBatch.materialID]);
                        objsw.WriteLine("usemtl " + materials[(int)renderBatch.materialID]);
                        objsw.WriteLine("s 1");
                    }
                    else
                    {
                        objsw.WriteLine("usemtl " + materials[(int)renderBatch.materialID]);
                    }
                }
                while (i < (renderBatch.firstFace + renderBatch.numFaces))
                {
                    objsw.WriteLine("f " +
                                    (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + " " +
                                    (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + " " +
                                    (indices[i] + 1) + "/" + (indices[i] + 1) + "/" + (indices[i] + 1));
                    i += 3;
                }
                currentChunk++;
            }

            objsw.Close();
        }
Ejemplo n.º 19
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;
        }
Ejemplo n.º 20
0
        private static void Main(string[] args)
        {
            string mapname = "";

            string basedir      = ConfigurationManager.AppSettings["basedir"];
            bool   buildmaps    = Boolean.Parse(ConfigurationManager.AppSettings["buildmaps"]);
            bool   buildWMOmaps = Boolean.Parse(ConfigurationManager.AppSettings["buildwmomaps"]);

            Console.WriteLine("Initializing CASC..");

            if (basedir != String.Empty)
            {
                CASC.InitCasc(null, basedir);
            }
            else
            {
                CASC.InitCasc(null, @"D:\World of Warcraft Beta", "wow_beta"); // Use beta for now
            }

            Console.WriteLine("CASC initialized!");
            Console.WriteLine("Current patch: " + CASC.cascHandler.Config.BuildName);

            if (buildmaps == true)
            {
                DB2Reader <MapRecordLegion> reader = new DB2Reader <MapRecordLegion>("DBFilesClient\\Map.db2");
                for (int i = 0; i < reader.recordCount; i++)
                {
                    //I used to check if WDT existed, but sometimes minimaps for maps without WDTs slip through the cracks
                    mapname = reader[i].Directory;

                    // if (reader[i].expansionID < 6) { Console.WriteLine("Skipping map " + mapname + " WoD and below!"); continue; }

                    var min_x = 64;
                    var min_y = 64;

                    var max_x = 0;
                    var max_y = 0;

                    for (int cur_x = 0; cur_x < 64; cur_x++)
                    {
                        for (int cur_y = 0; cur_y < 64; cur_y++)
                        {
                            if (CASC.FileExists("World\\Minimaps\\" + mapname + "\\map" + cur_x + "_" + cur_y + ".blp"))
                            {
                                if (cur_x > max_x)
                                {
                                    max_x = cur_x;
                                }
                                if (cur_y > max_y)
                                {
                                    max_y = cur_y;
                                }

                                if (cur_x < min_x)
                                {
                                    min_x = cur_x;
                                }
                                if (cur_y < min_y)
                                {
                                    min_y = cur_y;
                                }
                            }
                        }
                    }

                    Console.WriteLine("[" + mapname + "] MIN: (" + min_x + " " + min_y + ") MAX: (" + max_x + " " + max_y + ")");

                    var res_x = (((max_x - min_x) * 256) + 256);
                    var res_y = (((max_y - min_y) * 256) + 256);

                    if (res_x < 0 || res_y < 0)
                    {
                        Console.WriteLine("[" + mapname + "] " + "Skipping map, has no minimap tiles");
                        continue;
                    }

                    Console.WriteLine("[" + mapname + "] " + "Creating new image of " + res_x + "x" + res_y);


                    Bitmap   bmp = new Bitmap(res_x, res_y);
                    Graphics g   = Graphics.FromImage(bmp);

                    Font drawFont = new Font("Arial", 16);

                    for (int cur_x = 0; cur_x < 64; cur_x++)
                    {
                        for (int cur_y = 0; cur_y < 64; cur_y++)
                        {
                            if (CASC.FileExists("World\\Minimaps\\" + mapname + "\\map" + cur_x + "_" + cur_y + ".blp"))
                            {
                                var blpreader = new BLPReader();
                                blpreader.LoadBLP("World\\Minimaps\\" + mapname + "\\map" + cur_x + "_" + cur_y + ".blp");
                                g.DrawImage(blpreader.bmp, (cur_x - min_x) * 256, (cur_y - min_y) * 256, new Rectangle(0, 0, 256, 256), GraphicsUnit.Pixel);
                            }
                        }
                    }
                    g.Dispose();
                    if (!Directory.Exists("done"))
                    {
                        Directory.CreateDirectory("done");
                    }
                    bmp.Save("done/" + mapname + ".png");

                    // SUPER MINIMAP COMPILER TIME!!!!!!!!!!!!!!!

                    /*
                     * var super_res_x = (((max_x - min_x) * 512) + 512);
                     * var super_res_y = (((max_y - min_y) * 512) + 512);
                     *
                     * if (super_res_x < 0 || super_res_y < 0)
                     * {
                     *  Console.WriteLine("[SUPER " + mapname + "] " + "Skipping map, has no minimap tiles");
                     *  continue;
                     * }
                     *
                     * Console.WriteLine("[SUPER " + mapname + "] " + "Creating new image of " + super_res_x + "x" + super_res_y);
                     *
                     * Bitmap super_bmp = new Bitmap(super_res_x, super_res_y);
                     * Graphics super_g = Graphics.FromImage(super_bmp);
                     *
                     * for (int cur_x = 0; cur_x < 64; cur_x++)
                     * {
                     *  for (int cur_y = 0; cur_y < 64; cur_y++)
                     *  {
                     *      if (CASC.FileExists("World\\Minimaps\\" + mapname + "\\map" + cur_x + "_" + cur_y + ".blp"))
                     *      {
                     *          var blpreader = new BLPReader();
                     *          blpreader.LoadBLP("World\\Minimaps\\" + mapname + "\\map" + cur_x + "_" + cur_y + ".blp");
                     *          super_g.DrawImage(blpreader.bmp, (cur_x - min_x) * 512, (cur_y - min_y) * 512, new Rectangle(0, 0, 512, 512), GraphicsUnit.Pixel);
                     *      }
                     *  }
                     * }
                     * super_g.Dispose();
                     * if (!Directory.Exists("done")) { Directory.CreateDirectory("done"); }
                     * super_bmp.Save("done/SUPER_" + mapname + ".png");
                     */
                }
            }


            if (buildWMOmaps == true)
            {
                List <string> linelist = new List <string>();

                if (CASC.FileExists("dbfilesclient/filedatacomplete.dbc"))
                {
                    var dbcreader = new DBCReader <FileDataRecord>("dbfilesclient/filedatacomplete.dbc");

                    if (dbcreader.recordCount > 0)
                    {
                        for (int i = 0; i < dbcreader.recordCount; i++)
                        {
                            if (CASC.cascHandler.FileExists(dbcreader[i].ID))
                            {
                                if (dbcreader[i].ID > 1023304)
                                {
                                    linelist.Add(dbcreader[i].FileName + dbcreader[i].FilePath);
                                }
                            }
                        }
                    }
                }

                DBCReader <MapRecord> reader = new DBCReader <MapRecord>("DBFilesClient\\Map.dbc");

                string[] unwantedExtensions = new string[513];
                for (int i = 0; i < 512; i++)
                {
                    unwantedExtensions[i] = "_" + i.ToString().PadLeft(3, '0') + ".wmo";
                }
                unwantedExtensions[512] = "LOD1.wmo";
                foreach (string s in linelist)
                {
                    if (s.Length > 8 && !unwantedExtensions.Contains(s.Substring(s.Length - 8, 8)))
                    {
                        if (!s.Contains("LOD") && s.EndsWith(".wmo", StringComparison.CurrentCultureIgnoreCase))
                        {
                            Console.WriteLine(s);
                            WMO wmocompiler = new WMO();
                            wmocompiler.Compile(s);
                        }
                    }
                }
                Console.ReadLine();
            }
        }
Ejemplo n.º 21
0
        public static void ExportM2(M2Reader reader, string fileName, BackgroundWorker exportworker = null, string destinationOverride = null, bool externalOverride = false, bool[] enabledGeosets = null)
        {
            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 exportDir = ConfigurationManager.AppSettings["outdir"];

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

            // 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
                };
            }

            string outDir = exportDir;

            if (destinationOverride != null)
            {
                if (externalOverride)
                {
                    outDir = destinationOverride;
                }
                else
                {
                    outDir = Path.Combine(outDir, destinationOverride);
                }
            }
            else
            {
                outDir = Path.Combine(outDir, Path.GetDirectoryName(fileName));
            }

            Directory.CreateDirectory(outDir);

            string filePath    = Path.Combine(outDir, Path.GetFileName(fileName).Replace(".m2", ""));
            string objFilePath = filePath + ".obj";
            string mtlFilePath = filePath + ".mtl";

            StreamWriter objWriter = new StreamWriter(objFilePath);
            StreamWriter mtlWriter = new StreamWriter(mtlFilePath);

            // Write OBJ header.
            objWriter.WriteLine("# Written by Marlamin's WoW Export Tools. Source file: " + fileName);
            objWriter.WriteLine("mtllib " + Path.GetFileName(mtlFilePath));

            foreach (var vertex in vertices)
            {
                objWriter.WriteLine("v " + vertex.Position.X + " " + vertex.Position.Y + " " + vertex.Position.Z);
                objWriter.WriteLine("vt " + vertex.TexCoord.X + " " + (vertex.TexCoord.Y - 1) * -1);
                objWriter.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++)
            {
                if (enabledGeosets != null && !enabledGeosets[i])
                {
                    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 (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..");

            uint defaultTexID = DEFAULT_TEXTURE;

            if (!CASC.FileExists(defaultTexID))
            {
                defaultTexID = DEFAULT_TEXTURE_SUB;
            }

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

            for (var i = 0; i < reader.model.textures.Count(); i++)
            {
                uint textureFileDataID = defaultTexID;

                materials[i].flags = reader.model.textures[i].flags;
                if (reader.model.textures[i].type == 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);
                    }
                }
                else
                {
                    Console.WriteLine("Texture type " + reader.model.textures[i].type + " not supported, falling back to placeholder texture");
                }

                materials[i].textureID = textureID + i;

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

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

                try
                {
                    var blpreader = new BLPReader();
                    blpreader.LoadBLP(textureFileDataID);
                    blpreader.bmp.Save(Path.Combine(outDir, materials[i].filename + ".png"));
                }
                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)
            {
                mtlWriter.WriteLine("newmtl " + material.filename);
                mtlWriter.WriteLine("illum 1");
                mtlWriter.WriteLine("map_Kd " + material.filename + ".png");
                if (ConfigurationManager.AppSettings["textureMetadata"] == "True")
                {
                    foreach (var renderbatch in renderbatches)
                    {
                        if (materials[renderbatch.materialID].filename == material.filename)
                        {
                            mtlWriter.WriteLine("blend " + material.blendMode);
                        }
                    }
                }
            }

            mtlWriter.Close();

            objWriter.WriteLine("o " + Path.GetFileName(fileName));

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

                objWriter.WriteLine("g " + renderbatch.groupID);
                objWriter.WriteLine("usemtl " + materials[renderbatch.materialID].filename);
                objWriter.WriteLine("s 1");
                while (i < (renderbatch.firstFace + renderbatch.numFaces))
                {
                    objWriter.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;
                }
            }

            objWriter.Close();

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

                objWriter = new StreamWriter(filePath + ".phys.obj");


                objWriter.WriteLine("# Written by Marlamin's WoW Export Tools. Source file: " + fileName);

                for (var i = 0; i < reader.model.boundingvertices.Count(); i++)
                {
                    objWriter.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];
                    objWriter.WriteLine("f " + (t.index_0 + 1) + " " + (t.index_1 + 1) + " " + (t.index_2 + 1));
                }

                objWriter.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
        }
Ejemplo n.º 22
0
        protected override void OnLoad(EventArgs e)
        {
            // Get OpenGL version
            Console.WriteLine("OpenGL version: " + GL.GetString(StringName.Version));
            Console.WriteLine("OpenGL vendor: " + GL.GetString(StringName.Vendor));

            this.CursorVisible = false;

            // Set up camera
            ActiveCamera = new OldCamera(Width, Height, new Vector3(0, 0, -1), new Vector3(0, 0, 1), Vector3.UnitY);

            // Vertex Attribute Object
            vertexAttribObject = GL.GenVertexArray();
            GL.BindVertexArray(vertexAttribObject);

            // Vertices
            float[] vertices = new float[] {
                -1.0f, -1.0f, -10f, 0.0f, 0.0f,     // Top-left
                1.0f, -1.0f, -10f, 1.0f, 0.0f,      // Top-right
                1.0f, 1.0f, -10f, 1.0f, 1.0f,       // Bottom-right
                -1.0f, 1.0f, -10f, 0.0f, 1.0f       // Bottom-left
            };

            vertexBuffer = GL.GenBuffer();

            GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBuffer);

            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Count() * sizeof(float)), vertices, BufferUsageHint.StaticDraw);

            int verticeBufferSize = 0;

            GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBuffer);
            GL.GetBufferParameter(BufferTarget.ArrayBuffer, BufferParameterName.BufferSize, out verticeBufferSize);

            Console.WriteLine("Vertices in buffer: " + verticeBufferSize / 5 / sizeof(float));

            // Elements
            int[] elements = new int[] {
                0, 1, 2,
                2, 3, 0
            };

            elementBuffer = GL.GenBuffer();

            GL.BindBuffer(BufferTarget.ElementArrayBuffer, elementBuffer);
            GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(elements.Count() * sizeof(int)), elements, BufferUsageHint.StaticDraw);

            // Vertex shader
            vertexShader = GL.CreateShader(ShaderType.VertexShader);

            string vertexSource = File.ReadAllText("Shaders/vertex.shader");

            Console.WriteLine(vertexSource);
            GL.ShaderSource(vertexShader, vertexSource);

            GL.CompileShader(vertexShader);

            int vertexShaderStatus;

            GL.GetShader(vertexShader, ShaderParameter.CompileStatus, out vertexShaderStatus);
            Console.WriteLine("[VERTEX] Shader compile status: " + vertexShaderStatus);

            string vertexShaderLog;

            GL.GetShaderInfoLog(vertexShader, out vertexShaderLog);
            Console.Write(vertexShaderLog);

            // Fragment shader
            fragmentShader = GL.CreateShader(ShaderType.FragmentShader);

            string fragmentSource = File.ReadAllText("Shaders/fragment.shader");

            Console.WriteLine(fragmentSource);
            GL.ShaderSource(fragmentShader, fragmentSource);

            GL.CompileShader(fragmentShader);

            int fragmentShaderStatus;

            GL.GetShader(fragmentShader, ShaderParameter.CompileStatus, out fragmentShaderStatus);
            Console.WriteLine("[FRAGMENT] Shader compile status: " + fragmentShaderStatus);

            string fragmentShaderLog;

            GL.GetShaderInfoLog(fragmentShader, out fragmentShaderLog);
            Console.Write(fragmentShaderLog);

            // Shader program
            shaderProgram = GL.CreateProgram();
            GL.AttachShader(shaderProgram, vertexShader);
            GL.AttachShader(shaderProgram, fragmentShader);

            GL.BindFragDataLocation(shaderProgram, 0, "outColor");

            GL.LinkProgram(shaderProgram);
            string programInfoLog = GL.GetProgramInfoLog(shaderProgram);

            Console.Write(programInfoLog);

            int programStatus;

            GL.GetProgram(shaderProgram, GetProgramParameterName.LinkStatus, out programStatus);
            Console.WriteLine("[FRAGMENT] Program link status: " + programStatus);
            GL.UseProgram(shaderProgram);

            GL.ValidateProgram(shaderProgram);

            GL.DetachShader(shaderProgram, vertexShader);
            GL.DeleteShader(vertexShader);

            GL.DetachShader(shaderProgram, fragmentShader);
            GL.DeleteShader(fragmentShader);
            // Set up matrix
            ActiveCamera.setupGLRenderMatrix(shaderProgram);

            // Shader settings
            int posAttrib = GL.GetAttribLocation(shaderProgram, "position");

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

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

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

            // Clear
            GL.ClearColor(Color.Black);

            // Uniforms
            int     uniColor = GL.GetUniformLocation(shaderProgram, "triangleColor");
            Vector3 uniCol3  = new Vector3(1.0f, 0.0f, 0.0f);

            GL.Uniform3(uniColor, uniCol3);

            // Textures
            int[] textureIds = new int[2];
            GL.GenTextures(2, textureIds);

            GL.ActiveTexture(TextureUnit.Texture0);
            GL.BindTexture(TextureTarget.Texture2D, textureIds[0]);

            var blp = new BLPReader();

            blp.LoadBLP(File.OpenRead(@"Z:\WoW extracts\20363_full\Textures\ShaneCube.blp"));

            System.Drawing.Imaging.BitmapData bmp_data = blp.bmp.LockBits(new System.Drawing.Rectangle(0, 0, blp.bmp.Width, blp.bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmp_data.Width, bmp_data.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bmp_data.Scan0);

            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);

            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);

            blp.bmp.UnlockBits(bmp_data);

            GL.Uniform1(GL.GetUniformLocation(shaderProgram, "tex"), 0);

            GL.ActiveTexture(TextureUnit.Texture1);
            GL.BindTexture(TextureTarget.Texture2D, textureIds[1]);
        }
Ejemplo n.º 23
0
        private Bitmap CompileGroup(string wmoname, string groupid)
        {
            Console.WriteLine("  group " + groupid);
            int min_x = 64;
            int min_y = 64;

            int max_x = 0;
            int max_y = 0;

            int x = 0;
            int y = 0;

            string        wmoonlyname = Path.GetFileNameWithoutExtension(wmoname);
            string        wmodir      = Path.GetDirectoryName(wmoname).Replace("World\\", "World\\Minimaps\\");
            List <string> filePaths   = new List <string>();
            string        lastpath    = "";

            for (int cur_x = 0; cur_x < 64; cur_x++)
            {
                for (int cur_y = 0; cur_y < 64; cur_y++)
                {
                    string wmogroupfilename = wmodir + "\\" + wmoonlyname + "_" + groupid + "_" + cur_x.ToString().PadLeft(2, '0') + "_" + cur_y.ToString().PadLeft(2, '0') + ".blp";
                    //wmogroupfilename = wmogroupfilename.Replace("\\", "\\\\");
                    if (wmogroupfilename.Contains("000_00_00"))
                    {
                        Console.WriteLine("CHECKING " + wmogroupfilename);
                    }
                    if (CASC.FileExists(wmogroupfilename))
                    {
                        Console.WriteLine(wmogroupfilename + " exists!");
                        filePaths.Add(wmogroupfilename);
                    }
                }
            }

            foreach (string path in filePaths)
            {
                Console.WriteLine(path);
                x = int.Parse(path.Substring(path.Length - 9, 2));
                y = int.Parse(path.Substring(path.Length - 6, 2));

                if (x > max_x)
                {
                    max_x = x;
                }
                if (y > max_y)
                {
                    max_y = y;
                }

                if (x < min_x)
                {
                    min_x = x;
                }
                if (y < min_y)
                {
                    min_y = y;
                }

                // Console.WriteLine("[" + groupid + "] MIN: " + min_x + " " + min_y);
                // Console.WriteLine("[" + groupid + "] MAX: " + max_x + " " + max_y);

                lastpath = path;
            }
            var res_x = 0;
            var res_y = 0;

            if (min_x == 0 && max_x == 0 && min_y == 0 && max_y == 0)
            {
                var blpreader = new BLPReader();
                blpreader.LoadBLP(lastpath);
                res_x = blpreader.bmp.Width;
                res_y = blpreader.bmp.Height;
            }
            else
            {
                res_x = (((max_x - min_x) * 256) + 256);
                res_y = (((max_y - min_y) * 256) + 256);
            }

            //Console.WriteLine("[" + groupid + "] " + "Creating new image of " + res_x + "x" + res_y + " for " + wmoname);

            if (res_x < 0)
            {
                res_x = 1;
            }
            if (res_y < 0)
            {
                res_y = 1;
            }

            Bitmap   bmp = new Bitmap(res_x, res_y);
            Graphics g   = Graphics.FromImage(bmp);

            foreach (string path in filePaths)
            {
                x = int.Parse(path.Substring(path.Length - 9, 2));
                y = int.Parse(path.Substring(path.Length - 6, 2));
                var blpreader = new BLPReader();
                blpreader.LoadBLP(path);
                //  Console.WriteLine("BLP Width: " + blpreader.bmp.Width);
                //  Console.WriteLine("BLP Height: " + blpreader.bmp.Height);
                var draw_x = (x - min_x) * 256;
                var draw_y = (max_y - (y - min_y)) * 256;
                //Console.WriteLine("Drawing tile at " + draw_x + " & " + draw_y);
                g.DrawImage(blpreader.bmp, draw_x, draw_y, new Rectangle(0, 0, blpreader.bmp.Width, blpreader.bmp.Height), GraphicsUnit.Pixel);
            }

            g.Dispose();
            return(bmp);
        }
Ejemplo n.º 24
0
        public static void ExportWMO(uint fileDataID, BackgroundWorker exportworker = null, string destinationOverride = null, short doodadSetExportID = short.MaxValue, string fileName = "", bool[] enabledGroups = null, bool[] enabledSets = null)
        {
            if (exportworker == null)
            {
                exportworker = new BackgroundWorker();
                exportworker.WorkerReportsProgress = true;
            }

            if (string.IsNullOrEmpty(fileName))
            {
                if (!Listfile.TryGetFilename(fileDataID, out fileName))
                {
                    CASCLib.Logger.WriteLine("Warning! Could not find filename for " + fileDataID + "!");
                }
            }

            fileName = fileName.ToLower();

            Console.WriteLine("Loading WMO file..");
            exportworker.ReportProgress(5, "Reading WMO..");

            var outDir = ConfigurationManager.AppSettings["outdir"];
            var wmo    = new WMOReader().LoadWMO(fileDataID, 0, fileName);

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

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

            exportworker.ReportProgress(30, "Reading WMO..");

            uint totalVertices = 0;
            var  groups        = new Structs.WMOGroup[wmo.group.Count()];

            for (var g = 0; g < wmo.group.Count(); g++)
            {
                if (enabledGroups != null && !enabledGroups[g])
                {
                    Console.WriteLine("Skipping group " + g + " due to WMO control");
                    continue;
                }

                Console.WriteLine("Loading group #" + g);
                if (wmo.group[g].mogp.vertices == null)
                {
                    Console.WriteLine("Group has no vertices!");
                    continue;
                }

                for (var i = 0; i < wmo.groupNames.Count(); i++)
                {
                    if (wmo.group[g].mogp.nameOffset == wmo.groupNames[i].offset)
                    {
                        groups[g].name = wmo.groupNames[i].name.Replace(" ", "_");
                    }
                }

                if (groups[g].name == "antiportal")
                {
                    Console.WriteLine("Group is antiportal");
                    continue;
                }

                groups[g].verticeOffset = totalVertices;
                groups[g].vertices      = new Structs.Vertex[wmo.group[g].mogp.vertices.Count()];

                for (var i = 0; i < wmo.group[g].mogp.vertices.Count(); i++)
                {
                    groups[g].vertices[i].Position = new Structs.Vector3D()
                    {
                        X = wmo.group[g].mogp.vertices[i].vector.X * -1,
                        Y = wmo.group[g].mogp.vertices[i].vector.Z,
                        Z = wmo.group[g].mogp.vertices[i].vector.Y
                    };

                    groups[g].vertices[i].Normal = new Structs.Vector3D()
                    {
                        X = wmo.group[g].mogp.normals[i].normal.X,
                        Y = wmo.group[g].mogp.normals[i].normal.Z,
                        Z = wmo.group[g].mogp.normals[i].normal.Y
                    };

                    groups[g].vertices[i].TexCoord = new Structs.Vector2D()
                    {
                        X = wmo.group[g].mogp.textureCoords[0][i].X,
                        Y = wmo.group[g].mogp.textureCoords[0][i].Y
                    };

                    totalVertices++;
                }

                var indicelist = new List <uint>();
                for (var i = 0; i < wmo.group[g].mogp.indices.Count(); i++)
                {
                    indicelist.Add(wmo.group[g].mogp.indices[i].indice);
                }

                groups[g].indices = indicelist.ToArray();
            }

            // Create output directory.
            if (destinationOverride == null)
            {
                Directory.CreateDirectory(fileName == null ? outDir : Path.Combine(outDir, Path.GetDirectoryName(fileName)));
            }

            exportworker.ReportProgress(55, "Exporting WMO doodads..");

            List <string> doodadList = new List <string>();

            doodadList.Add("ModelFile;PositionX;PositionY;PositionZ;RotationW;RotationX;RotationY;RotationZ;ScaleFactor;DoodadSet");

            if (doodadSetExportID > -1)
            {
                for (var i = 0; i < wmo.doodadSets.Count(); i++)
                {
                    if (enabledSets != null && !enabledSets[i])
                    {
                        Console.WriteLine("Skipping doodadSet " + i + " due to WMO control");
                        continue;
                    }

                    var doodadSet            = wmo.doodadSets[i];
                    var currentDoodadSetName = doodadSet.setName.Replace("Set_", "").Replace("SET_", "").Replace("$DefaultGlobal", "Default");

                    if (doodadSetExportID != short.MaxValue)
                    {
                        if (i != 0 && i != doodadSetExportID)
                        {
                            Console.WriteLine("Skipping doodadset with ID " + i + " (" + currentDoodadSetName + ") because export filter is set to " + doodadSetExportID);
                            continue;
                        }
                    }

                    for (var j = doodadSet.firstInstanceIndex; j < (doodadSet.firstInstanceIndex + doodadSet.numDoodads); j++)
                    {
                        var doodadDefinition = wmo.doodadDefinitions[j];

                        var  doodadFileName   = "";
                        uint doodadFileDataID = 0;
                        var  doodadNotFound   = false;

                        if (wmo.doodadIds != null)
                        {
                            doodadFileDataID = wmo.doodadIds[doodadDefinition.offset];
                            if (!Listfile.TryGetFilename(doodadFileDataID, out doodadFileName))
                            {
                                CASCLib.Logger.WriteLine("Could not find filename for " + doodadFileDataID + ", setting filename to filedataid..");
                                doodadFileName = doodadFileDataID.ToString();
                            }
                        }
                        else
                        {
                            CASCLib.Logger.WriteLine("Warning!! File " + fileName + " ID: " + fileDataID + " still has filenames!");
                            foreach (var doodadNameEntry in wmo.doodadNames)
                            {
                                if (doodadNameEntry.startOffset == doodadDefinition.offset)
                                {
                                    doodadFileName = doodadNameEntry.filename.Replace(".MDX", ".M2").Replace(".MDL", ".M2").ToLower();
                                    if (!Listfile.TryGetFileDataID(doodadFileName, out doodadFileDataID))
                                    {
                                        CASCLib.Logger.WriteLine("Error! Could not find filedataid for " + doodadFileName + "!");
                                        doodadNotFound = true;
                                        continue;
                                    }
                                }
                            }
                        }

                        if (!doodadNotFound)
                        {
                            string objFileName = Path.GetFileNameWithoutExtension(doodadFileName ?? doodadFileDataID.ToString()) + ".obj";
                            string objPath     = Path.Combine(destinationOverride ?? outDir, destinationOverride != null ? "" : Path.GetDirectoryName(fileName));
                            string objName     = Path.Combine(objPath, objFileName);

                            if (!File.Exists(objName))
                            {
                                M2Exporter.ExportM2(doodadFileDataID, null, objPath, doodadFileName);
                            }

                            if (File.Exists(objName))
                            {
                                doodadList.Add(objFileName + ";" + doodadDefinition.position.X.ToString("F09") + ";" + doodadDefinition.position.Y.ToString("F09") + ";" + doodadDefinition.position.Z.ToString("F09") + ";" + doodadDefinition.rotation.W.ToString("F15") + ";" + doodadDefinition.rotation.X.ToString("F15") + ";" + doodadDefinition.rotation.Y.ToString("F15") + ";" + doodadDefinition.rotation.Z.ToString("F15") + ";" + doodadDefinition.scale + ";" + currentDoodadSetName);
                            }
                        }
                    }
                }
            }

            if (doodadList.Count > 1)
            {
                string mpiFile = (fileName == null ? fileDataID.ToString() : Path.GetFileNameWithoutExtension(fileName.Replace(" ", ""))) + "_ModelPlacementInformation.csv";
                File.WriteAllText(Path.Combine(outDir, destinationOverride ?? Path.GetDirectoryName(fileName), mpiFile), string.Join("\n", doodadList.ToArray()));
            }

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

            var mtlsb     = new StringBuilder();
            var textureID = 0;

            if (wmo.materials == null)
            {
                CASCLib.Logger.WriteLine("Unable to find materials for WMO " + fileDataID + ", not exporting!");
                return;
            }

            var materials      = new Structs.Material[wmo.materials.Count()];
            var extraMaterials = new List <Structs.Material>();

            for (var i = 0; i < wmo.materials.Count(); i++)
            {
                var blpReader = new BLPReader();

                if (wmo.textures == null)
                {
                    if (Listfile.TryGetFilename(wmo.materials[i].texture1, out var textureFilename))
                    {
                        materials[i].filename = Path.GetFileNameWithoutExtension(textureFilename).Replace(" ", "").ToLower();
                    }
                    else
                    {
                        materials[i].filename = wmo.materials[i].texture1.ToString();
                    }

                    blpReader.LoadBLP(wmo.materials[i].texture1);
                }
                else
                {
                    for (var ti = 0; ti < wmo.textures.Count(); ti++)
                    {
                        if (wmo.textures[ti].startOffset == wmo.materials[i].texture1)
                        {
                            materials[i].filename = Path.GetFileNameWithoutExtension(wmo.textures[ti].filename).Replace(" ", "").ToLower();
                            blpReader.LoadBLP(wmo.textures[ti].filename);
                        }
                    }
                }

                materials[i].textureID   = textureID + i;
                materials[i].transparent = wmo.materials[i].blendMode != 0;

                materials[i].blendMode   = wmo.materials[i].blendMode;
                materials[i].shaderID    = wmo.materials[i].shader;
                materials[i].terrainType = wmo.materials[i].groundType;

                string saveLocation = Path.Combine(outDir, destinationOverride ?? Path.GetDirectoryName(fileName), materials[i].filename + ".png");
                if (!File.Exists(saveLocation))
                {
                    try
                    {
                        if (materials[i].transparent)
                        {
                            blpReader.bmp.Save(saveLocation);
                        }
                        else
                        {
                            blpReader.bmp.Clone(new Rectangle(0, 0, blpReader.bmp.Width, blpReader.bmp.Height), PixelFormat.Format32bppRgb).Save(saveLocation);
                        }
                    }
                    catch (Exception e)
                    {
                        CASCLib.Logger.WriteLine("Exception while saving BLP " + materials[i].filename + ": " + e.Message);
                    }
                }

                textureID++;

                string extraPath = Path.Combine(outDir, destinationOverride ?? Path.GetDirectoryName(fileName));
                ExportExtraMaterials(wmo.materials[i].texture2, wmo, extraMaterials, i, extraPath);
                ExportExtraMaterials(wmo.materials[i].texture3, wmo, extraMaterials, i, extraPath);
            }

            var numRenderbatches = 0;

            //Get total amount of render batches
            for (var i = 0; i < wmo.group.Count(); i++)
            {
                if (wmo.group[i].mogp.renderBatches == null)
                {
                    continue;
                }

                numRenderbatches = numRenderbatches + wmo.group[i].mogp.renderBatches.Count();
            }

            exportworker.ReportProgress(75, "Exporting WMO model..");

            bool exportMetadata = ConfigurationManager.AppSettings["textureMetadata"] == "True";

            //No idea how MTL files really work yet. Needs more investigation.
            foreach (var material in materials)
            {
                mtlsb.Append("newmtl " + material.filename + "\n");
                mtlsb.Append("Ns 96.078431\n");
                mtlsb.Append("Ka 1.000000 1.000000 1.000000\n");
                mtlsb.Append("Kd 0.640000 0.640000 0.640000\n");
                mtlsb.Append("Ks 0.000000 0.000000 0.000000\n");
                mtlsb.Append("Ke 0.000000 0.000000 0.000000\n");
                mtlsb.Append("Ni 1.000000\n");
                mtlsb.Append("d 1.000000\n");
                mtlsb.Append("illum 1\n");
                mtlsb.Append("map_Kd " + material.filename + ".png\n");

                if (material.transparent)
                {
                    mtlsb.Append("map_d " + material.filename + ".png\n");
                }

                if (exportMetadata)
                {
                    for (var g = 0; g < wmo.group.Count(); g++)
                    {
                        groups[g].renderBatches = new Structs.RenderBatch[numRenderbatches];

                        var group = wmo.group[g];
                        if (group.mogp.renderBatches == null)
                        {
                            continue;
                        }

                        for (var i = 0; i < group.mogp.renderBatches.Count(); i++)
                        {
                            var batch = group.mogp.renderBatches[i];
                            if (materials[batch.materialID].filename == material.filename)
                            {
                                mtlsb.Append("blend " + material.blendMode + "\n");
                            }
                        }
                    }
                }
            }

            foreach (var material in extraMaterials)
            {
                mtlsb.Append("newmtl " + material.filename + "\n");
                mtlsb.Append("Ns 96.078431\n");
                mtlsb.Append("Ka 1.000000 1.000000 1.000000\n");
                mtlsb.Append("Kd 0.640000 0.640000 0.640000\n");
                mtlsb.Append("Ks 0.000000 0.000000 0.000000\n");
                mtlsb.Append("Ke 0.000000 0.000000 0.000000\n");
                mtlsb.Append("Ni 1.000000\n");
                mtlsb.Append("d 1.000000\n");
                mtlsb.Append("illum 1\n");
                mtlsb.Append("map_Kd " + material.filename + ".png\n");

                if (material.transparent)
                {
                    mtlsb.Append("map_d " + material.filename + ".png\n");
                }
            }

            string mtlFile = fileName != null?fileName.Replace(".wmo", ".mtl") : fileDataID + ".mtl";

            if (destinationOverride != null)
            {
                mtlFile = Path.GetFileName(mtlFile);
            }

            File.WriteAllText(Path.Combine(destinationOverride ?? outDir, mtlFile), mtlsb.ToString());

            var rb = 0;

            for (var g = 0; g < wmo.group.Count(); g++)
            {
                groups[g].renderBatches = new Structs.RenderBatch[numRenderbatches];

                var group = wmo.group[g];
                if (group.mogp.renderBatches == null)
                {
                    continue;
                }

                for (var i = 0; i < group.mogp.renderBatches.Count(); i++)
                {
                    var batch = group.mogp.renderBatches[i];

                    groups[g].renderBatches[rb].firstFace  = batch.firstFace;
                    groups[g].renderBatches[rb].numFaces   = batch.numFaces;
                    groups[g].renderBatches[rb].materialID = batch.flags == 2 ? (uint)batch.possibleBox2_3 : batch.materialID;
                    groups[g].renderBatches[rb].blendType  = wmo.materials[batch.materialID].blendMode;
                    groups[g].renderBatches[rb].groupID    = (uint)g;
                    rb++;
                }
            }

            exportworker.ReportProgress(95, "Writing WMO files..");

            string objFile = fileName != null?fileName.Replace(".wmo", ".obj") : fileDataID + ".obj";

            if (destinationOverride != null)
            {
                objFile = Path.GetFileName(objFile);
            }

            string       fileID    = fileName ?? fileDataID.ToString();
            StreamWriter objWriter = new StreamWriter(Path.Combine(destinationOverride ?? outDir, objFile));

            objWriter.WriteLine("# Written by Marlamin's WoW Export Tools. Original file: " + fileID);
            objWriter.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(fileID) + ".mtl");
            objWriter.WriteLine("o " + Path.GetFileName(fileID));

            foreach (var group in groups)
            {
                if (group.vertices == null)
                {
                    continue;
                }

                Console.WriteLine("Writing " + group.name);

                //Adjusted according to the WaveFront Object (.obj) File Format spec
                //https://people.cs.clemson.edu/~dhouse/courses/405/docs/brief-obj-file-format.html
                foreach (var vertex in group.vertices)
                {
                    objWriter.WriteLine("v " + vertex.Position.X + " " + vertex.Position.Y + " " + vertex.Position.Z);
                }
                foreach (var vertex in group.vertices)
                {
                    objWriter.WriteLine("vt " + vertex.TexCoord.X + " " + (vertex.TexCoord.Y - 1) * -1 + " 0.0000");
                }
                foreach (var vertex in group.vertices)
                {
                    objWriter.WriteLine("vn " + (-vertex.Normal.X).ToString("F12") + " " + vertex.Normal.Y.ToString("F12") + " " + vertex.Normal.Z.ToString("F12"));
                }


                var indices = group.indices;
                for (int rbi = 0; rbi < group.renderBatches.Count(); rbi++)
                {
                    var renderbatch = group.renderBatches[rbi];
                    var i           = renderbatch.firstFace;
                    if (renderbatch.numFaces > 0)
                    {
                        objWriter.WriteLine("o " + group.name + rbi);
                        objWriter.WriteLine("g " + group.name + rbi); //3DS Max's OBJ importer fails with invalid normal index without groups being defined
                        objWriter.WriteLine("usemtl " + materials[renderbatch.materialID].filename);
                        objWriter.WriteLine("s 1");
                        while (i < (renderbatch.firstFace + renderbatch.numFaces))
                        {
                            objWriter.WriteLine("f " + (indices[i] + group.verticeOffset + 1) + "/" + (indices[i] + group.verticeOffset + 1) + "/" + (indices[i] + group.verticeOffset + 1) + " " + (indices[i + 1] + group.verticeOffset + 1) + "/" + (indices[i + 1] + group.verticeOffset + 1) + "/" + (indices[i + 1] + group.verticeOffset + 1) + " " + (indices[i + 2] + group.verticeOffset + 1) + "/" + (indices[i + 2] + group.verticeOffset + 1) + "/" + (indices[i + 2] + group.verticeOffset + 1));
                            i = i + 3;
                        }
                    }
                }
            }
            objWriter.Close();
        }
Ejemplo n.º 25
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
        }
Ejemplo n.º 26
0
        public static void exportWMO(string file, BackgroundWorker exportworker = null, string destinationOverride = null)
        {
            if (exportworker == null)
            {
                exportworker = new BackgroundWorker();
                exportworker.WorkerReportsProgress = true;
            }

            Logger.WriteLine("WMO glTF Exporter: Loading file {0}...", file);

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

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

            reader.LoadWMO(file);

            System.Globalization.CultureInfo 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)));
                }
            }

            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"
                }
            };

            var        groups = new Structs.WMOGroup[reader.wmofile.group.Count()];
            FileStream stream;

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

            var writer = new BinaryWriter(stream);

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

            for (int g = 0; g < reader.wmofile.group.Count(); g++)
            {
                if (reader.wmofile.group[g].mogp.vertices == null)
                {
                    Console.WriteLine("Group has no vertices!");  continue;
                }
                for (int i = 0; i < reader.wmofile.groupNames.Count(); i++)
                {
                    if (reader.wmofile.group[g].mogp.nameOffset == reader.wmofile.groupNames[i].offset)
                    {
                        groups[g].name = reader.wmofile.groupNames[i].name.Replace(" ", "_");
                    }
                }

                if (groups[g].name == "antiportal")
                {
                    Console.WriteLine("Group is antiportal"); continue;
                }

                // 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 (int i = 0; i < reader.wmofile.group[g].mogp.vertices.Count(); i++)
                {
                    writer.Write(reader.wmofile.group[g].mogp.vertices[i].vector.X * -1);
                    writer.Write(reader.wmofile.group[g].mogp.vertices[i].vector.Z);
                    writer.Write(reader.wmofile.group[g].mogp.vertices[i].vector.Y);

                    if (reader.wmofile.group[g].mogp.vertices[i].vector.X * -1 < minPosX)
                    {
                        minPosX = reader.wmofile.group[g].mogp.vertices[i].vector.X * -1;
                    }
                    if (reader.wmofile.group[g].mogp.vertices[i].vector.Z < minPosY)
                    {
                        minPosY = reader.wmofile.group[g].mogp.vertices[i].vector.Z;
                    }
                    if (reader.wmofile.group[g].mogp.vertices[i].vector.Y < minPosZ)
                    {
                        minPosZ = reader.wmofile.group[g].mogp.vertices[i].vector.Y;
                    }

                    if (reader.wmofile.group[g].mogp.vertices[i].vector.X * -1 > maxPosX)
                    {
                        maxPosX = reader.wmofile.group[g].mogp.vertices[i].vector.X * -1;
                    }
                    if (reader.wmofile.group[g].mogp.vertices[i].vector.Z > maxPosY)
                    {
                        maxPosY = reader.wmofile.group[g].mogp.vertices[i].vector.Z;
                    }
                    if (reader.wmofile.group[g].mogp.vertices[i].vector.Y > maxPosZ)
                    {
                        maxPosZ = reader.wmofile.group[g].mogp.vertices[i].vector.Y;
                    }
                }

                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.wmofile.group[g].mogp.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 (int i = 0; i < reader.wmofile.group[g].mogp.vertices.Count(); i++)
                {
                    writer.Write(reader.wmofile.group[g].mogp.normals[i].normal.X);
                    writer.Write(reader.wmofile.group[g].mogp.normals[i].normal.Z);
                    writer.Write(reader.wmofile.group[g].mogp.normals[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.wmofile.group[g].mogp.vertices.Count(),
                    type          = "VEC3"
                });

                bufferViews.Add(normalBuffer);

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

                for (int i = 0; i < reader.wmofile.group[g].mogp.vertices.Count(); i++)
                {
                    writer.Write(reader.wmofile.group[g].mogp.textureCoords[0][i].X);
                    writer.Write(reader.wmofile.group[g].mogp.textureCoords[0][i].Y);
                }

                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.wmofile.group[g].mogp.vertices.Count(),
                    type          = "VEC2"
                });

                bufferViews.Add(texCoordBuffer);

                var indexBufferPos = bufferViews.Count();

                for (int i = 0; i < reader.wmofile.group[g].mogp.renderBatches.Count(); i++)
                {
                    var batch = reader.wmofile.group[g].mogp.renderBatches[i];

                    accessorInfo.Add(new Accessor()
                    {
                        name          = "indices",
                        bufferView    = indexBufferPos,
                        byteOffset    = batch.firstFace * 2,
                        componentType = 5123,
                        count         = batch.numFaces,
                        type          = "SCALAR"
                    });

                    var mesh = new Mesh();
                    mesh.name       = groups[g].name + "_" + i;
                    mesh.primitives = new Primitive[1];
                    mesh.primitives[0].attributes = new Dictionary <string, int>
                    {
                        { "POSITION", posLoc },
                        { "NORMAL", normalLoc },
                        { "TEXCOORD_0", texLoc }
                    };

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

                    if (batch.flags == 2)
                    {
                        mesh.primitives[0].material = (uint)batch.possibleBox2_3;
                    }
                    else
                    {
                        mesh.primitives[0].material = batch.materialID;
                    }

                    mesh.primitives[0].mode = 4;

                    meshes.Add(mesh);
                }

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

                for (int i = 0; i < reader.wmofile.group[g].mogp.indices.Count(); i++)
                {
                    writer.Write(reader.wmofile.group[g].mogp.indices[i].indice);
                }

                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..");

            if (reader.wmofile.materials == null)
            {
                Logger.WriteLine("WMO glTF exporter: Materials empty"); return;
            }

            var materialCount = reader.wmofile.materials.Count();

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

            for (int i = 0; i < materialCount; i++)
            {
                for (int ti = 0; ti < reader.wmofile.textures.Count(); ti++)
                {
                    if (reader.wmofile.textures[ti].startOffset == reader.wmofile.materials[i].texture1)
                    {
                        var textureFilename = Path.GetFileNameWithoutExtension(reader.wmofile.textures[ti].filename).ToLower();

                        glTF.images[i].uri = textureFilename + ".png";

                        glTF.textures[i].sampler = 0;
                        glTF.textures[i].source  = i;

                        glTF.materials[i].name = textureFilename;
                        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;

                        switch (reader.wmofile.materials[i].blendMode)
                        {
                        case 0:
                            glTF.materials[i].alphaMode   = "OPAQUE";
                            glTF.materials[i].alphaCutoff = 0.0f;
                            break;

                        case 1:
                            glTF.materials[i].alphaMode   = "MASK";
                            glTF.materials[i].alphaCutoff = 0.90393700787f;
                            break;

                        case 2:
                            glTF.materials[i].alphaMode   = "MASK";
                            glTF.materials[i].alphaCutoff = 0.5f;
                            break;

                        default:
                            glTF.materials[i].alphaMode   = "OPAQUE";
                            glTF.materials[i].alphaCutoff = 0.0f;
                            break;
                        }

                        var saveLocation = "";

                        if (destinationOverride == null)
                        {
                            saveLocation = Path.Combine(outdir, Path.GetDirectoryName(file), textureFilename + ".png");
                        }
                        else
                        {
                            saveLocation = Path.Combine(outdir, destinationOverride, textureFilename + ".png");
                        }

                        if (!File.Exists(saveLocation))
                        {
                            var blpreader = new BLPReader();

                            blpreader.LoadBLP(reader.wmofile.textures[ti].filename);

                            try
                            {
                                blpreader.bmp.Save(saveLocation);
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine("Error exporting texture " + reader.wmofile.textures[ti].filename + ": " + e.Message);
                            }
                        }
                    }
                }
            }

            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;

            string currentDoodadSetName = "";

            for (int i = 0; i < reader.wmofile.doodadDefinitions.Count(); i++)
            {
                var doodadDefinition = reader.wmofile.doodadDefinitions[i];

                foreach (var doodadSet in reader.wmofile.doodadSets)
                {
                    if (doodadSet.firstInstanceIndex == i)
                    {
                        Console.WriteLine("At set: " + doodadSet.setName);
                        currentDoodadSetName = doodadSet.setName.Replace("Set_", "").Replace("SET_", "").Replace("$DefaultGlobal", "Default");
                    }
                }

                foreach (var doodadNameEntry in reader.wmofile.doodadNames)
                {
                    if (doodadNameEntry.startOffset == doodadDefinition.offset)
                    {
                        if (!File.Exists(Path.GetFileNameWithoutExtension(doodadNameEntry.filename).ToLower() + ".gltf"))
                        {
                            if (destinationOverride == null)
                            {
                                M2Exporter.exportM2(doodadNameEntry.filename.Replace(".MDX", ".M2").Replace(".MDL", ".M2").ToLower(), null, Path.Combine(outdir, Path.GetDirectoryName(file)));
                            }
                            else
                            {
                                M2Exporter.exportM2(doodadNameEntry.filename.Replace(".MDX", ".M2").Replace(".MDL", ".M2").ToLower(), null, destinationOverride);
                            }
                        }
                    }
                }
            }

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

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

            Logger.WriteLine("Done exporting WMO file!");
        }
Ejemplo n.º 27
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
             */
        }
Ejemplo n.º 28
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));
        }