using System; using System.Collections.Generic; using global::System.Drawing; using Color = System.Drawing.Color; using Point = System.Drawing.Point; using System.Linq; using System.Runtime.CompilerServices; using global::System.Windows.Forms; using global::OpenTK; using global::OpenTK.Graphics.OpenGL; using Key = OpenTK.Input.Key; using Keyboard = OpenTK.Input.Keyboard; using global::Pilz.Drawing.Drawing3D.OpenGLFactory.CameraN; using global::Pilz.Drawing.Drawing3D.OpenGLFactory.RenderingN; using global::Pilz.S3DFileParser; namespace Pilz.Drawing.Drawing3D.OpenGLFactory.PreviewN { public partial class ModelPreview { public ModelPreview(Object3D[] objs, float scale) { MyCamera = new Camera(); RenderTimer = new System.Timers.Timer(25d) { AutoReset = true }; SuspendLayout(); InitializeComponent(); DoubleBuffered = true; // glControl1 glControl1 = new GLControl(); glControl1.BackColor = Color.Black; glControl1.Location = new Point(0, 0); glControl1.MinimumSize = new Size(600, 120); glControl1.Name = "glControl1"; glControl1.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom; glControl1.Location = new Point(0, 0); glControl1.Size = ClientSize; glControl1.TabIndex = 0; glControl1.TabStop = false; glControl1.VSync = false; Controls.Add(glControl1); ResumeLayout(false); // RenderTimer.SynchronizingObject = Nothing Scaling = scale; // Toolkit.Init() glControl1.CreateControl(); glControl1.MouseWheel += glControl1_Wheel; ProjMatrix = Matrix4.CreatePerspectiveFieldOfView(FOV, (float)(glControl1.Width / (double)glControl1.Height), 100.0f, 100000.0f); glControl1.Enabled = false; MyCamera.SetCameraMode(CameraMode.FLY, ref camMtx); MyCamera.UpdateMatrix(ref camMtx); ResumeLayout(); foreach (Object3D obj in objs) AddModel(obj); } private GLControl _glControl1; private GLControl glControl1 { [MethodImpl(MethodImplOptions.Synchronized)] get { return _glControl1; } [MethodImpl(MethodImplOptions.Synchronized)] set { if (_glControl1 != null) { _glControl1.Load -= glControl1_Load; _glControl1.Paint -= HandlesOnPaint; _glControl1.Resize -= glControl1_Resize; _glControl1.MouseDown -= glControl1_MouseDown; _glControl1.MouseLeave -= glControl1_MouseLeave; _glControl1.MouseUp -= glControl1_MouseLeave; _glControl1.MouseMove -= glControl1_MouseMove; } _glControl1 = value; if (_glControl1 != null) { _glControl1.Load += glControl1_Load; _glControl1.Paint += HandlesOnPaint; _glControl1.Resize += glControl1_Resize; _glControl1.MouseDown += glControl1_MouseDown; _glControl1.MouseLeave += glControl1_MouseLeave; _glControl1.MouseUp += glControl1_MouseLeave; _glControl1.MouseMove += glControl1_MouseMove; } } } private Camera _MyCamera; private Camera MyCamera { [MethodImpl(MethodImplOptions.Synchronized)] get { return _MyCamera; } [MethodImpl(MethodImplOptions.Synchronized)] set { if (_MyCamera != null) { _MyCamera.NeedSelectedObject -= Camera_NeedSelectedObject; _MyCamera.PerspectiveChanged -= MyCamera_PerspectiveChanged; } _MyCamera = value; if (_MyCamera != null) { _MyCamera.NeedSelectedObject += Camera_NeedSelectedObject; _MyCamera.PerspectiveChanged += MyCamera_PerspectiveChanged; } } } private Matrix4 ProjMatrix = default; private float FOV = 1.048f; private Matrix4 camMtx = Matrix4.Identity; private Vector3 savedCamPos = new Vector3(); private bool _isMouseDown = false; private bool isDeactivated = false; private readonly Dictionary myModels = new Dictionary(); private System.Timers.Timer _RenderTimer; private System.Timers.Timer RenderTimer { [MethodImpl(MethodImplOptions.Synchronized)] get { return _RenderTimer; } [MethodImpl(MethodImplOptions.Synchronized)] set { if (_RenderTimer != null) { _RenderTimer.Elapsed -= RenderTimer_Elapsed; } _RenderTimer = value; if (_RenderTimer != null) { _RenderTimer.Elapsed += RenderTimer_Elapsed; } } } private bool _EnableCameraControlling = false; public float Scaling { get; set; } = 500.0f; public Color ClearColor { get; set; } = Color.CornflowerBlue; public bool EnableCameraControlling { get { return _EnableCameraControlling; } set { _EnableCameraControlling = value; if (value) { if (!RenderTimer.Enabled) { RenderTimer.Start(); } } else if (RenderTimer.Enabled) { RenderTimer.Stop(); } } } public double RenderInterval { get { return RenderTimer.Interval; } set { RenderTimer.Interval = value; } } public Camera Camera { get { return MyCamera; } } public Matrix4 CameraMatrix { get { return camMtx; } } public IReadOnlyDictionary Models { get { return myModels; } } public Control GLControl { get { return glControl1; } } private bool IsStrgPressed { get { var state = Keyboard.GetState(); return state[Key.ControlLeft] || state[Key.ControlRight]; } } private bool IsShiftPressed { get { var state = Keyboard.GetState(); return state[Key.ShiftLeft] || state[Key.ShiftRight]; } } public bool IsMouseDown { get { return _isMouseDown; } set { _isMouseDown = value; glControl1.Refresh(); } } public ModelPreview() : this(Array.Empty(), 1.0f) { } public ModelPreview(Object3D obj) : this(obj, 1.0f) { } public ModelPreview(Object3D obj, float scale) : this(new[] { obj }, scale) { } public void UpdateOrbitCamera() { if (Camera.IsOrbitCamera()) { Camera.UpdateOrbitCamera(ref camMtx); } } public void UpdateView() { if (glControl1.Enabled) { glControl1.Invoke(new Action(() => glControl1.Invalidate())); } } public Renderer AddModel(Object3D obj) { var rndr = new Renderer(obj); AddModel(rndr); return rndr; } public void AddModel(Renderer rndr) { myModels.Add(rndr.Model, rndr); } public void HandlesOnShown(object sender, EventArgs e) { glControl1.Enabled = true; RenderModels(); glControl1.Invalidate(); } public void RenderModels() { foreach (Renderer rndr in myModels.Values) RenderModel(rndr); } public void RenderModel(Renderer rndr) { if (myModels.Values.Contains(rndr)) { rndr.ModelScaling = Scaling; rndr.RenderModel(); } } private void glControl1_Load(object sender, EventArgs e) { GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); GL.Enable(EnableCap.DepthTest); GL.DepthFunc(DepthFunction.Lequal); GL.Enable(EnableCap.Texture2D); GL.Enable(EnableCap.AlphaTest); GL.AlphaFunc(AlphaFunction.Gequal, 0.5f); GL.Enable(EnableCap.CullFace); } public void HandlesOnActivated(object sender, EventArgs e) { if (isDeactivated) { isDeactivated = false; } } public void HandlesOnDeactivate(object sender, EventArgs e) { isDeactivated = true; } private void RenderTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { if (!isDeactivated) { MoveCameraViaWASDQE(); } } public void HandlesOnPaint(object sender, PaintEventArgs e) { GL.ClearColor(ClearColor); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); GL.MatrixMode(MatrixMode.Projection); GL.LoadMatrix(ref ProjMatrix); GL.MatrixMode(MatrixMode.Modelview); GL.LoadMatrix(ref camMtx); foreach (Renderer rndr in myModels.Values) { if (rndr.HasRendered) { rndr.DrawModel(RenderMode.FillOutline); } } glControl1.SwapBuffers(); } private void glControl1_Resize(object sender, EventArgs e) { glControl1.Context.Update(glControl1.WindowInfo); GL.Viewport(0, 0, glControl1.Width, glControl1.Height); ProjMatrix = Matrix4.CreatePerspectiveFieldOfView(FOV, (float)(glControl1.Width / (double)glControl1.Height), 100.0f, 100000.0f); glControl1.Invalidate(); } private void glControl1_Wheel(object sender, MouseEventArgs e) { MyCamera.ResetMouseStuff(); MyCamera.UpdateCameraMatrixWithScrollWheel((int)Math.Truncate(e.Delta * (IsShiftPressed ? 3.5f : 1.5f)), ref camMtx); savedCamPos = MyCamera.Position; glControl1.Invalidate(); } private void glControl1_MouseDown(object sender, MouseEventArgs e) { IsMouseDown = true; savedCamPos = MyCamera.Position; } private void glControl1_MouseLeave(object sender, EventArgs e) { MyCamera.ResetMouseStuff(); IsMouseDown = false; } private void glControl1_MouseMove(object sender, MouseEventArgs e) { if (IsMouseDown && e.Button == MouseButtons.Left) { if (IsShiftPressed) { MyCamera.UpdateCameraOffsetWithMouse(savedCamPos, e.X, e.Y, glControl1.Width, glControl1.Height, ref camMtx); } else { MyCamera.UpdateCameraMatrixWithMouse(e.X, e.Y, ref camMtx); } glControl1.Invalidate(); } } public void MoveCameraViaWASDQE() { int moveSpeed = Convert.ToInt32(Math.Round((IsShiftPressed ? 60 : 30) * MyCamera.CamSpeedMultiplier, 0)); bool allowCamMove = !(IsMouseDown && IsShiftPressed); if (allowCamMove) { var state = Keyboard.GetState(); if (state[Key.W]) { // camera.Move(moveSpeed, moveSpeed, camMtx) MyCamera.UpdateCameraMatrixWithScrollWheel(moveSpeed, ref camMtx); savedCamPos = MyCamera.Position; } if (state[Key.S]) { // camera.Move(-moveSpeed, -moveSpeed, camMtx) MyCamera.UpdateCameraMatrixWithScrollWheel(-moveSpeed, ref camMtx); savedCamPos = MyCamera.Position; } if (state[Key.A]) { // camera.Move(-moveSpeed, 0, camMtx) MyCamera.UpdateCameraOffsetDirectly(-moveSpeed, 0, ref camMtx); } if (state[Key.D]) { // camera.Move(moveSpeed, 0, camMtx) MyCamera.UpdateCameraOffsetDirectly(moveSpeed, 0, ref camMtx); } if (state[Key.E]) { // camera.Move(0, -moveSpeed, camMtx) MyCamera.UpdateCameraOffsetDirectly(0, -moveSpeed, ref camMtx); } if (state[Key.Q]) { // camera.Move(0, moveSpeed, camMtx) MyCamera.UpdateCameraOffsetDirectly(0, moveSpeed, ref camMtx); } } } private void Camera_NeedSelectedObject(object sender, Camera.NeedSelectedObjectEventArgs e) { e.Points = null; } private void MyCamera_PerspectiveChanged(object sender, EventArgs e) { UpdateView(); } private void ModelPreview_FormDisposed(object sender, EventArgs e) { foreach (Renderer rndr in myModels.Values) rndr.ReleaseBuffers(); } } }