コード例 #1
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
        static void LinkBSPNodes(WMOGroup group)
        {
            foreach (var n in group.BSPNodes)
            {
                if (n.posChild != -1)
                {
                    n.Positive = group.BSPNodes[n.posChild];
                }
                if (n.negChild != -1)
                {
                    n.Negative = group.BSPNodes[n.negChild];
                }

                if (n.faceStart == 0 && n.nFaces == 0)
                {
                    // empty?
                    continue;
                }

                //var faces = new ushort[n.nFaces];
                n.TriIndices = new List<Index3>(n.nFaces);
                for (var j = 0; j < n.nFaces; j++)
                {
                    var triIndex = group.Indices[group.MOBR[n.faceStart + j]];
                    n.TriIndices.Add(triIndex);
                }
            }

            //group.DumpBSPNodes();
        }
コード例 #2
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
        /// <summary>
        /// Gets a WMOGroup from the WMO Group file
        /// </summary>
        /// <param name="manager"></param>
        /// <param name="filePath">File path to the WMOGroup</param>
        /// <param name="root"></param>
        /// <param name="groupIndex">Current index in the WMO Group</param>
        /// <returns>A WMOGroup from the WMO Group file</returns>
        public static WMOGroup Process(MpqManager manager, string filePath, WMORoot root, int groupIndex)
        {
            if (!manager.FileExists(filePath))
            {
                log.Error("WMOGroup file does not exist: ", filePath);
            }

            var currentWMOGroup = new WMOGroup(root, groupIndex);

            using (var stream = manager.OpenFile(filePath))
            using (var br = new BinaryReader(stream))
            {
                ReadRequiredChunks(br, currentWMOGroup);
                ReadOptionalChunks(br, currentWMOGroup);
            }

            return currentWMOGroup;
        }
コード例 #3
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
 static void ReadMVER(BinaryReader br, WMOGroup group)
 {
     group.Version = br.ReadUInt32();
 }
コード例 #4
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
        private static void ReadOptionalChunks(BinaryReader br, WMOGroup currentWMOGroup)
        {
            // We start here at the end of the required chunks
            uint type = 0;
            uint size = 0;
            var curPos = AdvanceToNextChunk(br, br.BaseStream.Position, ref type, ref size);

            if (currentWMOGroup.Header.HasMOLR)
            {
                if (type == Signatures.MOLR)
                {
                    ReadMOLR(br, currentWMOGroup, size);
                }
                else
                {
                    Console.WriteLine(
                        "ERROR: WMO Group did not have optional chunk MOLR, but was specified in the flags");
                }

                curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);
            }

            if (currentWMOGroup.Header.HasMODR)
            {
                if (type == Signatures.MODR)
                {
                    ReadMODR(br, currentWMOGroup, size);
                }
                else
                {
                    Console.WriteLine(
                        "ERROR: WMO Group did not have optional chunk MODR, but was specified in the flags");
                }

                curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);
            }

            if (currentWMOGroup.Header.HasBSPInfo)
            {
                if (type == Signatures.MOBN)
                {
                    ReadMOBN(br, currentWMOGroup, size);
                }
                else
                {
                    Console.WriteLine(
                        "ERROR: WMO Group did not have optional chunk MOBN, but was specified in the flags");
                }

                curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);

                if (type == Signatures.MOBR)
                {
                    ReadMOBR(br, currentWMOGroup, size);
                }
                else
                {
                    Console.WriteLine(
                        "ERROR: WMO Group did not have optional chunk MOBR, but was specified in the flags");
                }

                curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);
            }

            if (currentWMOGroup.Header.HasMPChunks)
            {
                if (type == Signatures.MPBV)
                {
                    ReadMPBV(br, currentWMOGroup);
                }
                else
                {
                    Console.WriteLine(
                        "ERROR: WMO Group did not have optional chunk MPBV, but was specified in the flags");
                }
                curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);

                if (type == Signatures.MPBP)
                {
                    ReadMPBP(br, currentWMOGroup);
                }
                else
                {
                    Console.WriteLine(
                        "ERROR: WMO Group did not have optional chunk MPBP, but was specified in the flags");
                }
                curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);

                if (type == Signatures.MPBI)
                {
                    ReadMPBI(br, currentWMOGroup);
                }
                else
                {
                    Console.WriteLine(
                        "ERROR: WMO Group did not have optional chunk MPBI, but was specified in the flags");
                }
                curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);

                if (type == Signatures.MPBG)
                {
                    ReadMPBG(br, currentWMOGroup);
                }
                else
                {
                    Console.WriteLine(
                        "ERROR: WMO Group did not have optional chunk MPBG, but was specified in the flags");
                }
                curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);
            }

            if (currentWMOGroup.Header.HasMOCV1)
            {
                if (type == Signatures.MOCV)
                {
                    ReadMOCV1(br, currentWMOGroup, size);
                }
                else
                {
                    Console.WriteLine(
                        "ERROR: WMO Group did not have optional chunk MOCV 1, but was specified in the flags");
                }
                curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);
            }

            if (currentWMOGroup.Header.HasMLIQ)
            {
                if (type == Signatures.MLIQ)
                {
                    ReadMLIQ(br, currentWMOGroup);
                }
                else
                {
                    Console.WriteLine(
                        "ERROR: WMO Group did not have optional chunk MLIQ, but was specified in the flags");
                }
                curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);
            }

            if (currentWMOGroup.Header.HasMORChunks)
            {
                if (type == Signatures.MORI)
                {
                    ReadMORI(br, currentWMOGroup);
                }
                else
                {
                    Console.WriteLine(
                        "ERROR: WMO Group did not have optional chunk MORI, but was specified in the flags");
                }
                curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);

                if (type == Signatures.MORB)
                {
                    ReadMORB(br, currentWMOGroup);
                }
                else
                {
                    Console.WriteLine(
                        "ERROR: WMO Group did not have optional chunk MORB, but was specified in the flags");
                }
                curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);
            }

            if (currentWMOGroup.Header.HasMOTV2)
            {
                if (type == Signatures.MOTV)
                {
                    ReadMOTV2(br, currentWMOGroup, size);
                }
                else
                {
                    Console.WriteLine(
                        "ERROR: WMO Group did not have optional chunk MOTV2, but was specified in the flags");
                }

                curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);
            }

            if (currentWMOGroup.Header.HasMOCV2)
            {
                if (type == Signatures.MOCV)
                {
                    ReadMOCV2(br, currentWMOGroup, size);
                }
                else
                {
                    Console.WriteLine(
                        "ERROR: WMO Group did not have optional chunk MOCV2, but was specified in the flags");
                }

                // This is the final chunk in the file (or should be...)
                //curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);
            }
        }
コード例 #5
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
        /// <summary>
        /// Reads the vertices for this wmo group
        /// </summary>
        /// <param name="file"></param>
        /// <param name="group"></param>
        /// <param name="size"></param>
        static void ReadMOVT(BinaryReader file, WMOGroup group, uint size)
        {
            group.VertexCount = size/(sizeof (float)*3);
            // let's hope it's padded to 12 bytes, not 16...

            for (uint i = 0; i < group.VertexCount; i++)
            {
                group.Vertices.Add(file.ReadWMOVector3());
            }
        }
コード例 #6
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
 private static void ReadMPBV(BinaryReader br, WMOGroup group)
 {
 }
コード例 #7
0
        private static void WriteGroupLiquidInfo(BinaryWriter writer, WMOGroup group)
        {
            // The zero point on the map
            writer.Write(group.LiquidInfo.BaseCoordinates);

            // Dimensions of the Map
            writer.Write(group.LiquidInfo.XTileCount);
            writer.Write(group.LiquidInfo.YTileCount);

            // Write the LiquidTile Map
            for (var y = 0; y < group.LiquidInfo.YTileCount; y++)
            {
                for (var x = 0; x < group.LiquidInfo.XTileCount; x++)
                {
                    writer.Write((group.LiquidInfo.LiquidTileFlags[x, y] & 0x0F) != 0x0F);
                }
            }

            for (var y = 0; y < group.LiquidInfo.YVertexCount; y++)
            {
                for (var x = 0; x < group.LiquidInfo.XVertexCount; x++)
                {
                    writer.Write(group.LiquidInfo.HeightMapMax[x, y]);
                }
            }
        }
コード例 #8
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
        static void ReadMOBN(BinaryReader file, WMOGroup group, uint size)
        {
            var count = size/0x10;

            group.BSPNodes = new List<BSPNode>((int)count);
            for (var i=0;i<count;i++)
            {
                var node = new BSPNode
                               {
                                   flags = (BSPNodeFlags) file.ReadUInt16(),
                                   negChild = file.ReadInt16(),
                                   posChild = file.ReadInt16(),
                                   nFaces = file.ReadUInt16(),
                                   faceStart = file.ReadUInt32(),
                                   planeDist = file.ReadSingle()
                               };

                group.BSPNodes.Add(node);
            }
        }
コード例 #9
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
        static void ReadMLIQ(BinaryReader file, WMOGroup group)
        {
            group.LiquidInfo = new LiquidInfo
                                   {
                                       XVertexCount = file.ReadInt32(),
                                       YVertexCount = file.ReadInt32(),
                                       XTileCount = file.ReadInt32(),
                                       YTileCount = file.ReadInt32(),
                                       BaseCoordinates = file.ReadVector3(),
                                       MaterialId = file.ReadUInt16()
                                   };

            // The following is untested, but is what the client appears to be doing
            // These are probably similar to the 2 floats in the old adt water chunk
            group.LiquidInfo.HeightMapMax = new float[group.LiquidInfo.XVertexCount, group.LiquidInfo.YVertexCount];
            group.LiquidInfo.HeightMapMin = new float[group.LiquidInfo.XVertexCount, group.LiquidInfo.YVertexCount];

            // This is different from the other ADT files, these are stored as [row, col] instead of [col, row]
            for (var y = 0; y < group.LiquidInfo.YVertexCount; y++)
            {
                for (var x = 0; x < group.LiquidInfo.XVertexCount; x++)
                {
                    // The first value is never used ...
                    group.LiquidInfo.HeightMapMin[x, y] = file.ReadSingle();
                    group.LiquidInfo.HeightMapMax[x, y] = file.ReadSingle();
                }
            }

            group.LiquidInfo.LiquidTileFlags = new byte[group.LiquidInfo.XTileCount, group.LiquidInfo.YTileCount];
            for (var y = 0; y < group.LiquidInfo.YTileCount; y++)
            {
                for (var x = 0; x < group.LiquidInfo.XTileCount; x++)
                {
                    group.LiquidInfo.LiquidTileFlags[x, y] = file.ReadByte();
                }
            }
        }
コード例 #10
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
        static void ReadMOCV2(BinaryReader br, WMOGroup group, uint size)
        {
            // Vertex colors, 4 bytes per vertex (BGRA), for WMO groups using indoor lighting.
            group.VertexColors2 = new Color4[size / 4];

            for (int i = 0; i < group.VertexColors2.Length; i++)
            {
                group.VertexColors2[i] = br.ReadColor4();
            }
        }
コード例 #11
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
 /// <summary>
 /// Reads the Normal vectors for this group
 /// </summary>
 /// <param name="file"></param>
 /// <param name="group"></param>
 static void ReadMONR(BinaryReader file, WMOGroup group)
 {
     // Read the vector normals
     for (var i=0;i<group.VertexCount;i++)
     {
         group.Normals.Add(file.ReadWMOVector3());
     }
 }
コード例 #12
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
        static void ReadMOPY(BinaryReader file, WMOGroup group, uint size)
        {
            group.TriangleCount = size / 2;
            // materials
            /*  0x01 - inside small houses and paths leading indoors
             *  0x02 - ???
             *  0x04 - set on indoor things and ruins
             *  0x08 - ???
             *  0x10 - ???
             *  0x20 - Always set?
             *  0x40 - sometimes set-
             *  0x80 - ??? never set
             *
             */
            group.TriangleMaterials = new MOPY[group.TriangleCount];

            for (var i = 0; i < group.TriangleCount; i++)
            {
                var t = new MOPY
                {
                    Flags = (MOPY.MaterialFlags)file.ReadByte(),
                    MaterialIndex = file.ReadByte()
                };
                group.TriangleMaterials[i] = t;
            }
        }
コード例 #13
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
        static void ReadMOLR(BinaryReader br, WMOGroup group, uint size)
        {
            // Light references, one 16-bit integer per light reference.
            // This is basically a list of lights used in this WMO group,
            // the numbers are indices into the WMO root file's MOLT table.
            group.LightReferences = new ushort[size/2];

            for (int i = 0; i < group.LightReferences.Length; i++)
            {
                group.LightReferences[i] = br.ReadUInt16();
            }
        }
コード例 #14
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
        static void ReadMOGP(BinaryReader file, WMOGroup group)
        {
            group.Header.NameStart = file.ReadInt32();
            if (group.Header.NameStart != -1)
            {
                group.Name = group.Root.GroupNames[group.Header.NameStart];
            }

            group.Header.DescriptiveNameStart = file.ReadInt32();
            if (group.Header.DescriptiveNameStart > 0)
            {
                group.DescriptiveName = group.Root.GroupNames[group.Header.DescriptiveNameStart];
            }

            group.Header.Flags = (WMOGroupFlags)file.ReadUInt32();

            group.Header.BoundingBox = new BoundingBox(file.ReadWMOVector3(), file.ReadWMOVector3());

            group.Header.PortalStart = file.ReadUInt16();
            group.Header.PortalCount = file.ReadUInt16();
            group.Header.BatchesA = file.ReadUInt16();
            group.Header.BatchesB = file.ReadUInt16();
            group.Header.BatchesC = file.ReadUInt16();
            group.Header.BatchesD = file.ReadUInt16();
            group.Header.Fogs = file.ReadBytes(4);
            group.Header.LiquidType = file.ReadUInt32();
            group.Header.WMOGroupId = file.ReadUInt32();
            group.Header.MOGP_0x3C = file.ReadUInt32();
            group.Header.MOGP_0x40 = file.ReadUInt32();
        }
コード例 #15
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
        static void ReadMODR(BinaryReader br, WMOGroup group, uint size)
        {
            // Doodad references, one 16-bit integer per doodad.
            // The numbers are indices into the doodad instance table (MODD chunk) of the WMO root file.
            // These have to be filtered to the doodad set being used in any given WMO instance.
            group.DoodadReferences = new ushort[size / 2];

            for (int i = 0; i < group.DoodadReferences.Length; i++)
            {
                group.DoodadReferences[i] = br.ReadUInt16();
            }
        }
コード例 #16
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
        private static void ReadRequiredChunks(BinaryReader br, WMOGroup currentWMOGroup)
        {
            uint type = 0;
            uint size = 0;

            var curPos = AdvanceToNextChunk(br, br.BaseStream.Position, ref type, ref size);
            if (type == Signatures.MVER)
            {
                ReadMVER(br, currentWMOGroup);
            }
            else
            {
                Console.WriteLine("ERROR: WMO Group did not have required chunk MVER");
            }

            curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);
            if (type == Signatures.MOGP)
            {
                size = 68; // MOGP is stupid and wants to use the entire rest of the file as its size
                ReadMOGP(br, currentWMOGroup);
            }
            else
            {
                Console.WriteLine("ERROR: WMO Group did not have required chunk MOGP");
            }

            curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);
            if (type == Signatures.MOPY)
            {
                ReadMOPY(br, currentWMOGroup, size);
            }
            else
            {
                Console.WriteLine("ERROR: WMO Group did not have required chunk MOPY");
            }

            curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);
            if (type == Signatures.MOVI)
            {
                ReadMOVI(br, currentWMOGroup);
            }
            else
            {
                Console.WriteLine("ERROR: WMO Group did not have required chunk MOVI");
            }

            curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);
            if (type == Signatures.MOVT)
            {
                ReadMOVT(br, currentWMOGroup, size);
            }
            else
            {
                Console.WriteLine("ERROR: WMO Group did not have required chunk MOVT");
            }

            curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);
            if (type == Signatures.MONR)
            {
                ReadMONR(br, currentWMOGroup);
            }
            else
            {
                Console.WriteLine("ERROR: WMO Group did not have required chunk MONR");
            }

            curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);
            if (type == Signatures.MOTV)
            {
                ReadMOTV1(br, currentWMOGroup, size);
            }
            else
            {
                Console.WriteLine("ERROR: WMO Group did not have required chunk MOTV1");
            }

            curPos = AdvanceToNextChunk(br, curPos, ref type, ref size);
            if (type == Signatures.MOBA)
            {
                ReadMOBA(br, currentWMOGroup, size);
            }
            else
            {
                Console.WriteLine("ERROR: WMO Group did not have required chunk MOBA");
            }

            br.BaseStream.Seek(curPos + size, SeekOrigin.Begin); // seek to the end of the required fields
        }
コード例 #17
0
        private static void WriteBSPTree(BinaryWriter writer, WMOGroup group)
        {
            var tree = new BSPTree(group.BSPNodes);

            writer.Write(tree.rootId);

            writer.Write(tree.nodes.Count);
            foreach (var node in tree.nodes)
            {
                WriteBSPNode(writer, node);
            }
        }
コード例 #18
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
 private static void ReadMORI(BinaryReader reader, WMOGroup group)
 {
 }
コード例 #19
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
        static void ReadMOBR(BinaryReader file, WMOGroup group, uint size)
        {
            uint count = size / 2;
            group.MOBR = new ushort[count];

            for (int i = 0; i < count; i++)
            {
                group.MOBR[i] = file.ReadUInt16();
            }

            LinkBSPNodes(group);
        }
コード例 #20
0
        private static void PrepareWMOGroupDoodadReferences(WMORoot root, WMOGroup wmoGroup)
        {
            foreach (var dRefId in wmoGroup.DoodadReferences)
            {
                var def = root.DoodadDefinitions[dRefId];
                if (def == null) continue;
                if (string.IsNullOrEmpty(def.FilePath)) continue;
                if (TileExtractor.ModelsToIgnore.Contains(def.FilePath)) continue;

                // Calculate and store the models' transform matrices
                Matrix scaleMatrix;
                Matrix.CreateScale(def.Scale, out scaleMatrix);

                Matrix rotMatrix;
                Matrix.CreateFromQuaternion(ref def.Rotation, out rotMatrix);

                Matrix modelToWMO;
                Matrix.Multiply(ref scaleMatrix, ref rotMatrix, out modelToWMO);

                Matrix wmoToModel;
                Matrix.Invert(ref modelToWMO, out wmoToModel);
                def.ModelToWMO = modelToWMO;
                def.WMOToModel = wmoToModel;

                M2Model model;
                if (!LoadedM2Models.TryGetValue(def.FilePath, out model))
                {
                    log.Error(String.Format("M2Model file: {0} missing from the Dictionary!", def.FilePath));
                    continue;
                }

                // Calculate the wmoSpace bounding box for this model
                CalculateModelsWMOSpaceBounds(def, model);
            }
        }
コード例 #21
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
        static void ReadMOTV2(BinaryReader br, WMOGroup group, uint size)
        {
            // Texture coordinates, 2 floats per vertex in (X,Y) order. The values range from 0.0 to 1.0.
            // Vertices, normals and texture coordinates are in corresponding order, of course.
            group.TextureVertices2 = new Vector2[size / 8];

            for (int i = 0; i < group.TextureVertices2.Length; i++)
            {
                group.TextureVertices2[i] = br.ReadVector2();
            }
        }
コード例 #22
0
        private static void WriteGroupDoodadRefs(BinaryWriter writer, WMORoot root, WMOGroup group)
        {
            if (group.DoodadReferences.IsNullOrEmpty())
            {
                writer.Write(0);
                return;
            }

            var list = new List<int>();
            foreach (var defId in group.DoodadReferences)
            {
                var def = root.DoodadDefinitions[defId];
                if (def == null) continue;
                if (TileExtractor.ModelsToIgnore.Contains(def.FilePath)) continue;

                list.Add(defId);
            }

            writer.Write(list);
        }
コード例 #23
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
        /// <summary>
        /// Reads the WMO Vertex Index List
        /// </summary>
        /// <param name="br"></param>
        /// <param name="group"></param>
        static void ReadMOVI(BinaryReader br, WMOGroup group)
        {
            //group.Triangles = new ushort[group.TriangleCount * 3];
            for (uint i = 0; i < group.TriangleCount; i++)
            {
                var one = br.ReadInt16();
                var two = br.ReadInt16();
                var three = br.ReadInt16();

                var ind = new Index3 {Index0 = three, Index1 = two, Index2 = one};
                //var ind = new Index3 { Index0 = one, Index1 = two, Index2 = three };
                group.Indices.Add(ind);
            }
        }
コード例 #24
0
ファイル: WMO.cs プロジェクト: WCell/WCell-Terrain
 public void AddWMOGroup(WMOGroup wmoGroup)
 {
     _wmoGroups.Add(wmoGroup);
 }
コード例 #25
0
ファイル: WMOGroupParser.cs プロジェクト: WCell/WCell-Terrain
        static void ReadMOBA(BinaryReader br, WMOGroup group, uint size)
        {
            // Render batches. Records of 24 bytes.
            group.Batches = new RenderBatch[size/24];

            for (int i = 0; i < group.Batches.Length; i++)
            {
                var batch = new RenderBatch
                                {
                                    BottomX = br.ReadInt16(),
                                    BottomY = br.ReadInt16(),
                                    BottomZ = br.ReadInt16(),
                                    TopX = br.ReadInt16(),
                                    TopY = br.ReadInt16(),
                                    TopZ = br.ReadInt16(),
                                    StartIndex = br.ReadInt32(),
                                    IndexCount = br.ReadUInt16(),
                                    VertexStart = br.ReadUInt16(),
                                    VertexEnd = br.ReadUInt16(),
                                    Byte_13 = br.ReadByte(),
                                    TextureIndex = br.ReadByte()
                                };

                group.Batches[i] = batch;
            }
        }