487 lines
14 KiB
C#
487 lines
14 KiB
C#
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<Object3D, Renderer> myModels = new Dictionary<Object3D, Renderer>();
|
|
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<Object3D, Renderer> 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<Object3D>(), 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();
|
|
}
|
|
}
|
|
} |