Browse Source

Model viewer changes to export region maps

Image 3 years ago
parent
commit
0dae7dccb7

+ 24 - 14
EQ2/devtools/EQ2ModelViewer/EQ2ModelViewer/Main.Designer.cs

@@ -31,10 +31,11 @@
             this.menuStrip1 = new System.Windows.Forms.MenuStrip();
             this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.loadVPLToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.exportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
             this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.pGraphics = new System.Windows.Forms.Panel();
-            this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
-            this.exportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItemExportWater = new System.Windows.Forms.ToolStripMenuItem();
             this.menuStrip1.SuspendLayout();
             this.SuspendLayout();
             // 
@@ -52,6 +53,7 @@
             // 
             this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
             this.loadVPLToolStripMenuItem,
+            this.toolStripMenuItemExportWater,
             this.exportToolStripMenuItem,
             this.toolStripSeparator2,
             this.exitToolStripMenuItem});
@@ -62,14 +64,26 @@
             // loadVPLToolStripMenuItem
             // 
             this.loadVPLToolStripMenuItem.Name = "loadVPLToolStripMenuItem";
-            this.loadVPLToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
+            this.loadVPLToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
             this.loadVPLToolStripMenuItem.Text = "Load Zone";
             this.loadVPLToolStripMenuItem.Click += new System.EventHandler(this.loadZoneToolStripMenuItem_Click);
             // 
+            // exportToolStripMenuItem
+            // 
+            this.exportToolStripMenuItem.Name = "exportToolStripMenuItem";
+            this.exportToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+            this.exportToolStripMenuItem.Text = "Export";
+            this.exportToolStripMenuItem.Click += new System.EventHandler(this.exportToolStripMenuItem_Click);
+            // 
+            // toolStripSeparator2
+            // 
+            this.toolStripSeparator2.Name = "toolStripSeparator2";
+            this.toolStripSeparator2.Size = new System.Drawing.Size(177, 6);
+            // 
             // exitToolStripMenuItem
             // 
             this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
-            this.exitToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
+            this.exitToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
             this.exitToolStripMenuItem.Text = "Exit";
             this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
             // 
@@ -82,17 +96,12 @@
             this.pGraphics.Size = new System.Drawing.Size(851, 448);
             this.pGraphics.TabIndex = 1;
             // 
-            // toolStripSeparator2
-            // 
-            this.toolStripSeparator2.Name = "toolStripSeparator2";
-            this.toolStripSeparator2.Size = new System.Drawing.Size(149, 6);
+            // toolStripMenuItemExportWater
             // 
-            // exportToolStripMenuItem
-            // 
-            this.exportToolStripMenuItem.Name = "exportToolStripMenuItem";
-            this.exportToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
-            this.exportToolStripMenuItem.Text = "Export";
-            this.exportToolStripMenuItem.Click += new System.EventHandler(this.exportToolStripMenuItem_Click);
+            this.toolStripMenuItemExportWater.Name = "toolStripMenuItemExportWater";
+            this.toolStripMenuItemExportWater.Size = new System.Drawing.Size(180, 22);
+            this.toolStripMenuItemExportWater.Text = "Export Water";
+            this.toolStripMenuItemExportWater.Click += new System.EventHandler(this.toolStripMenuItemExportWater_Click);
             // 
             // frmMain
             // 
@@ -122,6 +131,7 @@
         private System.Windows.Forms.ToolStripMenuItem loadVPLToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem exportToolStripMenuItem;
         private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemExportWater;
     }
 }
 

+ 204 - 13
EQ2/devtools/EQ2ModelViewer/EQ2ModelViewer/Main.cs

@@ -2,6 +2,7 @@
 using System.Threading.Tasks;
 using System.Windows.Forms;
 using System.Collections.Generic;
+using System.Xml;
 
 using SlimDX;
 using SlimDX.D3DCompiler;
@@ -16,17 +17,21 @@ using Everquest2.Util;
 using Everquest2.Visualization;
 using System.IO;
 using SlimDX.DirectInput;
+using SlimDX.Direct2D;
+using System.Security.Permissions;
 
 namespace EQ2ModelViewer
 {
     public partial class frmMain : Form
     {
         private System.Collections.Generic.List<Model> m_Models = new System.Collections.Generic.List<Model>();
+        private System.Collections.Generic.List<VeRegion> m_Regions = new System.Collections.Generic.List<VeRegion>();
         private GraphicClass Graphics = new GraphicClass();
         public Model SelectedModel = null;
         private string ZoneFile;
         private bool Render3DAspect = true;
         private bool AutoExportOnLoad = false;
+        private bool AutoExportRegionOnLoad = false;
         private String AutoLoadFileName = "";
         public frmMain()
         {
@@ -55,6 +60,7 @@ namespace EQ2ModelViewer
         private Key hitKey = Key.NoConvert;
         double timestamp = 0;
         private CameraClass camera;
+        int region_nodes = 0;
         private void frmMain_Load(object sender, EventArgs e)
         {
             this.WindowState = FormWindowState.Maximized;
@@ -104,6 +110,10 @@ namespace EQ2ModelViewer
                     {
                         AutoExportOnLoad = true;
                     }
+                    else if (cmd.Equals("exportregion"))
+                    {
+                        AutoExportRegionOnLoad = true;
+                    }
                     else
                     {
                         AutoLoadFileName = args[i];
@@ -116,6 +126,8 @@ namespace EQ2ModelViewer
                 LoadZoneFile(AutoLoadFileName);
             if (AutoExportOnLoad)
                 exportToolStripMenuItem_Click(null, EventArgs.Empty);
+            if (AutoExportRegionOnLoad)
+                toolStripMenuItemExportWater_Click(null, EventArgs.Empty);
 
             if (!Render3DAspect)
             {
@@ -228,7 +240,6 @@ namespace EQ2ModelViewer
                         camera.Render();
 
                         //frustum.ConstructFrustum(1000.0f, Graphics.GetProjectionMatrix(), camera.GetViewMatrix());
-
                         foreach (Model model in m_Models) {
                             //if (frustum.CheckSphere(model.Position.X, model.Position.Y, model.Position.Z, 10.0f))
                             //{
@@ -239,7 +250,6 @@ namespace EQ2ModelViewer
                             //lightShader.Render(Graphics.Context, model.GetIndexCount(), temp, camera.GetViewMatrix(), Graphics.GetProjectionMatrix(), model.GetTexture(), new Vector3(0.0f, 0.0f, 0.0f), new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 0.0f, 0.0f), camera.GetPosition(), new Vector4(0.0f, 0.0f, 0.0f, 0.0f), 0.0f);
                             //}
                         }
-
                         // 2D
                         Graphics.TurnZBufferOff();
                         Graphics.TurnOnAlphaBlending();
@@ -299,12 +309,13 @@ namespace EQ2ModelViewer
             LoadZoneFile();
         }
 
+        public String DirName = "";
         private void LoadZoneFile(String filename="")
         {
             bool isDrawFile = false;
 
             string fullName = "";
-            String dirName = "";
+            DirName = "";
             if (filename.Length < 1)
             {
                 OpenFileDialog fd = new OpenFileDialog();
@@ -320,7 +331,7 @@ namespace EQ2ModelViewer
                         string temp = fd.FileName.Substring(0, fd.FileName.LastIndexOf("\\"));
                         ZoneFile = fd.SafeFileName.Substring(0, fd.SafeFileName.IndexOf(".draw"));
                         fullName = ZoneFile;
-                        dirName = temp;
+                        DirName = temp;
                         filename = fd.FileName;
                     }
                     else
@@ -328,7 +339,7 @@ namespace EQ2ModelViewer
                         string temp = fd.FileName.Substring(0, fd.FileName.IndexOf("zones"));
                         ZoneFile = fd.SafeFileName.Substring(0, fd.SafeFileName.IndexOf(".lut"));
                         fullName = ZoneFile;
-                        dirName = temp;
+                        DirName = temp;
                         filename = fd.FileName;
                     }
                 }
@@ -341,14 +352,14 @@ namespace EQ2ModelViewer
                     string temp = filename.Substring(0, filename.LastIndexOf("\\"));
                     ZoneFile = filename.Substring(0, filename.IndexOf(".draw"));
                     fullName = filename;
-                    dirName = temp;
+                    DirName = temp;
                 }
                 else
                 {
                     string temp = filename.Substring(0, filename.IndexOf("zones"));
                     ZoneFile = filename.Substring(0, filename.IndexOf(".lut"));
                     fullName = filename;
-                    dirName = temp;
+                    DirName = temp;
                 }
             }
 
@@ -376,7 +387,8 @@ namespace EQ2ModelViewer
                 MessageBox.Show("No filename provided for loading a zonefile!", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                 return;
             }
-                System.IO.BinaryReader reader2 = new System.IO.BinaryReader(new System.IO.FileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read));
+            region_nodes = 0;
+            System.IO.BinaryReader reader2 = new System.IO.BinaryReader(new System.IO.FileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read));
                 // Image(2020): Was ReadUint32, qey_harbor.lut however has 00 1F 00 7A, so that as an int32 is a very large number!
                 reader2.ReadUInt32();
                 do
@@ -391,13 +403,17 @@ namespace EQ2ModelViewer
                     // was duplicating drive name
                     file = file.Replace("/", "\\");
 
-                    file = dirName + file;
+                    file = DirName + file;
                     AppendLoadFile("VOC Loading: " + file);
 
+                if ( file.Contains("qey_harbor_qey_terrain_harbor_geo05_rmob_0"))
+                    {
+                    int test = 0;
+                    }
                     Eq2Reader reader = new Eq2Reader(new System.IO.FileStream(file, System.IO.FileMode.Open, System.IO.FileAccess.Read));
                     VeNode venode = reader.ReadNodeObject();
 
-                    CheckNode(dirName, venode, false);
+                    CheckNode(DirName, venode, false, false);
 
                     //MessageBox.Show("Done!");
 
@@ -410,8 +426,66 @@ namespace EQ2ModelViewer
         float yaw, pitch, roll = 0;
         float scale = 0;
         UInt32 widgetID;
+        UInt32 regionMapVersion = 1;
+
+        private void toolStripMenuItemExportWater_Click(object sender, EventArgs e)
+        {
+
+            StreamWriter swfile = new StreamWriter(ZoneFile + ".regionread");
+                using (BinaryWriter file = new BinaryWriter(File.Open(ZoneFile + ".EQ2Region", FileMode.Create)))
+            {
+                file.Write(ZoneFile);
+                file.Write(regionMapVersion);
+                file.Write(m_Regions.Count);
+                Int32 regionNum = 0;
+                foreach (VeRegion region in m_Regions)
+                {
+                    file.Write(regionNum);
+                    regionNum += 1;
+                    Int32 node = 0;
+                    file.Write(region.region_type);
+                    file.Write(region.position[0]);
+                    file.Write(region.position[1]);
+                    file.Write(region.position[2]);
+                    file.Write(region.splitdistance);
+                    file.Write(region.vert_count);
+                    swfile.WriteLine();
+                    swfile.WriteLine("REGION: " + region.position[0] + " " + region.position[1] + " " + region.position[2] + " " + region.splitdistance + " - RegionType: " + region.region_type);
+                    if (region.parentNode.regionDefinitionFile != null)
+                        swfile.WriteLine("REGIONFILE: " + region.parentNode.regionDefinitionFile);
+                    if (region.parentNode.environmentDefinitions != null)
+                    {
+                        foreach (string str in region.parentNode.environmentDefinitions)
+                            swfile.WriteLine("EnvDefinition: " + str);
+                    }
+                    swfile.WriteLine("EnvData: " + region.unkcount + " / " + region.parentNode.unk1 + " / " + region.parentNode.unk2);
+
+                    for (ushort i = 0; i < region.vert_count; ++i)
+                    {
+                        Int32 regiontype = 1;
+                        Int32 special = region.special;
+                        swfile.WriteLine(node + " " + region.m_normals[i, 0] + " " + region.m_normals[i, 1] + " " +
+                            region.m_normals[i, 2] + " " + region.m_distance[i] + " " + regiontype + " " + special + " " +
+                           region.m_childindex[i, 0] + " " + region.m_childindex[i, 1]);
+                        file.Write(node);
+                        node += 1;
+                        file.Write(region.m_normals[i, 0]);
+                        file.Write(region.m_normals[i, 1]);
+                        file.Write(region.m_normals[i, 2]);
+                        file.Write(region.m_distance[i]);
+                        file.Write(regiontype);
+                        file.Write(special);
+                        file.Write((Int32)region.m_childindex[i, 0]);
+                        file.Write((Int32)region.m_childindex[i, 1]);
+                    }
+                }
+                file.Close();
+            }
+            swfile.Close();
+        }
+
         UInt32 GridID;
-        private void CheckNode(string temp, object item, bool parentXform)
+        private void CheckNode(string temp, object item, bool parentXform, bool selectNodeParent)
         {
             if (item is VeMeshGeometryNode)
             {
@@ -422,6 +496,15 @@ namespace EQ2ModelViewer
                 // testing tutorial_island02 boat
                 //if (widgetID == 1253219127)
 
+                // tutorial_island02 water
+                if(widgetID == 1864854785)
+                {
+                    int test = 0;
+                }
+                if(widgetID == 2720558016)
+                {
+                    int test = 0;
+                }
                 Model model = new Model();
                 model.Initialize(Graphics.Device, (VeMeshGeometryNode)item, temp);
                 model.Position.X = x;
@@ -437,10 +520,93 @@ namespace EQ2ModelViewer
             }
             else
             {
+
+                if (widgetID == 2720558016)
+                {
+                    int test = 0;
+                }
                 float x1 = 0.0f;
                 float y1 = 0.0f;
                 float z1 = 0.0f;
-                if (item is VeRoomItemNode)
+
+                if (item is VeEnvironmentNode)
+                {
+                    VeEnvironmentNode env = (VeEnvironmentNode)item;
+                    if (env.regionDefinitionFile != null && env.regionDefinitionFile.Length > 0)
+                    {
+                        int waterType = 0;
+                        String envFile = "";
+                        if (env.environmentDefinitions != null)
+                        {
+                            foreach (string str in env.environmentDefinitions)
+                            {
+                                envFile = str;
+                                envFile = envFile.Replace("/", "\\");
+
+                                envFile = DirName + envFile;
+                                waterType = LoadEnvXmlParseLiquid(envFile);
+                                if (waterType != 0)
+                                    break;
+                            }
+                        }
+
+                        bool watervol = env.regionDefinitionFile.Contains("watervol");
+                        bool waterregion = env.regionDefinitionFile.Contains("waterregion");
+                        bool waterregion2 = env.regionDefinitionFile.Contains("water_region");
+                        bool iswater = env.regionDefinitionFile.Contains("water");
+                        bool isocean = env.regionDefinitionFile.Contains("ocean");
+                        bool isvolume = env.regionDefinitionFile.Contains("volume");
+                        AppendLoadFile("Region established: " + waterType + ", " + envFile
+                            + " WaterVol: " + watervol + " WaterRegion: " + waterregion +
+                            " WaterRegion2: " + waterregion2 + " IsWater: " + iswater +
+                            " IsOcean: " + isocean + " IsVolume: " + isvolume);
+                        if (waterType>0)
+                        {
+                            AppendLoadFile("Region accepted: " + waterType + ", " + envFile
+                                + " WaterVol: " + watervol + " WaterRegion: " + waterregion +
+                                " WaterRegion2: " + waterregion2 + " IsWater: " + iswater +
+                                " IsOcean: " + isocean + " IsVolume: " + isvolume);
+                            Eq2Reader reader2 = new Eq2Reader(new System.IO.FileStream(DirName + env.regionDefinitionFile, System.IO.FileMode.Open, System.IO.FileAccess.Read));
+                            VeRegion region = (VeRegion)reader2.ReadObject();
+                            region.parentNode = env;
+                            region.region_type = 0; // default water volume
+
+                            if (waterregion) // 'sea'/ocean/waterregion in tutorial_island02 / qeynos_harbor
+                                region.region_type = 1;
+                            else if (waterregion2)
+                                region.region_type = 0;
+                            else if (isvolume && selectNodeParent)
+                                region.region_type = 4;
+                            else if ((isocean && selectNodeParent)) // ocean in antonica/commonlands/tutorial
+                                region.region_type = 3;
+                            else if (isocean && iswater) // caves in frostfang(halas)
+                                region.region_type = 4;
+                            else if (isocean)
+                                region.region_type = 5;
+
+                            region.special = waterType;
+                            MeshClass tmpMesh = new MeshClass();
+                            region_nodes += region.vert_count;
+                            m_Regions.Add(region);
+                        }
+                        else
+                        {
+                            if (env.regionDefinitionFile != null)
+                            {
+                                AppendLoadFile("Region skipped: " + env.regionDefinitionFile);
+                            }
+                            else
+                                AppendLoadFile("Region skipped: ???");
+
+                            if (env.environmentDefinitions != null)
+                            {
+                                foreach (string str in env.environmentDefinitions)
+                                    AppendLoadFile("EnvDefinition: " + str);
+                            }
+                        }
+                    }
+                }
+                else if (item is VeRoomItemNode)
                 {
                     yaw = ((VeRoomItemNode)item).orientation[0];
                     pitch = ((VeRoomItemNode)item).orientation[1];
@@ -482,9 +648,10 @@ namespace EQ2ModelViewer
 
                     System.Collections.IEnumerator enumerator = ((VeNode)item).EnumerateChildren();
                     bool parentBool = item is VeXformNode;
+                    bool selectNode = item is VeSelectNode;
                     while (enumerator.MoveNext())
                     {
-                        CheckNode(temp, enumerator.Current, parentBool);
+                        CheckNode(temp, enumerator.Current, parentBool, selectNodeParent ? true : selectNode);
                     }
 
                     x = old_x;
@@ -689,5 +856,29 @@ namespace EQ2ModelViewer
             if (sender != null)
                MessageBox.Show("Export Complete!");
         }
+
+        private int LoadEnvXmlParseLiquid(string filename)
+        {
+            try
+            {
+                XmlDocument xmlDoc = new XmlDocument();
+                xmlDoc.Load(filename);
+
+                var nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
+                nsmgr.AddNamespace("vdl", "Vdl");
+                nsmgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
+                XmlNode atmosphereNode = xmlDoc.SelectSingleNode("/vdl:VdlFile/vdl:Environment/vdl:iAtmosphere", nsmgr);
+                if (atmosphereNode != null && Convert.ToInt32(atmosphereNode.InnerText) < 0)
+                    return Convert.ToInt32(atmosphereNode.InnerText); // lava
+
+                XmlNode liquidNode = xmlDoc.SelectSingleNode("/vdl:VdlFile/vdl:Environment/vdl:nLiquid", nsmgr);
+                if (liquidNode != null)
+                    return Convert.ToInt32(liquidNode.InnerText);
+            }catch(Exception ex)
+            {
+
+            }
+            return 0;
+        }
     }
 }

+ 14 - 1
EQ2/devtools/EQ2ModelViewer/EQ2ModelViewer/MeshClass.cs

@@ -115,6 +115,15 @@ namespace EQ2ModelViewer
             context.InputAssembler.SetIndexBuffer(m_IndexBuffer, Format.R32_UInt, 0);
             context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
         }
+        public void RenderBuffersExt(DeviceContext context)
+        {
+            int stride = System.Runtime.InteropServices.Marshal.SizeOf(typeof(EQ2Region));
+            int offset = 0;
+
+            context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(m_VertexBuffer, stride, offset));
+            context.InputAssembler.SetIndexBuffer(m_IndexBuffer, Format.R32_UInt, 0);
+            context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
+        }
 
         public void ShutDown()
         {
@@ -130,12 +139,16 @@ namespace EQ2ModelViewer
 
         public ShaderResourceView GetTexture()
         {
+            if (m_Texture == null)
+                return null;
+
             return m_Texture.GetTexture();
         }
 
         private void ReleaseTexture()
         {
-            m_Texture.ShutDown();
+            if (m_Texture != null)
+                m_Texture.ShutDown();
         }
 
         public bool LoadTexture(Device device, string filename)

+ 3 - 0
EQ2/devtools/EQ2ModelViewer/EQ2ModelViewer/Model.cs

@@ -165,6 +165,9 @@ namespace EQ2ModelViewer
 
             foreach (MeshClass mesh in m_meshes)
             {
+                if (mesh.GetTexture() == null)
+                    continue;
+
                 mesh.RenderBuffers(Graphics.Context);
                 lightShader.Render(Graphics.Context, mesh.GetIndexCount(), temp, camera.GetViewMatrix(), Graphics.GetProjectionMatrix(), mesh.GetTexture(), new Vector3(0.0f, 0.0f, 0.0f), ambientColor/*new Vector4(1.0f, 1.0f, 1.0f, 1.0f)*/, new Vector4(0.0f, 0.0f, 0.0f, 0.0f), camera.GetPosition(), new Vector4(0.0f, 0.0f, 0.0f, 0.0f), 0.0f);
             }

+ 8 - 3
EQ2/devtools/EQ2ModelViewer/EQ2ModelViewer/libeq2/Visualization/VeEnvironmentNode.cs

@@ -50,7 +50,10 @@ namespace Everquest2.Visualization
 
             bool hasRegionDefinition = reader.ReadBoolean();
 
-            if (hasRegionDefinition) regionDefinitionFile = reader.ReadString(2);
+            if (hasRegionDefinition)
+            {
+                regionDefinitionFile = reader.ReadString(2);
+            }
 
             byte environmentDefinitionCount = reader.ReadByte();
 
@@ -66,17 +69,19 @@ namespace Everquest2.Visualization
             if (classVersion >= 2)
             {
                 //4 bytes, not sure if its a float
-                float unk1 = reader.ReadSingle();
+                unk1 = reader.ReadInt32();
             }
 
             if (classVersion >= 3)
             {
-                byte unk2 = reader.ReadByte();
+                unk2 = reader.ReadByte();
             }
         }
 
 
         public string   regionDefinitionFile;
         public string[] environmentDefinitions;
+        public int unk1 = 0;
+        public int unk2 = 0;
     }
 }

+ 32 - 27
EQ2/devtools/EQ2ModelViewer/EQ2ModelViewer/libeq2/Visualization/VeRegion.cs

@@ -46,43 +46,48 @@ namespace Everquest2.Visualization {
             if (classVersion == 0) unk0 = reader.ReadSingle();
 
             ushort count = reader.ReadUInt16();
-
-            unk1 = new float[count, 3];
-            unk2 = new float[count];
-            unk3 = new short[count, 2];
+            vert_count = count;
+            m_normals = new float[count, 3];
+            m_distance = new float[count];
+            m_childindex = new short[count, 2];
             for (ushort i = 0; i < count; ++i) {
-                unk1[i, 0] = reader.ReadSingle();
-                unk1[i, 1] = reader.ReadSingle();
-                unk1[i, 2] = reader.ReadSingle();
-                unk2[i] = reader.ReadSingle();
-                unk3[i, 0] = reader.ReadInt16();
-                unk3[i, 1] = reader.ReadInt16();
+                m_normals[i, 0] = reader.ReadSingle();
+                m_normals[i, 1] = reader.ReadSingle();
+                m_normals[i, 2] = reader.ReadSingle();
+                m_distance[i] = reader.ReadSingle();
+                m_childindex[i, 0] = reader.ReadInt16();
+                m_childindex[i, 1] = reader.ReadInt16();
             }
 
             if (classVersion >= 2) {
-                uint unkcount = reader.ReadUInt32();
-                float[,] unk6 = new float[unkcount, 4];
+                unkcount = reader.ReadUInt32();
+                m_center = new float[unkcount, 4];
 
                 for (int i = 0; i < unkcount; i++) {
-                    unk6[i, 0] = reader.ReadSingle();
-                    unk6[i, 1] = reader.ReadSingle();
-                    unk6[i, 2] = reader.ReadSingle();
-                    unk6[i, 3] = reader.ReadSingle();
+                    m_center[i, 0] = reader.ReadSingle();
+                    m_center[i, 1] = reader.ReadSingle();
+                    m_center[i, 2] = reader.ReadSingle();
+                    m_center[i, 3] = reader.ReadSingle();
                 }
             }
 
-            unk4[0] = reader.ReadSingle();
-            unk4[1] = reader.ReadSingle();
-            unk4[2] = reader.ReadSingle();
-            unk5 = reader.ReadSingle();
+            position[0] = reader.ReadSingle();
+            position[1] = reader.ReadSingle();
+            position[2] = reader.ReadSingle();
+            splitdistance = reader.ReadSingle();
         }
 
-
-        private float unk0;
-        private float[,] unk1;
-        private float[] unk2;
-        private short[,] unk3;
-        private float[] unk4 = new float[3];
-        private float unk5;
+        public int vert_count;
+        public float unk0;
+        public uint unkcount;
+        public float[,] m_normals;
+        public float[] m_distance;
+        public short[,] m_childindex;
+        public float[] position = new float[3];
+        public float splitdistance;
+        public VeEnvironmentNode parentNode;
+        float[,] m_center; // 1-3 is vector center, 4th is radius
+        public int region_type;
+        public int special = 0;
     }
 }