Beispiel #1
0
        private static void LoadSourceAnimationData(BinaryReader br, ModelData modelData, int numAnim, int animIndex)
        {
            modelData.SourceAnimations = new List<SourceAnimation>();

            var restorePoint = br.BaseStream.Position;
            br.BaseStream.Position = animIndex;

            for (var i = 0; i < numAnim; i++)
            {
                var animStartPos = br.BaseStream.Position;

                var basePointer = br.ReadInt32();
                var szNameIndex = br.ReadInt32();

                var fps = br.ReadSingle();
                var animDescFlags = br.ReadInt32();

                var numframes = br.ReadInt32();

                var numMovements = br.ReadInt32();
                var movementIndex = br.ReadInt32();

                br.ReadCoordinateFArray(2); // bounding box; unused

                var ablock = br.ReadInt32();
                var aindex = br.ReadInt32();

                var numIkRules = br.ReadInt32();
                var ikRuleIndex = br.ReadInt32();

                var animBlockIkRuleIndex = br.ReadInt32();
                br.ReadIntArray(7); // Unused

                var animEndPos = br.BaseStream.Position;

                var sourceAnim = new SourceAnimation(i, numframes, fps, animDescFlags, numMovements, movementIndex,
                                                     ablock, aindex, numIkRules, ikRuleIndex, animBlockIkRuleIndex);

                var currentOffset = aindex;
                short nextOffset;
                do
                {
                    br.BaseStream.Position = animStartPos + currentOffset;
                    var animBone = br.ReadByte();
                    var animFlags = br.ReadByte();
                    nextOffset = br.ReadInt16();
                    currentOffset += nextOffset;

                    var aniBone = new SourceAnimationBone(animBone, animFlags, numframes);
                    aniBone.ReadData(br);
                    sourceAnim.AnimationBones.Add(aniBone);

                } while (nextOffset != 0);

                modelData.SourceAnimations.Add(sourceAnim);

                br.BaseStream.Position = animEndPos;
            }

            br.BaseStream.Position = restorePoint;
        }
Beispiel #2
0
        private static void ReadStudioModel(BinaryReader br, string groupName, int bodyPartIndex, int modelIndex, ModelData data, DataStructures.Models.Model model)
        {
            var startModelPos = br.BaseStream.Position;
            var name = br.ReadFixedLengthString(Encoding.ASCII, 64);
            var type = br.ReadInt32();
            var radius = br.ReadSingle();

            var numMesh = br.ReadInt32();
            var meshIndex = br.ReadInt32();

            var numVerts = br.ReadInt32();
            var vertInfoIndex = 0;
            if (data.Version == MDLVersionGoldsource)
            {
                vertInfoIndex = br.ReadInt32();
            }
            var vertIndex = br.ReadInt32();
            int numNorms = 0, normInfoIndex = 0, normIndex = 0;
            if (data.Version == MDLVersionGoldsource)
            {
                numNorms = br.ReadInt32();
                normInfoIndex = br.ReadInt32();
                normIndex = br.ReadInt32();
            }
            else if (data.Version >= MDLVersionSource2006)
            {
                var tangentsIndex = br.ReadInt32();
            }

            var numGroups = br.ReadInt32(); // Attachments in source
            var groupIndex = br.ReadInt32(); // Attachments

            if (data.Version >= MDLVersionSource2006)
            {
                var numEyeballs = br.ReadInt32();
                var eyeballIndex = br.ReadInt32();

                var vertexDataPointer = br.ReadInt32();
                var tangentDataPointer = br.ReadInt32();

                br.ReadIntArray(8); // Unused
            }

            var endPos = br.BaseStream.Position;

            if (data.Version == MDLVersionGoldsource)
            {
                ReadVerticesGoldSource(br, groupName, modelIndex, model, numVerts, vertInfoIndex, vertIndex, numMesh, meshIndex, numNorms, normInfoIndex, normIndex);
            }
            else if (data.Version >= MDLVersionSource2006)
            {
                ReadVerticesSource(br, groupName, bodyPartIndex, modelIndex, data, model, numMesh, startModelPos + meshIndex);
            }

            br.BaseStream.Position = endPos;
        }
Beispiel #3
0
        private static void ReadSequence(BinaryReader br, int index, ModelData data, DataStructures.Models.Model model, IList<SequenceGroup> groups)
        {
            var startReadIndex = br.BaseStream.Position;
            var name = "";
            var fps = 0f;
            if (data.Version == MDLVersionGoldsource)
            {
                name = br.ReadFixedLengthString(Encoding.ASCII, 32);
                fps = br.ReadSingle();
            }
            else if (data.Version >= MDLVersionSource2006)
            {
                var baseIndex = br.ReadInt32();
                var labelIndex = br.ReadInt32();
                var activityNameIndex = br.ReadInt32();
            }

            var flags = br.ReadInt32();

            var activity = br.ReadInt32();
            var actweight = br.ReadInt32();

            var numevents = br.ReadInt32();
            var eventindex = br.ReadInt32();

            var numframes = 0;

            if (data.Version == MDLVersionGoldsource)
            {
                numframes = br.ReadInt32();
                var numpivots = br.ReadInt32();
                var pivotindex = br.ReadInt32();
                var motiontype = br.ReadInt32();
                var motionbone = br.ReadInt32();
                var linearmovement = br.ReadCoordinateF();
                var automoveposindex = br.ReadInt32();
                var automoveangleindex = br.ReadInt32();
            }

            var bbmin = br.ReadCoordinateF();
            var bbmax = br.ReadCoordinateF();

            var numblends = br.ReadInt32();

            var animindex = br.ReadInt32();

            var groupsize = new int[0];
            if (data.Version >= MDLVersionSource2006)
            {
                var movementindex = br.ReadInt32();
                groupsize = br.ReadIntArray(2);
            }

            var blendtype = br.ReadIntArray(2); // paramindex in source
            var blendstart = br.ReadSingleArray(2); // paramstart
            var blendend = br.ReadSingleArray(2); // paramend
            var blendparent = br.ReadInt32(); // paramparent

            var seqgroup = 0;
            if (data.Version == MDLVersionGoldsource)
            {
                seqgroup = br.ReadInt32();
            }

            if (data.Version >= MDLVersionSource2006)
            {
                var fadeintime = br.ReadSingle();
                var fadeouttime = br.ReadSingle();
            }

            var entrynode = br.ReadInt32();
            var exitnode = br.ReadInt32();
            var nodeflags = br.ReadInt32();

            if (data.Version >= MDLVersionSource2006)
            {
                var entryphase = br.ReadSingle();
                var exitphase = br.ReadSingle();

                var lastframe = br.ReadSingle();
            }

            var nextseq = br.ReadInt32();

            if (data.Version >= MDLVersionSource2006)
            {
                var pose = br.ReadInt32();

                var numikrules = br.ReadInt32();

                var numautolayers = br.ReadInt32();
                var autolayerindex = br.ReadInt32();

                var weightlistindex = br.ReadInt32();

                var wlpos = br.BaseStream.Position;
                br.BaseStream.Position = startReadIndex + weightlistindex;

                var weightList = br.ReadSingleArray(model.Bones.Count);

                br.BaseStream.Position = wlpos;

                var posekeyindex = br.ReadInt32();

                var numiklocks = br.ReadInt32();
                var iklockindex = br.ReadInt32();

                var keyvalueindex = br.ReadInt32();
                var keyvaluesize = br.ReadInt32();

                var cycleposeindex = br.ReadInt32();
                br.ReadIntArray(7); // Unused
            }

            // Load animtion values
            var pos = br.BaseStream.Position;

            if (data.Version == MDLVersionGoldsource)
            {
                if (seqgroup > 0)
                {
                    //TODO: load animations from other files
                    return;
                    // sub out br for another br against the new SG file
                    // br = new BinaryReader(file....etc)
                    // br.BaseStream.Position = animindex;
                }
                br.BaseStream.Position = groups[seqgroup].GroupZeroDataIndex + animindex;
                ReadAnimationGoldsource(br, model, numframes);
            }
            else if (data.Version >= MDLVersionSource2006)
            {
                br.BaseStream.Position = startReadIndex + animindex;
                ReadAnimationSource(br, data, model, groupsize);
            }

            br.BaseStream.Position = pos;
        }
Beispiel #4
0
        private static DataStructures.Models.Model ReadModel(BinaryReader br, IFile file, ModelLoadItems loadItems)
        {
            // int id - Not really an int. This is a magic string, either "IDST" or "IDSQ".
            var magicString = br.ReadFixedLengthString(Encoding.UTF8, 4);
            if (magicString != MagicStringIDST && magicString != MagicStringIDSQ)
            {
                throw new ProviderException("Bad magic number for model. Expected [IDST,IDSQ], got: " + magicString);
            }

            // int version - Half-life 1 models are version 10.
            var version = br.ReadInt32();
            if (version != MDLVersionGoldsource
                && version != MDLVersionSource2006
                && version != MDLVersionSourceEpisode2
                && version != MDLVersionSourcePortal
                && version != MDLVersionSource2007
                && version != MDLVersionSource2012)
            {
                throw new ProviderException("Bad version number for model. Expected [10,44,45,46,48,49], got: " + version);
            }

            var modelData = new ModelData {Version = version};

            if (version >= MDLVersionSource2006)
            {
                if (loadItems.HasFlag(ModelLoadItems.Meshes))
                {
                    // Source vertex and mesh info is stored in flat file structures, preload these separately.
                    LoadSourceMeshData(modelData, file);
                }
            }

            long checksum = 0;
            if (version >= MDLVersionSource2006)
            {
                checksum = br.ReadInt32(); // This is a long in the headers but is only written to the file in 4 bytes. Why? I don't know.
            }

            // char name[64] - The name of the model (file path)
            var path = br.ReadFixedLengthString(Encoding.UTF8, 64);

            // int length - The size of the model file in bytes
            var fileSize = br.ReadInt32();

            var eyePosition = br.ReadCoordinateF();

            var illumPosition = CoordinateF.Zero;
            if (version >= MDLVersionSource2006)
            {
                illumPosition = br.ReadCoordinateF();
            }

            var hullMin = br.ReadCoordinateF();
            var hullMax = br.ReadCoordinateF();

            var bbMin = br.ReadCoordinateF();
            var bbMax = br.ReadCoordinateF();

            // int flags - Unknown.
            var flags = br.ReadInt32();

            var numBones = br.ReadInt32();
            var boneIndex = br.ReadInt32();

            var numBoneControllers = br.ReadInt32();
            var boneControllerIndex = br.ReadInt32();

            var numHitBoxes = br.ReadInt32();
            var hitboxIndex = br.ReadInt32();

            if (version >= MDLVersionSource2006)
            {
                var numAnim = br.ReadInt32();
                var animIndex = br.ReadInt32();
                if (loadItems.HasFlag(ModelLoadItems.Animations))
                {
                    // Source animation data is stored on their own instead of inside the sequence
                    LoadSourceAnimationData(br, modelData, numAnim, animIndex);
                }
            }

            var numSeq = br.ReadInt32();
            var seqIndex = br.ReadInt32();

            int numSeqGroups = 0, seqGroupIndex = 0, activitylistversion = 0, eventsindexed = 0;
            if (version >= MDLVersionSource2006)
            {
                activitylistversion = br.ReadInt32();
                eventsindexed = br.ReadInt32();
            }
            else if (version == MDLVersionGoldsource)
            {
                numSeqGroups = br.ReadInt32();
                seqGroupIndex = br.ReadInt32();
            }

            var numTextures = br.ReadInt32();
            var textureIndex = br.ReadInt32();
            var textureDataIndex = 0;

            if (version == MDLVersionGoldsource)
            {
                textureDataIndex = br.ReadInt32();
            }

            if (version >= MDLVersionSource2006)
            {
                var numcdtextures = br.ReadInt32();
                var cdtextureindex = br.ReadInt32();
            }

            var numSkinRef = br.ReadInt32();
            var numSkinFamilies = br.ReadInt32();
            var skinIndex = br.ReadInt32();

            var numBodyParts = br.ReadInt32();
            var bodyPartIndex = br.ReadInt32();

            var numAttachments = br.ReadInt32();
            var attachmentIndex = br.ReadInt32();

            if (version >= MDLVersionSource2006)
            {
                var numlocalnodes = br.ReadInt32();
                var localnodeindex = br.ReadInt32();
                var localnodenameindex = br.ReadInt32();

                var numflexdesc = br.ReadInt32();
                var flexdescindex = br.ReadInt32();

                var numflexcontrollers = br.ReadInt32();
                var flexcontrollerindex = br.ReadInt32();

                var numflexrules = br.ReadInt32();
                var flexruleindex = br.ReadInt32();

                var numikchains = br.ReadInt32();
                var ikchainindex = br.ReadInt32();

                var nummouths = br.ReadInt32();
                var mouthindex = br.ReadInt32();

                var numlocalposeparameters = br.ReadInt32();
                var localposeparamindex = br.ReadInt32();

                var surfacepropindex = br.ReadInt32();

                var keyvalueindex = br.ReadInt32();
                var keyvaluesize = br.ReadInt32();

                var numlocalikautoplaylocks = br.ReadInt32();
                var localikautoplaylockindex = br.ReadInt32();

                var mass = br.ReadSingle();
                var contents = br.ReadInt32();

                var numincludemodels = br.ReadInt32();
                var includemodelindex = br.ReadInt32();

                var virtualModelPointer = br.ReadInt32();

                var szanimblocknameindex = br.ReadInt32();
                var numanimblocks = br.ReadInt32();
                var animblockindex = br.ReadInt32();
                var animblockModelPointer = br.ReadInt32();

                var bonetablebynameindex = br.ReadInt32();

                var pVertexBasePointer = br.ReadInt32();
                var pIndexBasePointer = br.ReadInt32();

                var constdirectionallightdot = br.ReadByte();
                var rootLod = br.ReadByte();
                var numAllowedRootLods = br.ReadByte(); // Unused in Source2006
                br.ReadByte(); // Unused

                var zeroframecacheindex = br.ReadInt32(); // Unused in Source2007

                if (version == MDLVersionSource2006)
                {
                    br.ReadBytes(6); // Unused
                }
                else if (version == MDLVersionSource2007)
                {
                    var numflexcontrollerui = br.ReadInt32();
                    var flexcontrolleruiindex = br.ReadInt32();

                    br.ReadIntArray(2); // Unused

                    var studiohdr2Index = br.ReadInt32();
                    br.ReadInt32(); // Unused
                }
            }
            else if (version == MDLVersionGoldsource)
            {
                var soundTable = br.ReadInt32();
                var soundIndex = br.ReadInt32();
                var soundGroups = br.ReadInt32();
                var soundGroupIndex = br.ReadInt32();

                var numTransitions = br.ReadInt32();
                var transitionIndex = br.ReadInt32();
            }

            var model = new DataStructures.Models.Model();
            model.Name = file.NameWithoutExtension;
            model.BonesTransformMesh = modelData.Version == MDLVersionGoldsource;

            if (loadItems.HasFlag(ModelLoadItems.Bones))
            {
                // Bones
                br.BaseStream.Position = boneIndex;
                for (var i = 0; i < numBones; i++) ReadBone(br, i, modelData, model);
            }

            // Controllers
            // TODO

            // Attachments
            // TODO

            // Hitboxes
            // TODO

            if (loadItems.HasFlag(ModelLoadItems.Animations))
            {
                if (version >= MDLVersionSource2006)
                {
                    throw new ProviderException("Source animations are currently not supported.");
                }

                // Sequence Groups
                var groups = new List<SequenceGroup>();
                br.BaseStream.Position = seqGroupIndex;
                for (var i = 0; i < numSeqGroups; i++) groups.Add(ReadSequenceGroup(br, modelData));

                // Sequences
                br.BaseStream.Position = seqIndex;
                for (var i = 0; i < numSeq; i++) ReadSequence(br, i, modelData, model, groups);
            }

            // Transitions
            // TODO

            if (loadItems.HasFlag(ModelLoadItems.Meshes))
            {
                // Body parts
                br.BaseStream.Position = bodyPartIndex;
                for (var i = 0; i < numBodyParts; i++) ReadBodyPart(br, i, modelData, model);
            }

            // Texture Info
            if (loadItems.HasFlag(ModelLoadItems.TextureInfo) || loadItems.HasFlag(ModelLoadItems.TextureData))
            {
                ReadTextureInfo(file, br, modelData, model, numTextures, textureIndex);
            }

            // Textures

            return model;
        }
Beispiel #5
0
        private static void ReadBone(BinaryReader br, int index, ModelData data, DataStructures.Models.Model model)
        {
            var name = "";
            var nameIndex = 0;
            if (data.Version >= MDLVersionSource2006)
            {
                nameIndex = br.ReadInt32();
            }
            else if (data.Version == MDLVersionGoldsource)
            {
                name = br.ReadFixedLengthString(Encoding.UTF8, 32);
            }
            var parent = br.ReadInt32();
            int flags = 0;
            if (data.Version == MDLVersionGoldsource)
            {
                flags = br.ReadInt32();
            }
            var boneController = br.ReadIntArray(6);        // 3 pos, 3 rot
            var defPos = br.ReadCoordinateF();
            QuaternionF quat = null;
            if (data.Version >= MDLVersionSource2006)
            {
                // quaternion
                quat = new QuaternionF(br.ReadCoordinateF(), br.ReadSingle());
            }
            var defAng = br.ReadCoordinateF();
            var defPosScale = br.ReadCoordinateF();
            var defAngScale = br.ReadCoordinateF();

            if (data.Version >= MDLVersionSource2006)
            {
                var poseToBone = br.ReadIntArray(12); // 3x4 matrix
                var qAlignment = new QuaternionF(br.ReadCoordinateF(), br.ReadSingle());
                flags = br.ReadInt32();
                var proctype = br.ReadInt32();
                var procindex = br.ReadInt32();
                var physicsbone = br.ReadInt32();
                var surfacepropidx = br.ReadInt32();
                var contents = br.ReadInt32();
                br.ReadIntArray(8); // Unused
            }

            var parentBone = parent < 0 ? null : model.Bones[parent];
            model.Bones.Add(new Bone(index, parent, parentBone, name, defPos, defAng, defPosScale, defAngScale));
        }
Beispiel #6
0
        private static void LoadSourceMeshData(ModelData modelData, IFile file)
        {
            modelData.Meshes = new List<VTXModel>();
            // In Source the vertices are saved to the VVD file
            // The vertex windings are saved in the VTX file
            var vvd = file.GetRelatedFile("vvd");
            var vtx = file.GetRelatedFile("vtx");
            if (vvd == null) throw new ProviderException("Unable to locate " + file.NameWithoutExtension + ".vvd");
            if (vtx == null) throw new ProviderException("Unable to locate " + file.NameWithoutExtension + ".vtx");

            var vertices = new List<VVDPoint>();

            using (var fs = vvd.Open())
            {
                using (var vbr = new BinaryReader(fs))
                {
                    var magicString = vbr.ReadFixedLengthString(Encoding.UTF8, 4);
                    if (magicString != MagicStringIDSV)
                    {
                        throw new ProviderException("Bad magic number for vertex file. Expected IDSV, got: " + magicString);
                    }

                    var version = vbr.ReadInt32();
                    if (version != VVDVersionSource)
                    {
                        throw new ProviderException("Bad version number for vertex file. Expected 4, got: " + version);
                    }

                    long checksum = vbr.ReadInt32();
                    var numLods = vbr.ReadInt32();
                    var numLodVertices = vbr.ReadIntArray(8);

                    var numFixups = vbr.ReadInt32();
                    var fixupTableStart = vbr.ReadInt32();
                    var vertexDataStart = vbr.ReadInt32();
                    var tangentDataStart = vbr.ReadInt32();

                    vbr.BaseStream.Position = vertexDataStart;

                    // Read all the vertices from LOD 0 (this should contain the vertices for all LODs)
                    for (var i = 0; i < numLodVertices[0]; i++)
                    {
                        var boneWeights = vbr.ReadSingleArray(3);
                        var bones = vbr.ReadBytes(3);
                        var numBones = vbr.ReadByte();
                        var position = vbr.ReadCoordinateF();
                        var normal = vbr.ReadCoordinateF();
                        var textureS = vbr.ReadSingle();
                        var textureT = vbr.ReadSingle();
                        vertices.Add(new VVDPoint(boneWeights, bones, numBones, position, normal, textureS, textureT));
                    }

                    // Apply the fixup table, this re-orders the indices in reverse LOD order for performance reasons
                    if (numFixups > 0)
                    {
                        vbr.BaseStream.Position = fixupTableStart;
                        var newVerts = new List<VVDPoint>();
                        for (var i = 0; i < numFixups; i++)
                        {
                            var fuLod = vbr.ReadInt32();
                            var fuvertid = vbr.ReadInt32();
                            var funumverts = vbr.ReadInt32();
                            newVerts.AddRange(vertices.GetRange(fuvertid, funumverts));
                        }
                        vertices.Clear();
                        vertices.AddRange(newVerts);
                    }

                    modelData.Vertices = vertices;
                }
            }
            using (var fs = vtx.Open())
            {
                using (var vbr = new BinaryReader(fs))
                {
                    var version = vbr.ReadInt32(); // 7
                    if (version != VTXVersionSource)
                    {
                        throw new ProviderException("Bad version number for vertex file. Expected 7, got: " + version);
                    }
                    var vertCacheSize = vbr.ReadInt32();
                    var maxBonesPerStrip = vbr.ReadUInt16();
                    var maxBonesPerTri = vbr.ReadUInt16();
                    var maxBonesPerVert = vbr.ReadInt32();
                    long checksum = vbr.ReadInt32();
                    var numLods = vbr.ReadInt32();
                    var materialReplacementListOffset = vbr.ReadInt32();
                    var numBodyParts = vbr.ReadInt32();
                    var bodyPartOffset = vbr.ReadInt32();

                    // BODY PARTS
                    long posbp = bodyPartOffset;
                    for (var bp = 0; bp < numBodyParts; bp++)
                    {
                        vbr.BaseStream.Position = posbp;

                        var numModels = vbr.ReadInt32();
                        var modelOffset = vbr.ReadInt32();

                        var posmdl = posbp + modelOffset;
                        posbp = vbr.BaseStream.Position;

                        // MODELS
                        for (var mdl = 0; mdl < numModels; mdl++)
                        {
                            vbr.BaseStream.Position = posmdl;

                            var numLod = vbr.ReadInt32();
                            var lodOffset = vbr.ReadInt32();

                            var poslod = posmdl + lodOffset;
                            posmdl = vbr.BaseStream.Position;

                            // LODS
                            for (var lod = 0; lod < numLod; lod++)
                            {
                                vbr.BaseStream.Position = poslod;

                                var meshNum = vbr.ReadInt32();
                                var meshOffset = vbr.ReadInt32();
                                var switchPoint = vbr.ReadSingle();

                                var posmesh = poslod + meshOffset;
                                poslod = vbr.BaseStream.Position;

                                // MESHES
                                for (var msh = 0; msh < meshNum; msh++)
                                {
                                    vbr.BaseStream.Position = posmesh;

                                    var sgNum = vbr.ReadInt32();
                                    var sgOffset = vbr.ReadInt32();
                                    var meshFlags = vbr.ReadByte();

                                    var possg = posmesh + sgOffset;
                                    posmesh = vbr.BaseStream.Position;

                                    var mesh = new VTXModel(bp, mdl, lod, msh);

                                    // STRIP GROUPS
                                    for (var sg = 0; sg < sgNum; sg++)
                                    {
                                        vbr.BaseStream.Position = possg;

                                        var vertNum = vbr.ReadInt32();
                                        var vertOffset = vbr.ReadInt32();
                                        var indexNum = vbr.ReadInt32();
                                        var indexOffset = vbr.ReadInt32();
                                        var stripNum = vbr.ReadInt32();
                                        var stripOffset = vbr.ReadInt32();
                                        var sgFlags = vbr.ReadByte();
                                        // vbr.ReadIntArray(2); //TODO FIXME Newer model format 49's (DOTA2, CSGO) have two extra integers here, (num + offset, purpose unknown)

                                        var posvert = possg + vertOffset;
                                        var posidx = possg + indexOffset;
                                        var posstrip = possg + stripOffset;
                                        possg = vbr.BaseStream.Position;

                                        var vertinfo = new List<VTXPoint>();
                                        vbr.BaseStream.Position = posvert;
                                        for (var vert = 0; vert < vertNum; vert++)
                                        {
                                            var boneWeightIndices = vbr.ReadBytes(3);
                                            var numBones = vbr.ReadByte();
                                            var meshVertex = vbr.ReadInt16();
                                            var boneIDs = vbr.ReadBytes(3);

                                            vertinfo.Add(new VTXPoint(boneWeightIndices, numBones, meshVertex, boneIDs));
                                        }

                                        vbr.BaseStream.Position = posidx;
                                        var indices = vbr.ReadShortArray(indexNum);

                                        // The strips hold info about whether this is a triangle strip or just a list
                                        vbr.BaseStream.Position = posstrip;
                                        for (var st = 0; st < stripNum; st++)
                                        {
                                            var numStIndices = vbr.ReadInt32();
                                            var stIndexOffset = vbr.ReadInt32();
                                            var numStVerts = vbr.ReadInt32();
                                            var stVertOffset = vbr.ReadInt32();
                                            var numStBones = vbr.ReadInt16();
                                            var stFlags = vbr.ReadByte();
                                            var numStBoneStateChanges = vbr.ReadInt32();
                                            var stBoneStateChangeOffset = vbr.ReadInt32();
                                            // vbr.ReadIntArray(2); //TODO FIXME Newer model format 49's (DOTA2, CSGO) have two extra integers here, (num + offset, purpose unknown)

                                            if ((stFlags & VTXStripGroupTriListFlag) > 0)
                                            {
                                                for (var j = stIndexOffset; j < stIndexOffset + numStIndices; j++)
                                                {
                                                    mesh.Mesh.Points.Add(vertinfo[indices[j]]);
                                                    //mesh.Vertices.Add(vertices[vertinfo[indices[j]]]);
                                                }
                                            }
                                            else if ((stFlags & VTXStripGroupTriStripFlag) > 0)
                                            {
                                                for (var j = stIndexOffset; j < stIndexOffset + numStIndices - 2; j++)
                                                {
                                                    var add = j % 2 == 1 ? new[] { j + 1, j, j + 2 } : new[] { j, j + 1, j + 2 };
                                                    foreach (var idx in add)
                                                    {
                                                        mesh.Mesh.Points.Add(vertinfo[indices[idx]]);
                                                        //mesh.Vertices.Add(vertices[vertinfo[indices[idx]]]);
                                                    }
                                                }
                                            }
                                        } // Strips
                                    } // Strip Groups
                                    modelData.Meshes.Add(mesh);
                                } // Meshes
                            } // LODs
                        } // Models
                    } // Body Parts
                } // using (var br)
            } // using (var fs)
        }
Beispiel #7
0
        private static void ReadVerticesSource(BinaryReader br, string groupName, int bodyPartIndex, int modelIndex, ModelData modelData, DataStructures.Models.Model model, int numMesh, long meshIndex)
        {
            br.BaseStream.Position = meshIndex;
            for (var i = 0; i < numMesh; i++)
            {
                var material = br.ReadInt32();
                var modelOffset = br.ReadInt32();
                var numVerts = br.ReadInt32();
                var vertexOffset = br.ReadInt32();
                var numFlexes = br.ReadInt32();
                var flexIndex = br.ReadInt32();
                var materialType = br.ReadInt32();
                var materialParam = br.ReadInt32();
                var meshId = br.ReadInt32();
                var center = br.ReadCoordinateF();
                var modelVertexDataPointer = br.ReadInt32();
                var numLODVertices = br.ReadIntArray(8);
                br.ReadIntArray(8); // Unused

                foreach (var mm in modelData.Meshes.Where(mm => mm.BodyPart == bodyPartIndex
                                                                && mm.Model == modelIndex
                                                                && mm.LOD == 0
                                                                && mm.MeshIndex == meshId))
                {
                    var mesh = new Mesh(mm.LOD);
                    foreach (var point in mm.Mesh.Points)
                    {
                        var vert = modelData.Vertices[point.VertexIndex + vertexOffset];
                        var boneWeights = new List<BoneWeighting>();
                        for (var j = 0; j < vert.NumBones; j++)
                        {
                            boneWeights.Add(new BoneWeighting(model.Bones[vert.Bones[j]], vert.BoneWeights[j]));
                        }
                        var mv = new MeshVertex(vert.Position, vert.Normal, boneWeights, vert.TextureS, vert.TextureT);
                        mesh.Vertices.Add(mv);
                    }
                    model.AddMesh(groupName, modelIndex, mesh);
                }
            }
        }