Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections.Generic;
- using System.Windows.Forms;
- using SlimDX.Direct3D9;
- using SlimDX;
- using System.Drawing;
- using System.Runtime.InteropServices;
- static class Program
- {
- static void Main(string[] args)
- {
- gui = new Model();
- gui.BackColor = System.Drawing.Color.Wheat;
- //gui.Objects.Add(GetMessyBox());
- gui.Objects.Add(GetMess());
- gui.ShowDialog();
- }
- private static Model gui;
- private static ModelObject GetMess()
- {/*Create a lot of objects to demonstrate flashing.*/
- const int messcount = 10000;
- var r = new System.Random();
- var verts = new Vertex[messcount];
- for (int i = 0; i < messcount; i++)
- verts[i] = getvert(r.NextDouble(), r.NextDouble(), r.NextDouble(), 1500);
- return new ModelObject(GetBuff(verts), messcount / 2, PrimitiveType.LineList);
- }
- private static VertexBuffer GetBuff(Vertex[] verts)
- {
- var ret = new VertexBuffer(gui.device, Vertex.Size * verts.Length, Usage.None, VertexFormat.PositionNormal, Pool.Managed);
- var l = ret.Lock(0, 0, LockFlags.None);
- l.WriteRange(verts);
- ret.Unlock();
- return ret;
- }
- private static ModelObject GetMessyBox()
- {
- List<Vertex> verts = new List<Vertex>();
- verts.Add(getvert(0, 0, 0, 200));
- for (int x = 0; x < 3; x++)
- {
- for (int y = 0; y < 3; y++)
- {
- for (int Z = 0; Z < 3; Z++)
- {
- verts.Add(getvert(x, y, Z, 200));
- verts.Add(getvert(x, y, Z, 200));
- }
- }
- }
- verts.Add(getvert(2, 2, 2, 200));
- return new ModelObject(GetBuff(verts.ToArray()), verts.Count / 2, PrimitiveType.LineList);
- }
- private static Vertex getvert(double x, double y, double z, double magnitude)
- {
- return new Vertex(new SlimDX.Vector3((float)(x * magnitude), (float)(y * magnitude), (float)(z * magnitude)), SlimDX.Vector3.Zero);
- }
- }
- //#define PROFILING
- public class Model : Form
- {
- public Model()
- {
- Objects = new List<ModelObject>();
- d3d = new Direct3D();
- device = new Device(d3d, 0, DeviceType.Hardware, Handle,
- CreateFlags.HardwareVertexProcessing, GetPresentParameters());
- vdecl = new VertexDeclaration(device, Vertex.GetVertexElements());
- Camera = new CameraHandler(this);
- lastsize = ClientSize;
- SetPerspective();
- ResetDevice();
- }
- protected override void OnClosed(System.EventArgs e)
- {
- d3d.Dispose();
- device.Dispose();
- vdecl.Dispose();
- foreach (var o in Objects)
- o.buff.Dispose();
- base.OnClosed(e);
- }
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- foreach (var item in ObjectTable.Objects)
- item.Dispose();
- base.Dispose(disposing);
- }
- private void SetPerspective()
- {
- this.p = Matrix.PerspectiveFovRH(3.1415f / 4, this.ClientSize.Width / (float)this.ClientSize.Height,
- .1f, 100000);
- }
- protected override void OnResize(System.EventArgs eventargs)
- {
- if (lastsize == this.ClientSize ||
- this.ClientSize.IsEmpty)
- return;
- lastsize = this.ClientSize;
- SetPerspective();
- ResetDevice();
- }
- private PresentParameters GetPresentParameters()
- {
- var ret = new PresentParameters();
- ret.BackBufferCount = 1;
- ret.SwapEffect = SwapEffect.Flip;
- ret.Windowed = true;
- ret.BackBufferFormat = Format.Unknown;
- ret.BackBufferHeight = ClientSize.Height - 100;
- ret.BackBufferWidth = ClientSize.Width;
- ret.PresentationInterval = PresentInterval.Immediate;
- return ret;
- }
- private void ResetDevice()
- {
- device.Reset(GetPresentParameters());
- #if DEBUG
- device.SetRenderState(RenderState.FillMode, FillMode.Wireframe);
- //device.SetRenderState(RenderState.FillMode, FillMode.Solid);
- #endif
- device.SetRenderState(RenderState.Ambient, AmbientLight.ToArgb());
- device.VertexDeclaration = vdecl;
- }
- protected override void OnPaint(PaintEventArgs e)
- {
- Draw();
- }
- public void Draw()
- {
- device.SetTransform(TransformState.View, Camera.GetRHCamMatrix());
- device.SetTransform(TransformState.Projection, p);
- device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, this.BackColor, 1.0f, 0);
- #if BADSPOT
- System.Threading.Thread.Sleep(700);
- #endif
- device.BeginScene();
- //System.Diagnostics.Debug.Print("{0} objects", objects.Count);
- foreach (var o in Objects)
- {
- device.SetStreamSource(0, o.buff, 0, Vertex.Size);
- device.DrawPrimitives(o.type, 0, o.primitivecount);
- }
- device.EndScene();
- #if BADSPOT2
- System.Threading.Thread.Sleep(500);
- #endif
- device.Present();
- #if GOODSPOT
- System.Threading.Thread.Sleep(500);
- #endif
- }
- public Color4 AmbientLight
- {
- get { return ambient; }
- set
- {
- ambient = value;
- device.SetRenderState(RenderState.Ambient, ambient.ToArgb());
- #if !CONSTANTREDRAW
- this.Invalidate(true);
- #endif
- }
- }
- /// <summary>Sets the ambient light color. Default is gray.</summary>
- private Color4 ambient = new Color4(0x020202);
- private Size lastsize;
- #if PROFILING
- private int primitives = 0;
- private System.Diagnostics.Stopwatch fpsclock = System.Diagnostics.Stopwatch.StartNew();
- private int frames = 0;
- private System.Diagnostics.Stopwatch insidedraw = new System.Diagnostics.Stopwatch(),
- outsidedraw = new System.Diagnostics.Stopwatch();
- #endif
- public readonly Device device;
- private readonly Direct3D d3d;
- private readonly VertexDeclaration vdecl;
- public readonly List<ModelObject> Objects;
- public readonly CameraHandler Camera;
- /// <summary>Perspective matrix</summary>
- private Matrix p;
- }
- public delegate void FrameUpdate(System.TimeSpan totaltime, System.TimeSpan timesincelastframe);
- [StructLayout(LayoutKind.Sequential)]
- public struct Vertex
- {
- public Vertex(Vector3 position)
- : this(position, Vector3.Zero) { }
- public Vertex(Vector3 position, Vector3 normal)
- {
- this.Position = position;
- this.Normal = normal;
- }
- public static VertexElement[] GetVertexElements()
- {
- return new[] {
- new VertexElement(0, 0, DeclarationType.Float3,
- DeclarationMethod.Default, DeclarationUsage.Position, 0),
- new VertexElement(0,(short)(sizeof(float)*3), DeclarationType.Float3,
- DeclarationMethod.Default, DeclarationUsage.Normal,0),
- VertexElement.VertexDeclarationEnd
- };
- }
- public static short Size { get { return (short)Marshal.SizeOf(typeof(Vertex)); } }
- public Vector3 Position;
- public Vector3 Normal;
- }
- public class ModelObject
- {
- public ModelObject(VertexBuffer buffer, int primitivecount, PrimitiveType type)
- {
- this.primitivecount = primitivecount;
- this.type = type;
- this.buff = buffer;
- }
- public readonly int primitivecount;
- public readonly PrimitiveType type;
- public readonly VertexBuffer buff;
- }
- public class CameraHandler
- {
- public CameraHandler(Control rendertarget)
- {
- this.rendertarget = rendertarget;
- rendertarget.MouseDown += rendertarget_MouseDown;
- rendertarget.MouseUp += rendertarget_MouseUp;
- rendertarget.MouseMove += rendertarget_MouseMove;
- rendertarget.MouseWheel += rendertarget_MouseWheel;
- rendertarget.MouseEnter += rendertarget_MouseEnter;
- up = Vector3.UnitZ;
- target = Vector3.Zero;
- Vector3 camoffset = new Vector3(1);
- camoffset.Normalize();
- camoffset *= dist;
- cam = target + camoffset;
- }
- private void rendertarget_MouseEnter(object sender, System.EventArgs e)
- {
- (sender as Control).Focus();
- }
- /// <summary>Hold shift to change distance, otherwise, we just
- /// move the camera.</summary>
- private void rendertarget_MouseWheel(object sender, MouseEventArgs e)
- {
- float delta = System.Math.Sign(e.Delta) * wheelfactor;
- if ((Control.ModifierKeys & Keys.Shift) > 0)
- {
- Vector3 camvec = cam - target;
- camvec.Normalize();
- Vector3 add = camvec * delta;
- cam += add;
- target += add;
- }
- else
- {
- Distance += delta;
- }
- }
- public Matrix GetRHCamMatrix()
- {
- return Matrix.LookAtRH(cam, target, up);
- }
- private bool GoAhead()
- {
- #if WAIT
- var now = System.DateTime.Now;
- if ((now - lastgoahead).TotalMilliseconds > msbetweengoahead)
- { //go ahead
- lastgoahead = now;
- return true;
- }
- return false;
- #else
- return true;
- #endif
- }
- private const double msbetweengoahead = 500;
- private System.DateTime lastgoahead = System.DateTime.MinValue;
- private void rendertarget_MouseMove(object sender, MouseEventArgs e)
- {
- if (mousedown)
- {
- if (!GoAhead())
- return;
- //System.Diagnostics.Debug.Print("Mouse moved.");
- MoveCamera(new Size(Point.Subtract(e.Location, new Size(downspot))), movetarget);
- downspot = e.Location;
- }
- }
- private void rendertarget_MouseUp(object sender, MouseEventArgs e)
- {
- mousedown = false;
- }
- private void rendertarget_MouseDown(object sender, MouseEventArgs e)
- {
- mousedown = true;
- movetarget = e.Button == MouseButtons.Right;
- downspot = e.Location;
- }
- private void MoveCamera(Size s, bool movetarget)
- {
- //System.Diagnostics.Debug.WriteLine(string.Format( "Moving by {0}", s));
- if (movetarget)
- {
- MoveTarget(new Vector2(s.Width * cameramovefactor, s.Height * cameramovefactor));
- }
- else
- {
- RotateCamera(new Vector2(-s.Width * camerarotfactor, s.Height * camerarotfactor));
- }
- }
- /// <param name="mousemovement">The movement that the mouse
- /// made with the scaling factor already present.</param>
- private void RotateCamera(Vector2 mousemovement)
- {
- //if (!GoAhead())
- // return;
- /*We will be rotating the camera position and the up vector about
- * the target. First, bring the target to zero (and the up and
- * camera vectors with it), then do the rotation, then come back.*/
- /*the camera vec with relation to the target*/
- var camtarvec = cam - target;
- var camtarvecn = camtarvec;
- camtarvecn.Normalize();
- var upn = up;
- upn.Normalize();
- /*The vector about which updown mouse movements are rotated*/
- var updownaxis = Vector3.Cross(-upn, camtarvecn);
- /*this matrix will rotate the camera according to the updown mouse movements.*/
- var updownmatrix = Matrix.RotationAxis(updownaxis, mousemovement.Y);
- /*The up vector is already at 0*/
- var lraxis = up;
- var lrmatrix = Matrix.RotationAxis(lraxis, mousemovement.X);
- /*the composition of matrices*/
- var finalmatrix = updownmatrix * lrmatrix;
- /*now, finally, rotate the up vector and the camera*/
- var up4 = Vector3.Transform(up, finalmatrix);
- /*we need to move the camera so that it is rotating about
- * target (so we need to move target back to zero taking
- * the camera with it), then move it back. That is
- * We need to conjugate camera by target's translation.*/
- var cam4 = Vector3.Transform(cam - target, finalmatrix) + new Vector4(target, 0);
- //System.Diagnostics.Debug.WriteLine(string.Format("Up was {0}", up));
- up = new Vector3(up4.X, up4.Y, up4.Z);
- //System.Diagnostics.Debug.WriteLine(string.Format("Up is {0}", up));
- //System.Diagnostics.Debug.WriteLine(string.Format("cam was {0}", cam));
- cam = new Vector3(cam4.X, cam4.Y, cam4.Z);
- //System.Diagnostics.Debug.WriteLine(string.Format("cam is {0}", cam));
- #if !CONSTANTREDRAW
- rendertarget.Invalidate();
- #endif
- }
- /// <param name="mousemovent">The movement that the mouse made with the
- /// scaling factor already in it.</param>
- private void MoveTarget(Vector2 mousemovent)
- {
- //if (!GoAhead())
- // return;
- /*the camera vector in relation to the target.*/
- var camtarvec = cam - target;/*or target - cam*/
- /*pick up some normalized vectors*/
- var camtarvecn = camtarvec;
- camtarvecn.Normalize();
- var upn = up;
- upn.Normalize();
- /*the vector about which z must be rotated to get up*/
- var xchange = Vector3.Cross(upn, camtarvecn);
- /*xchange.normalize should be unnecessary since we used two
- * normalized vectors*/
- var movevec = up * mousemovent.Y - xchange * mousemovent.X;
- target += movevec;
- cam += movevec;
- #if !CONSTANTREDRAW
- rendertarget.Invalidate();
- #endif
- }
- private Control rendertarget;
- private bool mousedown = false;
- private bool movetarget = false;
- private float cameramovefactor = 4, wheelfactor = -100;
- /*The camera will rotate a number of degrees per pixel moved on screen.
- This number is in radians.*/
- private float camerarotfactor = 2f * (float)System.Math.PI / 180;
- private float dist = 8000;
- public Vector3 CameraUp { get { return up; } }
- /// <summary>
- /// Keeps the same CameraUp value. Moves the target and the camera
- /// to the specified spot.
- /// </summary>
- public Vector3 Target
- {
- get
- {
- return target;
- }
- set
- {
- //target = new Vector3(1) * 1000;
- Vector3 camoffset = cam - target;
- camoffset.Normalize();
- camoffset *= dist;
- cam = target + camoffset;
- #if !CONSTANTREDRAW
- rendertarget.Invalidate();
- #endif
- }
- }
- /// <summary>Sets the camer's distance from the target. The
- /// default is 8000</summary>
- public float Distance
- {
- get
- {
- return dist;
- }
- set
- {
- if (value == dist)
- return;
- dist = System.Math.Max(1, value);
- var targetcamvec = cam - target;
- targetcamvec.Normalize();
- targetcamvec *= dist;
- cam = target + targetcamvec;
- #if !CONSTANTREDRAW
- rendertarget.Invalidate();
- #endif
- }
- }
- public Vector3 CameraPos { get { return cam; } }
- private Vector3 up, target, cam;
- /*The spot at which the mouse was seen to go "down"*/
- private Point downspot;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement