예제 #1
0
        //TODO
        //public Boolean HasTangents;

        //TODO:
        //Fix missed vertexes on some meshes. (on lod's & sometimes the main model)
        public VVDFile(Stream FileInput, MDLFile mdl)
        {
            using (uReader FileStream = new uReader(FileInput))
            {
                FileStream.ReadTypeFixed(ref VVD_Header, 64);

                if (VVD_Header.checksum != mdl.MDL_Header.checksum)
                {
                    throw new FileLoadException(String.Format("{0}: Does not match the checksum in the .mdl", mdl.MDL_Header.Name));
                }

                if (VVD_Header.numFixups > 0)
                {
                    VVD_Fixups = new vertexFileFixup_t[VVD_Header.numFixups];
                    FileStream.ReadArrayFixed(ref VVD_Fixups, 12, VVD_Header.fixupTableStart);
                }

                //TODO
                //HasTangents = VVD_Header.tangentDataStart != 0;

                //"HasTagents" used to avoid non-zero length
                //Int64 TotalVerts = (HasTangents ? VVD_Header.tangentDataStart - VVD_Header.vertexDataStart : FileStream.InputStream.Length - VVD_Header.vertexDataStart) / 48;
                mstudiovertex_t[] tempVerts = new mstudiovertex_t[VVD_Header.numLODVertexes[0]];
                FileStream.ReadArrayFixed(ref tempVerts, 48, VVD_Header.vertexDataStart);

                VVD_Vertexes = new mstudiovertex_t[VVD_Header.numLODs][];
                List <mstudiovertex_t> TempVerts = new List <mstudiovertex_t>();

                for (Int32 LODID = 0; LODID < VVD_Header.numLODs; ++LODID)
                {
                    if (VVD_Header.numFixups == 0)
                    {
                        VVD_Vertexes[LODID] = tempVerts.Take(VVD_Header.numLODVertexes[LODID]).ToArray();
                        continue;
                    }

                    TempVerts.Clear();

                    for (Int32 FixupID = 0; FixupID < VVD_Fixups.Length; FixupID++)
                    {
                        if (VVD_Fixups[FixupID].lod >= LODID)
                        {
                            TempVerts.AddRange(tempVerts.Skip(VVD_Fixups[FixupID].sourceVertexID).Take(VVD_Fixups[FixupID].numVertexes));
                        }
                    }

                    VVD_Vertexes[LODID] = TempVerts.ToArray();
                }
            }
        }
예제 #2
0
        public MDLFile(Stream FileInput, Boolean parseAnims = false, Boolean parseHitboxes = false)
        {
            using (uReader FileStream = new uReader(FileInput))
            {
                FileStream.ReadTypeFixed(ref MDL_Header, 392);

                if (MDL_Header.id != 0x54534449)
                {
                    throw new FileLoadException("File signature does not match 'IDST'");
                }

                //Bones
                #region Bones
                //Bones
                MDL_StudioBones = new mstudiobone_t[MDL_Header.bone_count];
                MDL_BoneNames   = new String[MDL_Header.bone_count];
                for (Int32 BoneID = 0; BoneID < MDL_Header.bone_count; BoneID++)
                {
                    Int32 boneOffset = MDL_Header.bone_offset + (216 * BoneID);
                    FileStream.ReadTypeFixed(ref MDL_StudioBones[BoneID], 216, boneOffset);
                    MDL_BoneNames[BoneID] = FileStream.ReadNullTerminatedString(boneOffset + MDL_StudioBones[BoneID].sznameindex);
                }
                //Bones
                #endregion

                #region Hitboxes
                if (parseHitboxes)
                {
                    MDL_Hitboxsets = new mstudiohitboxset_t[MDL_Header.hitbox_count];
                    Hitboxes       = new Hitbox[MDL_Header.hitbox_count][];
                    for (Int32 HitboxsetID = 0; HitboxsetID < MDL_Header.hitbox_count; HitboxsetID++)
                    {
                        Int32 HitboxsetOffset = MDL_Header.hitbox_offset + (12 * HitboxsetID);
                        FileStream.ReadTypeFixed(ref MDL_Hitboxsets[HitboxsetID], 12, HitboxsetOffset);
                        Hitboxes[HitboxsetID] = new Hitbox[MDL_Hitboxsets[HitboxsetID].numhitboxes];

                        for (Int32 HitboxID = 0; HitboxID < MDL_Hitboxsets[HitboxsetID].numhitboxes; HitboxID++)
                        {
                            Int32 HitboxOffset = HitboxsetOffset + (68 * HitboxID) + MDL_Hitboxsets[HitboxsetID].hitboxindex;
                            Hitboxes[HitboxsetID][HitboxID].BBox = new mstudiobbox_t();

                            FileStream.ReadTypeFixed(ref Hitboxes[HitboxsetID][HitboxID].BBox, 68, HitboxOffset);
                        }
                    }
                }
                #endregion

                #region Animations
                if (parseAnims)
                {
                    try
                    {
                        //Animations
                        MDL_AniDescriptions = new mstudioanimdesc_t[MDL_Header.localanim_count];
                        Animations          = new AniInfo[MDL_Header.localanim_count];

                        for (Int32 AnimID = 0; AnimID < MDL_Header.localanim_count; AnimID++)
                        {
                            Int32 AnimOffset = MDL_Header.localanim_offset + (100 * AnimID);
                            FileStream.ReadTypeFixed(ref MDL_AniDescriptions[AnimID], 100, AnimOffset);
                            mstudioanimdesc_t StudioAnim = MDL_AniDescriptions[AnimID];

                            String StudioAnimName = FileStream.ReadNullTerminatedString(AnimOffset + StudioAnim.sznameindex);
                            Animations[AnimID] = new AniInfo {
                                name = StudioAnimName, studioAnim = StudioAnim
                            };
                            Animations[AnimID].AnimationBones = new List <AnimationBone>();

                            //mstudioanim_t
                            FileStream.BaseStream.Position = AnimOffset;

                            Int64 StartOffset = FileStream.BaseStream.Position;

                            Int32 CurrentOffset = MDL_AniDescriptions[AnimID].animindex;
                            Int16 NextOffset;
                            do
                            {
                                FileStream.BaseStream.Position = StartOffset + CurrentOffset;
                                Byte BoneIndex = FileStream.ReadByte();
                                Byte BoneFlag  = FileStream.ReadByte();
                                NextOffset     = FileStream.ReadInt16();
                                CurrentOffset += NextOffset;

                                AnimationBone AnimatedBone = new AnimationBone(BoneIndex, BoneFlag, MDL_AniDescriptions[AnimID].numframes);
                                AnimatedBone.ReadData(FileStream);
                                Animations[AnimID].AnimationBones.Add(AnimatedBone);
                            } while (NextOffset != 0);
                            //mstudioanim_t

                            List <AnimationBone> AnimationBones = Animations[AnimID].AnimationBones;
                            Int32 NumBones  = MDL_Header.bone_count;
                            Int32 NumFrames = StudioAnim.numframes;

                            //Used to avoid "Assertion failed" key count in Unity (if frames less than 2)
                            Boolean FramesLess = NumFrames < 2;
                            if (FramesLess)
                            {
                                NumFrames += 1;
                            }

                            Animations[AnimID].PosX = new Keyframe[NumFrames][];
                            Animations[AnimID].PosY = new Keyframe[NumFrames][];
                            Animations[AnimID].PosZ = new Keyframe[NumFrames][];

                            Animations[AnimID].RotX = new Keyframe[NumFrames][];
                            Animations[AnimID].RotY = new Keyframe[NumFrames][];
                            Animations[AnimID].RotZ = new Keyframe[NumFrames][];
                            Animations[AnimID].RotW = new Keyframe[NumFrames][];
                            for (Int32 FrameID = 0; FrameID < NumFrames; FrameID++)
                            {
                                Animations[AnimID].PosX[FrameID] = new Keyframe[NumBones];
                                Animations[AnimID].PosY[FrameID] = new Keyframe[NumBones];
                                Animations[AnimID].PosZ[FrameID] = new Keyframe[NumBones];

                                Animations[AnimID].RotX[FrameID] = new Keyframe[NumBones];
                                Animations[AnimID].RotY[FrameID] = new Keyframe[NumBones];
                                Animations[AnimID].RotZ[FrameID] = new Keyframe[NumBones];
                                Animations[AnimID].RotW[FrameID] = new Keyframe[NumBones];
                            }

                            for (Int32 boneID = 0; boneID < NumBones; boneID++)
                            {
                                AnimationBone AnimBone = AnimationBones.FirstOrDefault(x => x.Bone == boneID);

                                //frameIndex < 30 && studioAnimName == "@ak47_reload"
                                for (Int32 frameID = 0; frameID < NumFrames; frameID++)
                                {
                                    //get current animation time (length) by divide frame index on "fps"
                                    Single time = frameID / StudioAnim.fps;

                                    mstudiobone_t StudioBone = MDL_StudioBones[boneID];
                                    //Transform bone = Bones[boneIndex];

                                    Vector3 Position = StudioBone.pos;
                                    Vector3 Rotation = StudioBone.rot;

                                    //BINGO! All animations are corrected :p
                                    if (AnimBone != null)
                                    {
                                        if ((AnimBone.Flags & STUDIO_ANIM_RAWROT) > 0)
                                        {
                                            Rotation = MathLibrary.ToEulerAngles(AnimBone.pQuat48);
                                        }

                                        if ((AnimBone.Flags & STUDIO_ANIM_RAWROT2) > 0)
                                        {
                                            Rotation = MathLibrary.ToEulerAngles(AnimBone.pQuat64);
                                        }

                                        if ((AnimBone.Flags & STUDIO_ANIM_RAWPOS) > 0)
                                        {
                                            Position = AnimBone.pVec48;
                                        }

                                        if ((AnimBone.Flags & STUDIO_ANIM_ANIMROT) > 0)
                                        {
                                            Rotation += AnimBone.FrameAngles[(FramesLess && frameID != 0) ? frameID - 1 : frameID].Multiply(StudioBone.rotscale);
                                        }

                                        if ((AnimBone.Flags & STUDIO_ANIM_ANIMPOS) > 0)
                                        {
                                            Position += AnimBone.FramePositions[(FramesLess && frameID != 0) ? frameID - 1 : frameID].Multiply(StudioBone.posscale);
                                        }

                                        if ((AnimBone.Flags & STUDIO_ANIM_DELTA) > 0)
                                        {
                                            Position = Vector3.zero;
                                            Rotation = Vector3.zero;
                                        }
                                    }

                                    //Invert right-handed position to left-handed
                                    if (StudioBone.parent == -1)
                                    {
                                        Position = MathLibrary.SwapY(Position);
                                    }
                                    else
                                    {
                                        Position.x = -Position.x;
                                    }

                                    //Corrects global scale and convert radians to degrees
                                    Position *= uLoader.UnitScale;
                                    Rotation *= Mathf.Rad2Deg;
                                    Quaternion quat;

                                    //Fix up bone rotations from right-handed to left-handed
                                    if (StudioBone.parent == -1)
                                    {
                                        quat = Quaternion.Euler(-90, 180, -90) * MathLibrary.AngleQuaternion(Rotation);
                                    }
                                    else
                                    {
                                        quat = MathLibrary.AngleQuaternion(Rotation);
                                    }

                                    Animations[AnimID].PosX[frameID][boneID] = new Keyframe(time, Position.x);
                                    Animations[AnimID].PosY[frameID][boneID] = new Keyframe(time, Position.y);
                                    Animations[AnimID].PosZ[frameID][boneID] = new Keyframe(time, Position.z);

                                    Animations[AnimID].RotX[frameID][boneID] = new Keyframe(time, quat.x);
                                    Animations[AnimID].RotY[frameID][boneID] = new Keyframe(time, quat.y);
                                    Animations[AnimID].RotZ[frameID][boneID] = new Keyframe(time, quat.z);
                                    Animations[AnimID].RotW[frameID][boneID] = new Keyframe(time, quat.w);
                                }
                            }
                        }
                        //Animations

                        //Sequences
                        MDL_SeqDescriptions = new mstudioseqdesc_t[MDL_Header.localseq_count];
                        Sequences           = new SeqInfo[MDL_Header.localseq_count];

                        for (Int32 seqID = 0; seqID < MDL_Header.localseq_count; seqID++)
                        {
                            Int32 sequenceOffset = MDL_Header.localseq_offset + (212 * seqID);
                            FileStream.ReadTypeFixed(ref MDL_SeqDescriptions[seqID], 212, sequenceOffset);
                            mstudioseqdesc_t Sequence = MDL_SeqDescriptions[seqID];
                            Sequences[seqID] = new SeqInfo {
                                name = FileStream.ReadNullTerminatedString(sequenceOffset + Sequence.szlabelindex), seq = Sequence
                            };

                            FileStream.BaseStream.Position = sequenceOffset + Sequence.animindexindex;

                            var animID = FileStream.ReadShortArray(Sequence.groupsize[0] * Sequence.groupsize[1]);
                            //Debug.LogWarning(animIndices[0]);
                            // Just use the first animation for now
                            Sequences[seqID].ani = Animations[animID[0]];
                        }
                        //Sequences
                    }
                    catch (Exception ex)
                    {
                        Debug.LogError(String.Format("\"{0}\" Parse animation failed: {1}", MDL_Header.Name, ex));
                    }
                }
                #endregion

                #region Materials
                //Materials
                MDL_TexturesInfo = new mstudiotexture_t[MDL_Header.texture_count];
                MDL_Textures     = new String[MDL_Header.texture_count];
                for (Int32 TexID = 0; TexID < MDL_Header.texture_count; TexID++)
                {
                    Int32 TextureOffset = MDL_Header.texture_offset + (64 * TexID);
                    FileStream.ReadTypeFixed(ref MDL_TexturesInfo[TexID], 64, TextureOffset);
                    MDL_Textures[TexID] = FileStream.ReadNullTerminatedString(TextureOffset + MDL_TexturesInfo[TexID].sznameindex);
                }

                Int32[] TDirOffsets = new Int32[MDL_Header.texturedir_count];
                MDL_TDirectories = new String[MDL_Header.texturedir_count];
                for (Int32 DirID = 0; DirID < MDL_Header.texturedir_count; DirID++)
                {
                    FileStream.ReadTypeFixed(ref TDirOffsets[DirID], 4, MDL_Header.texturedir_offset + (4 * DirID));
                    MDL_TDirectories[DirID] = FileStream.ReadNullTerminatedString(TDirOffsets[DirID]);
                }
                //Materials
                #endregion

                #region BodyParts
                //Bodyparts
                MDL_Bodyparts = new StudioBodyPart[MDL_Header.bodypart_count];
                for (Int32 BodypartID = 0; BodypartID < MDL_Header.bodypart_count; BodypartID++)
                {
                    mstudiobodyparts_t BodyPart = new mstudiobodyparts_t();
                    Int32 BodyPartOffset        = MDL_Header.bodypart_offset + (16 * BodypartID);
                    FileStream.ReadTypeFixed(ref BodyPart, 16, BodyPartOffset);

                    if (BodyPart.sznameindex != 0)
                    {
                        MDL_Bodyparts[BodypartID].Name = FileStream.ReadNullTerminatedString(BodyPartOffset + BodyPart.sznameindex);
                    }
                    else
                    {
                        MDL_Bodyparts[BodypartID].Name = String.Empty;
                    }

                    MDL_Bodyparts[BodypartID].Models = new StudioModel[BodyPart.nummodels];

                    for (Int32 ModelID = 0; ModelID < BodyPart.nummodels; ModelID++)
                    {
                        mstudiomodel_t Model       = new mstudiomodel_t();
                        Int64          ModelOffset = BodyPartOffset + (148 * ModelID) + BodyPart.modelindex;
                        FileStream.ReadTypeFixed(ref Model, 148, ModelOffset);

                        MDL_Bodyparts[BodypartID].Models[ModelID].isBlank = (Model.numvertices <= 0 || Model.nummeshes <= 0);
                        MDL_Bodyparts[BodypartID].Models[ModelID].Model   = Model;

                        MDL_Bodyparts[BodypartID].Models[ModelID].Meshes = new mstudiomesh_t[Model.nummeshes];
                        for (Int32 MeshID = 0; MeshID < Model.nummeshes; MeshID++)
                        {
                            mstudiomesh_t Mesh       = new mstudiomesh_t();
                            Int64         MeshOffset = ModelOffset + (116 * MeshID) + Model.meshindex;
                            FileStream.ReadTypeFixed(ref Mesh, 116, MeshOffset);

                            MDL_Bodyparts[BodypartID].Models[ModelID].Meshes[MeshID] = Mesh;
                        }

                        MDL_Bodyparts[BodypartID].Models[ModelID].IndicesPerLod = new Dictionary <Int32, List <Int32> > [8];

                        for (Int32 i = 0; i < 8; i++)
                        {
                            MDL_Bodyparts[BodypartID].Models[ModelID].IndicesPerLod[i] = new Dictionary <Int32, List <Int32> >();
                        }

                        MDL_Bodyparts[BodypartID].Models[ModelID].VerticesPerLod = new mstudiovertex_t[8][];
                    }
                }
                //BodyParts
                #endregion
            }
        }
예제 #3
0
        //http://wiki.xentax.com/index.php/Source_VTF
        /// <summary>
        /// Parser VTF format
        /// <br>Supported versions: 7.1 - 7.5 (maybe 7.0)</br>
        /// </summary>
        /// <param name="stream">Stream of input file</param>
        /// <param name="FileName">Name of input file (optional)</param>
        public VTFFile(Stream stream, String FileName = "")
        {
            using (uReader FileStream = new uReader(stream))
            {
                String TempHeader = FileStream.ReadFixedLengthString(Encoding.ASCII, 4);
                if (TempHeader != VTFHeader)
                {
                    throw new Exception("Invalid VTF header. Expected '" + VTFHeader + "', got '" + TempHeader + "'.");
                }

                Header = new VTFHeader();

                UInt32  VersionMajor = FileStream.ReadUInt32();
                UInt32  VersionMinor = FileStream.ReadUInt32();
                Decimal Version      = VersionMajor + (VersionMinor / 10m); // e.g. 7.3
                Header.Version = Version;

                UInt32 headerSize = FileStream.ReadUInt32();
                Width  = FileStream.ReadUInt16();
                Height = FileStream.ReadUInt16();

                Header.Flags = (VTFImageFlag)FileStream.ReadUInt32();

                UInt16 NumFrames  = FileStream.ReadUInt16();
                UInt16 FirstFrame = FileStream.ReadUInt16();

                FileStream.ReadBytes(4); // padding

                Header.Reflectivity = FileStream.ReadVector3D(false);

                FileStream.ReadBytes(4); // padding

                Header.BumpmapScale = FileStream.ReadSingle();

                VTFImageFormat HighResImageFormat = (VTFImageFormat)FileStream.ReadUInt32();
                Byte           MipmapCount        = FileStream.ReadByte();
                VTFImageFormat LowResImageFormat  = (VTFImageFormat)FileStream.ReadUInt32();
                Byte           LowResWidth        = FileStream.ReadByte();
                Byte           LowResHeight       = FileStream.ReadByte();

                UInt16 Depth        = 1;
                UInt32 NumResources = 0;

                if (Version >= 7.2m)
                {
                    Depth = FileStream.ReadUInt16();
                }
                if (Version >= 7.3m)
                {
                    FileStream.ReadBytes(3);
                    NumResources = FileStream.ReadUInt32();
                    FileStream.ReadBytes(8);
                }

                Int32 NumFaces = 1;
                if (Header.Flags.HasFlag(VTFImageFlag.TEXTUREFLAGS_ENVMAP))
                {
                    NumFaces = Version < 7.5m && FirstFrame != 0xFFFF ? 7 : 6;
                }

                VTFImageFormatInfo HighResFormatInfo = VTFImageFormatInfo.FromFormat(HighResImageFormat);
                VTFImageFormatInfo LowResFormatInfo  = VTFImageFormatInfo.FromFormat(LowResImageFormat);

                Int32 ThumbnailSize = LowResImageFormat == VTFImageFormat.IMAGE_FORMAT_NONE ? 0 : LowResFormatInfo.GetSize(LowResWidth, LowResHeight);

                UInt32 ThumbnailOffset = headerSize;
                Int64  DataOffset      = headerSize + ThumbnailSize;

                Resources = new VTFResource[NumResources];
                for (Int32 i = 0; i < NumResources; i++)
                {
                    VTFResourceType type     = (VTFResourceType)FileStream.ReadUInt32();
                    UInt32          DataSize = FileStream.ReadUInt32();
                    switch (type)
                    {
                    case VTFResourceType.LowResImage:
                        // Low res image
                        ThumbnailOffset = DataSize;
                        break;

                    case VTFResourceType.Image:
                        // Regular image
                        DataOffset = DataSize;
                        break;

                    case VTFResourceType.Sheet:
                    case VTFResourceType.CRC:
                    case VTFResourceType.TextureLodSettings:
                    case VTFResourceType.TextureSettingsEx:
                    case VTFResourceType.KeyValueData:
                        // todo
                        Resources[i] = new VTFResource
                        {
                            Type = type,
                            Data = DataSize
                        };
                        break;

                    default:
                        throw new ArgumentOutOfRangeException(nameof(type), (uint)type, "Unknown resource type");
                    }
                }

                if (LowResImageFormat != VTFImageFormat.IMAGE_FORMAT_NONE)
                {
                    FileStream.BaseStream.Position = ThumbnailOffset;
                    Int32 thumbSize = LowResFormatInfo.GetSize(LowResWidth, LowResHeight);
                    LowResImage = new VTFImage
                    {
                        Format = LowResImageFormat,
                        Width  = LowResWidth,
                        Height = LowResHeight,
                        Data   = FileStream.ReadBytes(thumbSize)
                    };
                }

                Boolean ConvertToBGRA32 = true;
                Boolean hasAlpha        = true;
                switch (HighResImageFormat)
                {
                //Unity support this formats natively
                case VTFImageFormat.IMAGE_FORMAT_A8:
                case VTFImageFormat.IMAGE_FORMAT_ABGR8888:
                case VTFImageFormat.IMAGE_FORMAT_ARGB8888:
                case VTFImageFormat.IMAGE_FORMAT_BGRA4444:
                case VTFImageFormat.IMAGE_FORMAT_DXT1_ONEBITALPHA:
                case VTFImageFormat.IMAGE_FORMAT_DXT3:
                case VTFImageFormat.IMAGE_FORMAT_DXT5:
                case VTFImageFormat.IMAGE_FORMAT_RGBA8888:
                case VTFImageFormat.IMAGE_FORMAT_BGRA8888:
                case VTFImageFormat.IMAGE_FORMAT_BGRX8888:
                case VTFImageFormat.IMAGE_FORMAT_RGBA16161616F:
                case VTFImageFormat.IMAGE_FORMAT_RGBA16161616:
                    ConvertToBGRA32 = false;
                    break;

                case VTFImageFormat.IMAGE_FORMAT_BGR565:
                case VTFImageFormat.IMAGE_FORMAT_RGB565:
                case VTFImageFormat.IMAGE_FORMAT_DXT1:
                case VTFImageFormat.IMAGE_FORMAT_RGB888:
                    hasAlpha        = false;
                    ConvertToBGRA32 = false;
                    break;
                }

                FileStream.BaseStream.Position = DataOffset;
                Frames = new Texture2D[NumFrames, NumFaces];
                List <Byte>[] FramesData = new List <Byte> [NumFrames];
                for (Int32 MipLevel = MipmapCount - 1; MipLevel >= 0; MipLevel--)
                {
                    for (Int32 FrameID = 0; FrameID < NumFrames; FrameID++)
                    {
                        if (FramesData[FrameID] == null)
                        {
                            FramesData[FrameID] = new List <Byte>();
                        }

                        for (Int32 FaceID = 0; FaceID < NumFaces; FaceID++)
                        {
                            for (Int32 SliceID = 0; SliceID < Depth; SliceID++)
                            {
                                Int32 Wid      = GetMipSize(Width, MipLevel);
                                Int32 Hei      = GetMipSize(Height, MipLevel);
                                Int32 DataSize = HighResFormatInfo.GetSize(Wid, Hei);

                                if (ConvertToBGRA32)
                                {
                                    FramesData[FrameID].InsertRange(0, VTFImageFormatInfo.FromFormat(HighResImageFormat).ConvertToBgra32(FileStream.ReadBytes(DataSize), Wid, Hei));
                                }
                                else
                                {
                                    FramesData[FrameID].InsertRange(0, FileStream.ReadBytes(DataSize));
                                }
                            }
                        }
                    }
                }

                TextureFormat InternalFormat = TextureFormat.BGRA32;
                Boolean       needCompress   = false;
                switch (HighResImageFormat)
                {
                case VTFImageFormat.IMAGE_FORMAT_A8:
                    InternalFormat = TextureFormat.Alpha8;
                    break;

                case VTFImageFormat.IMAGE_FORMAT_ABGR8888:
                case VTFImageFormat.IMAGE_FORMAT_ARGB8888:
                    InternalFormat = TextureFormat.ARGB32;
                    break;

                case VTFImageFormat.IMAGE_FORMAT_BGR565:
                case VTFImageFormat.IMAGE_FORMAT_RGB565:
                    InternalFormat = TextureFormat.RGB565;
                    break;

                case VTFImageFormat.IMAGE_FORMAT_BGRA4444:
                    InternalFormat = TextureFormat.RGBA4444;
                    break;

                case VTFImageFormat.IMAGE_FORMAT_DXT1:
                case VTFImageFormat.IMAGE_FORMAT_DXT1_ONEBITALPHA:
                    InternalFormat = TextureFormat.DXT1;
                    break;

                case VTFImageFormat.IMAGE_FORMAT_DXT3:
                case VTFImageFormat.IMAGE_FORMAT_DXT5:
                    InternalFormat = TextureFormat.DXT5;
                    break;

                case VTFImageFormat.IMAGE_FORMAT_RGB888:
                    InternalFormat = TextureFormat.RGB24;
                    break;

                case VTFImageFormat.IMAGE_FORMAT_RGBA8888:
                    InternalFormat = TextureFormat.RGBA32;
                    break;

                case VTFImageFormat.IMAGE_FORMAT_RGBA16161616F:
                case VTFImageFormat.IMAGE_FORMAT_RGBA16161616:
                    InternalFormat = TextureFormat.RGBAHalf;
                    break;

                default:
                    //needCompress = true;
                    break;
                }

                Boolean mipmaps = MipmapCount > 1;
                for (Int32 FrameID = 0; FrameID < NumFrames; FrameID++)
                {
                    for (Int32 FaceID = 0; FaceID < NumFaces; FaceID++)
                    {
                        Frames[FrameID, FaceID]      = new Texture2D(Width, Height, InternalFormat, mipmaps);
                        Frames[FrameID, FaceID].name = FileName;
                        Frames[FrameID, FaceID].alphaIsTransparency = hasAlpha;
                        Frames[FrameID, FaceID].LoadRawTextureData(FramesData[FrameID].ToArray());
                        Frames[FrameID, FaceID].Apply();

                        if (needCompress)
                        {
                            Frames[FrameID, FaceID].Compress(false);
                            Debug.LogWarning(FileName + " compressed!");
                        }
                    }
                }
            }
        }
예제 #4
0
        public VTXFile(Stream FileInput, MDLFile StudioMDL, VVDFile StudioVVD)
        {
            using (uReader FileStream = new uReader(FileInput))
            {
                studiohdr_t MDL_Header = StudioMDL.MDL_Header;
                FileStream.ReadTypeFixed(ref VTX_Header, 36);

                if (VTX_Header.checkSum != MDL_Header.checksum)
                {
                    throw new FileLoadException(String.Format("{0}: Does not match the checksum in the .mdl", MDL_Header.Name));
                }

                #region BodyParts
                Int32[] VertexLODOffsets = new Int32[8];
                for (Int32 BodypartID = 0; BodypartID < MDL_Header.bodypart_count; BodypartID++)
                {
                    BodyPartHeader_t BodyPart       = new BodyPartHeader_t();
                    Int64            BodyPartOffset = VTX_Header.bodyPartOffset + (8 * BodypartID);
                    FileStream.ReadTypeFixed(ref BodyPart, 8, BodyPartOffset);

                    StudioBodyPart StudioBodyPart = StudioMDL.MDL_Bodyparts[BodypartID];

                    #region Models
                    for (Int32 ModelID = 0; ModelID < BodyPart.numModels; ModelID++)
                    {
                        StudioModel StudioModel = StudioBodyPart.Models[ModelID];

                        if (StudioModel.isBlank)
                        {
                            Debug.Log(String.Format("Model ID - {0} in bodypart \"{1}\" is blank, skip", ModelID, StudioBodyPart.Name));
                            continue;
                        }

                        ModelHeader_t Model       = new ModelHeader_t();
                        Int64         ModelOffset = BodyPartOffset + (8 * ModelID) + BodyPart.modelOffset;
                        FileStream.ReadTypeFixed(ref Model, 8, ModelOffset);

                        StudioBodyPart.Models[ModelID].NumLODs = Model.numLODs;
                        StudioBodyPart.Models[ModelID].LODData = new ModelLODHeader_t[Model.numLODs];

                        #region LOD's
                        //TODO: Strip unused vertexes on lower lod's ("first" lod is fine)
                        for (Int32 LODID = 0; LODID < Model.numLODs; LODID++)
                        {
                            ModelLODHeader_t LOD       = new ModelLODHeader_t();
                            Int64            LODOffset = ModelOffset + (12 * LODID) + Model.lodOffset;
                            FileStream.ReadTypeFixed(ref LOD, 12, LODOffset);

                            StudioBodyPart.Models[ModelID].LODData[LODID] = LOD;

                            #region Mesh LOD
                            //Temp remember verts count per lod model
                            Int32 VertexOffset = 0;
                            //List<mstudiovertex_t> VertexesPerLod = new List<mstudiovertex_t>();
                            for (Int32 MeshID = 0; MeshID < StudioModel.Model.nummeshes; MeshID++)
                            {
                                mstudiomesh_t StudioMesh = StudioBodyPart.Models[ModelID].Meshes[MeshID];

                                //TODO: StudioModel.Meshes[MeshID].VertexData.numlodvertices[LODID]; - we no longer need this??
                                VertexOffset += StudioMesh.numvertices;
                                List <Int32> IndicesPerMesh = new List <Int32>();

                                MeshHeader_t Mesh       = new MeshHeader_t();
                                Int64        MeshOffset = LODOffset + (9 * MeshID) + LOD.meshOffset;
                                FileStream.ReadTypeFixed(ref Mesh, 9, MeshOffset);

                                #region StripGroups
                                for (Int32 StripGroupID = 0; StripGroupID < Mesh.numStripGroups; StripGroupID++)
                                {
                                    StripGroupHeader_t StripGroup = new StripGroupHeader_t();
                                    Int64 StripGroupOffset        = MeshOffset + (25 * StripGroupID) + Mesh.stripGroupHeaderOffset;
                                    FileStream.ReadTypeFixed(ref StripGroup, 25, StripGroupOffset);

                                    Vertex_t[] Vertexes = new Vertex_t[StripGroup.numVerts];
                                    FileStream.BaseStream.Position = StripGroupOffset + StripGroup.vertOffset;
                                    FileStream.ReadArrayFixed(ref Vertexes, 9);

                                    FileStream.BaseStream.Position = StripGroupOffset + StripGroup.indexOffset;
                                    Int16[] Indices = FileStream.ReadShortArray(StripGroup.numIndices);

                                    #region Strips
                                    for (Int32 StripID = 0; StripID < StripGroup.numStrips; StripID++)
                                    {
                                        StripHeader_t VTXStrip       = new StripHeader_t();
                                        Int64         VTXStripOffset = StripGroupOffset + (27 * StripID) + StripGroup.stripOffset;
                                        FileStream.ReadTypeFixed(ref VTXStrip, 27, VTXStripOffset);

                                        //TODO:
                                        //Strip / "Split" vertexes
                                        //Pseudo code:

                                        /*for (Int32 VertID = 0; VertID < maxVertsPerLod; VertID++)
                                         * {
                                         *      Int32 Index = MeshID * VTXStrip.numVerts + VertID;
                                         *
                                         *      if (Index < numStripVerts)
                                         *      {
                                         *              splitVerts.Add(verts[Index]);
                                         *              splitIndices.Add(j);
                                         *      }
                                         * }*/

                                        //Hmmmmm... Well, it's looks what we want.... but still doesn't perfect (for lod's mesh)

                                        /*Int32 NumVerts = VTXStrip.indexOffset + VTXStrip.numVerts;
                                         * for (Int32 VertID = VTXStrip.indexOffset; VertID < NumVerts; VertID++)
                                         * {
                                         *      Int32 Index0 = VertID + StudioMesh.vertexoffset + VertexLODOffsets[LODID];
                                         *      VertexesPerLod.Add(StudioVVD.tempVerts[Index0]);
                                         * }*/

                                        if ((VTXStrip.flags & VTXStripGroupTriStripFlag) > 0)
                                        {
                                            for (Int32 TempIdx = VTXStrip.indexOffset; TempIdx < VTXStrip.indexOffset + VTXStrip.numIndices - 2; TempIdx++)
                                            {
                                                Int32[] add = TempIdx % 2 == 1 ?
                                                              new[] { TempIdx + 1, TempIdx, TempIdx + 2 } :
                                                new[] { TempIdx, TempIdx + 1, TempIdx + 2 };

                                                foreach (Int32 Index in add)
                                                {
                                                    IndicesPerMesh.Add(Vertexes[Indices[Index]].origMeshVertId + StudioMesh.vertexoffset);
                                                }
                                            }
                                        }
                                        else
                                        {
                                            for (Int32 Index = VTXStrip.indexOffset; Index < VTXStrip.indexOffset + VTXStrip.numIndices; Index++)
                                            {
                                                IndicesPerMesh.Add(Vertexes[Indices[Index]].origMeshVertId + StudioMesh.vertexoffset);
                                            }
                                        }
                                    }
                                    #endregion
                                }
                                #endregion

                                StudioMDL.SetIndices(BodypartID, ModelID, LODID, MeshID, IndicesPerMesh);
                            }
                            #endregion

                            //StudioMDL.MDL_Bodyparts[BodypartID].Models[ModelID].VerticesPerLod[LODID] = VertexesPerLod.ToArray();
                            ///TODO: Strip unused vertexes in <seealso cref="VVDFile.VVD_Vertexes"/> per lod
                            StudioMDL.SetVertices(BodypartID, ModelID, LODID, VertexOffset, VertexLODOffsets[LODID], StudioVVD.VVD_Vertexes[0]);

                            VertexLODOffsets[LODID] += VertexOffset;
                        }
                        #endregion
                    }
                    #endregion
                }
                #endregion
            }
        }
예제 #5
0
            public void ReadData(uReader br)
            {
                var delta = (Flags & STUDIO_ANIM_DELTA) > 0;

                if ((Flags & STUDIO_ANIM_ANIMROT) > 0)
                {
                    // Why is this so painful :(
                    // Read the per-frame data using RLE, just like GoldSource models
                    var startPos  = br.BaseStream.Position;
                    var offsets   = br.ReadShortArray(3);
                    var endPos    = br.BaseStream.Position;
                    var rotFrames = new List <float[]>();
                    for (var i = 0; i < NumFrames; i++)
                    {
                        rotFrames.Add(new float[] { 0, 0, 0 });
                    }
                    for (var i = 0; i < 3; i++)
                    {
                        if (offsets[i] == 0)
                        {
                            continue;
                        }
                        br.BaseStream.Position = startPos + offsets[i];
                        var values = br.ReadAnimationFrameValues(NumFrames);
                        for (var f = 0; f < values.Length; f++)
                        {
                            rotFrames[f][i] = +values[f];
                            if (f > 0 && delta)
                            {
                                rotFrames[f][i] += values[f - 1];
                            }
                        }
                    }
                    FrameAngles.AddRange(rotFrames.Select(x => new Vector3(x[0], x[1], x[2])));
                    br.BaseStream.Position = endPos;
                }
                if ((Flags & STUDIO_ANIM_ANIMPOS) > 0)
                {
                    // Same as above, except for the position coordinate
                    var startPos  = br.BaseStream.Position;
                    var offsets   = br.ReadShortArray(3);
                    var endPos    = br.BaseStream.Position;
                    var posFrames = new List <float[]>();
                    for (var i = 0; i < NumFrames; i++)
                    {
                        posFrames.Add(new float[] { 0, 0, 0 });
                    }
                    for (var i = 0; i < 3; i++)
                    {
                        if (offsets[i] == 0)
                        {
                            continue;
                        }
                        br.BaseStream.Position = startPos + offsets[i];
                        var values = br.ReadAnimationFrameValues(NumFrames);
                        for (var f = 0; f < values.Length; f++)
                        {
                            posFrames[f][i] = +values[f];
                            if (f > 0 && delta)
                            {
                                posFrames[f][i] += values[f - 1];
                            }
                        }
                    }
                    FramePositions.AddRange(posFrames.Select(x => new Vector3(x[0], x[1], x[2])));
                    br.BaseStream.Position = endPos;
                }
                if ((Flags & STUDIO_ANIM_RAWROT) > 0)
                {
                    var quat48 = new Quaternion48();
                    br.ReadTypeFixed(ref quat48, 6);

                    this.pQuat48 = quat48.quaternion;
                }
                if ((Flags & STUDIO_ANIM_RAWROT2) > 0)
                {
                    var quat64 = new Quaternion64();
                    br.ReadTypeFixed(ref quat64, 8);

                    this.pQuat64 = quat64.quaternion;
                }
                if ((Flags & STUDIO_ANIM_RAWPOS) > 0)
                {
                    var vec48 = new Vector48();
                    br.ReadTypeFixed(ref vec48, 6);

                    this.pVec48 = vec48.ToVector3();
                }
            }
예제 #6
0
        public PhysModel(Int32 modelIndex, Int32 solidCount, Byte[] collisionData, Byte[] keyData)
        {
            ModelIndex = modelIndex;
            KeyData    = System.Text.Encoding.ASCII.GetString(keyData);

            using (var ms = new MemoryStream(collisionData))
            {
                using (var br = new uReader(ms))
                {
                    for (Int32 i = 0; i < solidCount; i++)
                    {
                        var solid = new PhysModelSolid();
                        Solids.Add(solid);

                        var size   = br.ReadInt32();
                        var maxPos = br.BaseStream.Position + size;
                        solid.vphysicsID = br.ReadInt16();                         // ??
                        solid.version    = br.ReadInt16();
                        br.ReadInt16();
                        solid.modelType = br.ReadInt16();

                        if (solid.modelType != 0x0)
                        {
                            br.BaseStream.Seek(maxPos - br.BaseStream.Position, SeekOrigin.Current);
                            continue;
                        }

                        // ???
                        br.BaseStream.Seek(68, SeekOrigin.Current);

                        while (true)
                        {
                            var cc = new PhysModelConvex();
                            solid.Convexes.Add(cc);

                            var pos          = br.BaseStream.Position;
                            var vertexOffset = (Int32)(pos + br.ReadUInt32());

                            cc.BrushIndex = br.ReadInt32();
                            cc.idk2       = br.ReadByte();
                            cc.idk3       = br.ReadByte();
                            cc.idk4       = br.ReadUInt16();

                            var triCount = br.ReadInt16();
                            cc.idk5 = br.ReadUInt16();

                            for (Int32 j = 0; j < triCount; j++)
                            {
                                br.BaseStream.Seek(4, SeekOrigin.Current);

                                var index1 = br.ReadInt16();
                                br.ReadInt16();
                                var index2 = br.ReadInt16();
                                br.ReadInt16();
                                var index3 = br.ReadInt16();
                                br.ReadInt16();

                                try
                                {
                                    Vector3 v1 = collisionData.ReadAtPosition <Vector3>(vertexOffset + index1 * 16);
                                    Vector3 v2 = collisionData.ReadAtPosition <Vector3>(vertexOffset + index2 * 16);
                                    Vector3 v3 = collisionData.ReadAtPosition <Vector3>(vertexOffset + index3 * 16);

                                    cc.Triangles.Add(cc.Verts.Count);
                                    cc.Triangles.Add(cc.Verts.Count + 1);
                                    cc.Triangles.Add(cc.Verts.Count + 2);
                                    cc.Verts.Add(v1);
                                    cc.Verts.Add(v2);
                                    cc.Verts.Add(v3);
                                }
                                catch (System.Exception e)
                                {
                                    Debug.Log("Error on solid type: " + solid.modelType);
                                    Debug.LogError(e);
                                }
                            }

                            if (br.BaseStream.Position >= vertexOffset)
                            {
                                break;
                            }
                        }

                        Int64 remainder = maxPos - br.BaseStream.Position;
                        if (remainder > 0)
                        {
                            br.BaseStream.Seek(remainder, SeekOrigin.Current);
                        }
                    }
                }
            }

            KeyValues = KeyValues.Parse(KeyData);
        }