private NTROSerialization.NTROStruct ReadStructure(ResourceIntrospectionManifest.ResourceDiskStruct refStruct, long startingOffset) { var structEntry = new NTROSerialization.NTROStruct(refStruct.Name); foreach (var field in refStruct.FieldIntrospection) { Reader.BaseStream.Position = startingOffset + field.OnDiskOffset; ReadFieldIntrospection(field, ref structEntry); } if (refStruct.BaseStructId != 0) { var previousOffset = Reader.BaseStream.Position; var newStruct = Resource.IntrospectionManifest.ReferencedStructs.First(x => x.Id == refStruct.BaseStructId); // Valve doesn't print this struct's type, so we can't just call ReadStructure *sigh* foreach (var field in newStruct.FieldIntrospection) { Reader.BaseStream.Position = startingOffset + field.OnDiskOffset; ReadFieldIntrospection(field, ref structEntry); } Reader.BaseStream.Position = previousOffset; } return structEntry; }
// Construct the Armature object from mesh skeleton KV data. public void ConstructFromNTRO(NTROStruct skeletonData, Dictionary<int, int> remapTable) { var boneNames = skeletonData.Get<NTROArray>("m_boneName").ToArray<string>(); var boneParents = skeletonData.Get<NTROArray>("m_nParent").ToArray<short>(); var bonePositions = skeletonData.Get<NTROArray>("m_bonePosParent").ToArray<Vector3>(); var boneRotations = skeletonData.Get<NTROArray>("m_boneRotParent").ToArray<Vector4>(); // Initialise bone array Bones = new Bone[boneNames.Length]; //Add all bones to the list for (var i = 0; i < boneNames.Length; i++) { var name = boneNames[i]; var position = new OpenTK.Vector3(bonePositions[i].X, bonePositions[i].Y, bonePositions[i].Z); var rotation = new Quaternion(boneRotations[i].X, boneRotations[i].Y, boneRotations[i].Z, boneRotations[i].W); // Create bone var index = remapTable.ContainsKey(i) ? remapTable[i] : -1; var bone = new Bone(name, index, position, rotation); if (boneParents[i] != -1) { bone.SetParent(Bones[boneParents[i]]); Bones[boneParents[i]].AddChild(bone); } Bones[i] = bone; } FindRoots(); }
private NTROSerialization.NTROStruct ReadStructure(ResourceIntrospectionManifest.ResourceDiskStruct refStruct, long startingOffset) { var structEntry = new NTROSerialization.NTROStruct(refStruct.Name); foreach (var field in refStruct.FieldIntrospection) { Reader.BaseStream.Position = startingOffset + field.OnDiskOffset; ReadFieldIntrospection(field, ref structEntry); } if (refStruct.BaseStructId != 0) { var previousOffset = Reader.BaseStream.Position; var newStruct = Resource.IntrospectionManifest.ReferencedStructs.First(x => x.Id == refStruct.BaseStructId); // Valve doesn't print this struct's type, so we can't just call ReadStructure *sigh* foreach (var field in newStruct.FieldIntrospection) { Reader.BaseStream.Position = startingOffset + field.OnDiskOffset; ReadFieldIntrospection(field, ref structEntry); } Reader.BaseStream.Position = previousOffset; } return(structEntry); }
public override void Read(BinaryReader reader, Resource resource) { Reader = reader; Resource = resource; foreach (var refStruct in resource.IntrospectionManifest.ReferencedStructs) { Output = ReadStructure(refStruct, Offset); break; } }
// Build animation from resource public Animation(Resource resource, NTROStruct decodeKey, Skeleton skeleton) { Name = string.Empty; Fps = 0; Frames = new Frame[0]; Skeleton = skeleton; var animationData = (NTRO)resource.Blocks[BlockType.DATA]; var animArray = (NTROArray)animationData.Output["m_animArray"]; if (animArray.Count == 0) { Console.WriteLine("Empty animation file found."); return; } var decoderArray = MakeDecoderArray((NTROArray)animationData.Output["m_decoderArray"]); var segmentArray = (NTROArray)animationData.Output["m_segmentArray"]; // Get the first animation description ConstructFromDesc(animArray.Get<NTROStruct>(0), decodeKey, decoderArray, segmentArray); }
private void HandleDecodeKey(NTROStruct decodeKey) { // TODO? }
// Construct an animation class from the animation description private void ConstructFromDesc(NTROStruct animDesc, NTROStruct decodeKey, AnimDecoderType[] decoderArray, NTROArray segmentArray) { // Get animation properties Name = animDesc.Get<string>("m_name"); Fps = animDesc.Get<float>("fps"); // Only consider first frame block for now var pData = animDesc.Get<NTROArray>("m_pData").Get<NTROStruct>(0); var frameBlockArray = pData.Get<NTROArray>("m_frameblockArray").ToArray<NTROStruct>(); FrameCount = pData.Get<int>("m_nFrames"); Frames = new Frame[FrameCount]; // Figure out each frame for (var frame = 0; frame < FrameCount; frame++) { // Create new frame object Frames[frame] = new Frame(); // Read all frame blocks foreach (var frameBlock in frameBlockArray) { var startFrame = frameBlock.Get<int>("m_nStartFrame"); var endFrame = frameBlock.Get<int>("m_nEndFrame"); // Only consider blocks that actual contain info for this frame if (frame >= startFrame && frame <= endFrame) { var segmentIndexArray = frameBlock.Get<NTROArray>("m_segmentIndexArray").ToArray<int>(); foreach (var segmentIndex in segmentIndexArray) { var segment = segmentArray.Get<NTROStruct>(segmentIndex); ReadSegment(frame - startFrame, segment, decodeKey, decoderArray, ref Frames[frame]); } } } } }
private void ReadSegment(int frame, NTROStruct segment, NTROStruct decodeKey, AnimDecoderType[] decoderArray, ref Frame outFrame) { //Clamp the frame number to be between 0 and the maximum frame frame = frame < 0 ? 0 : frame; frame = frame >= FrameCount ? FrameCount - 1 : frame; var localChannel = segment.Get<int>("m_nLocalChannel"); var dataChannel = decodeKey.Get<NTROArray>("m_dataChannelArray").Get<NTROStruct>(localChannel); var boneNames = dataChannel.Get<NTROArray>("m_szElementNameArray").ToArray<string>(); var channelAttribute = dataChannel.Get<string>("m_szVariableName"); // Read container var container = segment.Get<NTROArray>("m_container").ToArray<byte>(); using (var containerReader = new BinaryReader(new MemoryStream(container))) { var elementIndexArray = dataChannel.Get<NTROArray>("m_nElementIndexArray").ToArray<int>(); var elementBones = new int[decodeKey.Get<int>("m_nChannelElements")]; for (var i = 0; i < elementIndexArray.Length; i++) { elementBones[elementIndexArray[i]] = i; } // Read header var decoder = decoderArray[containerReader.ReadInt16()]; var cardinality = containerReader.ReadInt16(); var numBones = containerReader.ReadInt16(); var totalLength = containerReader.ReadInt16(); // Read bone list var elements = new List<int>(); for (var i = 0; i < numBones; i++) { elements.Add(containerReader.ReadInt16()); } // Skip data to find the data for the current frame. // Structure is just | Bone 0 - Frame 0 | Bone 1 - Frame 0 | Bone 0 - Frame 1 | Bone 1 - Frame 1| containerReader.BaseStream.Position += decoder.Size() * frame * numBones; // Read animation data for all bones for (var element = 0; element < numBones; element++) { //Get the bone we are reading for var bone = elementBones[elements[element]]; // Look at the decoder to see what to read switch (decoder) { case AnimDecoderType.CCompressedStaticFullVector3: case AnimDecoderType.CCompressedFullVector3: case AnimDecoderType.CCompressedDeltaVector3: outFrame.SetAttribute(boneNames[bone], channelAttribute, new Vector3( containerReader.ReadSingle(), containerReader.ReadSingle(), containerReader.ReadSingle())); break; case AnimDecoderType.CCompressedStaticVector: outFrame.SetAttribute(boneNames[bone], channelAttribute, new Vector3( ReadHalfFloat(containerReader), ReadHalfFloat(containerReader), ReadHalfFloat(containerReader))); break; case AnimDecoderType.CCompressedAnimQuaternion: outFrame.SetAttribute(boneNames[bone], channelAttribute, ReadQuaternion(containerReader)); break; } } } }
private void ReadFieldIntrospection(ResourceIntrospectionManifest.ResourceDiskStruct.Field field, ref NTROSerialization.NTROStruct structEntry) { uint count = (uint)field.Count; bool pointer = false; // TODO: get rid of this if (count == 0) { count = 1; } long prevOffset = 0; if (field.Indirections.Count > 0) { // TODO if (field.Indirections.Count > 1) { throw new NotImplementedException("More than one indirection, not yet handled."); } // TODO if (field.Count > 0) { throw new NotImplementedException("Indirection.Count > 0 && field.Count > 0"); } var indirection = field.Indirections[0]; // TODO: depth needs fixing? var offset = Reader.ReadUInt32(); if (indirection == 0x03) { pointer = true; if (offset == 0) { structEntry.Add(field.FieldName, new NTROSerialization.NTROValue <byte?>(field.Type, (byte?)null, true)); //being byte shouldn't matter return; } prevOffset = Reader.BaseStream.Position; Reader.BaseStream.Position += offset - 4; } else if (indirection == 0x04) { count = Reader.ReadUInt32(); prevOffset = Reader.BaseStream.Position; if (count > 0) { Reader.BaseStream.Position += offset - 8; } } else { throw new NotImplementedException(string.Format("Unknown indirection. ({0})", indirection)); } } //if (pointer) //{ // Writer.Write("{0} {1}* = (ptr) ->", ValveDataType(field.Type), field.FieldName); //} if (field.Count > 0 || field.Indirections.Count > 0) { var ntroValues = new NTROSerialization.NTROArray(field.Type, (int)count, pointer, field.Indirections.Count > 0); for (var i = 0; i < count; i++) { ntroValues[i] = ReadField(field, pointer); } structEntry.Add(field.FieldName, ntroValues); } else { for (var i = 0; i < count; i++) { structEntry.Add(field.FieldName, ReadField(field, pointer)); } } if (prevOffset > 0) { Reader.BaseStream.Position = prevOffset; } }
private void ReadFieldIntrospection(ResourceIntrospectionManifest.ResourceDiskStruct.Field field, ref NTROStruct structEntry) { var count = (uint)field.Count; var pointer = false; // TODO: get rid of this if (count == 0) { count = 1; } long prevOffset = 0; if (field.Indirections.Count > 0) { // TODO if (field.Indirections.Count > 1) { throw new NotImplementedException("More than one indirection, not yet handled."); } // TODO if (field.Count > 0) { throw new NotImplementedException("Indirection.Count > 0 && field.Count > 0"); } var indirection = field.Indirections[0]; // TODO: depth needs fixing? var offset = Reader.ReadUInt32(); if (indirection == 0x03) { pointer = true; if (offset == 0) { structEntry.Add(field.FieldName, new NTROValue<byte?>(field.Type, null, true)); //being byte shouldn't matter return; } prevOffset = Reader.BaseStream.Position; Reader.BaseStream.Position += offset - 4; } else if (indirection == 0x04) { count = Reader.ReadUInt32(); prevOffset = Reader.BaseStream.Position; if (count > 0) { Reader.BaseStream.Position += offset - 8; } } else { throw new NotImplementedException(string.Format("Unknown indirection. ({0})", indirection)); } } //if (pointer) //{ // Writer.Write("{0} {1}* = (ptr) ->", ValveDataType(field.Type), field.FieldName); //} if (field.Count > 0 || field.Indirections.Count > 0) { var ntroValues = new NTROArray(field.Type, (int)count, pointer, field.Indirections.Count > 0); for (var i = 0; i < count; i++) { ntroValues[i] = ReadField(field, pointer); } structEntry.Add(field.FieldName, ntroValues); } else { for (var i = 0; i < count; i++) { structEntry.Add(field.FieldName, ReadField(field, pointer)); } } if (prevOffset > 0) { Reader.BaseStream.Position = prevOffset; } }