private void ParseSceneryObjectsBlock(BinaryReader reader) { reader.BaseStream.Position = 0x15B0C; reader.BaseStream.Position += 1800; //jump over unknown index int objectDescriptorCount = reader.ReadInt32(); int objectCount = reader.ReadInt32(); reader.ReadChars(4); //'OBJS' reader.BaseStream.Position += 8; for (int i = 0; i < objectDescriptorCount; i++) { SceneryObjectDescriptor sd = new SceneryObjectDescriptor(); byte[] bytes = reader.ReadBytes(16); sd.Flags = (SceneryFlags)bytes[0]; sd.Type = (SceneryType)bytes[1]; sd.Width = BitConverter.ToInt16(bytes, 6); sd.Width *= GameConfig.TerrainScale * 65000; sd.Height = BitConverter.ToInt16(bytes, 14); sd.Height *= GameConfig.TerrainScale * 65000; sd.ResourceId = bytes[2]; if (sd.Type == SceneryType.TwoSidedBitmap) { sd.Resource2Id = bytes[3]; } if ((sd.Flags & SceneryFlags.Animated) == SceneryFlags.Animated) { sd.AnimationFrameCount = bytes[8]; } sd.Id = ObjectDescriptors.Count; ObjectDescriptors.Add(sd); } long currentPos = reader.BaseStream.Position; for (int i = 0; i < objectCount; i++) { int referenceNode = reader.ReadInt32(); if (referenceNode == -1) { break; } SceneryObject obj = new SceneryObject(); obj.ReferenceNode = referenceNode % Nodes.Count; //why do some tracks reference nodes above the node count? int descriptorRef = reader.ReadByte(); obj.Descriptor = ObjectDescriptors[descriptorRef]; obj.Orientation = (float)reader.ReadByte(); byte[] flags = reader.ReadBytes(4); obj.RelativePosition = new Vector3(reader.ReadInt16(), reader.ReadInt16(), -reader.ReadInt16()); Scenery.Add(obj); } reader.BaseStream.Position = currentPos + 16000; //jump to end of billboards reader.BaseStream.Position += 492; //blank space }