Files
Pilz/Pilz.Drawing.Drawing3D.OpenGLRenderer/Preview/ModelPreview.vb
2020-12-02 16:10:17 +01:00

357 lines
12 KiB
VB.net

Imports System.Drawing
Imports System.Windows.Forms
Imports Pilz.Drawing.Drawing3D.OpenGLFactory.CameraN
Imports Pilz.Drawing.Drawing3D.OpenGLFactory.RenderingN
Imports OpenTK
Imports OpenTK.Graphics.OpenGL
Imports Pilz.S3DFileParser
Imports Point = System.Drawing.Point
Imports Color = System.Drawing.Color
Imports System.Windows.Forms.Integration
Imports OpenTK.Mathematics
Imports System.Windows.Input
Imports Key = OpenTK3.Input.Key
Imports OpenTK.Wpf
Namespace PreviewN
Public Class ModelPreview
Private WithEvents glControl1 As Wpf.GLWpfControl
Private WithEvents glControlHost As ElementHost
Private WithEvents MyCamera As New Camera
Private ProjMatrix As Matrix4 = Nothing
Private FOV As Single = 1.048F
Private camMtx As Matrix4 = Matrix4.Identity
Private savedCamPos As New Vector3
Private _isMouseDown As Boolean = False
Private isDeactivated As Boolean = False
Private ReadOnly myModels As New Dictionary(Of Object3D, Renderer)
Private WithEvents RenderTimer As New Timers.Timer(25) With {.AutoReset = True}
Private _EnableCameraControlling As Boolean = False
Private finishedLoading As Boolean = False
Public Property Scaling As Single = 500.0F
Public Property ClearColor As Color = Color.CornflowerBlue
Public ReadOnly Property Keyboard As OpenTK3.Input.KeyboardState
Get
Return OpenTK3.Input.Keyboard.GetState
End Get
End Property
Public Property EnableCameraControlling As Boolean
Get
Return _EnableCameraControlling
End Get
Set
_EnableCameraControlling = Value
If Value Then
If Not RenderTimer.Enabled Then
RenderTimer.Start()
End If
ElseIf RenderTimer.Enabled Then
RenderTimer.Stop()
End If
End Set
End Property
Public Property RenderInterval As Double
Get
Return RenderTimer.Interval
End Get
Set
RenderTimer.Interval = Value
End Set
End Property
Public ReadOnly Property Camera As Camera
Get
Return MyCamera
End Get
End Property
Public ReadOnly Property CameraMatrix As Matrix4
Get
Return camMtx
End Get
End Property
Public ReadOnly Property Models As IReadOnlyDictionary(Of Object3D, Renderer)
Get
Return myModels
End Get
End Property
Public ReadOnly Property GLControl As Control
Get
Return glControlHost
End Get
End Property
Private ReadOnly Property IsStrgPressed As Boolean
Get
Dim state = Keyboard
Return state.IsKeyDown(Key.ControlLeft) OrElse state.IsKeyDown(Key.ControlRight)
End Get
End Property
Private ReadOnly Property IsShiftPressed As Boolean
Get
Dim state = Keyboard
Return state.IsKeyDown(Key.ShiftLeft) OrElse state.IsKeyDown(Key.ShiftRight)
End Get
End Property
Public Property IsMouseDown As Boolean
Get
Return _isMouseDown
End Get
Set(value As Boolean)
_isMouseDown = value
glControlHost.Refresh()
End Set
End Property
Public Sub New()
Me.New({}, 1.0F)
End Sub
Public Sub New(obj As Object3D)
Me.New(obj, 1.0F)
End Sub
Public Sub New(obj As Object3D, scale As Single)
Me.New({obj}, scale)
End Sub
Public Sub New(objs As Object3D(), scale As Single)
SuspendLayout()
InitializeComponent()
'glControl1
Dim glControl1 As New GLWpfControl
Dim glControlHost = New ElementHost
glControlHost.BackColor = Color.Black
glControlHost.Name = "glControl1"
glControlHost.Anchor = AnchorStyles.Left Or AnchorStyles.Top Or AnchorStyles.Right Or AnchorStyles.Bottom
glControlHost.Location = New Point(0, 0)
glControlHost.Size = Me.ClientSize
glControlHost.MinimumSize = New Size(600, 120)
glControlHost.TabIndex = 0
glControlHost.TabStop = False
Me.glControl1 = glControl1
Me.glControlHost = glControlHost
Dim controlSettings As New GLWpfControlSettings With
{
.RenderContinuously = False,
.GraphicsProfile = Windowing.Common.ContextProfile.Compatability
}
glControl1.Start(controlSettings)
glControlHost.Child = glControl1
Controls.Add(glControlHost)
Scaling = scale
ProjMatrix = Matrix4.CreatePerspectiveFieldOfView(FOV, glControlHost.Width / glControlHost.Height, 100.0F, 100000.0F)
ResumeLayout()
MyCamera.SetCameraMode(CameraMode.FLY, camMtx)
MyCamera.UpdateMatrix(camMtx)
For Each obj As Object3D In objs
AddModel(obj)
Next
finishedLoading = True
End Sub
Public Sub UpdateOrbitCamera()
If Camera.IsOrbitCamera Then
Camera.UpdateOrbitCamera(camMtx)
End If
End Sub
Public Sub UpdateView()
If glControlHost.Enabled AndAlso finishedLoading Then
Invoke(Sub() InvalidateGL())
End If
End Sub
Private Sub InvalidateGL()
glControl1.InvalidateVisual()
glControlHost.Invalidate()
End Sub
Public Function AddModel(obj As Object3D) As Renderer
Dim rndr As New Renderer(obj)
AddModel(rndr)
Return rndr
End Function
Public Sub AddModel(rndr As Renderer)
myModels.Add(rndr.Model, rndr)
End Sub
Public Sub HandlesOnShown(sender As Object, e As EventArgs) Handles MyBase.Shown
RenderModels()
InvalidateGL()
End Sub
Public Sub RenderModels()
For Each rndr As Renderer In myModels.Values
RenderModel(rndr)
Next
End Sub
Public Sub RenderModel(rndr As Renderer)
If myModels.Values.Contains(rndr) Then
rndr.ModelScaling = Scaling
rndr.RenderModel()
End If
End Sub
Private Sub glControl1_Load() Handles glControl1.Ready
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)
End Sub
Public Sub HandlesOnActivated(sender As Object, e As EventArgs) Handles Me.Activated
If isDeactivated Then
isDeactivated = False
End If
End Sub
Public Sub HandlesOnDeactivate(sender As Object, e As EventArgs) Handles Me.Deactivate
isDeactivated = True
End Sub
Private Sub RenderTimer_Elapsed(sender As Object, e As Timers.ElapsedEventArgs) Handles RenderTimer.Elapsed
If Not isDeactivated Then
MoveCameraViaWASDQE()
End If
End Sub
Public Sub HandlesOnPaint(renderTime As TimeSpan) Handles glControl1.Render
GL.ClearColor(ClearColor)
GL.Clear(ClearBufferMask.ColorBufferBit Or ClearBufferMask.DepthBufferBit)
GL.LoadIdentity()
GL.MatrixMode(MatrixMode.Projection)
GL.LoadMatrix(ProjMatrix)
GL.MatrixMode(MatrixMode.Modelview)
GL.LoadMatrix(camMtx)
For Each rndr As Renderer In myModels.Values
If rndr.HasRendered Then
rndr.DrawModel(RenderMode.FillOutline)
End If
Next
GL.End()
GL.Finish()
'glControl1.SwapBuffers()
End Sub
Private Sub glControl1_Resize(sender As Object, e As EventArgs) Handles glControlHost.Resize
'glControl1.Context.Update(glControl1.WindowInfo)
GL.Viewport(0, 0, glControlHost.Width, glControlHost.Height)
ProjMatrix = Matrix4.CreatePerspectiveFieldOfView(FOV, glControlHost.Width / glControlHost.Height, 100.0F, 100000.0F)
InvalidateGL()
End Sub
Private Sub glControl1_Wheel(sender As Object, e As Windows.Input.MouseWheelEventArgs) Handles glControl1.MouseWheel
MyCamera.ResetMouseStuff()
MyCamera.UpdateCameraMatrixWithScrollWheel(CInt(Math.Truncate(e.Delta * (If(IsShiftPressed, 3.5F, 1.5F)))), camMtx)
savedCamPos = MyCamera.Position
InvalidateGL()
End Sub
Private Sub glControl1_MouseDown(ByVal sender As Object, ByVal e As Windows.Input.MouseButtonEventArgs) Handles glControl1.MouseDown
IsMouseDown = True
savedCamPos = MyCamera.Position
End Sub
Private Sub glControl1_MouseLeave(ByVal sender As Object, ByVal e As EventArgs) Handles glControl1.MouseLeave, glControl1.MouseUp
MyCamera.ResetMouseStuff()
IsMouseDown = False
End Sub
Private Sub glControl1_MouseMove(ByVal sender As Object, ByVal e As Windows.Forms.MouseEventArgs) Handles glControlHost.MouseMove
If IsMouseDown AndAlso e.Button = MouseButtons.Left Then
If IsShiftPressed Then
MyCamera.UpdateCameraOffsetWithMouse(savedCamPos, e.X, e.Y, glControl1.Width, glControl1.Height, camMtx)
Else
MyCamera.UpdateCameraMatrixWithMouse(e.X, e.Y, camMtx)
End If
InvalidateGL()
End If
End Sub
Public Sub MoveCameraViaWASDQE()
Dim moveSpeed As Integer = Convert.ToInt32(Math.Round((If(IsShiftPressed, 60, 30)) * (MyCamera.CamSpeedMultiplier), 0))
Dim allowCamMove As Boolean = Not (IsMouseDown AndAlso IsShiftPressed)
Dim state = Keyboard
If allowCamMove Then
If state.IsKeyDown(Key.W) Then
'camera.Move(moveSpeed, moveSpeed, camMtx)
MyCamera.UpdateCameraMatrixWithScrollWheel(moveSpeed, camMtx)
savedCamPos = MyCamera.Position
End If
If state.IsKeyDown(Key.S) Then
'camera.Move(-moveSpeed, -moveSpeed, camMtx)
MyCamera.UpdateCameraMatrixWithScrollWheel(-moveSpeed, camMtx)
savedCamPos = MyCamera.Position
End If
If state.IsKeyDown(Key.A) Then
'camera.Move(-moveSpeed, 0, camMtx)
MyCamera.UpdateCameraOffsetDirectly(-moveSpeed, 0, camMtx)
End If
If state.IsKeyDown(Key.D) Then
'camera.Move(moveSpeed, 0, camMtx)
MyCamera.UpdateCameraOffsetDirectly(moveSpeed, 0, camMtx)
End If
If state.IsKeyDown(Key.E) Then
'camera.Move(0, -moveSpeed, camMtx)
MyCamera.UpdateCameraOffsetDirectly(0, -moveSpeed, camMtx)
End If
If state.IsKeyDown(Key.Q) Then
'camera.Move(0, moveSpeed, camMtx)
MyCamera.UpdateCameraOffsetDirectly(0, moveSpeed, camMtx)
End If
End If
End Sub
Private Sub Camera_NeedSelectedObject(sender As Object, e As Camera.NeedSelectedObjectEventArgs) Handles MyCamera.NeedSelectedObject
e.Points = Nothing
End Sub
Private Sub MyCamera_PerspectiveChanged(sender As Object, e As EventArgs) Handles MyCamera.PerspectiveChanged
UpdateView()
End Sub
Private Sub ModelPreview_FormDisposed(sender As Object, e As EventArgs) Handles Me.Disposed
For Each rndr As Renderer In myModels.Values
rndr.ReleaseBuffers()
Next
End Sub
End Class
End Namespace