public void InjectDds(TagSerializer serializer, TagDeserializer deserializer, Bitmap bitmap, int imageIndex, Stream ddsStream)
        {
            // Deserialize the old definition
            var resourceContext = new ResourceSerializationContext(bitmap.Resources[imageIndex].Resource);
            var definition = deserializer.Deserialize<BitmapTextureResourceDefinition>(resourceContext);
            if (definition.Texture == null || definition.Texture.Definition == null)
                throw new ArgumentException("Invalid bitmap definition");
            var texture = definition.Texture.Definition;

            // Read the DDS header and modify the definition to match
            var dds = DdsHeader.Read(ddsStream);
            var dataSize = (int)(ddsStream.Length - ddsStream.Position);
            texture.Data = new ResourceDataReference(dataSize, new ResourceAddress(ResourceAddressType.Resource, 0));
            texture.Width = (short)dds.Width;
            texture.Height = (short)dds.Height;
            texture.Depth = (sbyte)Math.Max(1, dds.Depth);
            texture.Levels = (sbyte)Math.Max(1, dds.MipMapCount);
            texture.Type = BitmapDdsFormatDetection.DetectType(dds);
            texture.D3DFormatUnused = (int)((dds.D3D10Format != DxgiFormat.Bc5UNorm) ? dds.FourCc : DdsFourCc.FromString("ATI2"));
            texture.Format = BitmapDdsFormatDetection.DetectFormat(dds);

            // Set flags based on the format
            switch (definition.Texture.Definition.Format)
            {
                case BitmapFormat.Dxt1:
                case BitmapFormat.Dxt3:
                case BitmapFormat.Dxt5:
                case BitmapFormat.Dxn:
                    definition.Texture.Definition.Flags = BitmapFlags.Compressed;
                    break;
                default:
                    definition.Texture.Definition.Flags = BitmapFlags.None;
                    break;
            }

            // Inject the resource data
            _resourceManager.Replace(bitmap.Resources[imageIndex].Resource, ddsStream);

            // Serialize the new resource definition
            serializer.Serialize(resourceContext, definition);

            // Modify the image data in the bitmap tag to match the definition
            var imageData = bitmap.Images[imageIndex];
            imageData.Width = texture.Width;
            imageData.Height = texture.Height;
            imageData.Depth = texture.Depth;
            imageData.Type = texture.Type;
            imageData.Format = texture.Format;
            imageData.Flags = texture.Flags;
            imageData.MipmapCount = (sbyte)(texture.Levels - 1);
            imageData.DataOffset = texture.Data.Address.Offset;
            imageData.DataSize = texture.Data.Size;
        }
        public void InjectDds(TagSerializer serializer, TagDeserializer deserializer, Bitmap bitmap, int imageIndex, Stream ddsStream)
        {
            var resource = bitmap.Resources[imageIndex].Resource;
            var newResource = (resource == null);
            ResourceSerializationContext resourceContext;
            BitmapTextureResourceDefinition definition;
            if (newResource)
            {
                // Create a new resource reference
                resource = new ResourceReference
                {
                    DefinitionFixups = new List<ResourceDefinitionFixup>(),
                    D3DObjectFixups = new List<D3DObjectFixup>(),
                    Type = 1, // TODO: Map out this type enum instead of using numbers
                    Unknown68 = 1
                };
                bitmap.Resources[imageIndex].Resource = resource;
                resourceContext = new ResourceSerializationContext(resource);
                definition = new BitmapTextureResourceDefinition
                {
                    Texture = new D3DPointer<BitmapTextureResourceDefinition.BitmapDefinition>
                    {
                        Definition = new BitmapTextureResourceDefinition.BitmapDefinition()
                    }
                };
            }
            else
            {
                // Deserialize the old definition
                resourceContext = new ResourceSerializationContext(resource);
                definition = deserializer.Deserialize<BitmapTextureResourceDefinition>(resourceContext);
            }
            if (definition.Texture == null || definition.Texture.Definition == null)
                throw new ArgumentException("Invalid bitmap definition");
            var texture = definition.Texture.Definition;
            var imageData = bitmap.Images[imageIndex];

            // Read the DDS header and modify the definition to match
            var dds = DdsHeader.Read(ddsStream);
            var dataSize = (int)(ddsStream.Length - ddsStream.Position);
            texture.Data = new ResourceDataReference(dataSize, new ResourceAddress(ResourceAddressType.Resource, 0));
            texture.Width = (short)dds.Width;
            texture.Height = (short)dds.Height;
            texture.Depth = (sbyte)Math.Max(1, dds.Depth);
            texture.Levels = (sbyte)Math.Max(1, dds.MipMapCount);
            texture.Type = BitmapDdsFormatDetection.DetectType(dds);
            texture.D3DFormatUnused = (int)((dds.D3D10Format != DxgiFormat.Bc5UNorm) ? dds.FourCc : DdsFourCc.FromString("ATI2"));
            texture.Format = BitmapDdsFormatDetection.DetectFormat(dds);

            // Set flags based on the format
            switch (texture.Format)
            {
                case BitmapFormat.Dxt1:
                case BitmapFormat.Dxt3:
                case BitmapFormat.Dxt5:
                case BitmapFormat.Dxn:
                    texture.Flags = BitmapFlags.Compressed;
                    break;
                default:
                    texture.Flags = BitmapFlags.None;
                    break;
            }
            if ((texture.Width & (texture.Width - 1)) == 0 && (texture.Height & (texture.Height - 1)) == 0)
                texture.Flags |= BitmapFlags.PowerOfTwoDimensions;

            // If creating a new image, then add a new resource, otherwise replace the existing one
            if (newResource)
                _resourceManager.Add(resource, ResourceLocation.Textures, ddsStream);
            else
                _resourceManager.Replace(resource, ddsStream);

            // Serialize the new resource definition
            serializer.Serialize(resourceContext, definition);

            // Modify the image data in the bitmap tag to match the definition
            imageData.Width = texture.Width;
            imageData.Height = texture.Height;
            imageData.Depth = texture.Depth;
            imageData.Type = texture.Type;
            imageData.Format = texture.Format;
            imageData.Flags = texture.Flags;
            imageData.MipmapCount = (sbyte)(texture.Levels - 1);
            imageData.DataOffset = texture.Data.Address.Offset;
            imageData.DataSize = texture.Data.Size;
            imageData.Unknown15 = texture.Unknown35;
        }
 private void SerializeDefinitionData(TagSerializer serializer, RenderGeometryResourceDefinition definition)
 {
     _model.Geometry.Resource = new ResourceReference
     {
         Type = 5, // FIXME: hax
         DefinitionFixups = new List<ResourceDefinitionFixup>(),
         D3DObjectFixups = new List<D3DObjectFixup>(),
         Unknown68 = 1,
     };
     var context = new ResourceSerializationContext(_model.Geometry.Resource);
     serializer.Serialize(context, definition);
 }
        private void BuildResourceData(TagSerializer serializer, Stream resourceDataStream)
        {
            var definition = new RenderGeometryResourceDefinition();
            definition.VertexBuffers = new List<D3DPointer<VertexBufferDefinition>>();
            definition.IndexBuffers = new List<D3DPointer<IndexBufferDefinition>>();
            foreach (var mesh in _meshes)
            {
                // Serialize the mesh's vertex buffer
                var vertexBufferStart = (int)resourceDataStream.Position;
                var vertexCount = SerializeVertexBuffer(mesh, resourceDataStream);
                var vertexBufferEnd = (int)resourceDataStream.Position;

                // Add a definition for it
                mesh.Mesh.VertexBuffers[0] = (ushort)definition.VertexBuffers.Count;
                definition.VertexBuffers.Add(new D3DPointer<VertexBufferDefinition>
                {
                    Definition = new VertexBufferDefinition
                    {
                        Count = vertexCount,
                        Format = mesh.VertexFormat,
                        VertexSize = VertexSizes[mesh.VertexFormat],
                        Data = new ResourceDataReference(vertexBufferEnd - vertexBufferStart, new ResourceAddress(ResourceAddressType.Resource, vertexBufferStart)),
                    },
                });

                // Serialize the mesh's index buffer
                var indexBufferStart = vertexBufferEnd;
                SerializeIndexBuffer(mesh, resourceDataStream);
                var indexBufferEnd = (int)resourceDataStream.Position;

                // Add a definition for it
                mesh.Mesh.IndexBuffers[0] = (ushort)definition.IndexBuffers.Count;
                definition.IndexBuffers.Add(new D3DPointer<IndexBufferDefinition>
                {
                    Definition = new IndexBufferDefinition
                    {
                        Type = mesh.Mesh.IndexBufferType,
                        Data = new ResourceDataReference(indexBufferEnd - indexBufferStart, new ResourceAddress(ResourceAddressType.Resource, indexBufferStart)),
                    },
                });
            }
            SerializeDefinitionData(serializer, definition);
        }
        /// <summary>
        /// Builds a model tag and resource data.
        /// </summary>
        /// <param name="serializer">The tag serializer to use to serialize the model definition data.</param>
        /// <param name="resourceDataStream">The stream to write resource data to.</param>
        /// <returns></returns>
        /// <exception cref="System.InvalidOperationException">Cannot build a model if a region is active</exception>
        public RenderModel Build(TagSerializer serializer, Stream resourceDataStream)
        {
            if (_currentRegion != null)
                throw new InvalidOperationException("Cannot build a model if a region is active");

            CompressVertices();
            BuildResourceData(serializer, resourceDataStream);
            return _model;
        }