/// <summary> /// Read the <see cref="Bounds"/> from the <paramref name="reader"/>. /// </summary> /// <param name="reader">The <see cref="BinaryReader"/> to read the <see cref="Bounds"/> from.</param> /// <returns>The new <see cref="Bounds"/> object.</returns> public static Bounds Read(BinaryReader reader) { return new Bounds() { Box = new Box3f(reader.ReadVector3f(), reader.ReadVector3f()), Valid = reader.ReadByte() != 0 }; }
public MDXSubmesh(byte[] data) { using (MemoryStream ms = new MemoryStream(data)) { using (BinaryReader br = new BinaryReader(ms)) { this.PartID = br.ReadUInt32(); this.StartVertexIndex = br.ReadUInt16(); this.VertexCount = br.ReadUInt16(); this.StartTriangleIndex = br.ReadUInt16(); this.TriangleCount = br.ReadUInt16(); this.BoneCount = br.ReadUInt16(); this.StartBoneIndex = br.ReadUInt16(); this.InfluencingBonesIndex = br.ReadUInt16(); this.RootBoneIndex = br.ReadUInt16(); this.SubmeshMedianPoint = br.ReadVector3f(); if (br.BaseStream.Length > 32) { this.BoundingShellMedianPoint = br.ReadVector3f(); this.BoundingSphereRadius = br.ReadSingle(); } } } }
public MDXVertex(byte[] data) { using (MemoryStream ms = new MemoryStream(data)) { using (BinaryReader br = new BinaryReader(ms)) { this.Position = br.ReadVector3f(); this.BoneWeights = new List<byte>(br.ReadBytes(4)); this.BoneIndices = new List<byte>(br.ReadBytes(4)); this.Normal = br.ReadVector3f(); this.UVCoordinates_Channel1 = br.ReadVector2f(); this.UVCoordinates_Channel2 = br.ReadVector2f(); } } }
public void LoadBinaryData(byte[] inData) { using (MemoryStream ms = new MemoryStream(inData)) { using (BinaryReader br = new BinaryReader(ms)) { this.WidthVertices = br.ReadUInt32(); this.HeightVertices = br.ReadUInt32(); this.WidthTileFlags = br.ReadUInt32(); this.HeightTileFlags = br.ReadUInt32(); this.Location = br.ReadVector3f(); this.MaterialIndex = br.ReadUInt16(); uint vertexCount = this.WidthVertices * this.HeightVertices; for (int i = 0; i < vertexCount; ++i) { this.LiquidVertices.Add(new LiquidVertex(br.ReadBytes(LiquidVertex.GetSize()))); } uint tileFlagCount = this.WidthTileFlags * this.HeightTileFlags; for (int i = 0; i < tileFlagCount; ++i) { this.LiquidTileFlags.Add((LiquidFlags)br.ReadByte()); } } } }
public void LoadBinaryData(byte[] inData) { using (MemoryStream ms = new MemoryStream(inData)) { using (BinaryReader br = new BinaryReader(ms)) { while (ms.Position < ms.Length) { this.Normals.Add(br.ReadVector3f()); } } } }
public void LoadBinaryData(byte[] inData) { using (MemoryStream ms = new MemoryStream(inData)) { using (BinaryReader br = new BinaryReader(ms)) { int vertexCount = inData.Length / 12; for (int i = 0; i < vertexCount; ++i) { this.VisibleVertices.Add(br.ReadVector3f()); } } } }
public FogInstance(byte[] inData) { using (MemoryStream ms = new MemoryStream(inData)) { using (BinaryReader br = new BinaryReader(ms)) { this.Flags = (FogFlags) br.ReadUInt32(); this.Position = br.ReadVector3f(); this.GlobalStartRadius = br.ReadSingle(); this.GlobalEndRadius = br.ReadSingle(); this.LandFog = new FogDefinition(br.ReadBytes(FogDefinition.GetSize())); this.UnderwaterFog = new FogDefinition(br.ReadBytes(FogDefinition.GetSize())); } } }
public DoodadInstance(byte[] inData) { using (MemoryStream ms = new MemoryStream(inData)) { using (BinaryReader br = new BinaryReader(ms)) { byte[] finalNameBytes = new byte[4]; byte[] nameOffsetBytes = br.ReadBytes(3); Buffer.BlockCopy(nameOffsetBytes, 0, finalNameBytes, 0, 3); this.NameOffset= BitConverter.ToUInt32(finalNameBytes, 0); this.Flags = (DoodadInstanceFlags) br.ReadByte(); this.Position = br.ReadVector3f(); // TODO: Investigate whether or not this is a Quat16 in >= BC this.Orientation = br.ReadQuaternion32(); this.Scale = br.ReadSingle(); this.StaticLightingColour = br.ReadBGRA(); } } }
public MapChunkHeader(byte[] data) { using (MemoryStream ms = new MemoryStream(data)) { using (BinaryReader br = new BinaryReader(ms)) { this.Flags = (MapChunkFlags)br.ReadUInt32(); this.MapIndexX = br.ReadUInt32(); this.MapIndexY = br.ReadUInt32(); this.TextureLayerCount = br.ReadUInt32(); this.ModelReferenceCount = br.ReadUInt32(); if (this.Flags.HasFlag(MapChunkFlags.UsesHighResHoles)) { this.HighResHoles = br.ReadUInt64(); } this.HeightmapOffset = br.ReadUInt32(); this.VertexNormalOffset = br.ReadUInt32(); this.TextureLayersOffset = br.ReadUInt32(); this.ModelReferencesOffset = br.ReadUInt32(); this.AlphaMapsOffset = br.ReadUInt32(); this.AlphaMapsSize = br.ReadUInt32(); this.BakedShadowsOffset = br.ReadUInt32(); this.BakedShadowsSize = br.ReadUInt32(); this.AreaID = br.ReadUInt32(); this.WorldModelObjectReferenceCount = br.ReadUInt32(); // TODO: Turn into bitmapped boolean field if (!this.Flags.HasFlag(MapChunkFlags.UsesHighResHoles)) { this.LowResHoles = br.ReadUInt16(); } this.Unknown = br.ReadUInt16(); // TODO: This is a set of 8 by 8 2-bit integers. Shift and read into a byte array. this.LowResTextureMap = br.ReadUInt16(); this.predTex = br.ReadUInt32(); this.noEffectDoodad = br.ReadUInt32(); this.SoundEmittersOffset = br.ReadUInt32(); this.SoundEmitterCount = br.ReadUInt32(); this.LiquidOffset = br.ReadUInt32(); this.LiquidSize = br.ReadUInt32(); this.MapTilePosition = br.ReadVector3f(); if (this.Flags.HasFlag(MapChunkFlags.HasVertexShading)) { this.VertexShadingOffset = br.ReadUInt32(); } } } }
public MDX(Stream MDXStream) { using (BinaryReader br = new BinaryReader(MDXStream)) { // Read Wrath header or read pre-wrath header WarcraftVersion Format = PeekFormat(br); if (Format < WarcraftVersion.Wrath) { this.Header = new MDXHeader(br.ReadBytes(324)); } else { ModelObjectFlags Flags = PeekFlags(br); if (Flags.HasFlag(ModelObjectFlags.HasBlendModeOverrides)) { this.Header = new MDXHeader(br.ReadBytes(308)); } else { this.Header = new MDXHeader(br.ReadBytes(312)); } } // Seek and read model name br.BaseStream.Position = this.Header.NameOffset; this.Name = new string(br.ReadChars((int) this.Header.NameLength)); // Seek to Global Sequences br.BaseStream.Position = this.Header.GlobalSequencesOffset; for (int i = 0; i < this.Header.GlobalSequenceCount; ++i) { this.GlobalSequenceTimestamps.Add(br.ReadUInt32()); } // Seek to Animation Sequences br.BaseStream.Position = this.Header.AnimationSequencesOffset; int sequenceSize = MDXAnimationSequence.GetSize(); for (int i = 0; i < this.Header.AnimationSequenceCount; ++i) { this.AnimationSequences.Add(new MDXAnimationSequence(br.ReadBytes(sequenceSize))); } // Seek to Animation Sequence Lookup Table br.BaseStream.Position = this.Header.AnimationLookupTableOffset; for (int i = 0; i < this.Header.AnimationLookupTableEntryCount; ++i) { this.AnimationSequenceLookupTable.Add(br.ReadInt16()); } if (MDXHeader.GetModelVersion(this.Header.Version) < WarcraftVersion.Wrath) { // Seek to Playable Animations Lookup Table br.BaseStream.Position = this.Header.PlayableAnimationLookupTableOffset; for (int i = 0; i < this.Header.PlayableAnimationLookupTableEntryCount; ++i) { this.PlayableAnimationLookupTable.Add(new MDXPlayableAnimationLookupTableEntry(br.ReadBytes(4))); } } // Seek to bone block br.BaseStream.Position = this.Header.BonesOffset; for (int i = 0; i < this.Header.BoneCount; ++i) { // TODO: properly skip to the next bone record, data is not aligned MDXBone Bone = new MDXBone(); Bone.AnimationID = br.ReadInt32(); Bone.Flags = (MDXBoneFlags)br.ReadUInt32(); Bone.ParentBone = br.ReadInt16(); Bone.SubmeshID = br.ReadUInt16(); if (MDXHeader.GetModelVersion(this.Header.Version) >= WarcraftVersion.BurningCrusade) { Bone.Unknown1 = br.ReadUInt16(); Bone.Unknown1 = br.ReadUInt16(); } // TODO: Rework animation track reading // Read bone animation header block //Bone.AnimatedTranslation = new MDXTrack<Vector3f>(br, MDXHeader.GetModelVersion(Header.Version)); //Bone.AnimatedRotation = new MDXTrack<Quaternion>(br, MDXHeader.GetModelVersion(Header.Version)); //Bone.AnimatedScale = new MDXTrack<Vector3f>(br, MDXHeader.GetModelVersion(Header.Version)); Bone.PivotPoint = br.ReadVector3f(); this.Bones.Add(Bone); } /* // Read bone animation data foreach (MDXBone Bone in Bones) { // Read animation translation block br.BaseStream.Position = Bone.AnimatedTranslation.Values.ElementsOffset; for (int j = 0; j < Bone.AnimatedTranslation.Values.Count; ++j) { Bone.AnimatedTranslation.Values.Add(br.ReadVector3f()); } // Read animation rotation block br.BaseStream.Position = Bone.AnimatedRotation.ValuesOffset; for (int j = 0; j < Bone.AnimatedRotation.ValueCount; ++j) { if (MDXHeader.GetModelVersion(Header.Version) > MDXFormat.Classic) { Bone.AnimatedRotation.Values.Add(br.ReadQuaternion16()); } else { Bone.AnimatedRotation.Values.Add(br.ReadQuaternion32()); } } // Read animation scale block br.BaseStream.Position = Bone.AnimatedScale.ValuesOffset; for (int j = 0; j < Bone.AnimatedScale.ValueCount; ++j) { Bone.AnimatedScale.Values.Add(br.ReadVector3f()); } } */ // Seek to Skeletal Bone Lookup Table br.BaseStream.Position = this.Header.KeyedBoneLookupTablesOffset; for (int i = 0; i < this.Header.KeyedBoneLookupTableCount; ++i) { this.KeyedBoneLookupTable.Add(br.ReadInt16()); } // Seek to vertex block br.BaseStream.Position = this.Header.VerticesOffset; for (int i = 0; i < this.Header.VertexCount; ++i) { this.Vertices.Add(new MDXVertex(br.ReadBytes(48))); } // Seek to view block if (MDXHeader.GetModelVersion(this.Header.Version) < WarcraftVersion.Wrath) { br.BaseStream.Position = this.Header.LODViewsOffset; // Read the view headers for (int i = 0; i < this.Header.LODViewsCount; ++i) { MDXViewHeader ViewHeader = new MDXViewHeader(br.ReadBytes(44)); MDXView View = new MDXView(); View.Header = ViewHeader; this.LODViews.Add(View); } // Read view data foreach (MDXView View in this.LODViews) { // Read view vertex indices View.VertexIndices = new List<ushort>(); br.BaseStream.Position = View.Header.VertexIndicesOffset; for (int j = 0; j < View.Header.VertexIndexCount; ++j) { View.VertexIndices.Add(br.ReadUInt16()); } // Read view triangles View.Triangles = new List<MDXTriangle>(); br.BaseStream.Position = View.Header.TriangleVertexIndicesOffset; for (int j = 0; j < View.Header.TriangleVertexCount / 3; ++j) { MDXTriangle Triangle = new MDXTriangle(br.ReadUInt16(), br.ReadUInt16(), br.ReadUInt16()); View.Triangles.Add(Triangle); } // Read view vertex properties View.VertexProperties = new List<MDXVertexProperty>(); br.BaseStream.Position = View.Header.VertexPropertiesOffset; for (int j = 0; j < View.Header.VertexPropertyCount; ++j) { View.VertexProperties.Add(new MDXVertexProperty(br.ReadByte(), br.ReadByte(), br.ReadByte(), br.ReadByte())); } // Read view submeshes View.Submeshes = new List<MDXSubmesh>(); br.BaseStream.Position = View.Header.SubmeshesOffset; for (int j = 0; j < View.Header.SubmeshCount; ++j) { byte[] submeshData; if (MDXHeader.GetModelVersion(this.Header.Version) >= WarcraftVersion.BurningCrusade) { submeshData = br.ReadBytes(48); } else { submeshData = br.ReadBytes(32); } View.Submeshes.Add(new MDXSubmesh(submeshData)); } View.TextureUnits = new List<MDXTextureUnit>(); br.BaseStream.Position = View.Header.TexturesOffset; for (int j = 0; j < View.Header.TextureCount; ++j) { View.TextureUnits.Add(new MDXTextureUnit(br.ReadBytes(24))); } } } else { throw new NotImplementedException(); } /* // TODO: Rework animation track reading // Seek to submesh animation block br.BaseStream.Position = Header.SubmeshColourAnimationsOffset; for (int i = 0; i < Header.SubmeshColourAnimationCount; ++i) { MDXTrack<RGB> ColourTrack = new MDXTrack<RGB>(br, MDXHeader.GetModelVersion(Header.Version)); MDXTrack<short> OpacityTrack = new MDXTrack<short>(br, MDXHeader.GetModelVersion(Header.Version)); MDXSubmeshColourAnimation ColourAnimation = new MDXSubmeshColourAnimation(); ColourAnimation.ColourTrack = ColourTrack; ColourAnimation.OpacityTrack = OpacityTrack; ColourAnimations.Add(ColourAnimation); } // Read submesh animation values foreach (MDXSubmeshColourAnimation ColourAnimation in ColourAnimations) { // Read the colour track br.BaseStream.Position = ColourAnimation.ColourTrack.ValuesOffset; for (int j = 0; j < ColourAnimation.ColourTrack.ValueCount; ++j) { ColourAnimation.ColourTrack.Values.Add(new RGB(br.ReadVector3f())); } // Read the opacity track br.BaseStream.Position = ColourAnimation.OpacityTrack.ValuesOffset; for (int j = 0; j < ColourAnimation.OpacityTrack.ValueCount; ++j) { ColourAnimation.OpacityTrack.Values.Add(br.ReadInt16()); } } */ // TODO: Use this pattern for the tracks as well, where values are outreferenced // from the block // Seek to Texture definition block br.BaseStream.Position = this.Header.TexturesOffset; for (int i = 0; i < this.Header.TextureCount; ++i) { MDXTexture Texture = new MDXTexture(br.ReadBytes(16)); this.Textures.Add(Texture); } // Read the texture definition strings foreach (MDXTexture Texture in this.Textures) { br.BaseStream.Position = Texture.FilenameOffset; Texture.Filename = new string(br.ReadChars((int)Texture.FilenameLength)); } /* // TODO: Rework animation track reading // Seek to transparency block br.BaseStream.Position = Header.TransparencyAnimationsOffset; for (int i = 0; i < Header.TransparencyAnimationCount; ++i) { TransparencyAnimations.Add(new MDXTrack<short>(br, MDXHeader.GetModelVersion(Header.Version))); } // Read transparency animation block data foreach (MDXTrack<short> TransparencyTrack in TransparencyAnimations) { // Read the opacity track br.BaseStream.Position = TransparencyTrack.ValuesOffset; for (int j = 0; j < TransparencyTrack.ValueCount; ++j) { TransparencyTrack.Values.Add(br.ReadInt16()); } } // TODO: Rework animation track reading // UV Animations br.BaseStream.Position = Header.UVTextureAnimationsOffset; for (int i = 0; i < Header.UVTextureAnimationCount; ++i) { br.BaseStream.Position = Header.UVTextureAnimationsOffset + (i * 84); MDXUVAnimation UVAnimation = new MDXUVAnimation(); UVAnimation.TranslationTrack = new MDXTrack<Vector3f>(br, MDXHeader.GetModelVersion(Header.Version)); UVAnimation.RotationTrack = new MDXTrack<Quaternion>(br, MDXHeader.GetModelVersion(Header.Version)); UVAnimation.ScaleTrack = new MDXTrack<Vector3f>(br, MDXHeader.GetModelVersion(Header.Version)); UVAnimations.Add(UVAnimation); } // Read UV animation track data foreach (MDXUVAnimation UVAnimation in UVAnimations) { // Read animation translation block br.BaseStream.Position = UVAnimation.TranslationTrack.ValuesOffset; for (int j = 0; j < UVAnimation.TranslationTrack.ValueCount; ++j) { UVAnimation.TranslationTrack.Values.Add(br.ReadVector3f()); } // Read animation rotation block br.BaseStream.Position = UVAnimation.RotationTrack.ValuesOffset; for (int j = 0; j < UVAnimation.RotationTrack.ValueCount; ++j) { if (MDXHeader.GetModelVersion(Header.Version) > MDXFormat.Classic) { UVAnimation.RotationTrack.Values.Add(br.ReadQuaternion16()); } else { UVAnimation.RotationTrack.Values.Add(br.ReadQuaternion32()); } } // Read animation scale block br.BaseStream.Position = UVAnimation.ScaleTrack.ValuesOffset; for (int j = 0; j < UVAnimation.ScaleTrack.ValueCount; ++j) { UVAnimation.ScaleTrack.Values.Add(br.ReadVector3f()); } } */ // Replaceable textures // Render flags // Seek to render flag block br.BaseStream.Position = this.Header.RenderFlagsOffset; for (int i = 0; i < this.Header.RenderFlagCount; ++i) { this.RenderFlags.Add(new MDXRenderFlagPair(br.ReadBytes(4))); } // Bone lookup // Texture lookup // Texture unit lookup // Seek to texture unit lookup block br.BaseStream.Position = this.Header.TextureUnitsOffset; for (int i = 0; i < this.Header.TextureUnitCount; ++i) { this.TextureUnitLookupTable.Add(br.ReadInt16()); } // Transparency lookup // Seek to transparency lookup table br.BaseStream.Position = this.Header.TransparencyLookupTablesOffset; for (int i = 0; i < this.Header.TransparencyLookupTableCount; ++i) { this.TransparencyLookupTable.Add(br.ReadInt16()); } // UV animation lookup // Bounding box // Bounding radius // Collision box // Collision radius // Bounding tris // Bounding verts // Bounding normals // Attachments // Attachment lookup // Anim notifies (events) // Lights // Cameras // Camera lookup // Ribbon Emitters // Particle Emitters // Blend maps (if flags say they exist) } }
public override object Read(object target, Package package, BinaryReader reader, long end) { return reader.ReadVector3f(); }
/// <summary></summary> public static Polygon Read(BinaryReader reader, Package package) { int vertexCount = UIndex.Read(reader); Polygon result = new Polygon() { Vertices = new Vector3f[vertexCount], Base = reader.ReadVector3f(), Normal = reader.ReadVector3f(), TextureU = reader.ReadVector3f(), TextureV = reader.ReadVector3f() }; for (var index = 0; index < vertexCount; index++) result.Vertices[index] = reader.ReadVector3f(); result.Flags = reader.ReadInt32(); result.ActorReference = package.ReadReference(reader); result.TextureReference = package.ReadReference(reader); result.ItemName = package.ReadNameValue(reader); result.Link = UIndex.Read(reader); result.BrushPolygon = UIndex.Read(reader); result.PanU = reader.ReadUInt16(); result.PanV = reader.ReadUInt16(); return result; }
/// <summary> /// Initializes a new instance of the <see cref="Warcraft.ADT.Chunks.ModelPlacementEntry"/> class. /// </summary> /// <param name="data">Data.</param> public ModelPlacementEntry(byte[] data) { using (MemoryStream ms = new MemoryStream(data)) { using (BinaryReader br = new BinaryReader(ms)) { this.ModelEntryIndex = br.ReadUInt32(); this.UniqueID = br.ReadUInt32(); this.Position = br.ReadVector3f(); this.Rotation = br.ReadRotator(); this.ScalingFactor = br.ReadUInt16(); this.Flags = (ModelPlacementFlags)br.ReadUInt16(); } } }
public StaticLight(byte[] inData) { using (MemoryStream ms = new MemoryStream(inData)) { using (BinaryReader br = new BinaryReader(ms)) { this.Type = (LightType) br.ReadByte(); this.bUseAttenuation = br.ReadBoolean(); this.bUseUnknown1 = br.ReadBoolean(); this.bUseUnknown2 = br.ReadBoolean(); this.Colour = br.ReadBGRA(); this.Position = br.ReadVector3f(); this.Intensity = br.ReadSingle(); this.AttenuationStartRadius = br.ReadSingle(); this.AttenuationEndRadius = br.ReadSingle(); this.Unknown1StartRadius = br.ReadSingle(); this.Unknown1EndRadius = br.ReadSingle(); this.Unknown2StartRadius = br.ReadSingle(); this.Unknown2EndRadius = br.ReadSingle(); } } }