Exemple #1
0
        private void SaveAlpha(BinaryWriter writer, int basePosition, ref Mcnk header)
        {
            header.Mcal = (int) writer.BaseStream.Position - basePosition;
            writer.Write(0x4D43414C);
            var sizePos = writer.BaseStream.Position;
            writer.Write(0);
            if(mLayers.Length == 0)
            {
                header.SizeAlpha = 8;
                return;
            }

            var curPos = 0;
            mLayers[0].Flags &= ~0x300u;
            mLayers[0].OfsMcal = 0;
            for(var i = 1; i < mLayers.Length; ++i)
            {
                bool compressed;
                var data = GetSavedAlphaForLayer(i, out compressed);
                mLayers[i].OfsMcal = curPos;
                if (compressed)
                    mLayers[i].Flags |= 0x300;
                else
                {
                    mLayers[i].Flags |= 0x100;
                    mLayers[i].Flags &= ~0x200u;
                }
                writer.Write(data);
                curPos += data.Length;
            }

            var endPos = writer.BaseStream.Position;
            writer.BaseStream.Position = sizePos;
            writer.Write((int) (endPos - sizePos - 4));
            writer.BaseStream.Position = endPos;

            header.SizeAlpha = curPos + 8;
        }
Exemple #2
0
        private void SaveUnusedChunks(BinaryWriter writer, int basePosition, ref Mcnk header)
        {
            int unusedSize;
            SaveUnusedChunk(writer, 0x4D435246, basePosition, out header.Mcrf, out unusedSize);
            SaveUnusedChunk(writer, 0x4D435348, basePosition, out header.Mcsh, out unusedSize);
            SaveUnusedChunk(writer, 0x4D435345, basePosition, out header.Mcse, out unusedSize);
            SaveUnusedChunk(writer, 0x4D434C51, basePosition, out header.Mclq, out unusedSize);
            SaveUnusedChunk(writer, 0x4D434C56, basePosition, out header.Mclv, out unusedSize);

            //header.NumSoundEmitters /= 0x1C;
        }
Exemple #3
0
        private void SaveLayers(BinaryWriter writer, int basePosition, ref Mcnk header)
        {
            header.NumLayers = mLayers.Length;
            if(header.NumLayers == 0)
            {
                header.Mcly = 0;
                return;
            }

            header.Mcly = (int) writer.BaseStream.Position - basePosition;
            writer.Write(0x4D434C59);
            writer.Write(mLayers.Length * SizeCache<Mcly>.Size);
            writer.WriteArray(mLayers);
        }
Exemple #4
0
        private void SaveMccv(BinaryWriter writer, int basePosition, ref Mcnk header)
        {
            if (HasMccv == false)
            {
                header.Mccv = 0;
                header.Flags &= ~0x40u;
                return;
            }

            header.Flags |= 0x40;

            var colors = mShadingFloats.Select(v =>
            {
                uint b = (byte)Math.Max(Math.Min((v.Z / 2.0f) * 255.0f, 255), 0);
                uint g = (byte)Math.Max(Math.Min((v.Y / 2.0f) * 255.0f, 255), 0);
                uint r = (byte)Math.Max(Math.Min((v.X / 2.0f) * 255.0f, 255), 0);
                return 0x7F000000 | (b << 16) | (g << 8) | r;
            }).ToArray();

            header.Mccv = (int)writer.BaseStream.Position - basePosition;
            writer.Write(0x4D434356);
            writer.Write(145 * 4);
            writer.WriteArray(colors.ToArray());
        }
Exemple #5
0
        private void SaveNormals(BinaryWriter writer, int basePosition, ref Mcnk header)
        {
            header.Mcnr = (int)writer.BaseStream.Position - basePosition;

            var normals =
                Vertices.SelectMany(v => new[] { (sbyte)(v.Normal.X * -127.0f), (sbyte)(v.Normal.Y * -127.0f), (sbyte)(v.Normal.Z * 127.0f) });

            writer.Write(0x4D434E52);
            writer.Write(145 * 3);
            writer.WriteArray(normals.ToArray());
            writer.Write(mNormalExtra);
        }
Exemple #6
0
 private void SaveHeights(BinaryWriter writer, int basePosition, ref Mcnk header)
 {
     header.Mcvt = (int) writer.BaseStream.Position - basePosition;
     var minPos = Vertices.Min(v => v.Position.Z);
     header.Position.Z = minPos;
     var heights = Vertices.Select(v => v.Position.Z - minPos);
     writer.Write(0x4D435654);
     writer.Write(145 * 4);
     writer.WriteArray(heights.ToArray());
 }
Exemple #7
0
        public bool AsyncLoad(BinaryReader reader, ChunkInfo chunkInfo)
        {
            // chunkInfo.Offset points to right after the MCNK signature, the offsets in the header are relative to the signature tho
            var basePosition = chunkInfo.Offset - 4;
            reader.BaseStream.Position = chunkInfo.Offset;
            reader.ReadInt32();
            mHeader = reader.Read<Mcnk>();
            reader.BaseStream.Position = basePosition + mHeader.Mcvt;
            var signature = reader.ReadUInt32();
            reader.ReadInt32();
            if (signature != 0x4D435654)
            {
                Log.Error("Chunk is missing valid MCVT sub chunk");
                return false;
            }

            LoadMcvt(reader);

            reader.BaseStream.Position = basePosition + mHeader.Mcnr;
            signature = reader.ReadUInt32();
            reader.ReadInt32();

            if (signature != 0x4D434E52)
            {
                Log.Error("Chunk is missing valid MCNR sub chunk");
                return false;
            }

            LoadMcnr(reader);

            if(mHeader.Mcrf > 0)
            {
                reader.BaseStream.Position = basePosition + mHeader.Mcrf;
                signature = reader.ReadUInt32();
                var chunkSize = reader.ReadInt32();
                if (signature == 0x4D435246)
                    LoadReferences(reader, chunkSize);
            }

            var hasMccv = false;
            if (mHeader.Mccv != 0)
            {
                reader.BaseStream.Position = basePosition + mHeader.Mccv;
                signature = reader.ReadUInt32();
                reader.ReadInt32();
                if (signature == 0x4D434356)
                {
                    LoadMccv(reader);
                    hasMccv = true;
                    HasMccv = true;
                }
            }

            reader.BaseStream.Position = basePosition + mHeader.Mcly;
            signature = reader.ReadUInt32();
            var size = reader.ReadInt32();

            if (signature != 0x4D434C59)
                return false;

            LoadLayers(reader, size);

            if (mHeader.SizeAlpha > 8)
            {
                reader.BaseStream.Position = basePosition + mHeader.Mcal;
                signature = reader.ReadUInt32();
                if (signature == 0x4D43414C)
                {
                    reader.ReadInt32();
                    mAlphaCompressed = reader.ReadBytes(mHeader.SizeAlpha - 8);
                }
            }

            InitLayerData();

            if(mHeader.SizeShadow > 8 && mHeader.Mcsh > 0)
            {
                reader.BaseStream.Position = basePosition + mHeader.Mcsh + 8;
                var curPtr = 0;
                for (var i = 0; i < 64; ++i)
                {
                    for (var j = 0; j < 8; ++j)
                    {
                        byte mask = reader.ReadByte();
                        for (var k = 0; k < 8; ++k)
                        {
                            AlphaValues[curPtr] &= 0xFFFFFF00;
                            AlphaValues[curPtr++] |= ((mask & (1 << k)) == 0) ? (byte)0xFF : (byte)0xCC;
                        }
                    }
                }
            }

            if(mHeader.Mclv > 0)
            {
                reader.BaseStream.Position = basePosition + mHeader.Mclv + 8;
                var colors = reader.ReadArray<uint>(145);
                for (var i = 0; i < 145; ++i)
                    Vertices[i].AdditiveColor = colors[i];
            }

            LoadHoles();

            if (hasMccv == false)
            {
                for (var i = 0; i < 145; ++i)
                    Vertices[i].Color = 0x7F7F7F7F;
            }

            if (mHeader.Mcrf > 0)
                LoadUnusedChunk(0x4D435246, basePosition + mHeader.Mcrf, (mHeader.NumDoodadRefs + mHeader.NumMapObjRefs) * 4, reader);
            if (mHeader.SizeShadow > 0)
                LoadUnusedChunk(0x4D435348, basePosition + mHeader.Mcsh, mHeader.SizeShadow, reader);
            if (mHeader.NumSoundEmitters > 0)
                LoadUnusedChunk(0x4D435345, basePosition + mHeader.Mcse, mHeader.NumSoundEmitters * 0x1C, reader);
            if (mHeader.SizeLiquid > 8)
                LoadUnusedChunk(0x4D434C51, basePosition + mHeader.Mclq, mHeader.SizeLiquid - 8, reader);

            if (mHeader.Mclv > 0)
                LoadUnusedChunk(0x4D434C56, basePosition + mHeader.Mclv, 0, reader);


            WorldFrame.Instance.MapManager.OnLoadProgress();

            return true;
        }