using SharpDX; using SharpDX.Direct3D11; using System.Collections.Generic; using System.Runtime.InteropServices; namespace VoidwalkerEngine.Framework.DirectX.Rendering { public enum FaceVisibilityOptions { None = 0, Front = 1, Back = 2, Left = 4, Right = 8, Top = 16, Bottom = 32, All = Front | Back | Left | Right | Top | Bottom } public class BrushVolume { public Vector3 Location { get; set; } public int Width { get; private set; } public int Height { get; private set; } public int Depth { get; private set; } public FaceVisibilityOptions FaceVisibility { get; private set; } public Material DiffuseMaterial { get; set; } public Device Device; private Buffer _vertexBuffer; private const float _stride = 16; // 36 Vertices maximum private int _drawCount; public BrushVolume(Device device, Material diffuseMaterial, int width, int height, int length, FaceVisibilityOptions visibilityOptions) { this.Device = device; this.Width = width; this.Height = height; this.Depth = length; this.FaceVisibility = visibilityOptions; this.DiffuseMaterial = diffuseMaterial; Rebuild(); } public void Resize(int width, int height, int depth) { this.Width = width; this.Height = height; this.Depth = depth; Rebuild(); } public void Rebuild(int width, int height, int depth, FaceVisibilityOptions visibilityOptions) { this.Width = width; this.Height = height; this.Depth = depth; this.FaceVisibility = visibilityOptions; Rebuild(); } public void SetFaceVisibility(FaceVisibilityOptions visibilityOptions) { this.FaceVisibility = visibilityOptions; Rebuild(); } private int CountVisibleFaces(FaceVisibilityOptions visibilityOptions) { int value = (int)visibilityOptions; value -= ((value >> 1) & 1431655765); value = (value & 858993459) + ((value >> 2) & 858993459); int count = ((value + (value >> 4) & 252645135) * 16843009) >> 24; return count; } public void Rebuild() { Vertex[] vertices = new Vertex[CountVisibleFaces(this.FaceVisibility) * 6]; float width = _stride * this.Width; float height = _stride * this.Height; float depth = _stride * this.Depth; float uvX = width / _stride; float uvY = height / _stride; float uvZ = depth / _stride; // Generate Front Face int index = 0; if (this.FaceVisibility.HasFlag(FaceVisibilityOptions.Front)) { Vector3 normal = new Vector3(0, 0, -1); vertices[index++] = new Vertex(new Vector3(-width, height, -depth), new Vector2(-uvX, -uvY), normal); vertices[index++] = new Vertex(new Vector3(width, -height, -depth), new Vector2(0, 0), normal); vertices[index++] = new Vertex(new Vector3(-width, -height, -depth), new Vector2(-uvX, 0), normal); vertices[index++] = new Vertex(new Vector3(-width, height, -depth), new Vector2(-uvX, -uvY), normal); vertices[index++] = new Vertex(new Vector3(width, height, -depth), new Vector2(0, -uvY), normal); vertices[index++] = new Vertex(new Vector3(width, -height, -depth), new Vector2(0, 0), normal); } // Generate Back Face if (this.FaceVisibility.HasFlag(FaceVisibilityOptions.Back)) { Vector3 normal = new Vector3(0, 0, 1); vertices[index++] = new Vertex(new Vector3(width, height, depth), new Vector2(-uvX, -uvY), normal); vertices[index++] = new Vertex(new Vector3(-width, -height, depth), new Vector2(0, 0), normal); vertices[index++] = new Vertex(new Vector3(width, -height, depth), new Vector2(-uvX, 0), normal); vertices[index++] = new Vertex(new Vector3(width, height, depth), new Vector2(-uvX, -uvY), normal); vertices[index++] = new Vertex(new Vector3(-width, height, depth), new Vector2(0, -uvY), normal); vertices[index++] = new Vertex(new Vector3(-width, -height, depth), new Vector2(0, 0), normal); } // Generate Right Face if (this.FaceVisibility.HasFlag(FaceVisibilityOptions.Right)) { Vector3 normal = new Vector3(1, 0, 0); vertices[index++] = new Vertex(new Vector3(width, height, -depth), new Vector2(-uvZ, -uvY), normal); vertices[index++] = new Vertex(new Vector3(width, -height, depth), new Vector2(0, 0), normal); vertices[index++] = new Vertex(new Vector3(width, -height, -depth), new Vector2(-uvZ, 0), normal); vertices[index++] = new Vertex(new Vector3(width, height, -depth), new Vector2(-uvZ, -uvY), normal); vertices[index++] = new Vertex(new Vector3(width, height, depth), new Vector2(0, -uvY), normal); vertices[index++] = new Vertex(new Vector3(width, -height, depth), new Vector2(0, 0), normal); } // Generate Left Face if (this.FaceVisibility.HasFlag(FaceVisibilityOptions.Left)) { Vector3 normal = new Vector3(-1, 0, 0); vertices[index++] = new Vertex(new Vector3(-width, height, depth), new Vector2(-uvZ, -uvY), normal); vertices[index++] = new Vertex(new Vector3(-width, -height, -depth), new Vector2(0, 0), normal); vertices[index++] = new Vertex(new Vector3(-width, -height, depth), new Vector2(-uvZ, 0), normal); vertices[index++] = new Vertex(new Vector3(-width, height, depth), new Vector2(-uvZ, -uvY), normal); vertices[index++] = new Vertex(new Vector3(-width, height, -depth), new Vector2(0, -uvY), normal); vertices[index++] = new Vertex(new Vector3(-width, -height, -depth), new Vector2(0, 0), normal); } // Generate Bottom Face if (this.FaceVisibility.HasFlag(FaceVisibilityOptions.Bottom)) { Vector3 normal = new Vector3(0, -1, 0); vertices[index++] = new Vertex(new Vector3(-width, -height, depth), new Vector2(-uvZ, -uvX), normal); vertices[index++] = new Vertex(new Vector3(width, -height, -depth), new Vector2(0, 0), normal); vertices[index++] = new Vertex(new Vector3(width, -height, depth), new Vector2(-uvZ, 0), normal); vertices[index++] = new Vertex(new Vector3(-width, -height, depth), new Vector2(-uvZ, -uvX), normal); vertices[index++] = new Vertex(new Vector3(-width, -height, -depth), new Vector2(0, -uvX), normal); vertices[index++] = new Vertex(new Vector3(width, -height, -depth), new Vector2(0, 0), normal); } // Generate Top Face if (this.FaceVisibility.HasFlag(FaceVisibilityOptions.Top)) { Vector3 normal = new Vector3(0, 1, 0); vertices[index++] = new Vertex(new Vector3(width, height, depth), new Vector2(-uvZ, -uvX), normal); vertices[index++] = new Vertex(new Vector3(-width, height, -depth), new Vector2(0, 0), normal); vertices[index++] = new Vertex(new Vector3(-width, height, depth), new Vector2(-uvZ, 0), normal); vertices[index++] = new Vertex(new Vector3(width, height, depth), new Vector2(-uvZ, -uvX), normal); vertices[index++] = new Vertex(new Vector3(width, height, -depth), new Vector2(0, -uvX), normal); vertices[index++] = new Vertex(new Vector3(-width, height, -depth), new Vector2(0, 0), normal); } if (this._vertexBuffer != null) { this._vertexBuffer.Dispose(); } this._drawCount = vertices.Length; _vertexBuffer = Buffer.Create(Device, BindFlags.VertexBuffer, vertices); } public void Draw(DeviceContext context) { context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(this._vertexBuffer, Marshal.SizeOf(), 0)); if (DiffuseMaterial != null) { context.PixelShader.SetShaderResource(0, DiffuseMaterial.ResourceView); context.PixelShader.SetSampler(0, DiffuseMaterial.SamplerState); } context.Draw(_drawCount, 0); } } }