using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Text; using System.Windows.Forms; using Microsoft.DirectX; using Microsoft.DirectX.Direct3D; using System.Drawing; namespace GoatCheez_KO_Private_Server_Map_Editor { public partial class View3DControl : UserControl { public enum SpatialPlane { PlaneXZ, PlaneXY, PlaneZY } private Device d3dDevice = null; private bool valid = false; private PresentParameters presentParameters; private Single cameraX = 50f; private Single cameraY = 50f; private Single cameraZ = -50f; private Single lookAtX = 0f; private Single lookAtY = 0f; private Single lookAtZ = 0f; private Single upX = 0f; private Single upY = 1f; private Single upZ = 0f; private Single fov = ((Single)(Math.PI / 4)); //45 degrees private Single clipNear = 0; private Single clipFar = 1000f; private string labelText = ""; private Microsoft.DirectX.Direct3D.Font labelStyle; private Int32 labelX = 2; private Int32 labelY = 2; private bool showGrid = true; private VertexBuffer gridLineBuffer; private SpatialPlane gridPlane = SpatialPlane.PlaneXZ; private Single gridSize = 500f; private Single gridSpacing = 25f; private Int32 gridLineCount = 0; private CreateFlags createFlags; private VertexBuffer userDataBuffer; CustomVertex.PositionColored[] userDataVertices; #region construction and initialization public View3DControl() { InitializeComponent(); this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true); } ~View3DControl() { valid = false; if (d3dDevice != null) d3dDevice.Dispose(); if (gridLineBuffer != null) gridLineBuffer.Dispose(); if (labelStyle != null) labelStyle.Dispose(); } private bool InitializeDirect3D() { try { presentParameters = new PresentParameters(); presentParameters.BackBufferFormat = Format.Unknown; presentParameters.Windowed = true; presentParameters.SwapEffect = SwapEffect.Discard; presentParameters.EnableAutoDepthStencil = true; presentParameters.AutoDepthStencilFormat = DepthFormat.D16; presentParameters.PresentationInterval = PresentInterval.Immediate; Caps caps = Manager.GetDeviceCaps(Manager.Adapters.Default.Adapter, DeviceType.Hardware); if (caps.DeviceCaps.SupportsHardwareTransformAndLight) { createFlags = CreateFlags.HardwareVertexProcessing; } else { createFlags = CreateFlags.SoftwareVertexProcessing; } d3dDevice = CreateD3DDevice(); d3dDevice.DeviceReset += new EventHandler(this.d3dDevice_DeviceReset); return true; } catch (Exception eX) { MessageBox.Show("Unable to initialize Direct3D." + Environment.NewLine + eX.Message); return false; } } private Device CreateD3DDevice() { Device device = new Device(0, DeviceType.Hardware, this, createFlags, presentParameters); SetupTransformMatrices(device); SetupRenderState(device); return device; } private void SetupRenderState(Device device) { device.RenderState.ZBufferEnable = true; device.RenderState.CullMode = Cull.None; device.RenderState.Lighting = false; device.RenderState.PointSize = 4.0f; device.RenderState.FillMode = FillMode.Solid; } private void SetupTransformMatrices(Device device) { device.Transform.World = Matrix.Identity; device.Transform.Projection = Matrix.PerspectiveFovLH(fov, ((Single)(this.Width)) / ((Single)(this.Height)), clipNear, clipFar); device.Transform.View = Matrix.LookAtLH( new Vector3(cameraX, cameraY, cameraZ), new Vector3(lookAtX, lookAtY, lookAtZ), new Vector3(upX, upY, upZ)); } #endregion #region data creation methods private void CreateDeviceObjects(Device device) { CreateLabel(device); CreateGridLines(device); CreateUserData(device); } private void CreateGridLines(Device device) { if (valid && device != null) { List newGridVertices = new List(); if (gridPlane == SpatialPlane.PlaneXZ) { newGridVertices.Add(new CustomVertex.PositionColored(-1 * gridSize, 0f, 0f, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(gridSize, 0f, 0f, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(0f, 0f, -1 * gridSize, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(0f, 0f, gridSize, Color.White.ToArgb())); for (float marker = 0; marker <= gridSize; marker += gridSpacing) { newGridVertices.Add(new CustomVertex.PositionColored(marker, 0f, -1 * gridSize, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(marker, 0f, gridSize, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(-marker, 0f, -1 * gridSize, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(-marker, 0f, gridSize, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(-1 * gridSize, 0f, marker, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(gridSize, 0f, marker, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(-1 * gridSize, 0f, -marker, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(gridSize, 0f, -marker, Color.White.ToArgb())); } } else if (gridPlane == SpatialPlane.PlaneXY) { newGridVertices.Add(new CustomVertex.PositionColored(-1 * gridSize, 0f, 0f, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(gridSize, 0f, 0f, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(0f, -1 * gridSize, 0f, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(0f, gridSize, 0f, Color.White.ToArgb())); for (float marker = 0; marker <= gridSize; marker += gridSpacing) { newGridVertices.Add(new CustomVertex.PositionColored(marker, -1 * gridSize, 0f, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(marker, gridSize, 0f, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(-marker, -1 * gridSize, 0f, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(-marker, gridSize, 0f, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(-1 * gridSize, marker, 0f, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(gridSize, marker, 0f, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(-1 * gridSize, -marker, 0f, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(gridSize, -marker, 0f, Color.White.ToArgb())); } } else if (gridPlane == SpatialPlane.PlaneZY) { newGridVertices.Add(new CustomVertex.PositionColored(0f, -1 * gridSize, 0f, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(0f, gridSize, 0f, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(0f, 0f, -1 * gridSize, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(0f, 0f, gridSize, Color.White.ToArgb())); for (float marker = 0; marker <= gridSize; marker += gridSpacing) { newGridVertices.Add(new CustomVertex.PositionColored(0f, marker, -1 * gridSize, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(0f, marker, gridSize, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(0f, -marker, -1 * gridSize, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(0f, -marker, gridSize, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(0f, -1 * gridSize, marker, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(0f, gridSize, marker, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(0f, -1 * gridSize, -marker, Color.White.ToArgb())); newGridVertices.Add(new CustomVertex.PositionColored(0f, gridSize, -marker, Color.White.ToArgb())); } } if (gridLineBuffer != null) gridLineBuffer.Dispose(); gridLineBuffer = new VertexBuffer(typeof(CustomVertex.PositionColored), newGridVertices.Count, device, Usage.Dynamic | Usage.WriteOnly, CustomVertex.PositionColored.Format, Pool.Default); using (GraphicsStream graphicsStream = gridLineBuffer.Lock(0, 0, 0)) { CustomVertex.PositionColored[] verts = newGridVertices.ToArray(); graphicsStream.Write(verts); } gridLineBuffer.Unlock(); gridLineCount = newGridVertices.Count / 2; } } private void CreateLabel(Device device) { if (valid && device != null) { if (labelStyle != null) labelStyle.Dispose(); labelStyle = new Microsoft.DirectX.Direct3D.Font(device, this.Font); } } private void CreateUserData(Device device) { if (valid && (device != null) && (userDataVertices != null)) { if (userDataBuffer != null) userDataBuffer.Dispose(); userDataBuffer = new VertexBuffer(typeof(CustomVertex.PositionColored), userDataVertices.Length, device, Usage.WriteOnly | Usage.Dynamic, CustomVertex.PositionColored.Format, Pool.Default); using (GraphicsStream graphicsStream = userDataBuffer.Lock(0, 0, 0)) { graphicsStream.Write(userDataVertices); } userDataBuffer.Unlock(); } } #endregion #region paint methods private void PaintLabel() { if (valid && (labelStyle != null) && (d3dDevice != null)) { labelStyle.DrawText(null, labelText, labelX, labelY, this.ForeColor); } } private void PaintAxisGrid() { if (valid && (d3dDevice != null) && (gridLineBuffer != null) && (gridLineCount > 0)) { d3dDevice.VertexFormat = CustomVertex.PositionColored.Format; d3dDevice.SetStreamSource(0, gridLineBuffer, 0); d3dDevice.DrawPrimitives(PrimitiveType.LineList, 0, gridLineCount); } } private void PaintUserData() { if (valid && (d3dDevice != null) && (userDataBuffer != null) && (userDataVertices != null)) { d3dDevice.VertexFormat = CustomVertex.PositionColored.Format; d3dDevice.SetStreamSource(0, userDataBuffer, 0); d3dDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, userDataVertices.Length / 3); } } #endregion #region Public Properties public Single CameraX { get { return cameraX; } set { cameraX = value; } } public Single CameraY { get { return cameraY; } set { cameraY = value; } } public Single CameraZ { get { return cameraZ; } set { cameraZ = value; } } public Single LookAtX { get { return lookAtX; } set { lookAtX = value; } } public Single LookAtY { get { return lookAtY; } set { lookAtY = value; } } public Single LookAtZ { get { return lookAtZ; } set { lookAtZ = value; } } public Single UpX { get { return upX; } set { upX = value; } } public Single UpY { get { return upY; } set { upY = value; } } public Single UpZ { get { return upZ; } set { upZ = value; } } public Single FieldOfView { get { return fov; } set { fov = value; } } public Single ClippingPlaneNear { get { return clipNear; } set { clipNear = value; } } public Single ClippingPlaneFar { get { return clipFar; } set { clipFar = value; } } public string Label { get { return labelText; } set { labelText = value; this.Refresh(); } } public Int32 LabelX { get { return labelX; } set { labelX = value; } } public Int32 LabelY { get { return labelY; } set { labelY = value; } } public bool ShowAxisGrid { get { return showGrid; } set { showGrid = value; CreateGridLines(d3dDevice); this.Refresh(); } } public SpatialPlane GridPlane { get { return gridPlane; } set { gridPlane = value; CreateGridLines(d3dDevice); this.Refresh(); } } public Single GridSize { get { return gridSize; } set { gridSize = value; CreateGridLines(d3dDevice); this.Refresh(); } } public Single GridSpacing { get { return gridSpacing; } set { gridSpacing = value; CreateGridLines(d3dDevice); this.Refresh(); } } #endregion #region events void d3dDevice_DeviceReset(object sender, EventArgs e) { SetupTransformMatrices((Device)sender); SetupRenderState((Device)sender); CreateDeviceObjects((Device)sender); valid = true; } private void View3DControl_Paint(object sender, PaintEventArgs e) { if (valid) { d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); d3dDevice.BeginScene(); SetupTransformMatrices(d3dDevice); PaintAxisGrid(); PaintUserData(); PaintLabel(); d3dDevice.EndScene(); d3dDevice.Present(); } } private void View3DControl_Load(object sender, EventArgs e) { valid = InitializeDirect3D(); CreateDeviceObjects(d3dDevice); } private void View3DControl_FontChanged(object sender, EventArgs e) { this.Refresh(); } private void View3DControl_ForeColorChanged(object sender, EventArgs e) { this.Refresh(); } private void View3DControl_Resize(object sender, EventArgs e) { valid = false; } private void View3DControl_MouseMove(object sender, MouseEventArgs e) { } protected override void OnMouseWheel(MouseEventArgs e) { base.OnMouseWheel(e); if (e.Delta != 0) { Vector3 cameraVector = new Vector3(cameraX, cameraY, CameraZ); Vector3 lookAtVector = new Vector3(lookAtX, lookAtY, lookAtZ); cameraVector.Subtract(lookAtVector); cameraVector.X *= -1f * (gridSpacing * e.Delta / 12000f); cameraVector.Y *= -1f * (gridSpacing * e.Delta / 12000f); cameraVector.Z *= -1f * (gridSpacing * e.Delta / 12000f); cameraX += cameraVector.X; cameraY += cameraVector.Y; cameraZ += cameraVector.Z; lookAtX += cameraVector.X; lookAtY += cameraVector.Y; lookAtZ += cameraVector.Z; } this.Refresh(); } private void View3DControl_MouseDown(object sender, MouseEventArgs e) { } private void View3DControl_MouseHover(object sender, EventArgs e) { this.Focus(); } private void View3DControl_MouseEnter(object sender, EventArgs e) { this.Focus(); } #endregion events #region public methods public void SetData(CustomVertex.PositionColored[] vertices) { userDataVertices = vertices; CreateUserData(d3dDevice); } #endregion } }