diff --git a/Pilz.Collections/SimpleHistory/SimpleHistory.vb b/Pilz.Collections/SimpleHistory/SimpleHistory.vb index 46dc39d..74c7339 100644 --- a/Pilz.Collections/SimpleHistory/SimpleHistory.vb +++ b/Pilz.Collections/SimpleHistory/SimpleHistory.vb @@ -7,6 +7,16 @@ Namespace SimpleHistory Private stackPast As New Stack(Of HistoryPoint) Private stackFuture As New Stack(Of HistoryPoint) + ''' + ''' Gets the count of history points. + ''' + ''' + Public ReadOnly Property ChangesCount As Boolean + Get + Return stackPast.Count + End Get + End Property + ''' ''' Checks if the History has past changes. ''' diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/Camera/Camera.vb b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Camera/Camera.vb new file mode 100644 index 0000000..9ca19d2 --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Camera/Camera.vb @@ -0,0 +1,570 @@ +Imports System.Windows.Forms +Imports OpenTK + +Namespace CameraN + + Public Class Camera + + Public Event NeedSelectedObject(e As NeedSelectedObjectEventArgs) + + 'P R I V A T E F I E L D S + + Private ReadOnly TAU As Single = Math.PI * 2 + Private myCamMode As CameraMode = CameraMode.FLY + Private pos As New Vector3(-5000.0F, 3000.0F, 4000.0F) + Private myLookat As New Vector3(0F, 0F, 0F) + Private myFarPoint As New Vector3(0F, 0F, 0F) + Private myNearPoint As New Vector3(0F, 0F, 0F) + Private lastMouseX As Integer = -1, lastMouseY As Integer = -1 + Private CamAngleX As Single = 0F, CamAngleY As Single = -(Math.PI / 2) + Private resetMouse As Boolean = True + + Private orbitDistance As Single = 500.0F + Private orbitTheta As Single = 0.0F, orbitPhi As Single = 0.0F + + Private currentLookDirection As LookDirection + Private lookPositions() As Vector3 = { + New Vector3(0, 12500, 0), + New Vector3(0, -12500, 0), + New Vector3(-12500, 0, 0), + New Vector3(12500, 0, 0), + New Vector3(0, 0, 12500), + New Vector3(0, 0, -12500) + } + + 'A U T O M A T I C P R O P E R T I E S + + Public Property CamSpeedMultiplier As Single = 1 + + 'P R O P E R T I E S + + Public ReadOnly Property CamMode As CameraMode + Get + Return myCamMode + End Get + End Property + + Public ReadOnly Property Yaw As Single + Get + Return CamAngleX + End Get + End Property + + Public ReadOnly Property Pitch As Single + Get + Return CamAngleY + End Get + End Property + + Public ReadOnly Property Yaw_Degrees As Single + Get + Return CamAngleX * (180.0F / 3.14159274F) + End Get + End Property + + Public ReadOnly Property Pitch_Degrees As Single + Get + Return CamAngleY * (180.0F / 3.14159274F) + End Get + End Property + + Public Property Position As Vector3 + Get + Return pos + End Get + Set(value As Vector3) + pos = value + End Set + End Property + + Public Property LookAt As Vector3 + Get + Return myLookat + End Get + Set(value As Vector3) + myLookat = value + End Set + End Property + + Public Property NearPoint As Vector3 + Get + Return myNearPoint + End Get + Set(value As Vector3) + myNearPoint = value + End Set + End Property + + Public Property FarPoint As Vector3 + Get + Return myFarPoint + End Get + Set(value As Vector3) + myFarPoint = value + End Set + End Property + + 'C O N S T R U C T O R + + Public Sub New() + SetRotationFromLookAt() + End Sub + + 'F E A T U R E S + + Private Function Clampf(value As Single, min As Single, max As Single) As Single + Return If(value > max, max, If(value < min, min, value)) + End Function + + Private Sub OrientateCam(ang As Single, ang2 As Single) + Dim CamLX As Single = CSng(Math.Sin(ang)) * CSng(Math.Sin(-ang2)) + Dim CamLY As Single = CSng(Math.Cos(ang2)) + Dim CamLZ As Single = CSng(-Math.Cos(ang)) * CSng(Math.Sin(-ang2)) + + myLookat.X = pos.X + (-CamLX) * 100.0F + myLookat.Y = pos.Y + (-CamLY) * 100.0F + myLookat.Z = pos.Z + (-CamLZ) * 100.0F + End Sub + + Private Sub OffsetCam(xAmt As Integer, yAmt As Integer, zAmt As Integer) + Dim pitch_Renamed As Double = CamAngleY - (Math.PI / 2) + Dim CamLX As Single = CSng(Math.Sin(CamAngleX)) * CSng(Math.Cos(-pitch_Renamed)) + Dim CamLY As Single = CSng(Math.Sin(pitch_Renamed)) + Dim CamLZ As Single = CSng(-Math.Cos(CamAngleX)) * CSng(Math.Cos(-pitch_Renamed)) + pos.X = pos.X + xAmt * (CamLX) * CamSpeedMultiplier + pos.Y = pos.Y + yAmt * (CamLY) * CamSpeedMultiplier + pos.Z = pos.Z + zAmt * (CamLZ) * CamSpeedMultiplier + End Sub + + Public Sub Move(y As Single, ByRef camMtx As Matrix4) + OffsetCam(0, y, 0) + OrientateCam(CamAngleX, CamAngleY) + UpdateMatrix(camMtx) + End Sub + + Public Sub Move(x As Single, z As Single, ByRef camMtx As Matrix4) + UpdateCameraOffsetDirectly(x, z, camMtx) + OrientateCam(CamAngleX, CamAngleY) + UpdateMatrix(camMtx) + End Sub + + Public Sub SetRotationFromLookAt() + Dim x_diff As Single = myLookat.X - pos.X + Dim y_diff As Single = myLookat.Y - pos.Y + Dim z_diff As Single = myLookat.Z - pos.Z + Dim dist As Single = CSng(Math.Sqrt(x_diff * x_diff + y_diff * y_diff + z_diff * z_diff)) + If z_diff = 0 Then + z_diff = 0.001F + End If + Dim nxz_ratio As Single = -x_diff / z_diff + If z_diff < 0 Then + CamAngleX = CSng(Math.Atan(nxz_ratio) + Math.PI) + Else + CamAngleX = CSng(Math.Atan(nxz_ratio)) + End If + CamAngleY = -3.1459F - (CSng(Math.Asin(y_diff / dist)) - 1.57F) + End Sub + + Public Sub ResetOrbitToSelectedObject() + Dim objs As ICameraPoint() = GetSelectedObject() + If objs?.Length > 0 Then + orbitTheta = -(CalculateCenterYRotationOfObjects(objs) * (CSng(Math.PI) / 180.0F)) + orbitPhi = -0.3F + orbitDistance = 1200.0F + End If + End Sub + + Public Sub UpdateOrbitCamera(ByRef cameraMatrix As Matrix4) + If myCamMode = CameraMode.ORBIT Then + Dim objs As ICameraPoint() = GetSelectedObject() + If objs?.Length > 0 Then + Dim centerPos As Numerics.Vector3 = CalculateCenterPositionOfObjects(objs) + pos.X = centerPos.X + CSng(Math.Cos(orbitPhi) * -Math.Sin(orbitTheta) * orbitDistance) + pos.Y = centerPos.Y + CSng(-Math.Sin(orbitPhi) * orbitDistance) + pos.Z = centerPos.Z + CSng(Math.Cos(orbitPhi) * Math.Cos(orbitTheta) * orbitDistance) + myLookat.X = centerPos.X + myLookat.Y = centerPos.Y + myLookat.Z = centerPos.Z + UpdateMatrix(cameraMatrix) + SetRotationFromLookAt() + End If + End If + End Sub + + Public Function IsOrbitCamera() As Boolean + Return myCamMode = CameraMode.ORBIT + End Function + + Public Sub SetCameraMode(mode As CameraMode, ByRef cameraMatrix As Matrix4) + myCamMode = mode + If IsOrbitCamera() Then + ResetOrbitToSelectedObject() + UpdateOrbitCamera(cameraMatrix) + End If + End Sub + + Public Sub SetCameraMode_LookDirection(dir As LookDirection, ByRef cameraMatrix As Matrix4) + myCamMode = CameraMode.LOOK_DIRECTION + currentLookDirection = dir + Select Case currentLookDirection + Case LookDirection.Top + pos = lookPositions(CInt(LookDirection.Top)) + myLookat = New Vector3(pos.X, -25000, pos.Z - 1) + UpdateMatrix(cameraMatrix) + SetRotationFromLookAt() + Case LookDirection.Bottom + pos = lookPositions(CInt(LookDirection.Bottom)) + myLookat = New Vector3(pos.X, 25000, pos.Z + 1) + UpdateMatrix(cameraMatrix) + SetRotationFromLookAt() + Case LookDirection.Left + pos = lookPositions(CInt(LookDirection.Left)) + myLookat = New Vector3(25000, pos.Y, pos.Z) + UpdateMatrix(cameraMatrix) + SetRotationFromLookAt() + Case LookDirection.Right + pos = lookPositions(CInt(LookDirection.Right)) + myLookat = New Vector3(-25000, pos.Y, pos.Z) + UpdateMatrix(cameraMatrix) + SetRotationFromLookAt() + Case LookDirection.Front + pos = lookPositions(CInt(LookDirection.Front)) + myLookat = New Vector3(pos.X, pos.Y, -25000) + UpdateMatrix(cameraMatrix) + SetRotationFromLookAt() + Case LookDirection.Back + pos = lookPositions(CInt(LookDirection.Back)) + myLookat = New Vector3(pos.X, pos.Y, 25000) + UpdateMatrix(cameraMatrix) + SetRotationFromLookAt() + End Select + End Sub + + Public Sub UpdateCameraMatrixWithMouse(mouseX As Integer, mouseY As Integer, ByRef cameraMatrix As Matrix4) + If myCamMode = CameraMode.ORBIT AndAlso GetSelectedObject() IsNot Nothing Then + UpdateCameraMatrixWithMouse_ORBIT(mouseX, mouseY, cameraMatrix) + ElseIf myCamMode = CameraMode.LOOK_DIRECTION Then + UpdateCameraMatrixWithMouse_LOOK(pos, mouseX, mouseY, cameraMatrix) + Else + UpdateCameraMatrixWithMouse_FLY(mouseX, mouseY, cameraMatrix) + End If + End Sub + + Public Sub UpdateCameraOffsetWithMouse(orgPos As Vector3, mouseX As Integer, mouseY As Integer, w As Integer, h As Integer, ByRef cameraMatrix As Matrix4) + If myCamMode = CameraMode.ORBIT AndAlso GetSelectedObject() IsNot Nothing Then + UpdateCameraOffsetWithMouse_ORBIT(mouseX, mouseY, cameraMatrix) + ElseIf myCamMode = CameraMode.LOOK_DIRECTION Then + UpdateCameraMatrixWithMouse_LOOK(pos, mouseX, mouseY, cameraMatrix) + Else + UpdateCameraOffsetWithMouse_FLY(orgPos, mouseX, mouseY, w, h, cameraMatrix) + End If + End Sub + + Public Sub UpdateCameraMatrixWithScrollWheel(amt As Integer, ByRef cameraMatrix As Matrix4) + If myCamMode = CameraMode.ORBIT AndAlso GetSelectedObject() IsNot Nothing Then + UpdateCameraMatrixWithScrollWheel_ORBIT(amt, cameraMatrix) + ElseIf myCamMode = CameraMode.LOOK_DIRECTION Then + UpdateCameraMatrixWithScrollWheel_LOOK(amt, cameraMatrix) + Else + UpdateCameraMatrixWithScrollWheel_FLY(amt, cameraMatrix) + End If + End Sub + + Private Sub UpdateCameraMatrixWithScrollWheel_FLY(amt As Integer, ByRef cameraMatrix As Matrix4) + OffsetCam(amt, amt, amt) + OrientateCam(CamAngleX, CamAngleY) + UpdateMatrix(cameraMatrix) + End Sub + + Public Sub UpdateMatrix(ByRef cameraMatrix As Matrix4) + cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, myLookat.X, myLookat.Y, myLookat.Z, 0, 1, 0) + End Sub + + Private Sub UpdateCameraMatrixWithScrollWheel_LOOK(amt As Integer, ByRef cameraMatrix As Matrix4) + OffsetCam(amt, amt, amt) + OrientateCam(CamAngleX, CamAngleY) + Select Case currentLookDirection + Case LookDirection.Top + cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, myLookat.X, myLookat.Y, myLookat.Z - 1, 0, 1, 0) + Case LookDirection.Bottom + cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, myLookat.X, myLookat.Y, myLookat.Z + 1, 0, 1, 0) + Case Else + UpdateMatrix(cameraMatrix) + End Select + End Sub + + Private Sub UpdateCameraMatrixWithMouse_LOOK(orgPos As Vector3, mouseX As Integer, mouseY As Integer, ByRef cameraMatrix As Matrix4) + If resetMouse Then + lastMouseX = mouseX + lastMouseY = mouseY + resetMouse = False + End If + Dim MousePosX As Integer = mouseX - lastMouseX + Dim MousePosY As Integer = mouseY - lastMouseY + + Dim pitch_Renamed As Double = CamAngleY - (Math.PI / 2) + Dim yaw_Renamed As Double = CamAngleX - (Math.PI / 2) + Dim CamLX As Single = CSng(Math.Sin(yaw_Renamed)) + Dim CamLY As Single = CSng(Math.Cos(pitch_Renamed)) + Dim CamLZ As Single = CSng(-Math.Cos(yaw_Renamed)) + + Dim m As Single = 8.0F + + Select Case currentLookDirection + Case LookDirection.Top + pos.X = orgPos.X - ((MousePosX * CamSpeedMultiplier) * (CamLX) * m) - ((MousePosY * CamSpeedMultiplier) * (CamLZ) * m) + pos.Z = orgPos.Z - ((MousePosX * CamSpeedMultiplier) * (CamLZ) * m) - ((MousePosY * CamSpeedMultiplier) * (CamLX) * m) + cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, pos.X, pos.Y - 1000, pos.Z - 1, 0, 1, 0) + lookPositions(CInt(currentLookDirection)) = pos + Case LookDirection.Bottom + pos.X = orgPos.X - ((MousePosX * CamSpeedMultiplier) * (CamLX) * m) + ((MousePosY * CamSpeedMultiplier) * (CamLZ) * m) + pos.Z = orgPos.Z - ((MousePosX * CamSpeedMultiplier) * (CamLZ) * m) + ((MousePosY * CamSpeedMultiplier) * (CamLX) * m) + cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, pos.X, pos.Y + 1000, pos.Z + 1, 0, 1, 0) + lookPositions(CInt(currentLookDirection)) = pos + Case LookDirection.Left + pos.X = orgPos.X - ((MousePosX * CamSpeedMultiplier) * (CamLX) * m) + pos.Y = orgPos.Y - ((MousePosY * CamSpeedMultiplier) * (-1.0F) * m) + pos.Z = orgPos.Z - ((MousePosX * CamSpeedMultiplier) * (CamLZ) * m) + cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, pos.X + 12500, pos.Y, pos.Z, 0, 1, 0) + lookPositions(CInt(currentLookDirection)) = pos + Case LookDirection.Right + pos.X = orgPos.X - ((MousePosX * CamSpeedMultiplier) * (CamLX) * m) + pos.Y = orgPos.Y - ((MousePosY * CamSpeedMultiplier) * (-1.0F) * m) + pos.Z = orgPos.Z - ((MousePosX * CamSpeedMultiplier) * (CamLZ) * m) + cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, pos.X - 12500, pos.Y, pos.Z, 0, 1, 0) + lookPositions(CInt(currentLookDirection)) = pos + Case LookDirection.Front + pos.X = orgPos.X - ((MousePosX * CamSpeedMultiplier) * (CamLX) * m) + pos.Y = orgPos.Y - ((MousePosY * CamSpeedMultiplier) * (-1.0F) * m) + pos.Z = orgPos.Z - ((MousePosX * CamSpeedMultiplier) * (CamLZ) * m) + cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, pos.X, pos.Y, pos.Z - 12500, 0, 1, 0) + lookPositions(CInt(currentLookDirection)) = pos + Case LookDirection.Back + pos.X = orgPos.X - ((MousePosX * CamSpeedMultiplier) * (CamLX) * m) + pos.Y = orgPos.Y - ((MousePosY * CamSpeedMultiplier) * (-1.0F) * m) + pos.Z = orgPos.Z - ((MousePosX * CamSpeedMultiplier) * (CamLZ) * m) + cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, pos.X, pos.Y, pos.Z + 12500, 0, 1, 0) + lookPositions(CInt(currentLookDirection)) = pos + End Select + + lastMouseX = mouseX + lastMouseY = mouseY + 'Console.WriteLine("CamAngleX = " + CamAngleX + ", CamAngleY = " + CamAngleY); + 'setRotationFromLookAt(); + End Sub + + Private Sub UpdateCameraMatrixWithMouse_FLY(mouseX As Integer, mouseY As Integer, ByRef cameraMatrix As Matrix4) + If resetMouse Then + lastMouseX = mouseX + lastMouseY = mouseY + resetMouse = False + End If + Dim MousePosX As Integer = mouseX - lastMouseX + Dim MousePosY As Integer = mouseY - lastMouseY + CamAngleX = CamAngleX + (0.01F * MousePosX) + ' This next part isn't neccessary, but it keeps the Yaw rotation value within [0, 2*pi] which makes debugging simpler. + If CamAngleX > TAU Then + CamAngleX -= TAU + ElseIf CamAngleX < 0 Then + CamAngleX += TAU + End If + + ' Lock pitch rotation within the bounds of [-3.1399.0, -0.0001], otherwise the LookAt function will snap to the + ' opposite side and reverse mouse looking controls. + CamAngleY = Clampf((CamAngleY + (0.01F * MousePosY)), -3.1399F, -0.0001F) + + lastMouseX = mouseX + lastMouseY = mouseY + OrientateCam(CamAngleX, CamAngleY) + UpdateMatrix(cameraMatrix) + 'Console.WriteLine("CamAngleX = " + CamAngleX + ", CamAngleY = " + CamAngleY); + 'setRotationFromLookAt(); + End Sub + + Private Sub UpdateCameraOffsetWithMouse_FLY(orgPos As Vector3, mouseX As Integer, mouseY As Integer, w As Integer, h As Integer, ByRef cameraMatrix As Matrix4) + If resetMouse Then + lastMouseX = mouseX + lastMouseY = mouseY + resetMouse = False + End If + Dim MousePosX As Integer = (-mouseX) + lastMouseX + Dim MousePosY As Integer = (-mouseY) + lastMouseY + Dim pitch_Renamed As Double = CamAngleY - (Math.PI / 2) + Dim yaw_Renamed As Double = CamAngleX - (Math.PI / 2) + Dim CamLX As Single = Math.Sin(yaw_Renamed) + Dim CamLZ As Single = -Math.Cos(yaw_Renamed) + pos.X = orgPos.X - ((MousePosX * CamSpeedMultiplier) * (CamLX) * 6.0F) + pos.Y = orgPos.Y - ((MousePosY * CamSpeedMultiplier) * (-1.0F) * 6.0F) + pos.Z = orgPos.Z - ((MousePosX * CamSpeedMultiplier) * (CamLZ) * 6.0F) + + OrientateCam(CamAngleX, CamAngleY) + UpdateMatrix(cameraMatrix) + End Sub + + Public Sub UpdateCameraOffsetDirectly(horz_amount As Integer, vert_amount As Integer, ByRef cameraMatrix As Matrix4) + If myCamMode = CameraMode.ORBIT Then + UpdateCameraOffsetDirectly_ORBIT(horz_amount / 5, vert_amount / 5, cameraMatrix) + Else + 'Console.WriteLine(MousePosX+","+ MousePosY); + Dim pitch_Renamed As Double = CamAngleY - (Math.PI / 2) + Dim yaw_Renamed As Double = CamAngleX - (Math.PI / 2) + Dim CamLX As Single = CSng(Math.Sin(yaw_Renamed)) + ' float CamLY = (float)Math.Cos(pitch); + Dim CamLZ As Single = CSng(-Math.Cos(yaw_Renamed)) + pos.X += ((horz_amount * CamSpeedMultiplier) * (CamLX)) + pos.Y += ((vert_amount * CamSpeedMultiplier) * (-1.0F)) + pos.Z += ((horz_amount * CamSpeedMultiplier) * (CamLZ)) + + OrientateCam(CamAngleX, CamAngleY) + UpdateMatrix(cameraMatrix) + End If + End Sub + + Private Sub UpdateCameraOffsetDirectly_ORBIT(moveSpeedX As Integer, moveSpeedY As Integer, ByRef cameraMatrix As Matrix4) + Dim MousePosX As Integer = moveSpeedX + Dim MousePosY As Integer = moveSpeedY + orbitTheta += MousePosX * 0.01F * CamSpeedMultiplier + orbitPhi -= MousePosY * 0.01F * CamSpeedMultiplier + orbitPhi = Clampf(orbitPhi, -1.57F, 1.57F) + UpdateOrbitCamera(cameraMatrix) + End Sub + + Private Sub UpdateCameraMatrixWithMouse_ORBIT(mouseX As Integer, mouseY As Integer, ByRef cameraMatrix As Matrix4) + UpdateCameraOffsetWithMouse_ORBIT(mouseX, mouseY, cameraMatrix) + End Sub + + Private Sub UpdateCameraOffsetWithMouse_ORBIT(mouseX As Integer, mouseY As Integer, ByRef cameraMatrix As Matrix4) + If resetMouse Then + lastMouseX = mouseX + lastMouseY = mouseY + resetMouse = False + End If + Dim MousePosX As Integer = (-mouseX) + lastMouseX + Dim MousePosY As Integer = (-mouseY) + lastMouseY + orbitTheta += MousePosX * 0.01F * CamSpeedMultiplier + orbitPhi -= MousePosY * 0.01F * CamSpeedMultiplier + orbitPhi = Clampf(orbitPhi, -1.57F, 1.57F) + UpdateOrbitCamera(cameraMatrix) + lastMouseX = mouseX + lastMouseY = mouseY + End Sub + + Private Sub UpdateCameraMatrixWithScrollWheel_ORBIT(amt As Integer, ByRef cameraMatrix As Matrix4) + orbitDistance -= amt + If orbitDistance < 300.0F Then + orbitDistance = 300.0F + End If + UpdateOrbitCamera(cameraMatrix) + End Sub + + Public Sub ResetMouseStuff() + resetMouse = True + End Sub + + Private Function CalculateCenterPositionOfObjects(objs As ICameraPoint()) As Numerics.Vector3 + If objs.Length <= 1 Then + Dim obj As ICameraPoint = objs.FirstOrDefault + If obj Is Nothing Then + Return Numerics.Vector3.Zero + Else + Return New Numerics.Vector3(obj.Position.X, + obj.Position.Y, + obj.Position.Z) + End If + End If + + Dim maxX As Single? = Nothing + Dim maxY As Single? = Nothing + Dim maxZ As Single? = Nothing + Dim minX As Single? = Nothing + Dim minY As Single? = Nothing + Dim minZ As Single? = Nothing + + For Each obj As ICameraPoint In objs + Dim pos As Numerics.Vector3 = obj.Position + If maxX Is Nothing OrElse pos.X > maxX Then maxX = pos.X + If maxY Is Nothing OrElse pos.Y > maxY Then maxY = pos.Y + If maxZ Is Nothing OrElse pos.Z > maxZ Then maxZ = pos.Z + If minX Is Nothing OrElse pos.X < minX Then minX = pos.X + If minY Is Nothing OrElse pos.Y < minY Then minY = pos.Y + If minZ Is Nothing OrElse pos.Z < minZ Then minZ = pos.Z + Next + + If maxX Is Nothing Then maxX = 0 + If maxY Is Nothing Then maxY = 0 + If maxZ Is Nothing Then maxZ = 0 + If minX Is Nothing Then minX = 0 + If minY Is Nothing Then minY = 0 + If minZ Is Nothing Then minZ = 0 + + Dim upper As New Numerics.Vector3(maxX, maxY, maxZ) + Dim lower As New Numerics.Vector3(minX, minY, minZ) + + Dim middle As Numerics.Vector3 = (upper + lower) / 2 + + Return middle + End Function + + Private Function CalculateCenterYRotationOfObjects(objs As ICameraPoint()) As Single + If objs.Length <= 1 Then + Dim obj As ICameraPoint = objs.FirstOrDefault + If obj Is Nothing Then + Return 0 + Else + Return obj.Rotation.Y + End If + End If + + Dim yRot As New List(Of Single) + + For Each obj As ICameraPoint In objs + yRot.Add(obj.Rotation.Y) + Next + + Return yRot.Average + End Function + + Private Function GetSelectedObject() As ICameraPoint() + Dim e As New NeedSelectedObjectEventArgs + RaiseEvent NeedSelectedObject(e) + + Dim stopw As New Stopwatch + stopw.Start() + + Do Until e.HasObjectSetted OrElse stopw.ElapsedMilliseconds > 1000 + Application.DoEvents() + Loop + + stopw.Stop() + + Return e.Points + End Function + + 'C A P S E L T C L A S S E S + + Public Class NeedSelectedObjectEventArgs + Inherits EventArgs + + Private _HasObjectSetted As Boolean = False + Public ReadOnly Property HasObjectSetted As Boolean + Get + Return _HasObjectSetted + End Get + End Property + + Private _Points As ICameraPoint() = Nothing + Public Property Points As ICameraPoint() + Get + Return _Points + End Get + Set(value As ICameraPoint()) + _Points = value + _HasObjectSetted = True + End Set + End Property + + End Class + + End Class + +End Namespace diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/Camera/CameraMode.vb b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Camera/CameraMode.vb new file mode 100644 index 0000000..57564c6 --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Camera/CameraMode.vb @@ -0,0 +1,9 @@ +Namespace CameraN + + Public Enum CameraMode + FLY = 0 + ORBIT = 1 + LOOK_DIRECTION = 2 + End Enum + +End Namespace diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/Camera/CameraPoint.vb b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Camera/CameraPoint.vb new file mode 100644 index 0000000..5fb91d1 --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Camera/CameraPoint.vb @@ -0,0 +1,10 @@ +Namespace CameraN + + Public Interface ICameraPoint + + Property Position As Numerics.Vector3 + Property Rotation As Numerics.Vector3 + + End Interface + +End Namespace diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/Camera/LookDirection.vb b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Camera/LookDirection.vb new file mode 100644 index 0000000..38853ac --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Camera/LookDirection.vb @@ -0,0 +1,12 @@ +Namespace CameraN + + Public Enum LookDirection + Top + Bottom + Left + Right + Front + Back + End Enum + +End Namespace diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/ModelPreview.Designer.vb b/Pilz.Drawing.Drawing3D.OpenGLRenderer/ModelPreview.Designer.vb new file mode 100644 index 0000000..2e53c09 --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/ModelPreview.Designer.vb @@ -0,0 +1,120 @@ + +Partial Class ModelPreview + Inherits DevComponents.DotNetBar.OfficeForm + + 'Form overrides dispose to clean up the component list. + + Protected Overrides Sub Dispose(ByVal disposing As Boolean) + Try + If disposing AndAlso components IsNot Nothing Then + components.Dispose() + End If + Finally + MyBase.Dispose(disposing) + End Try + End Sub + + 'Required by the Windows Form Designer + Private components As System.ComponentModel.IContainer + + 'NOTE: The following procedure is required by the Windows Form Designer + 'It can be modified using the Windows Form Designer. + 'Do not modify it using the code editor. + + Private Sub InitializeComponent() + Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(ModelPreview)) + Me.PanelEx1 = New DevComponents.DotNetBar.PanelEx() + Me.PanelEx2 = New DevComponents.DotNetBar.PanelEx() + Me.DoubleInput1 = New DevComponents.Editors.DoubleInput() + Me.LabelX1 = New DevComponents.DotNetBar.LabelX() + Me.PanelEx2.SuspendLayout() + CType(Me.DoubleInput1, System.ComponentModel.ISupportInitialize).BeginInit() + Me.SuspendLayout() + ' + 'PanelEx1 + ' + Me.PanelEx1.CanvasColor = System.Drawing.Color.Empty + Me.PanelEx1.ColorSchemeStyle = DevComponents.DotNetBar.eDotNetBarStyle.StyleManagerControlled + Me.PanelEx1.DisabledBackColor = System.Drawing.Color.Empty + Me.PanelEx1.Dock = System.Windows.Forms.DockStyle.Fill + Me.PanelEx1.Location = New System.Drawing.Point(0, 47) + Me.PanelEx1.Name = "PanelEx1" + Me.PanelEx1.Size = New System.Drawing.Size(880, 491) + Me.PanelEx1.Style.Alignment = System.Drawing.StringAlignment.Center + Me.PanelEx1.Style.BorderColor.ColorSchemePart = DevComponents.DotNetBar.eColorSchemePart.PanelBorder + Me.PanelEx1.Style.ForeColor.ColorSchemePart = DevComponents.DotNetBar.eColorSchemePart.PanelText + Me.PanelEx1.Style.GradientAngle = 90 + Me.PanelEx1.TabIndex = 0 + ' + 'PanelEx2 + ' + Me.PanelEx2.CanvasColor = System.Drawing.Color.Empty + Me.PanelEx2.ColorSchemeStyle = DevComponents.DotNetBar.eDotNetBarStyle.StyleManagerControlled + Me.PanelEx2.Controls.Add(Me.DoubleInput1) + Me.PanelEx2.Controls.Add(Me.LabelX1) + Me.PanelEx2.DisabledBackColor = System.Drawing.Color.Empty + Me.PanelEx2.Dock = System.Windows.Forms.DockStyle.Top + Me.PanelEx2.Location = New System.Drawing.Point(0, 0) + Me.PanelEx2.Name = "PanelEx2" + Me.PanelEx2.Size = New System.Drawing.Size(880, 47) + Me.PanelEx2.Style.Alignment = System.Drawing.StringAlignment.Center + Me.PanelEx2.Style.BorderColor.ColorSchemePart = DevComponents.DotNetBar.eColorSchemePart.PanelBorder + Me.PanelEx2.Style.ForeColor.ColorSchemePart = DevComponents.DotNetBar.eColorSchemePart.PanelText + Me.PanelEx2.Style.GradientAngle = 90 + Me.PanelEx2.TabIndex = 7 + Me.PanelEx2.Visible = False + ' + 'DoubleInput1 + ' + ' + ' + ' + Me.DoubleInput1.BackgroundStyle.Class = "DateTimeInputBackground" + Me.DoubleInput1.BackgroundStyle.CornerType = DevComponents.DotNetBar.eCornerType.Square + Me.DoubleInput1.ButtonFreeText.Shortcut = DevComponents.DotNetBar.eShortcut.F2 + Me.DoubleInput1.Increment = 1.0R + Me.DoubleInput1.Location = New System.Drawing.Point(62, 13) + Me.DoubleInput1.Name = "DoubleInput1" + Me.DoubleInput1.ShowUpDown = True + Me.DoubleInput1.Size = New System.Drawing.Size(80, 20) + Me.DoubleInput1.TabIndex = 0 + ' + 'LabelX1 + ' + ' + ' + ' + Me.LabelX1.BackgroundStyle.CornerType = DevComponents.DotNetBar.eCornerType.Square + Me.LabelX1.Location = New System.Drawing.Point(12, 12) + Me.LabelX1.Name = "LabelX1" + Me.LabelX1.Size = New System.Drawing.Size(44, 23) + Me.LabelX1.TabIndex = 1 + Me.LabelX1.Text = "Scaling:" + ' + 'ModelPreview + ' + Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) + Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font + Me.ClientSize = New System.Drawing.Size(880, 538) + Me.Controls.Add(Me.PanelEx1) + Me.Controls.Add(Me.PanelEx2) + Me.DoubleBuffered = True + Me.EnableGlass = False + Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon) + Me.KeyPreview = True + Me.Name = "ModelPreview" + Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen + Me.Text = "ModelPreview" + Me.TopLeftCornerSize = 0 + Me.TopRightCornerSize = 0 + Me.PanelEx2.ResumeLayout(False) + CType(Me.DoubleInput1, System.ComponentModel.ISupportInitialize).EndInit() + Me.ResumeLayout(False) + + End Sub + + Friend WithEvents PanelEx1 As DevComponents.DotNetBar.PanelEx + Friend WithEvents PanelEx2 As DevComponents.DotNetBar.PanelEx + Friend WithEvents DoubleInput1 As DevComponents.Editors.DoubleInput + Friend WithEvents LabelX1 As DevComponents.DotNetBar.LabelX +End Class diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/Application.Designer.vb b/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/Application.Designer.vb new file mode 100644 index 0000000..8ab460b --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/Application.Designer.vb @@ -0,0 +1,13 @@ +'------------------------------------------------------------------------------ +' +' Dieser Code wurde von einem Tool generiert. +' Laufzeitversion:4.0.30319.42000 +' +' Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +' der Code erneut generiert wird. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/Application.myapp b/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/Application.myapp new file mode 100644 index 0000000..758895d --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/Application.myapp @@ -0,0 +1,10 @@ + + + false + false + 0 + true + 0 + 1 + true + diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/AssemblyInfo.vb b/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/AssemblyInfo.vb new file mode 100644 index 0000000..05b61da --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/AssemblyInfo.vb @@ -0,0 +1,35 @@ +Imports System +Imports System.Reflection +Imports System.Runtime.InteropServices + +' Allgemeine Informationen über eine Assembly werden über die folgenden +' Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +' die einer Assembly zugeordnet sind. + +' Werte der Assemblyattribute überprüfen + + + + + + + + + + +'Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird. + + +' Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +' +' Hauptversion +' Nebenversion +' Buildnummer +' Revision +' +' Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, +' übernehmen, indem Sie "*" eingeben: +' + + + diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/Resources.Designer.vb b/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/Resources.Designer.vb new file mode 100644 index 0000000..300e380 --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/Resources.Designer.vb @@ -0,0 +1,63 @@ +'------------------------------------------------------------------------------ +' +' Dieser Code wurde von einem Tool generiert. +' Laufzeitversion:4.0.30319.42000 +' +' Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +' der Code erneut generiert wird. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + +Imports System + +Namespace My.Resources + + 'Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + '-Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + 'Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + 'mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + ''' + ''' Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + ''' + _ + Friend Module Resources + + Private resourceMan As Global.System.Resources.ResourceManager + + Private resourceCulture As Global.System.Globalization.CultureInfo + + ''' + ''' Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + ''' + _ + Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager + Get + If Object.ReferenceEquals(resourceMan, Nothing) Then + Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("Pilz.Drawing.Drawing3D.OpenGLFactory.Resources", GetType(Resources).Assembly) + resourceMan = temp + End If + Return resourceMan + End Get + End Property + + ''' + ''' Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + ''' Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + ''' + _ + Friend Property Culture() As Global.System.Globalization.CultureInfo + Get + Return resourceCulture + End Get + Set + resourceCulture = value + End Set + End Property + End Module +End Namespace diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/Resources.resx b/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/Settings.Designer.vb b/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/Settings.Designer.vb new file mode 100644 index 0000000..7ef730a --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/Settings.Designer.vb @@ -0,0 +1,73 @@ +'------------------------------------------------------------------------------ +' +' Dieser Code wurde von einem Tool generiert. +' Laufzeitversion:4.0.30319.42000 +' +' Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +' der Code erneut generiert wird. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + + +Namespace My + + _ + Partial Friend NotInheritable Class MySettings + Inherits Global.System.Configuration.ApplicationSettingsBase + + Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()),MySettings) + +#Region "Automatische My.Settings-Speicherfunktion" +#If _MyType = "WindowsForms" Then + Private Shared addedHandler As Boolean + + Private Shared addedHandlerLockObject As New Object + + _ + Private Shared Sub AutoSaveSettings(sender As Global.System.Object, e As Global.System.EventArgs) + If My.Application.SaveMySettingsOnExit Then + My.Settings.Save() + End If + End Sub +#End If +#End Region + + Public Shared ReadOnly Property [Default]() As MySettings + Get + +#If _MyType = "WindowsForms" Then + If Not addedHandler Then + SyncLock addedHandlerLockObject + If Not addedHandler Then + AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings + addedHandler = True + End If + End SyncLock + End If +#End If + Return defaultInstance + End Get + End Property + End Class +End Namespace + +Namespace My + + _ + Friend Module MySettingsProperty + + _ + Friend ReadOnly Property Settings() As Global.Pilz.Drawing.Drawing3D.OpenGLFactory.My.MySettings + Get + Return Global.Pilz.Drawing.Drawing3D.OpenGLFactory.My.MySettings.Default + End Get + End Property + End Module +End Namespace diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/Settings.settings b/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/Settings.settings new file mode 100644 index 0000000..85b890b --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/My Project/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/OpenTK.dll.config b/Pilz.Drawing.Drawing3D.OpenGLRenderer/OpenTK.dll.config new file mode 100644 index 0000000..7098d39 --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/OpenTK.dll.config @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/Pilz.Drawing.Drawing3D.OpenGLFactory.vbproj b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Pilz.Drawing.Drawing3D.OpenGLFactory.vbproj new file mode 100644 index 0000000..1829246 --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Pilz.Drawing.Drawing3D.OpenGLFactory.vbproj @@ -0,0 +1,142 @@ + + + + + Debug + AnyCPU + {5E9F0B0A-F7B8-49A9-80FC-6DFE0D44CC84} + Library + Pilz.Drawing.Drawing3D.OpenGLFactory + Pilz.Drawing.Drawing3D.OpenGLFactory + 512 + Windows + v4.5 + + + true + full + true + true + bin\Debug\ + Pilz.Drawing.Drawing3D.OpenGLFactory.xml + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + pdbonly + false + true + true + bin\Release\ + Pilz.Drawing.Drawing3D.OpenGLFactory.xml + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + On + + + Binary + + + Off + + + On + + + + ..\packages\OpenTK.3.0.1\lib\net20\OpenTK.dll + + + ..\packages\OpenTK.GLControl.3.0.1\lib\net20\OpenTK.GLControl.dll + + + + + + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\portable-net45+win8+wp8+wpa81\System.Numerics.Vectors.dll + + + + + + + + + + + + + + + + + + + + + + + + + ModelPreview.vb + + + Form + + + + + + + True + Application.myapp + + + True + True + Resources.resx + + + True + Settings.settings + True + + + + + + + VbMyResourcesResXFileCodeGenerator + Resources.Designer.vb + My.Resources + Designer + + + ModelPreview.vb + + + + + + MyApplicationCodeGenerator + Application.Designer.vb + + + SettingsSingleFileGenerator + My + Settings.Designer.vb + + + + + + + {ac955819-7910-450c-940c-7c1989483d4b} + Pilz.Simple3DFileParser + + + + + \ No newline at end of file diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/Preview/ModelPreview.Designer.vb b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Preview/ModelPreview.Designer.vb new file mode 100644 index 0000000..0ee6e5e --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Preview/ModelPreview.Designer.vb @@ -0,0 +1,42 @@ +Namespace PreviewN + + + Partial Class ModelPreview + Inherits System.Windows.Forms.Form + + 'Form overrides dispose to clean up the component list. + + Protected Overrides Sub Dispose(ByVal disposing As Boolean) + Try + If disposing AndAlso components IsNot Nothing Then + components.Dispose() + End If + Finally + MyBase.Dispose(disposing) + End Try + End Sub + + 'Required by the Windows Form Designer + Private components As System.ComponentModel.IContainer + + 'NOTE: The following procedure is required by the Windows Form Designer + 'It can be modified using the Windows Form Designer. + 'Do not modify it using the code editor. + + Private Sub InitializeComponent() + Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(ModelPreview)) + Me.SuspendLayout() + ' + 'ModelPreview + ' + Me.ClientSize = New System.Drawing.Size(880, 538) + Me.DoubleBuffered = True + Me.Name = "ModelPreview" + Me.Text = "ModelPreview" + Me.ResumeLayout(False) + + End Sub + + End Class + +End Namespace diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/Preview/ModelPreview.resx b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Preview/ModelPreview.resx new file mode 100644 index 0000000..42188b9 --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Preview/ModelPreview.resx @@ -0,0 +1,1978 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAIAgIAAAAEAIAAoCAEAJgAAAAAAAAABACAAz6kAAE4IAQAoAAAAgAAAAAABAAABACAAAAAAAAAA + AQATCwAAEwsAAAAAAAAAAAAA////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////ALjx/xK59fozuPT6Xrjz+YK39fqYtvT5pbf0+qS28/mlt/P6mLf1 + +3+28PZXt/L4J6r//wP///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AuPX1Gbr0+Vm79/yiuvb72bj1 + +vi7+v//vPz//7v8//+5/P//ufz//7r7//+5+///ufz//7j5//+39vztt/T6v7bz+m289P8X////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8AtvX6Mbz2/ZC69fzgvPr//778//+6+f//tfb8/7P1+/+y9Pr/sfT6/7D0+v+v9Pr/r/T6/6/0 + +v+w9Pr/sfT7/7T3/f+4+///ufv//7f1/Ny19Phyv+r/DP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8Auu/0ML33/aK79/3yv/7//7r5//+29fv/tPX6/7Hz + +v+s8Pn/qO33/6Tp9f+h5/P/nubz/57m8v+d5vL/n+fz/6Ho9P+l7Pb/qvD4/67z+v+x9Pr/tvn//7v7 + //+49/u/tfT0MP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AtufzFbr0 + +Yi89/3wwP3//7n3/f+29fr/s/T6/63w+P+l6vX/n+Ty/5rh8P+X4O//ld/v/5Tf7/+T3+//k97v/5Pf + 7/+T3+//k9/v/5Xf7/+Y4fD/neXy/6bs9v+u8vr/s/X7/7v9//+69/zktPP3Qf///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////ALz4+0i99vvQwP3//7r4/f+39fr/s/T6/6zu9/+i5fP/m+Hw/5jf + 7/+V4O//lODv/5Pf7/+R3+//kd7v/5De7/+Q3u7/kN7u/5De7v+Q3u//kd7v/5Lf7/+U3+//luDv/53k + 8v+q7vf/svT6/7r7//+7+P3muPH6Nv///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AMz//wW89Pt5vfj+9r/7 + //+49fr/tvX6/67v+P+i5fL/m+Dw/5jf7/+W4O//leDv/5Pf7/+R3+//j97v/47e7v+N3u7/jd7u/4ze + 7v+N3u7/jN7u/43e7v+O3u7/j97u/5Hf7/+T3+//leDv/5rh7/+n6vX/s/P6/779//+69frOw///Ef// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wC27f8OuvX6n7/7//+7+P7/uPb7/7Ly+f+n6PT/nuHw/5rg8P+Y4O//leDv/5Pf + 7/+R3+//j9/v/43e7v+M3u7/i97u/4rd7v+K3e7/it3u/4rd7v+K3e7/it3u/4ze7v+M3u7/j97u/5Hf + 7/+T3+//l+Dv/5vf7/+n6fX/tfT6/7/9//+89ft9////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AyP//Drv1+7HC////uvb8/7j1 + +/+v7/f/ouPy/5zg8P+b4PD/mODv/5Tf7/+S3+//kN/v/47e7v+M3u7/it7u/4rd7v+K3e7/id3u/4nd + 7v+J3e7/iN3u/4nd7v+K3e7/it3u/4ve7v+N3u7/j97u/5Pf7/+W4O//muDw/5zg8P+q6vX/vPn+/7n0 + +eO19PQY////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AKrj/wm79fuswf///7r2+/+49vv/rez2/5/h8P+d4PD/muDw/5ff7/+U3+//kd7v/4/d + 7/+N3e7/i93u/4rd7v+J3u7/h93u/4jd7v+I3e7/h93u/4jd7v+I3e7/iN3u/4nd7v+K3e7/i93u/43e + 7v+P3u7/kt/v/5Xg7/+Z4O//neDw/6Hh8P+y7/j/v/z//7v0+mH///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8Auvb6jMH9//+69vz/t/X7/6rq + 9f+f4PD/nODw/5ng8P+W3+//k9/v/5De7/+O3e//i93v/4rc7v+J3O7/iN3u/4fd7v+H3e7/h93u/4bd + 7v+H3e7/h93u/4fc7v+H3O7/id3u/4rd7v+L3u7/jd/u/4/f7/+S3+//leDv/5jf7/+c3/D/oODw/6jl + 8v/A/P//vPb8pAD//wH///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////ALz0+Vu++f38u/f9/7n1+/+s6/X/n+Dw/5zg8P+Z4PD/lt/v/5Pf7/+Q3u//jd7v/4vd + 7/+J3O7/h9zu/4fc7v+H2+7/h9zu/4fd7v+H3e7/htzu/4fd7v+J3+//iuHx/4/l8v+T6PT/len1/5fr + 9v+b7Pb/nez2/57s9v+h6/X/ounz/6Hl8v+i4vH/o+Hw/7fz/P+99/vXsf/rDf///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wC59/chvPb84r/7//+69fv/r+z2/6Dg + 8P+d4PD/muDw/5bf8P+T3+//kN7v/43e7v+K3e7/idzu/4fc7v+G3O7/htzu/4Tb7v+F2+7/htzu/4je + 7/+N4/H/kun1/5bt9/+Y7/j/mvD4/5vw+P+c7/j/nfD4/5/w+P+i8fn/pPH5/6ny+f+t8/r/sPP6/7Lx + +f+u6/X/s+75/732++u9+Pgj////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8AgICAArr0+qbC////uvX7/7Lw+f+i4fH/neDw/5rg8P+W4PD/k9/v/5De7v+M3e7/id3t/4jc + 7f+G3O3/hdzu/4Xc7v+F3O7/hNvu/4fd7/+P5fP/lOz3/5jv+P+Y7/j/me/4/5rv+P+a7/j/nPD4/53w + +P+e8Pj/oPD4/6Px+f+m8fn/qvL5/67z+v+z9Pr/t/X6/7n2+/+89v3/vfb89L71+jP///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wC69fhKvvn8+rz3/P+39Pv/puXy/57g + 8P+b4PD/l+Dw/5Pf7/+P3u7/i93t/4nd7f+G3O3/hdzs/4Pc7P+D3Oz/hNzt/4Xd7v+N5PP/lOz3/5fv + +P+Y7/j/me/4/5nv+P+a7/j/nO/4/53w+P+e8Pj/n/D4/6Dw+P+j8fn/pfH5/6jy+f+s8/n/sPP6/7P0 + +v+39fr/uvX7/733/f+89vv5vPb7Of///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8Av///CLz2+8PB/f//ufb7/6zr9v+f4PD/nODw/5jg8P+U3+//kN7u/4ze7f+I3e3/htzt/4Tc + 7f+D3Oz/g9zs/4Pb7P+H4e//ker2/5bu+P+W7vj/mO74/5nv+P+b7/j/m/D4/53w+P+e8Pj/nvD4/6Dw + +P+i8fn/o/H5/6Xx+f+o8vn/qvL5/67z+v+x9Pr/tfT6/7j1+v+69fv/vff9/7z2+vW+9foz////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wC59Plbvfj8/7v2/P+08fn/o+Lx/53g + 8P+a4PD/ld/v/5Hf7v+M3u3/idzt/4bb7f+D2u3/gtrs/4Ha7P+B3Oz/i+Xx/5Lt9v+U7vf/le74/5fu + +P+Z7vj/m+/4/5zw+P+d8Pj/nvD4/6Dw+f+i8fn/o/H5/6Xx+f+n8vn/qfL5/6vy+f+u8/n/sPP6/7T0 + +v+39Pr/ufX7/7v1+/+/+f7/vvb77MH4/yX///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A1f//Brv2+8TA/f//ufX7/6nn9P+e4PD/m+Dw/5bg7v+R3+7/jN7t/4nc7f+F2+3/g9rs/4Ha + 7P+A2ez/gtzt/4vm8/+Q7vb/ku72/5Tu9/+X7vj/me74/5rv+P+d7/n/n/D5/6Dx+f+h8fn/pPH5/6Xx + +f+n8vn/qPL5/6ry+f+s8vn/rvP6/7Hz+v+z9Pr/tfT6/7j1+v+69fv/vPX7/8D6//++9vzew/D/Ef// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wC8+PtEvPj8/Lv2/P+z7/n/oeHx/53g + 8P+Z4O//k9/u/47e7v+J3e3/htvt/4Pa7f+B2uz/f9rs/4Db7f+K6PT/kO32/5Dt9v+S7vb/le73/5ju + +P+a7/j/nO/4/57v+f+i8Pn/o/H5/6Xy+f+n8vn/qfL5/6vy+f+s8vn/rvP6/6/z+v+x8/r/s/T6/7b0 + +v+49fr/ufX7/7v1+/+99vv/w/z//771+7mq//8D////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////Abz2/KfB/v//ufX7/6no9P+e3/D/m+Dw/5Xg7/+Q3+7/jN3t/4fb7f+D2+3/gdrs/3/a + 7P9/2+z/iefz/47s9v+P7Pb/ke32/5Pu9/+W7vf/me74/5zv+f+e7/n/ofH5/6Tx+f+m8vn/qPL5/6vy + +f+s8/r/rvP6/7Dz+v+y8/r/s/T6/7T0+v+29Pr/uPX6/7r1+/+79fv/vPX7/772+//F////vfT5i/// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wC58vkovPb78rz4/f+z8Pn/oeHx/53g + 8P+Y4O//kt/u/43d7f+I3O3/hdvt/4La7P9/2uz/ftrs/4bl8v+N7fb/jez2/4/s9v+R7Pb/le73/5jv + 9/+b7/j/nu/5/6Lw+f+k8Pn/p/L5/6jy+f+s8/r/rvP6/7Dz+v+y9Pr/s/T6/7X0+v+29Pr/t/X6/7j1 + +v+69fv/u/X7/7z1+/+99vv/v/f8/8H5/f+68/lV////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////ALz3+3rB/v//ufX8/6vp9f+d3/D/muDv/5Tg7v+R3u7/i9zt/4bb7f+D2+3/gNrs/33Z + 7P+C4fD/jOz2/43s9v+O7Pb/kez2/5Tt9/+X7/f/mu/3/57w+P+h8Pn/pPD5/6fx+f+q8/n/rPP6/6/z + +v+y9Pr/s/T6/7X0+v+29Pr/uPX6/7n1+v+59fv/uvX7/7v1+/+89vv/vfb7/772+//A+f7/vvX77MHw + 9yH///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wC///8Mu/T60776//+28vr/o+Px/53g + 7/+Y4O//k9/u/43d7v+I2+3/hNvt/4Hb7f9+2uz/gN7u/4vr9f+N7Pb/jez2/4/s9v+S7Pf/le33/5jv + 9/+e8Pf/oPD5/6Tw+f+n8fn/qvL6/67z+v+w9Pr/svT6/7T0+v+29fr/uPX6/7j1+/+69fv/u/X7/7v1 + +/+89fv/vfb7/772+/+99vv/vvb7/8T9//++9fm3////Af///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////ALr0+Ea89/z9uvb9/67s9/+f4fD/m+Dv/5bg7v+Q3u7/itzt/4bb7f+C2+3/gNrs/37a + 7P+I6PP/je32/43s9v+P7Pb/ke33/5Tt9/+Y7vf/m/D3/5/w+P+j8fn/p/H5/6vy+v+u8/r/sPT6/7P0 + +v+09Pr/t/X6/7j1+/+69fv/u/X7/7v1+/+89vv/vPb7/732+/++9vv/vvb7/772+/+/9vv/xPz//733 + +mX///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8Au/P6mcH+//+49Pv/pebz/53g + 8P+Z4O//k9/u/47d7v+J3O3/hNvt/4Ha7f9/2ez/hOLx/4zs9v+O7Pb/juz2/5Ds9/+T7ff/l+33/5vv + 9/+f8Pf/o/H4/6fx+f+q8vr/rvL6/7Hz+v+z9Pr/tfX6/7f1+/+69fv/uvX7/7v1+/+89fv/vfb7/732 + +/++9vv/vvb7/772+/+/9vv/v/b7/8L5/v++9fvnv/b/HP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////ALbz8xW79PrhvPn+/7Pw+f+g4fD/nODv/5fg7/+R3u7/i93u/4fc7f+D2+3/gNrt/4Hc + 7v+L6vX/jez2/47s9v+P7Pf/k+33/5bt9/+b7vf/nvD4/6Lx+P+m8fn/qvL6/67y+v+w8/r/tPT6/7b1 + +v+49fv/uvX7/7v1+/+79vv/vfb7/732+/++9vv/vvb7/772+/++9vv/v/b7/7/2+/+/9vv/xv///73z + +pf///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8Au/b5U735/f+59vz/rOv2/53g + 7/+a4O//lN/u/4/d7v+J3O3/hdzt/4Lb7f9/2u3/huPy/43t9v+N7Pf/j+33/5Ht9/+V7vf/me73/53v + +P+h8Pj/pvH4/6ry+f+t8/r/sPP6/7P0+v+29fr/uPX7/7r1+/+79fv/vPb7/732+/++9vv/vvb7/772 + +/++9vv/v/b7/7/2+/+/9vv/v/b7/8D4/f/A+Pz2vfb2Nv///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wC69PyjwP7//7bz+/+k5fL/nODv/5jf7/+S3u7/jN3u/4jc7f+E2+3/gdvt/4Hd + 7v+M6/b/ju33/47s9/+R7ff/lO33/5fu9/+b7vf/oO/4/6Ty+P+p8vn/rfP6/7Dz+v+z8/r/tvT6/7j1 + +/+69fv/vPb7/7z2+/+99vv/vvb7/772+/+/9vv/vvb7/7/2+/+/9vv/v/b7/7/2+/+/9vv/xf///772 + +qn///8B////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AuPX1Gbn0++W7+P7/sO/4/5/h + 8P+a4O//ld/v/5De7v+L3e7/htzt/4Pb7f9/2e3/huTz/43s9/+O7ff/j+33/5Lu9/+W7vf/mu73/53v + +P+j8Pj/qPL4/6zy+f+v8/r/s/P6/7b0+v+49fv/u/X7/7v1+/+99vv/vfb7/772+/++9vv/v/b7/7/2 + +/+/9vv/v/b7/7/2+/+/9vv/v/b7/8H4/f/B+Pz2vPL2Of///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wC59vxUvPn9/7j2/P+p6vX/nN/v/5jf7/+T3+//jt7u/4nd7v+E3O3/gdrt/4Hd + 7v+M6/b/jez3/4/s9/+R7ff/le33/5jv+P+d7/j/ofD4/6bx+P+r8vn/rvP6/7Lz+v+19Pr/t/T7/7n1 + +/+79vv/vPb7/732+/++9vv/vvb7/7/2+/+/9vv/v/b7/7/2+/+/9vv/v/b7/7/2+/+/9vv/xv///770 + +pz///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////ALn0+qO//v//tPP5/6Lk + 8f+b4O//lt/v/5De7v+L3e7/h9zt/4Pb7f9/2e3/h+Tz/47t9/+N7Pf/j+z3/5Lt9/+W7vf/m+/4/5/w + +P+l8fj/qfH5/63z+f+x8/r/tPT7/7f0+/+59fv/u/b7/7z2+/+99vv/vvb7/7/2+/+/9vv/v/b7/7/2 + +/+/9vv/v/b7/7/2+/+/9vv/v/b7/8L6/v+/9/znvfj4I////wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wC49fUZufT75br4/f+u7/f/neDv/5ng7/+T3+//jt7u/4nd7v+F3O3/gNvt/4Hc + 7v+L6vb/jez3/47s9/+Q7ff/k+33/5ju+P+d7/j/ovD4/6bx+P+s8vn/r/P5/7P0+v+19Pv/ufT7/7v1 + +/+89vv/vfb7/772+/++9vv/vvb7/7/2+/+/9vv/v/b7/7/2+/+/9vv/v/b7/7/2+/+/9/z/xPz+/7z0 + +G////8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////ALfw9lW7+f3/t/X7/6jp + 9P+b3+//luDv/5De7v+M3e7/htzu/4Lb7f9/2u3/hOLy/4zt9/+N7Pf/j+33/5Ht9/+V7ff/mu/4/5/w + +P+k8fj/qfL5/67z+f+x8/n/tPT7/7j0+/+69fv/u/b7/7z2+/+99vv/vvb7/772+/++9vv/v/b7/7/2 + +/+/9vv/v/b7/7/2+/+/9vv/v/b7/8X+//+/9fu6v///CP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wAA//8Bt/T5p739//+y8vn/oOLx/5ng7/+U3+//jt7u/4nc7v+E2+3/gNvt/3/b + 7f+J6fX/i+z3/4zs9/+P7ff/ku33/5fu+P+b7/j/ofD4/6fx+f+r8vn/sPP5/7P0+v+29Pv/ufX7/7r1 + +/+89vv/vfb7/732+/++9vv/v/b7/7/2+/+/9vv/v/b7/7/2+/+/9vv/v/b7/7/2+//C+v7/wPf87Lz0 + +S7///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////ALbt9hy49fvoufj9/6zu + 9/+c4O//l+Dv/5Hf7/+M3e7/htzu/4Lb7f992uz/geDv/4vs9v+L7Pb/jez3/4/t9/+T7ff/me74/53w + +P+k8Pj/qfH5/63y+f+x9Pn/tfT6/7j0+/+69fv/u/b7/7z2+/+99vv/vvb7/772+/++9vv/v/b7/7/2 + +/+/9vv/v/b7/7/2+/+/9vv/wPf8/8P7/v7A+P1p////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8Auvb8Vbr4/P+19Pv/pef0/5rf7/+U3+//j97u/4nd7v+E3O7/f9rs/33a + 6/+F5vP/iez1/4rs9f+N7Pb/kO33/5Tu+P+a7/j/oPD4/6bx+f+q8vn/r/P5/7L0+f+29Pv/uPX7/7r1 + +/+89vv/vfb7/772+/++9vv/v/b7/7/2+/+/9vv/v/b7/7/2+/+/9vv/v/b7/7/2+//G////v/T6o6qq + qgP///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wC49fqfvf3//7Hx + +f+e4vH/l+Dv/5Pf7/+M3e7/htzu/4Lb7f982ev/ftzt/4fq9f+I6/X/iuv1/43s9v+R7vf/lu74/5vv + +P+h8Pn/p/L5/63y+f+w8/n/tPT6/7f0+/+59fv/u/X7/731+/+99vv/vfb7/732+/++9vv/vvb7/7/2 + +/+/9vv/v/b7/7/2+/+/9vv/xP3//7/2+9C19PQY////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8AuPHxErf2+tu4+P7/rO33/5rg7/+V3+//j97v/4nd7v+E2+3/f9rr/3vY + 7P+C4/D/iOv1/4fr9f+K6/b/jez2/5Lu9/+Y7/j/ne/4/6Lw+f+p8vn/rfL5/7Lz+v+19Pr/uPX6/7n1 + +/+79fv/vfb7/732+/++9vv/vvb7/772+/+/9vv/v/b7/7/2+/+/9vv/v/b7/8L6///A9/zqvvD6M/// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wC48vs9t/b7+7X1 + /P+l6PT/mN/v/5Pe7/+O3u//h9zt/4La6/992ev/e9vs/4Xo9P+H6/X/h+v1/4nr9v+O7Pb/k+73/5nv + +P+e8Pn/pPH5/6ry+f+u8/n/s/T6/7X0+v+59fv/uvX7/7z1+/+99vv/vfb7/772+/++9vv/vvb7/772 + +/+/9vv/v/b7/7/2+//B+P3/wvr9+L72/Fb///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////ALf3+3m8/f//sPL6/57j8v+X3+//kd7u/4rd7f+F2uz/gNrr/3rY + 6/9/3+//hur0/4br9f+H6/X/iuv2/47s9v+U7vf/mu/4/6Dw+f+m8vn/q/L5/7Dz+f+z9Pr/tvX6/7n1 + +/+79fv/vPX7/732+/+99vv/vvb7/772+/++9vv/v/b7/7/2+/+/9vv/wPf8/8P6/f+99Pt4////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wCA//8CtvT5trn7 + //+s7/j/m+Dw/5Tf7/+P3u7/iNvs/4LZ6/992ev/edjr/4Lm8v+F6/T/hev1/4fq9f+L6/b/j+z2/5Xt + 9v+b7/j/ofD5/6jx+f+s8/n/sfP6/7X0+v+39fv/uvX7/7v1+/+99vv/vfb7/732+/++9vv/vvb7/7/2 + +/+/9vv/v/b7/8D3/P/E/f//vfb6k////wH///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////ALXq9Bi29Pvjtvj+/6bq9f+X3u//kt7u/4zc7P+F2uv/f9jr/3rX + 6v973O3/hOf0/4Po8/+F6vT/h+r1/4vs9v+R7Pb/lu32/53v+P+j8fn/qfL5/67z+f+y8/r/tfT6/7f1 + +/+69fv/u/X7/732+/++9vv/vvb7/772+/+/9vv/v/b7/7/2+/+/9vv/xv///771+6yz5uYK////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AtfP3PrX1 + +/uz9fv/n+Ty/5Xe7f+Q3e3/idrr/4PY6v991+n/edXo/3/h7/+D5/P/gufz/4Tp9P+I6vX/jOz2/5Lt + 9v+Z7vf/n/D5/6Xx+f+r8/n/r/P5/7T0+v+39fr/ufX7/7v1+/+89fv/vfb7/772+/++9vv/vvb7/7/2 + +/+/9vv/v/b7/8b///+/9/u+v/LyFP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wC18/puuvz//67x+f+a4fD/k97u/43c7P+H2Ov/gdfp/3rU + 5/941uj/gePw/4Ll8f+C5vL/hOj0/4nq9f+N7Pb/k+33/5vv9/+h8Pj/p/H5/6zz+f+x8/r/tPT6/7f1 + +v+59fv/u/X7/7z2+/+99vv/vfb7/772+/+/9vv/v/b7/7/2+//F/v//wPb7zbb29hz///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////ALTy + +aO5/P//qu73/5ff7/+R3e3/itnr/4XX6f9+1ef/eNLm/3ra6f+B5PD/gOTw/4Lm8f+E6PT/ier1/4/s + 9v+V7ff/nO/3/6Px+f+p8fn/rvP6/7Hz+v+19fr/uPX6/7r1+/+79fv/vPX7/732+/++9vv/vvb7/7/2 + +/++9vv/xf7//8D4+9a68fgl////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wCq4+MJtPT5zbT4//+l6fX/ld7u/5Dc6/+I2Or/gdbn/3vT + 5f930eT/ft3r/3/j7v9/5O//guXx/4bn8/+K6vT/kez2/5ju9/+f8Pf/pfH5/6ry+f+w8/r/s/T6/7b1 + +v+49fv/uvX7/7v1+/+99vv/vvb7/772+/++9vv/vvb7/8T9//+/9/revvT6L////wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AK/w + 8COy8vrusvX8/57l8v+S3Oz/jNrq/4bY6P9/1Ob/eNHj/3fT5P9+4Oz/fuHt/3/j7/+C5PH/h+fy/4zq + 9P+T7fb/me73/6Dw+P+n8fn/rPL5/7Dz+v+09Pr/tvX6/7j1+/+69fv/u/X7/732+/+99vv/vvb7/772 + +//D+///wPj95r/2+jj///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8As/T3Q7L1+/yu8vr/muHw/5Hc6/+K2Or/g9Xm/3zS + 5f92z+H/edfm/37g6/994Oz/f+Pu/4Pl8f+J6PP/juv1/5Xu9v+c7vf/ovD4/6jx+f+t8vr/sfP6/7T0 + +v+39fr/ufX7/7r1+/+99fv/vfb7/732+/++9vv/wvv//8D3/e288/dB////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wCz8/pot/v//6ru9/+W3u3/j9rr/4jX6f+B0+X/etDj/3XO4P972ub/fd7q/33g7P+A4u7/heXw/4vo + 8/+R6/X/l+32/5/v9/+l8fn/q/L5/6/z+v+y8/r/tvT6/7j1+v+69fv/u/X7/732+/+99vv/vfb7/8H6 + ///B+f3xvvX8S////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////ALHz+JS2/P//pev1/5Td7P+N2er/hdXn/3/S + 5P94zuH/ddDh/33c5/993en/ft/r/4Hj7v+G5vH/jejz/5Ps9f+a7vb/oe/4/6fx+f+s8vn/sfP6/7T0 + +v+29fr/ufX7/7r1+/+79fv/vfb7/732+//A+f7/wfr99MD2/Fn///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wCAgP8CsfP4u7P5//+h5/P/kdrr/4rY6f+E1OX/fNHj/3XN3/940+H/fdzn/33d6P9/4Ov/hOPu/4nm + 8f+Q6vT/l+31/53u9/+k8Pj/qfL6/67z+v+y9Pr/tPT6/7f1+v+69fv/u/X7/7z1+/+89vv/wPn9/8L7 + /vq98/pp////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////ALvu/w+w8vnYsPb9/5zj8P+O2Or/iNbo/4DS + 5P96zuH/dMze/3rW4/993ef/fd7o/4Hh6/+F5O//jOfy/5Lr9P+Z7vb/n+/3/6bx+P+q8vr/rvP6/7P0 + +v+19Pr/uPX7/7r1+/+79fv/vPb7/774/P/B+v7+uvT5d////wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8As/H4Ja/y+fKr8vr/l9/t/43Y6f+G1eb/f9Dj/3fM3/90zN7/fNnk/33b5v9/3+n/g+Ls/4jl + 8P+O6PP/lez1/5zu9/+j8Pf/qPL5/6zy+v+w8/r/tPT6/7b0+v+49fv/uvX7/7z1+/+99vz/wfz//7z0 + +Yn///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wCx8/tBrvL4/Kjv9/+U3Ov/i9fo/4TT + 5f99z+H/dsvd/3fP3/9+2+X/ftvm/4Df6f+F4u7/jObx/5Lp8/+Y7PX/n+/3/6Xw+P+p8vr/rvP6/7H0 + +v+19Pr/t/X6/7n1+/+69fv/vPX7/8P+//+79PqmzP//Bf///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////ALLy+mCy+P7/o+v1/5Da6v+J1uf/gtLj/3vN3/91ytz/etPh/3/b5f9/3Of/g+Dq/4fk + 7v+O5/H/lev0/5vu9v+i8Pf/pvH5/6zy+v+v9Pr/s/T6/7X0+v+49fr/ufX7/7v1+//D/f//vvb7yL/y + /xT///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8ArvD3hbL7//+g6PP/jtjo/4jV + 5f9/0eL/esze/3XK3P981uP/f9vm/4Hd6P+E4ev/ieTv/5Do8v+Y7PX/ne/3/6Pw9/+o8vn/rfL6/7D0 + +v+z9Pr/tvT6/7j1+v+69fv/v/n//7z2/Oa++f8r////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wCt8feosPj//5vj8P+M1+f/hdPk/37P4f94yt3/d8zd/3/Z5P9/2+b/gt7p/4bi + 7f+M5vD/k+rz/5vt9v+g7/f/pfD4/6ry+v+u8/r/svT6/7T0+v+39fr/ufX6/7z3/P/A+v75u/b5U/// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8Amcz/Bazx+MSs9fz/lt/t/4rV + 5v+D0uP/fM7f/3bK2/94z97/gNrk/4Db5/+D3+r/ieTu/4/n8f+W6/X/nO72/6Lw9/+n8fn/rPL6/6/z + +v+z9Pr/tfT6/7j1+v+69fv/wP3//7r0+In///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wCz8v8Uq/D34Kjx+f+T3Or/iNXl/4HR4v97zd7/dsnb/3rT4P+A2uX/gt3o/4Xg + 6v+L5e//keny/5js9f+e7/f/pPD3/6nx+f+t8/r/sfP6/7P0+v+29Pr/uPT6/8D8//+89vvDxP//Df// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AKTn8yqn7fb0o+32/47Z + 6P+G0+T/f8/g/3nM3f91ytv/fdbi/4Db5v+C3ej/huLs/43m8P+U6vP/mu32/6Hv9/+l8fj/qvL5/6/z + +v+y9Pr/tfT6/7b1+v+7+P3/uvX77rr0+jD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8An9/tSJzk8f2e5/L/jNfo/4TS4/99zt//d8rc/3XL3P9+2OT/gNvm/4Pe + 6f+I4+3/j+jx/5br9P+b7fb/ovD3/6bx+P+r8/r/sPP6/7P0+v+19Pr/uPb7/736/f+68/pr////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wCa3OxgmuPz/43X + 6P+F0uP/gtHi/3vN3v90ydv/d87d/3/Z5P+A3Of/hOHr/4rl7/+R6fL/l+v1/53u9/+j8Pf/qfH5/6zz + +v+w8/r/tPT6/7b0+v++/f//uvX7rcz//wX///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8AFRXVDBIS0CsSEtFIFBHVWhQS1WYUEtRwFxLWcBcU + 1HEXFdhuFxTZZCMm0mY1PMxqPkfRXkxZ1E1icdM0anvTHXaJ2A3b/9sHzP8zBf//AAL///8A////AP// + /wD///8A////AP///wD///8A////AJnd7YCZ5PX/hs/k/3jD2/95yNz/ecrd/3PI2/950d//f9rl/4Hd + 5/+G4uz/jObw/5Pq9P+Z7Pb/oO/3/6Xx+P+q8/r/rvP6/7L0+v+z9Pr/uvn+/7n2+uK28Pgj////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AID//wKn1fc9msXyjSUo + 16wTD9TaFBPS9BMR0v4UEdX/FRLZ/xQS2/8VE93/FhTe/xcU4P8YFuD/FRXS/xcXzP8YGcz/GBrJ/xsc + y/YeIMvtJinN4Cku0MwpLc61LDPOnDU6zog6Q85zR1LSWl5q0Dxre84fgJXVDNX/qgb//wADm+Duppbh + 8v+CzOD/dcHZ/2+91v9tvdT/b8PW/3vU4f9/2ub/gt7p/4fj7f+M5/H/lev0/5vu9v+h8Pf/pvH5/6vz + +v+v8/r/svT6/7b1+/+6+P38uvb8Vf///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wCezfNCn8n0uZ/M9fik0fz/RFPl/w4L0/8SENH/Eg/Q/xIQzv8REM//EhDP/xMR + 0f8TEdP/FBLS/xMSzv8QEMP/EBDE/xERx/8SEsj/EhLK/xISzP8SEc3/ERDP/xAQ0P8QEdD/ERDP/wwN + zP8QEsb/EBHC+BMXwO0cH8DdHSG/wyYqwKOHxObhk93s/37I3v9zwNf/bbzU/2i50f9nutL/csrb/3nT + 4v+B3un/ieTu/4/p8v+X6/X/ne73/6Pw+P+n8vn/rPP6/7Dz+v+z9Pr/vf3//7bz+pn///8B////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wCWw/ARncv2kp/L9/eiz/v/ncn1/6LP + 9P9rhub/DQvK/w4MxP8ODL//DQy8/w0MvP8NDLz/DQ29/w4Nvv8ODb7/DQ29/w4OwP8ODsL/Dw/F/xAP + x/8QEMj/EBDI/w0NyP8LC8j/CwvJ/wwNyP8UE8n/QD/T/wYGw/8HB8L/BQW+/wMDvP8CAbz/DhHB/366 + 5f+O2uj/esXb/3G/1v9su9P/ZrjR/2i70/9wx9r/csrd/3jQ4v+A2en/iuLv/5To8/+d7fb/pPD4/6nx + +f+u8/r/sfP6/7f5//+29PrVter0GP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8Aj7TwIpzJ9MGj0Pz/nsr1/53I8/+dyfP/l8Xv/2uQ2/8PEbj/Cgmy/woKsf8LCrL/Cgqz/woK + s/8LCrb/DQy6/xMRvv8WFcH/GhrC/yYnxv8nJ8j/KinK/yorzP81NdD/VVXZ/2dn3/9OTtv/KCjS/yop + 0P9oZ93/AADB/wcHv/8FBrz/BQW5/wMBt/8YIL7/iMvn/4nV5f91wdn/b7zV/2q60v9lt8//ab7U/3HI + 2/9yy9//eNDj/33U5v+D1+r/itvs/5Hf7v+X4vD/neXy/6Lm8/+l6PX/qen1+Krm8Uj///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AIev7yCaxPXRo9D9/53I9P+eyfP/msbx/4Wz + 5P9yotr/Y47S/xUatP8IB6//CQmv/wkKsP8JCrD/Cgqz/w0Mtf8UFK7/IiKl/ygpnP8iJZb/HiCQ/x4g + jv8fIo7/ICKQ/xwekP8XGY//HB2X/xgZof8uL6//Pj2//1BPz/83OM7/ERHF/woKwP8FBLv/AQC3/yQ0 + w/+N0+j/htHi/3O/1/9tu9P/Z7jQ/2S2z/9swdX/cMjb/3LL3/950eT/ftXo/4XZ6/+L2+z/kN7t/5Tf + 7/+Z3+//nODw/6Tp9f2p5+2C////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wCHpfARmMPzwqPQ/f+dyPP/ncnz/5TA7f94p9z/bZzW/26d1/9qmNX/Fx60/wYFrf8ICK3/CAmx/wwM + uP8QEaX/EBKL/wwPfP8IC3f/BQl1/wQIdf8EB3T/Awd1/wMGc/8CBXL/AgZv/wIFa/8AA2f/AAJk/wAA + Yf8AAGH/BARo/xYWev8jI4z/EhOY/wMCo/8AAK//NEvI/5Db6f+Czd//cL3V/2u50f9mts//Y7bP/23D + 1v9xyNv/dMzf/3rS5P+A1un/htnr/43d7f+S3u7/lt/v/5rg8P+h5vP/jcDw6Ds/7j0AAL8E////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AJW+85ii0P3/ncn0/57J9P+Rvuz/c6La/22c + 1v9tndb/bp7W/2iW1P8WHLH/BgSq/wgItf8ODbj/EROR/w4Ref8MD3b/CQx1/wgLdv8GCXX/BQh0/wQH + df8DB3T/AgVy/wIEcP8BA23/AANr/wABZ/8AAGP/AABf/wAAW/8AAFf/AABS/wAAUP8AAFP/AABY/wAA + X/9DY6j/kN7r/3zI3P9vu9P/abjQ/2S1zf9kt8//bsXX/3DJ3P91zuD/e9Pl/4LX6v+I2uz/jt3t/5Pf + 7/+Y4O//nePw/5bU8f86RO/9IRrt8yMg7sIkIOx5IyPoLAAA/wH///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wCPs/Fbnsr5/Z7K9f+eyfT/kr/t/3Ki2v9tnNf/bZ3W/22d1v9vn9b/YYvQ/xEVrf8GBbP/Dw67/xQW + i/8PEnX/DRB2/woOdP8IC3P/Bgpy/wUIcf8DBnD/AgVw/wEEcP8AAm//AAJt/wACa/8AAGf/AABk/wAA + YP8AAF3/AABZ/wAAV/8AAFT/AABS/wAAUv8AAFP/AABU/1iEr/+O3Or/eMPZ/2260f9nt87/Y7PM/2a6 + z/9vxdf/ccnc/3fO4f991Ob/hNjq/4ra7P+Q3u3/leDv/5nh8P+f5fD/VXLi/xoW3/8iHun/JCDz/yUh + 9P8kH+3zJB7tuCUg72EjI+gW////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8AgJvtHJjC9d+hzvr/nsn0/5jE8P92pd3/bZzX/22d + 1v9tndb/bZ3V/3Ch1v9Uecn/CQmv/wkHvf8ZGaD/ERN1/w8Rdf8MD3P/Cgxx/wcKb/8FCG//BAdu/wIG + bv8BBG3/AANs/wACbP8AAWr/AABn/wAAZP8AAGD/AABd/wAAWf8AAFb/AABU/wAAUv8AAFH/AABR/wAA + U/8BAVj/aJ3B/4vY5v91wdf/a7nQ/2a1zf9is8z/aL3R/3DG2P9zy93/eM/i/3/V5/+F2Or/jNzs/5Le + 7v+V3+7/nubx/3qr6v8dHdT/GBbT/xoZ1P8cG9r/Hx3h/yMf6v8lIfT/JSDx/yMg7t8iHOyQUWDwRcH/ + 5R3///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wCPs/GUotD+/53J9P+dyPP/fq3h/2yc1/9tndf/bZ3W/22d1f9tnNX/caHW/ztUvv8EA7T/DAu8/x0e + jP8QEnP/DhBz/wwOcf8JDG//Bwlt/wUIbP8DBmv/AQVr/wADav8AAWn/AABm/wAAZf8AAGP/AABg/wAA + XP8AAFr/AABW/wAAU/8AAFH/AABQ/wAAT/8AAFD/AABS/wkNX/93ttD/htPj/3G+1f9quND/ZbXM/2Kz + zP9qv9P/cMbY/3TL3f960OP/gdXo/4fZ6/+N3Oz/k97u/5jh8P+W2e3/NULR/xUT0v8aGNf/GhnW/xoZ + 1P8ZGNP/GhnV/x0b2/8gHuT/JCDv/yQg9f8sKu76f5333bLl+Yu25/kq////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8Ad5nuLZnC9PKfzPf/nsn0/4266v9undf/bZ3X/22d + 1v9tndb/bZzU/26d1f9pltL/GSKu/wQCtP8RELv/FhmD/xAScv8OD3H/Cw1u/wgLa/8HCWv/BQdp/wIF + aP8AA2b/AAJm/wABZf8AAGP/AABi/wAAYP8AAF3/AABY/wAAVf8AAFP/AABP/wAATf8AAEz/AABM/wAA + Tv8AAE//Ex1o/4LJ3f+Cz+D/b7zT/2i40P9jtMz/Y7XN/23C1f9xx9n/dsze/3zS5P+D1un/idnr/47c + 7P+V3u7/nefz/1qCvf8ICYP/Dg+U/xESqf8WFsH/GRjQ/xoZ1v8aGdb/GRjU/xkY1P8bGtj/Hx3h/yEc + 6/8xMvP/iKn9/6nY+uup2fibter6MP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wCKsPGUo8/9/53I9P+bx/L/d6bd/22c1v9tndb/bZ3W/22d1f9tnNT/caHW/0NfwP8DA6H/BQWw/xAP + uv8hIon/DhFw/w0Qb/8LDWz/CApq/wYIaP8FB2j/AgVl/wADZP8AAWP/AABi/wAAX/8AAF7/AABa/wAA + WP8AAFX/AABR/wAAT/8AAEv/AABK/wAASf8AAEr/AABM/wAATP8hMXT/h9Di/33L3v9tu9P/aLfP/2Oz + zP9luM7/b8XW/3LJ2/94zuD/f9Tm/4XX6f+L2uv/kN3t/5ji8P+JyeP/GiWK/wYHev8HCnr/Bgp6/wcL + f/8LDY3/EBGi/xUVvP8ZGND/GhnW/xoZ1v8ZGdT/GhnW/xsZ3v8rK+r/d5L3/6jV//+m1Pruqtj5orLk + +jj///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8AYoDrGpW+8+Shzfj/nsn0/4266v9tndj/bZ3X/22d + 1v9tndX/bZzU/3Cg1f9eh83/EBWn/wMCn/8FBaf/Cwm4/y0unf8QEm7/DQ9u/woNa/8ICmj/Bghl/wQG + Zf8CBGP/AAJh/wAAX/8AAF7/AABb/wAAWf8AAFj/AABU/wAAUf8AAE7/AABL/wAASf8AAEb/AABH/wAA + R/8AAEn/AABH/y9Igv+K2Of/esfb/2u50f9nt8//Y7TM/2i70P9xxtf/dMnb/3rP4f+B1Of/htjq/4zb + 7P+S3e7/m+by/01vsf8EBHj/Bwl7/wYIe/8FCHr/Bgl7/wYJef8HCnn/CQt9/wwOi/8REqL/Fhe+/xoY + 0f8aGdb/GRnV/xkX1v8fHN3/V2nt/5a9+v+q2P//pdT68qnY+aOz5voy////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wCAoe5cnsn6/57J9P+dyPP/fKvg/2yc1/9tndb/bZ3V/22c1f9vn9X/Z5PR/x8rrv8CAZ//BQWe/wUF + n/8EBK3/Kyq2/x0eev8LDWv/Cg1q/wgKaP8GCGX/BAZi/wIEYP8AAl7/AABc/wAAWv8AAFj/AABV/wAA + VP8AAFD/AABN/wAASf8AAEf/AABE/wAAQv8AAEP/AABE/wAARf8AAET/QGKT/4vb6f92w9j/a7nR/2a2 + zv9jtMz/bL/T/3PH2f93y97/fNHj/4PW6P+J2ev/jtzs/5Xh8P+GxeD/Fh6F/wUHeP8FCHn/BAd4/wQH + ef8FB3n/BQh6/wYKev8HCnv/CAx6/woNev8MD4D/EBKP/xUWqv8ZGMb/GhnU/xkY1v8XFNX/LjLf/2R7 + 7v+Tufn/ptT//6nY+u6u4Pibv/r6MP//AAH///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AIes8aij0Pz/nsn0/5XC7/9xoNr/bZ3X/22d + 1v9tnNX/b5/V/2mW0f8oN7H/AgCe/wUFnv8FBZ3/BQWc/wMDof8REbX/Ozul/wwOav8JDGn/CApn/wYI + Y/8DBWD/AgRe/wACXf8AAFr/AABY/wAAVP8AAFP/AABQ/wAATf8AAEr/AABG/wAAQ/8AAEH/AABA/wAA + P/8AAED/AABD/wAARv9Vg6n/iNjn/3PB1v9quND/ZrbN/2W2zv9vw9X/c8jZ/3jN3/9+0uT/hdbo/4va + 6/+Q3e3/meXy/05zsf8CA3P/BQh2/wQHdv8EB3X/BAd3/wQHd/8FCHj/Bgl4/wgKef8IC3r/Cw59/wwP + ff8OEXz/DxJ9/xIVhP8VF5n/Fxi1/xoZzv8YFtb/FxXX/ygq3v9LVuz/aoH2/4Oi/P+Rtvnul773mpnE + 9x7///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wBAUN8Qkrry2qHO+v+eyfT/irjo/22c1v9tndb/bZ3W/3Gh1v9kjtD/IzCw/wIBnv8FBZ3/BQSb/wUE + m/8EBJr/BASa/wIBpP8pKbz/RUac/wgKZv8GCGX/Bghi/wQGYP8CBF3/AQJb/wAAWf8AAFX/AABT/wAA + UP8AAE7/AABL/wAASP8AAET/AABB/wAAPv8AADz/AAA8/wAAPf8AAD//AgNG/2efvP+D0uL/b73T/2i3 + z/9ktcz/Z7jO/3HF1v90yNr/ec3g/4DS5f+G1+n/jNrr/5Lf7v+N0eb/HCiD/wIEcP8EBnL/AwVx/wMG + c/8CBnP/Awd0/wQHdf8GCHX/Bwt3/wkMeP8KDnr/DA97/w4RfP8PE33/ERR+/xIVfv8SFn//FBeM/xYY + pP8YGcH/GBfS/xYU2P8bGN7/IyDp/yoo8P8wMfX/KSfuzCQe7VUAAKoD////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AGuG6TmVvvT7n8v1/53J9P9/ruL/bJzW/26f + 1v9wodb/VXnJ/xggrP8BAaD/BQWd/wUEnP8FBJr/BQOZ/wUEmv8EBJn/BASb/wIBqv88O8L/UlSe/wsN + Zv8DBWD/AwZf/wIEXf8BAlr/AAFY/wAAVf8AAFL/AABP/wAAS/8AAEj/AABF/wAAQf8AAD7/AAA7/wAA + Ov8AADr/AAA6/wAAOv8ME0//d7vQ/33L3f9ruND/ZrXN/2Szyv9ous7/csbW/3XI2v97zuD/gdPl/4fW + 6P+N2uv/l+Tx/2mbxf8EBmz/BAZt/wIFbf8CBW7/AgVv/wIFb/8DBnD/BAdy/wUJc/8IC3T/CQx2/wsN + d/8MD3n/DhF7/w8Te/8QE3z/ERR+/xEVfv8SFX7/EhV8/xIVgf8UFpT/Fxe3/xkY0/8aGdf/HRze/yIe + 6v8lIPT/JCDu/yQg7rIlH+wp////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8Ab4jrWp3J+/+eyvT/nMjz/3io3f9wotj/ZZDS/zhPvf8KDKb/AwKg/wUFnv8FBZv/BQSa/wUE + mP8FBJj/BQSX/wQDmP8EBJj/BASd/wICrP83N8P/Y2Ss/xgabP8AAVz/AgRd/wEDW/8AAlf/AABV/wAA + Uv8AAE7/AABL/wAAR/8AAET/AABA/wAAPv8AADn/AAA4/wAAOP8AADn/AAA2/x8vYv9+yNn/dsPV/2e1 + y/9kscn/YbDJ/2m7zv9xxNX/dsja/3vO3/+B0uP/iNXn/43a6/+U3u3/OVSX/wAAZP8CBWn/AARo/wED + af8BBGr/AQRr/wIFbP8EB27/Bghv/wgKcf8JC3L/Cg10/wwPdv8OEXj/DhF4/xASef8QEnr/EBN7/xEU + fP8QE33/ERN8/xATev8QEnz/EhSZ/xkYyv8aGdT/GxrX/yEf5/8kIO//JSH1/yUh8OMkIepV////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wBpg+x5p9b+/6DM9f+Svu7/YIjT/zxV + w/8VHLH/AwKm/wUEo/8FBaD/BQWd/wUEmv8FBJf/BASW/wQDlv8EA5b/BAOX/wQDmP8EBJr/BASe/wAA + qv8lJMD/Xl+9/zc5g/8GB1z/AAJY/wACWf8AAVT/AABS/wAATv8AAEv/AABH/wAAQ/8AAD//AAA8/wAA + Of8AADb/AAA2/wAAN/8AADT/OVmB/4DN2v9tuc3/Y6/H/2Ctxf9frcT/abrM/27A0v90xtf/esvc/4HQ + 4f+H1OX/j9vq/4LC2/8QGG7/AABh/wACY/8AAWP/AAFk/wACZf8BA2b/AQRn/wQGaf8FB2z/Bglt/wgK + b/8JDHH/Cw5y/wwPdP8NEHT/DhF2/w8ReP8PEXf/DxF4/w4Ref8OEXn/DRB5/w0Qev8OEXf/EhOR/xkZ + 0P8aGdT/GxrW/yIf6P8kIO3/JSHy/yQg8fUkHuxd////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////ADtD4phccO7/RlXg/y020v8OEbf/BgSu/wUEqv8GB6b/BQWj/wUFn/8FBJr/BQSY/wQE + l/8EA5X/BAOV/wQClP8EA5X/BAOW/wQEmP8EBJr/BQSd/wIBpv8IB7f/NzbD/0JCpf8dHnD/AQNW/wAA + Uf8AAFH/AABP/wAASv8AAEf/AABD/wAAP/8AADv/AAA4/wAANv8AADX/AAA2/wECOf9ZjKf/eMPT/2Wv + xP9fqsD/XKi//1yrwf9nuMn/a7zO/3LC0/94x9j/f83d/4XR4f+R3ev/X423/wEBW/8AAV3/AABd/wAA + Xf8AAF7/AABf/wAAYf8AAmP/AgRl/wMGZ/8FB2j/Bglp/wcKbP8JC27/Cgxu/wsOcP8MDnL/DA5y/wwP + dP8MDnX/Cw51/woOdv8LDnb/Cw53/wwPeP8NEHj/FRau/xoZ1v8ZGNP/HRva/yQg7P8kIO3/JSHx/yUg + 8PQiH+pK////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AFhPcrxIP3/8PC9P/CwnH/wkJ + s/8ICK7/Bweq/wYGpP8FBaL/BQWe/wUEmv8EA5f/BASV/wQDlP8DA5P/AwOT/wMDk/8EA5T/BAOW/wQE + mP8EBJn/BQSe/wUEo/8BAK3/Dg2+/ycnwP8pKqL/FhZ4/wkJW/8AAE3/AABG/wAARv8AAEL/AAA//wAA + PP8AADn/AAA3/wAANv8AADP/FSBQ/3Gzxf9vuMj/X6a8/1mjuf9Xorj/W6i8/2SzxP9pt8n/br3O/3bE + 1P99ydn/g83d/4vT4v8xSoj/AABU/wAAWP8AAFj/AABY/wAAWf8AAFr/AABb/wABXv8AAmD/AQNh/wMF + ZP8EBmX/BQdn/wYJaf8ICmv/CAtr/wkMbf8JDG7/CQtu/wgLb/8IC3D/CAty/wgLcv8JC3T/Cg11/woN + dP8RE5P/GhnU/xoZ1P8aGdX/IR7o/yQg7v8kIO3/JSHz/yMg7NogIOoY////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wAYFdvBFhTe/xIR0/8PDcf/CQmw/wgIrf8HB6j/Bgak/wUFof8FBJv/BQOY/wQD + lv8EA5T/AwOS/wMDkf8DA5H/AwOR/wMDkv8DApT/BAOW/wQDmP8EA5z/BQSe/wUEov8EA6f/AwOx/wsK + v/8ZGMX/HRy6/xoanv8QD37/BQVe/wICS/8AAED/AAA5/wAAN/8AADf/AAA3/wAAM/8+YIP/d7/N/2Wt + vv9Zobb/Vp+0/1Sds/9aprn/Ya+//2SyxP9rucn/cr7O/3rE1P+Cy9r/ebfN/w0TYv8AAFL/AABU/wAA + U/8AAFT/AABV/wAAV/8AAFj/AABZ/wAAW/8AAVz/AAJf/wIEYf8CBWL/AwZk/wQGZf8FB2f/Bgho/wUI + av8GCGn/Bghq/wUIbP8FCG3/Bglv/wcKcf8IC3L/Cgxy/w8Rkf8aGdX/GhnU/xoZ1P8hHuX/JCDu/yQg + 7f8kIO3/JSH2/yQg7If///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////ABgV3MIWE93/EhDS/w8O + x/8JCbH/CAes/wYHqP8GBqP/BQWf/wUEmv8EA5f/BAOU/wMDk/8DA5D/AwOQ/wMDkP8DA5D/AwOS/wMD + kv8EA5T/BAOW/wQDmv8FBJ3/BQSf/wUEof8FBaT/BQWo/wUFr/8FBbf/CwvC/xAOxf8TEsD/DQ2p/wgI + kf8ICHr/BgZj/wMDTf8AAD7/Ex1P/3Gwvv91vcj/Yai5/1igtP9VnLH/Upuw/1mlt/9frLv/Y7DA/2m1 + xf9vusr/dsDQ/4PM2f9biq7/AQFR/wAAUf8AAFH/AABR/wAAUv8AAFL/AABT/wAAVP8AAFX/AABX/wAA + WP8AAFr/AAFc/wACXv8BA1//AgRh/wIFYv8CBWP/AwVl/wIFZf8CBGb/AgVo/wMGa/8EBmz/BQht/wcJ + bv8JDHL/FRWy/xoZ1v8aGdP/GxnV/yIf6f8kIO3/JCDt/yQg7f8kIPH/JCDt5Ccn6xr///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8AGBXawhYT3f8SENL/Dg3G/wkJsP8IB6z/Bgen/wUFo/8FBZ7/BQSa/wQD + l/8DA5T/AwOR/wMDkP8DA4//AwOP/wMDjv8DA4//AwOQ/wMCkv8DA5T/BAOX/wQDmv8FBJz/BQSf/wUE + of8FBKX/BQWm/wYGqf8GBqz/Bwav/wcHsf8ICbX/Cgu5/wsLu/8MDLn/DAuy/wgHoP8ZIaD/QmO1/017 + r/9TjbD/Vpqu/1aerv9XorL/Xau4/2Ctu/9jr77/aLPD/2+5yP92vs7/gMjV/zhUif8AAEv/AABQ/wAA + T/8AAE//AABP/wAAUP8AAFH/AABR/wAAUv8AAFT/AABW/wAAV/8AAFn/AABa/wABW/8AAV3/AAFe/wAB + X/8AAWH/AAJi/wACYv8AAmT/AQNn/wMFaf8DBmn/Bglt/xASoP8aGdX/GhnU/xoZ0/8eHN7/JCDu/yQg + 7f8kIO3/JCDt/yQg7f8lIfP/JiDsX////wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wAYFdrCFRPc/xIQ + 0v8ODMX/CQmv/wgHqv8GB6f/BQWh/wUFnf8FBJn/BASV/wMDk/8DA5H/AwOP/wMDjv8DA47/AwON/wMC + jv8CAo//AgKQ/wMDkv8DApX/AwOW/wQDmf8EA5z/BQSf/wUEof8FBaT/BQWm/wYGqP8GB6v/Bwes/wgI + r/8ICLD/CAmy/woKtP8LC7b/DAu6/wsJuv8JB7f/DAq5/xIVtf8eLa//K0et/zxoqf9QjrL/XaW3/2ay + vP9uu8X/c73J/3nBz/96vc3/HChr/wAATf8AAE//AABO/wAATv8AAE//AABO/wAAT/8AAE//AABP/wAA + Uv8AAFP/AABV/wAAVf8AAFf/AABY/wAAWv8AAFz/AABd/wAAXv8AAF7/AABd/wAAYf8AAGL/AQNi/wUH + c/8SE63/GhnV/xoZ1f8ZGdP/HRvc/yMg7P8kIO3/JCDt/yQg7f8kIO3/JCDt/yUh9f8jIO2o////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////ABgV2sEWE93/EhDR/w4MxP8JCK//CAeq/wYHpv8FBaH/BQWd/wUE + mf8EBJT/AwOR/wMDkf8DA4//AwOO/wMCjf8DAo3/AwKO/wIDjv8DAo//AwKR/wMCkv8DApX/BAOY/wQD + mf8EA5z/BASe/wUEof8FBaP/BQWl/wYGp/8GB6n/Bger/wcHrP8ICK7/CAmw/woKtv8MC73/DQu//w0N + v/8NDLz/DQy8/wsJvP8MCb3/Dgy//xETvP8eK7b/Lke1/0Nstv9bkr7/dLfM/3Oxwv8KEFj/AABK/wAA + TP8AAE3/AABN/wAATf8AAE3/AABN/wsLV/8UFF//AABP/wAAUf8AAFL/AABT/wAAU/8AAFX/AABW/wAA + V/8AAFf/AABX/wQEXf9GRoj/CQlr/xUWfP8OD5z/FxfG/xsZ1/8aGdP/GhnV/x8d4P8kIO3/JCDt/yQg + 7f8kIO3/JCDt/yQg7f8kIO3/JSDx/yMg7d8cHPES////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AFxTbsBYT + 3f8SD9H/Dg3F/wkIr/8HB6v/Bgem/wUFov8FBJz/BASY/wQDlf8DA5H/AwOQ/wMDj/8DAo3/AwKL/wMD + jP8DAoz/AgKM/wMCjv8CApD/AwKQ/wMCkv8DApT/AwKW/wQDmf8EA5z/BQSc/wUEoP8FBKL/BQWk/wYG + pf8GB6f/Bgeo/wcHqv8KCLf/DAvC/w0LxP8ODMb/Dw3G/xAOyP8QDsf/Dw3C/w4Ovv8ODrz/Dg7A/w4N + xP8ODMT/Dw7E/xUYxf8lMML/MELD/w4Qmv8JCYX/BQVw/wUFYP8IB1n/CQlW/wsLVP8PD1b/Ojp2/yAg + Zv8AAE3/BwdW/wkJWf8WFmL/Hh5o/yYmbf8hIW//GRlx/ygohv9CQp//RUSu/0dGxf9OTsv/OjrY/xsa + 1v8aGdX/GxrW/x4c3v8iH+n/JCDu/yQg7f8kIO3/Ix/t/yMf7f8kIO3/JCDt/yQg7f8kIO7/JCDt+iEd + 7j3///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wAXFNubFhTd/xIR0f8ODcb/CQmw/wgHq/8GBqX/BgWh/wUF + nP8FBJj/BAOU/wMDkf8DA4//AwON/wMCjf8DAov/AwKL/wICi/8DAov/AgKL/wICjf8DAo//AwKR/wMC + k/8DApX/AwOW/wMDmf8EA5r/BASb/wUEnf8FBKD/BQWh/wUGpP8GBqT/Bwes/woIvP8LCbz/DAq//wwL + wf8NDMP/DgzF/xANyP8RD8z/EQ/M/w8Qxv8OD8D/Dw/A/xAQwv8QEMX/ERHH/xAPyv8QDsz/FBPQ/xUV + 0P8UFMz/FxfF/x8ewP8jIrr/JiW3/yYmt/8cHbH/Oju2/0JCtP8/QLv/QkLB/0lJzP9NTdT/XV3b/1RU + 2f9FRdf/NzbX/yEg1/8dHNf/FxbU/x4e1/8WFtX/HBrb/yAd4/8jIOv/JSDt/yQg7v8kIO3/JCDt/yUh + 7f8uKu7/NjLu/zMw7/8iHe3/Ih3t/yId7f8kH/T/IR3sa////wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////ABgU + 234XFOD/EhDS/w8NyP8JCrH/Bwer/wYHpv8FBaH/BQSd/wUDmP8EBJX/AwOR/wMDj/8DAo3/AwKM/wMC + i/8DAov/AwKK/wMCi/8CAoz/AgKN/wMCjf8CAo//AwKR/wMCk/8DApT/AwKW/wQDmP8EA5j/BAOa/wUD + nv8FBJ//BQWf/wUFoP8IB67/CQe2/wkIuf8KCbr/Cwq7/wwLwP8NC8H/DgzE/w8NyP8QDsv/EhDP/xIR + 0f8REcv/ERDG/xARxP8REcX/EhLH/xMTyf8TE8v/FBTO/xUVz/8VFdH/FBTS/xQU0/8UFNT/FBTV/xUW + 1v8ZGdb/Hh7Y/xkZ1/8ZGdb/FRXU/xIS0/8QENL/EhHS/xQT0v8VFdL/GRjU/xoZ1/8dG93/IB3l/yIf + 6v8kIO3/JSHu/yYi7v8lIe7/JSHt/yQg7f8mIu3/My/v/zk17/89OO//RUPv/zY47/80Nu//NDbv/y4u + 9v8mJO6V////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8AGBXaYRYU3f8TENH/Dw3K/woKtP8ICKv/Bwam/wYG + ov8FBZz/BAOY/wQDlf8DA5H/AwOO/wMCjf8DAoz/AwKL/wMCi/8DAon/AwKJ/wICiv8CAoz/AgKN/wIC + jv8CAo//AgKR/wMCk/8DApT/AwOV/wMDl/8EA5j/BAOY/wQDmv8FBJz/BQWc/wcGq/8IB7L/CAe0/wkI + t/8KCLn/Cwm6/wwLvv8NC8D/DgzE/w8NyP8RD8z/EhDR/xMR1P8UEtb/FRPV/xQS0v8TEs3/ExPM/xQT + y/8UE8z/FRTO/xUVz/8VFc//FhXQ/xYV0P8WFtH/FhbR/xYW0f8WF9H/FxfR/xcX0v8YGNL/GBjT/xkY + 1P8aGdf/HBrc/x4c4f8hHef/Ix/r/yQg7f8kIO7/JCDt/yQg7f8nIu//JyPu/yYi7v8lIe7/KCTu/zIt + 7v82Me//TE3w/3iK9P+Ztff/msD3/5fA9/+Xv/f/kbX8/4ms9suOxv8J////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wAaFtw6FhPX+hMR1P8QDs7/Cwq3/wgIq/8HB6j/Bgaj/wUFnf8FBJn/BAOV/wMDkv8DAo//AwON/wMC + jP8DAov/AgKJ/wICiv8DAYr/AgKK/wICiv8CAoz/AgKM/wMCjv8CAo//AgKQ/wMCk/8DApX/AwKV/wMD + lf8EA5b/BAOX/wUEmP8FBJn/BgWm/wcGr/8IBrD/CAey/wkItf8KCLf/Cwq6/wsKvv8NC8L/DgzF/xAO + yf8RD87/ExHS/xQS1v8WE9r/FxTe/xgV3/8YFt7/GRbe/xgX3P8YFtn/GBfY/xgX1/8YFtb/GBfW/xgX + 1v8YGNf/GBjY/xoZ2f8bGtz/HRrf/x4c4v8gHOX/IB3o/yMf6/8jH+3/Ix/t/yMf7f8jH+3/Ix/s/yMg + 7f8jIO3/JSHu/ykk7/8oI+//JiLv/ykk7v8wK+7/QD7w/3WG9P+jxfj/stj5/7LX+f+kz/j/ocz4/6HN + +P+l0fz/o8/45pXB9h3///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////ABIS2xwWFNnlFBLX/xEPzv8NDL3/CAis/wcH + qP8GBqP/BQWf/wUEmf8EBJb/BAOS/wMDj/8DAo7/AwKL/wMCi/8DAon/AwKJ/wICif8CAon/AgKJ/wIC + i/8CAYz/AwKN/wICjv8DApD/AwOQ/wMCkv8DApL/AwKU/wMDlP8DA5T/BAOV/wUElv8FBJ3/BgWr/wcF + rP8HBq//CAex/wkItP8KCLf/Cwm6/wwKvv8NDMT/Dw3I/xAOzP8SEND/FBHV/xUS1/8VEtv/FRLe/xcT + 4f8ZFOT/Ghbm/xsY5/8dGun/Hhrp/x4b6f8fG+r/Hxzq/x8c6v8gHev/IR3r/yEd7P8iHu3/Ih7t/yIe + 7f8iHu3/Ix/s/yMf7P8jH+z/Ix/t/yMg7P8jH+3/Ix/t/yMg7f8oI+//KSXw/ygk7/8oJO//MCrv/1Vb + 8v+XtPf/stf5/6/V+f+w1Pn/sNT5/6PN+P+gy/j/oMv4/6LN+/+fyvjvm8H5Kf///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8AAAD/AhcU2L8WEtr/EhDQ/w4Nwv8JCa7/CAep/wYHpf8FBqH/BQSa/wMClf8DApL/AgKQ/wMC + jv8DAoz/AwKL/wMCif8DAon/AgKJ/wMCiv8CAor/AgKL/wIBi/8CAYz/AgKM/wICjv8CAo//AwKP/wMC + kP8DApH/AwKR/wMDkf8DA5P/BAOU/wQDlf8FBaT/BgWq/wYGrP8HBq7/CAey/wkItf8KCbn/Cwq8/w0L + wf8ODMb/Dw3L/xANz/8OC9L/EA3W/xoZ3P8iI+D/Ky7k/y0x5v8nKOf/IR/n/xkV6P8aFen/HRrq/x8b + 6v8fHOr/IBzr/yAd6/8gHev/IR3r/yEd6/8hHuv/Ih7s/yIe7P8jH+z/Ix/s/yMf7f8jH+3/Ix/t/yMf + 7f8kIO3/JyPv/ywn8f8qJvD/KiTw/zEs8P9pc/T/q875/7PY+f+w1Pn/sdT5/7HV+f+y1fn/o834/6DL + +P+gy/j/os36/5/J+PKYw/ov////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AFxPYhBYT3v8TENH/EA3J/woJ + sv8HBqn/BAOk/wEAn/8DApv/BgWY/wUFlf8EBJH/AACN/wAAi/8AAIr/AgCJ/wICiv8CAor/AwKK/wIC + if8CAor/AgKL/wICi/8CAYv/AgKM/wIBjv8CAY7/AwKO/wMCj/8DA5D/AwKR/wMCkf8DA5H/BAOS/wQD + mv8GBaj/BgWp/wcGrP8HBq//CAez/wkIuP8LCbz/DArB/wwKxP8KB8j/GBnQ/z9L3v9lfuj/f6Hv/4yy + 8v+VvfX/lr/1/4619f+DpvT/aoLx/0NN7f8hH+r/Gxfq/x8c6/8gHOv/IBzr/yAd6/8hHev/IR3r/yEe + 6/8iHuz/Ih/s/yIf7P8iH+z/Ix/t/yMf7P8jH+z/Ix/s/yUh7f8sJ/H/LSjy/ysn8f8wLPH/d4X1/7XW + +v+12Pr/s9X6/7PW+f+z1vn/s9b5/7PV+f+jzfj/oMv4/6DL+P+izfv/oMr58Za89C7///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wAXE9lDFhPY+xMR0/8PDcz/BwW4/w0Prf8hLbL/OE+6/0dlv/9RdMP/UnbD/09x + v/9DYLb/M0mr/xsmm/8JCo7/AACI/wEAiP8DAor/AgGK/wIBiv8CAov/AgKL/wIBi/8CAoz/AgKN/wIC + jf8CAo7/AgKN/wMCj/8DAo//AwOQ/wMDkP8DA5H/AwOU/wQEov8GBan/BgWr/wcGsP8HB7P/CQi2/woJ + vP8IBr//EBDG/0lZ2f+Fqez/nsvz/6HO9f+gzfX/n8v1/5/L9v+fyvb/oMz3/6HO9/+j0Pf/n8v4/4Cg + 9P8/R+7/HBjr/x8c6/8gHOv/IR3r/yEd6/8hHuz/IR7s/yIe7P8iHuz/Ih/s/yIf7P8jH+3/Ix/s/yMf + 7f8jH+3/KSXw/y8q8/8tKPL/MCry/3F89f+72/r/udn6/7bY+v+21/r/tdf6/7XX+f+21/n/stX5/6HL + +P+gy/j/oMv4/6LO+/+eyffrirbwI////wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AB4P4REWFNfZEQ3X/xcX + 0P9CVdH/XILP/22c1f9woNX/cKHW/3Cg1f9woNT/cKHT/3Ch0/9woNL/bJvP/1qBw/84T63/DxWS/wAA + h/8CAIr/AgKL/wIBi/8CAov/AgKM/wICi/8CAo3/AgGM/wICjv8DAo3/AwKM/wMCjf8DAo//AwOP/wMD + kP8EA5L/BAOY/wUFp/8GBqv/Bwav/wgHsv8IB7b/BgO5/yAlx/91lOT/n8zy/5/M8/+cyPP/nMj0/53I + 9P+dyfX/ncn1/57J9v+eyvb/nsr3/5/K9/+fyvf/o8/4/5vF9/9WZvD/Hhnq/yAc6/8hHev/IR3r/yIe + 7P8iHuz/Ih7s/yIf7P8jH+z/Ix/s/yMf7f8jH+z/Ix/s/yYi7/8wKvP/MCvz/zAq8/9aXvX/utb6/77d + +v+72vr/udn6/7nZ+v+42fr/uNj5/7nZ+f+y1fn/ocz4/6DL+P+gy/j/o8/8/5/J99+Apv8U////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////ABQQ2YwtM+L/fJzr/5rH8P91pdr/bZzV/22c1P9tnNT/bZzT/22c + 0v9tnNL/bZzR/22c0P9tnND/b5/R/3Gg0f9ijMj/Mkep/wUGjP8BAIr/AgKL/wICiv8CAYv/AgGL/wIC + i/8CAoz/AwGN/wMCjf8DAo3/AgKN/wMCj/8DApD/AwOP/wMDkf8DA5P/BASg/wYGrP8GBq7/CAay/wQC + tv8jK8T/iK7p/6DO8f+bx/H/nMfy/5zI8/+cyPT/ncj0/53J9f+dyfb/nsn2/57J9/+eyvf/n8r3/5/K + 9/+fyvj/oMz4/5/L+P9PXvD/HRjr/yAd6/8hHev/IR7r/yIe7P8iHuz/Ix/s/yMf7P8jH+z/Ix/t/yMf + 7P8kIO3/MCrz/zIs9f80L/T/Pzz0/6W6+P/F4vv/wNz7/77c+v+82/r/vNr6/7va+v+72vr/vNr6/6/T + +f+izPj/oMv4/6DL+P+k0P7/mcL3yGaZzAX///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AISbZPYGk + 8Pmj0fb/ncnz/4Ct4f9snNT/bZ3V/22c1P9tnNT/bZzT/22c0v9tnNH/bZzR/22c0P9tm9D/bZzP/2+e + 0P9woNH/TW67/wwRkP8AAIn/AgKL/wICi/8CAor/AgKM/wICjf8CAYz/AgKN/wICjf8CAo3/AwKO/wMC + j/8DApD/AwOR/wMDlP8EBJj/BQWn/wYFsP8FBLL/FBe9/4Gl5f+gzfH/m8fw/5vH8f+cx/L/nMjz/5zI + 9P+dyPT/ncn1/53J9v+eyfb/nsn3/57K9/+fyvf/n8r3/5/K+P+fyvj/oc34/5W99/80N+3/Hhrr/yEd + 6/8hHuv/Ih7s/yMe7P8jHuz/Ih/s/yMf7P8jH+3/Ix/s/ywn8f81L/b/NzH2/zky9f9veff/yeT7/8Xf + +//D3vv/wd37/8Dc+v+/3Pr/vtv6/73b+/++2/r/rdL5/6LM+P+hzPj/oMv4/6bS//+Tufeh////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wAAAP8FeJbtw6LQ+/+eyfP/kLzq/26e1/9tndX/bZ3V/22c + 1P9tnNP/bZzT/22c0v9tnNH/bZzR/22c0P9tnND/bZvP/22cz/9xodL/VXrA/wwSkv8AAIv/AgKM/wIB + jP8CAoz/AgKM/wIBjf8CAo3/AgKN/wICjv8DAo//AwKQ/wMDkf8DApL/AwOU/wQElv8FBJ3/BgWu/wQD + tP9actb/oc7w/5vH8P+bx/H/m8fy/5zH8v+cyPP/nMj0/53I9f+dyPX/nsn2/57J9v+eyvf/nsr3/5/K + 9/+fyvf/n8r4/5/K+P+fy/j/o9H4/2qB8v8eGuv/IR7s/yEe7P8iHuz/Ih/s/yMf7P8iH+z/Ix/t/yMf + 7P8pJO//NjD2/zgx9/8+OPf/RD/2/6q8+v/O5/v/yOH7/8bg+//E3/v/w976/8Hd+v/A3fr/wNz7/7/b + +/+r0fn/pM34/6LM+P+hzPj/pND//5W792X///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wBYZ+VjmMH4/5/K9P+bx/H/eafd/2yc1f9tndX/bZzU/22c1P9tnNP/bZzT/22c0v9tnNH/bZzR/22c + 0P9tm9D/bZvQ/2yb0P9xodL/T3C8/wYIj/8CAYz/AwKN/wICjP8CAoz/AgKN/wMCjv8CAo3/AwKO/wMC + j/8DApD/AwOS/wQDlP8DA5b/BAOY/wUEm/8DAqP/GyG8/5C56v+dyO//m8bw/5vH8f+bx/L/nMfz/5zI + 8/+cyPT/ncj1/53J9f+eyfb/nsn2/57K9/+eyvf/n8r3/5/K9/+fyvj/n8r4/5/K+P+gzfj/k7r3/y8w + 7f8gG+v/Ih7s/yIf7P8iH+z/Ih/s/yMf7P8jH+z/JiLu/zYw9v85M/j/PTf3/0E79/9eX/f/zOD7/8/l + /P/L4/v/yeL7/8fg+//F4Pv/xN/6/8Pe+//C3vv/v9v7/6rQ+f+mzvj/o834/6PP+/+cxfnveZnyKP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////ABsb1xN9nu3aos/5/57K8/+KuOf/bZzW/22d + 1f9tndX/bZzU/22c1P9tnNT/bZzS/22c0v9tnNH/bZzR/22c0P9tnND/bZvQ/22b0P9woNH/M0is/wAA + i/8CAo3/AwKN/wICjf8CAo7/AgKO/wICj/8DAo//AwKQ/wMDkv8EA5P/AwOW/wQDmP8FBJr/BQSd/wAA + nv8wP7v/msfv/5zH8P+bx/D/m8fx/5vH8v+cx/P/nMj0/5zI9P+dyPX/ncn2/57J9v+eyff/nsr3/57K + 9/+fyvf/n8r3/5/K+P+fyvj/n8v4/5/M+P+hzfj/SVTv/x0Y6/8iHuz/Ih7s/yIf7P8jH+z/Ih7s/yQg + 7f80L/b/OzX5/z03+P9DPfj/Qjv4/4aQ+f/W7Pz/0eb8/87k+//M4/v/yuL7/8jh+//G4Pv/xd/7/8Xf + +/+92/r/qtD5/6fP+P+kzfj/p9L//5S697j///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AF5z6Hicx/v/nsr0/5rF8P91pNv/bZzV/22d1v9tndT/bZzU/22c1P9tnNP/bZzS/22c + 0v9tnNH/bZzR/22c0f9tnNH/bZzQ/2+e0f9gisn/DRGV/wEAjv8CAo//AgKO/wICjv8CApD/AwKQ/wMC + kP8DA5H/BAOT/wQDlf8EA5b/AwOZ/wUDnf8FBKD/AQCh/zJHuf+AsOD/msXw/5vH8f+bx/H/m8fy/5zH + 8/+cyPT/nMj0/53I9f+dyfb/nsn2/57J9v+eyvf/nsr3/5/K9/+fyvj/n8r4/5/K+P+fy/j/n8v4/6TS + +P9kefL/Hxns/yIe7P8iHuz/Ih7s/yIe7P8jIO3/NC71/z02+v8+N/r/Qzz5/0hB+f9HQPj/oqr6/9zv + /P/T5/z/0eb8/87l+//M4/v/yuL7/8nh+//H4fv/x+H7/7nZ+v+q0fn/qM/5/6bO+P+mz///kLH1Zf// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AICDfGH+h7uGiz/j/nsnz/4i2 + 5v9tnNb/bp3W/22d1f9tndT/bZzU/22c1P9tnNP/bZzT/22c0v9tnNH/bZzR/22c0f9tnNH/bZzQ/2+f + 0f8sPqj/AACN/wMCkP8CApD/AgGQ/wMCkf8DApL/AwKS/wQCk/8DA5b/BAOX/wQDmP8EA5z/BAOf/wQE + ov8CAKT/Nky9/2+g1v9/reD/m8bx/5vH8v+bx/P/nMfz/5zI9P+cyPX/ncj1/53J9v+eyfb/nsr3/57K + 9/+fyvf/n8r3/5/K+P+fyvj/n8v4/5/L+P+fy/j/o9D4/3mV9P8iHuz/Ih7s/yMf7P8jH+z/Ix/t/zMt + 9f8/OPv/Pzj7/0M9+v9IQfr/S0T6/01H+f+uuPv/3/D8/9bp/P/T5/z/0eX8/8/l+//M5Pv/y+L7/8nh + +//J4fv/ttf6/6vR+f+p0Pn/qdL8/5/G+Ol3kfce////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8AX3LoeZzH/P+ey/T/msbx/3em3f9tndb/bZ3W/22d1f9tndX/bZzU/22c + 1P9tnNP/bZzS/22c0v9tnNL/bZzS/22c0f9tnNH/caHT/0dluv8BAJD/AwOR/wMCkv8DApH/AwKS/wMC + kv8DApX/AwOW/wMDl/8EBJr/BASb/wQDnv8FA6L/BQSk/wEApv8zSL7/caHY/2yb1v+AruL/m8fy/5zH + 8/+cyPP/nMj0/53I9f+dyfb/nsn2/57J9v+eyvf/nsr3/5/K9/+fyvj/n8r4/5/K+P+fy/j/n8v4/6DL + +P+iz/j/g6P1/yUh7P8iHuz/Ix/s/yIf7P80LvX/QTr8/0E5/P9DPPz/SEL7/0xG+/9QSfr/U075/7G7 + +//h8f3/2er8/9bo/P/T5/z/0eX7/87k/P/M5Pv/zOP7/8nh+/+01vn/rdL5/6rQ+f+s1v//lLj2ov// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wAjI9wWfJzv3KPQ + +v+eyvT/jrrq/26e2P9tndf/bZ3W/22d1f9tnNT/bZzU/22c1P9tnNT/bZzT/22c0/9tnNL/bZzS/22c + 0v9voNP/VnrE/wYGlf8CAZT/AwOU/wMClP8DA5X/AwOV/wMDlv8EApf/BAOZ/wQDnP8EA57/BQOh/wUE + pP8FBKf/AQCo/ys7u/9woNf/bZ3X/2yc1/+DseX/ncj0/5zI9P+cyPT/ncj1/53J9v+eyfb/nsn3/57K + 9/+eyvf/n8r3/5/K+P+fyvj/n8r4/5/L+P+fy/j/oMv4/6PP+P+Hqfb/JiTs/yIe7P8jH+z/NC/2/0M7 + /f9DO/3/RD39/0hA/P9NRvz/UUr7/1ZP+v9XUPr/r7b7/+Py/f/b6/z/2Or8/9Xo/P/S5/z/0OX8/8/k + /P/O5Pv/xuD7/7LU+f+u0vn/rNL7/6TL+/mCnvM/////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wBQX+Vjlbz3/6DM9f+dyPP/gK7i/2yc1v9undf/bp3W/22d + 1v9tnNX/bZzU/22c1P9tnNT/bZzT/22c0/9tnNL/bZzS/2+f0/9ZgMf/CQqZ/wIBlf8DApX/AwKW/wQD + l/8EA5j/BAOZ/wQDmv8EA57/BASf/wUEov8FBKT/BQSm/wUFqf8DAar/ICu5/2ua1v9undj/bZ3Y/22d + 2f+Iten/ncn1/53I9f+dyfX/ncn2/57J9/+eyff/nsr3/5/K9/+fyvj/n8r4/5/K+P+fyvj/oMv4/6DL + +P+gy/j/o8/4/4Sl9f8kIez/Ix/s/zYx9/9EPf7/RDz+/0M8/f9IQf3/TET8/1FL/P9VTvv/WVP7/1lS + +v+iqfv/4/P9/9zs/P/Z6vz/1uj8/9To/P/R5vz/0OX8/8/l+/+/3Pr/stX5/67T+f+w2v//lrf2sQAA + /wL///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAA + tgduh+23o8/9/57K9P+ZxfH/d6Xd/22d1/9undf/bZ3W/22d1f9tnNT/bZzU/22c1P9tnNT/bZzT/22c + 0/9tnNP/b5/U/1l/x/8JC5z/AwKY/wQDmf8EBJn/BAOZ/wQDmv8EBJz/BASd/wUEoP8FBKL/BQWk/wUF + pv8FBan/BQWr/wUErv8RFrb/ZI/U/26f2f9tndn/bZzZ/2+f2/+PvO3/nsr2/53J9v+dyfb/nsn2/57K + 9/+eyvf/n8r3/5/K9/+fyvj/n8v4/5/L+P+gy/j/oMv4/6DL+P+k0Pj/eZb0/yYi7v85M/n/RT7+/0U9 + /v9FPf7/R0D+/0pE/f9QSf3/VE78/1pT/P9eWPv/YFn6/4SH+v/f7v3/3u38/9vr/P/Y6fz/1ej8/9Pn + /P/S5vz/zeT7/7jY+v+y1fn/stf8/6TJ+/F6lPUy////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AC4u4iyCo/Too8/5/57K9P+TwO7/cqHa/22d + 1/9undf/bZ3W/22d1v9tndX/bZzU/22c1P9tnNT/bZzU/22c1P9wodX/UnbF/wYGnf8EA5z/BQSd/wUE + nP8EBJ3/BASd/wUEnv8FBKD/BQSj/wUEpP8FBKb/BQWp/wYFrP8GBq7/Bgax/wYGtP9Mbc3/cKLa/22d + 2f9undr/bZ3Z/3al3v+ZxPP/nsr2/57J9v+eyvf/nsr3/5/K9/+fyvf/n8r4/5/L+P+fy/j/oMv4/6DL + +P+gy/j/oMv4/6PQ+P9sf/X/ODH6/0U9/v9FPf//Rj7//0Y///9KQ/7/Tkf+/1RN/f9ZUfz/Xlj8/2Nc + +/9mYfr/b2v6/8vX/P/h8Pz/2+v8/9jq/P/W6fz/1Of8/9Pn/P/G4Pv/ttf6/7TX+v+v0///jKb0c/// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AEpa52CQt/b+oc73/5/K9P+PvOv/cKDa/22d1/9untf/bp3W/22d1v9tndX/bZzV/22c + 1P9tnNT/bZzU/3Ch1v9GZMD/AgGe/wUFn/8FBZ//BQWg/wUEoP8FBKH/BQWi/wUFpP8FBaf/BgWn/wYF + qf8GBaz/Bgat/wYGsP8HB7P/BQO2/yUzwv9untn/bp7a/26d2v9untr/bZzZ/4Kw5v+fyvf/nsn3/57K + 9/+eyvf/n8r4/5/K+P+fyvj/n8v4/5/L+P+gy/j/oMv4/5/K+P+hy/j/vt76/2xx/P8/Nv7/RT3+/0U9 + //9GPv//SkL//01G/v9RSv7/WFD9/11W/P9hWvz/ZmD7/2xl+v9sZvr/pKr7/+Lx/P/c7Pz/2er8/9fp + /P/W6Pz/zuT7/7za+v+32Pr/uNv//5Kt9qIAAP8E////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AAAAAAVps6YuYwfv/oM32/57K + 9P+Nuur/caDa/22d1/9undf/bp3W/22d1v9tndX/bZzV/22c1P9tnNT/b5/V/zFEt/8CAKH/BQWj/wUF + o/8FBaL/BQWj/wUFpP8GBqX/BQWm/wUFqP8GBqr/Bgas/wYHr/8GB7H/CAe0/wgIt/8ICLr/Cgq9/01s + 0f9xo9v/bp7a/2+e2v9vntv/caDc/5TB8f+fy/f/n8r3/5/K9/+fyvj/n8r4/5/L+P+fy/j/n8v4/6DL + +P+eyvj/ps74/9Lo/P/H1f3/SEP9/0I6/f9EPP7/RT7+/0c//v9MRP7/UEn+/1RN/f9cVP3/YFr8/2Ve + /P9rZPv/cGr6/3Ru+v+Affn/0Nz8/9/u/f/a6vz/2Or8/9Lm/P/B3fr/u9v6/7zd//+Ys/e1W23tDv// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8AAADbB2B07KKbxfz/ocz2/5/K9P+Rvez/c6Lb/2yd1/9untj/bp3X/26d + 1v9tndb/bZ3V/26d1f9qmNP/GiSw/wQEpv8GB6f/Bgam/wYGpv8GBqf/BQWo/wYGqf8GBqr/Bger/wYH + rv8GB6//CAex/wgHtP8ICLf/CAi5/wkJvP8IB77/GB3D/2GL1/9yotr/b57a/2+e2/9unNr/gK/l/5/L + 9/+fyvf/n8r3/5/K+P+fyvj/n8v4/6DL+P+fy/j/nsr4/7LV+f/c7fz/5O/9/2dn/P89NPz/Qzv9/0M8 + /f9FPf7/SUH+/01F/v9TTP7/WFH9/19Y/f9iXPz/aGP8/25o+/9zbfv/eXP6/3p0+f+hpPr/3u39/9vr + /P/V6Pz/xd/7/8De+/+/3v//mrP3tVBg7xD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AAADRC2B3 + 66Waw/3/oc32/5/K9f+Vwu//eqjg/22d2P9tntf/bp3X/26d1/9tndb/cKHX/1Z7zP8JC6z/Bgaq/wcH + qf8HB6r/Bgeq/wcHqf8GB6v/Bges/wcHrf8HB6//Bwew/wcIsv8ICLT/CAi3/wkJuv8KCrv/Cwq+/wwL + wf8KB8L/JS/K/2aR2f9zo9z/cJ7b/3Ce2/90ot7/mcXz/6DL9/+fyvf/n8r4/5/L+P+fy/j/nsr4/6bO + +P/C3vv/5PP9/93q/f91e/v/OjP7/0E5/P9CO/3/Qjv9/0U9/f9KQ/3/T0j9/1VP/f9bVP3/YFr8/2Zf + /P9tZvv/cmz7/3Zw+v97dvr/gHr5/4R/+f/Ayfv/3O78/8nh+//G4v3/vdr//5aq96JOTusN////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8AAADmCltv6ZeSufj/o9D5/5/K9f+bx/L/hrPm/3Kh + 2/9tnNf/bp3X/26d1/9xodj/MkbA/wYErv8JCa//CAiu/wgIrf8IB63/CAiu/wgIr/8ICK//CAmx/wgI + sv8JCLT/CQm1/woKt/8LCrr/Cwq8/wwLvv8MDMH/DQzC/w4NxP8MCsb/IivL/1l91/9yotz/c6Pc/3Gg + 3P+Ou+3/oc34/5/L+P+gy/j/n8z4/6PO+P+22vr/1Or8/9zu/P+0xPv/XmD6/zgx+v8+N/v/QDn8/0A5 + /P9COvz/RT79/0tE/f9RSv3/V1D8/11X/P9jXPz/aWP7/29p+/90bvv/eXP6/396+v+Ef/n/ioT5/3x8 + +P+xx/r/z+r//7XP/faRpvZ2AADMBf///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8AAAD/Ak5e6XKCo/Lyo9D9/6DM9f+eyvT/lcHv/4Cu4/9woNr/b6DY/16G0v8RFLf/Cgiz/woK + s/8KCrP/Cgmx/wkKsf8JCrL/CQqz/wkKs/8JCrT/Cgm2/woKt/8LCrn/DAq7/wwLvf8MC77/DQzA/w0M + wv8ODcT/Dg7G/xAQyP8PDsj/FhjL/zVH0/9Wd9j/ZY7a/36p5v+fy/n/n8v4/53I+P+lzfj/stD5/7HB + +v+Uofn/YWf5/zw3+P83L/n/PDb6/z02+v8/OPv/Pzj7/0E6+/9HQPz/TEX8/1NM/P9ZUvz/X1j8/2Zf + +/9rZPv/cWv7/3dx+v99d/r/hH/5/4R/+f9oY/f/Ni/4/1VX//+kuvnQfoz0Rf///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////ADA05TtshfDBk7v5/6PQ + +/+hzfX/nsr0/5XC7/+FsuX/MUDJ/wkHuP8MDLf/DAy3/wwLtv8MC7b/Cwu2/wsLtf8LC7f/Cwu3/wsL + uP8MC7n/DAu6/wwMvP8NDL3/DQy//w0Mwf8ODcP/Dw7E/w8Pxv8PEMj/ERHJ/xISyv8TEsz/EhDN/xUU + zv8eI9D/LDTa/0JL7v9IUvD/SE/z/01R9P9GSfX/NjL2/zAp9v8yK/f/ODH4/zo0+P87NPn/PTb6/z44 + +v8+N/v/Qzz7/0hC+/9PSPv/VE37/1tV+/9hWvv/Z2H7/2xm+v9zbvr/e3X5/314+f9qZfj/SEL5/zYw + //84MvfxOzP0hhsN5BP///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AAAA0QtJVeRpdI/u1pK4+P+j0Pz/pNH4/2N66P8UEdT/EhDO/xEQ + yP8PDsL/Dg6//w4NvP8NDLr/DAy5/wwMuv8MDLr/DQy7/wwMu/8NDb3/Dg2//w4Nwf8ODcH/Dw/D/w8P + xf8PEMf/ERHI/xISyf8TE8v/FBTM/xUUzf8VFc7/FRXP/xUU0P8YFtn/Ih3u/ych8P8pJPL/KyXz/y8o + 9P8zLfX/NS72/zYw9/84Mff/OjT4/zs0+P87NPn/PDb5/z84+v9EPfr/SkP6/09J+/9WUPv/XFX6/2Nc + +v9pZPr/cWv6/3Rv+v9nYfn/SUP4/zgx/v83Mvj8QDv2rk5F8DT///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wAAAMkTSFPkX3GL7rlmfe3sHRzj/xcV4f8YFd7/FxTc/xYT2f8UE9T/FBLR/xQRz/8TEM3/EhDM/xER + yf8REMj/EBDG/xEPxv8QEMX/EBDF/xAQxf8QEMX/ERHG/xESx/8TE8n/ExPK/xQUzP8VFc7/FRXP/xYV + 0P8XF9L/GBnW/yAe4v8pJPD/KyXx/y0n8v8uKfP/MSz0/zIt9f80LvX/NS/1/zYw9/83Mff/OTP4/zs0 + +P87Nfn/QDn5/0Q++f9KRPn/UUv6/1dS+v9eWPr/ZV/6/2Zg+v9gWfn/SkT5/zkz//85M/j+QDv4u0xF + 9Ur///8C////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAA2CcYEt1hGhfcmxgW + 3McZFtzkGBXa9xkW4P8YFuD/GBXg/xgV4f8YFeD/GBXf/xkV3v8XFd3/GBXd/xcV2/8YFdv/FxXa/xcV + 2P8XFdb/FhXS/xUV0f8VFc//FRXO/xUVzv8WFtD/FxfT/xgZ1f8aG9n/JCHq/ykk8P8rJvH/LCfy/y4p + 8v8vKvP/Miv0/zMt9f80LvX/NjD2/zYw9v83Mff/OTP4/zw1+P9AOvj/RkD5/01G+f9TTPn/VE75/1FK + +f9IQvj/Pzn6/zkz//86M/n+Qj34vE5I8k6ZmcwF////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8AJCTbBxoa3R4YGNk2GRbaUxkX3W8aFt6LGRbbpBkW + 27gZFdvMGhbd3BkW3egaF9/0Gxfi/xwY6f8cGer/HBnq/x0Z6f8dGuj/HRrm/x4b5P8dG+L/HBre/xsa + 3P8cG9v/HRze/yMg6P8nI+//KSTv/yom8f8tKPH/Liny/y8q8/8xK/P/MSz0/zMt9f8zLvX/NS/2/zcw + 9v84Mvf/PTb3/0E79/9GP/j/RkD4/0I7+P87Nfj/ODL6/zkz//87Nfj7Qz34t05L8k6ZzMwF////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////ABoa5goYGNsVFxfgIRoV4DEcFeBKHBfjZRwY + 44kcGeOsHBrkzx4b5uYfG+f9IR3x/yIe8f8iHvD/Ix/v/yMf7v8lIe3/JiLu/ycj7v8oJO//KiXw/ywn + 8f8tKPH/Liny/y8q8/8wK/T/Miz0/zMu9f80LvX/NS/2/zcx9v85M/b/OTP2/zkz9/84Mfj/ODL8/zoz + //89N/jyRD/3qU1J80L//6oD////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wAVFeoMIRnmHyAY5z8gHetoIh3rlyIe + 674iHurfIx/r9iUh8/8mIvb/KCP2/ykk9f8qJfT/Kybz/ywn8/8tKPL/Liny/y8q8/8wKvP/Miz0/zMt + 9P8zLvb/NC74/zUv+f82MP3/NzH+/zkz9v0+OfXTR0H1hVFR9C///wAB////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8AAACqAyAg6hgjHuszJSLrWSYj7IUnI+6oKCTuxykm + 794sJ/DsLSjx+C0o8/8uKfr/MCr6/zEr+/8xLPv/My36/zQu9P43MvTyODL14Ds19LtCPvWESUXzP3dm + 7g////8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wBJSf8HNzfpFzcw8SUzLvAyMCvyOysn8EIuK/BCLivwQi4r + 80I0LPNAOzfxOEtG8yxcXPUZ//8AAf///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP////////////////////////////////// + 4AD//////////////////wAAP/////////////////wAAA/////////////////wAAAH//////////// + ////wAAAA////////////////4AAAAH///////////////4AAAAA///////////////8AAAAAP////// + ////////+AAAAAB///////////////AAAAAAf//////////////wAAAAAD//////////////4AAAAAA/ + /////////////8AAAAAAP/////////////+AAAAAAD//////////////gAAAAAA//////////////wAA + AAAAP/////////////8AAAAAAD/////////////+AAAAAAA//////////////gAAAAAAP/////////// + //wAAAAAAH/////////////8AAAAAAB//////////////AAAAAAAf/////////////gAAAAAAH////// + ///////4AAAAAAD/////////////+AAAAAAA//////////////AAAAAAAf/////////////wAAAAAAH/ + ////////////8AAAAAAB/////////////+AAAAAAA//////////////gAAAAAAf/////////////4AAA + AAAH/////////////8AAAAAAD//////////////AAAAAAA//////////////gAAAAAAf//////////// + /4AAAAAAP/////////////+AAAAAAD//////////////gAAAAAB//////////////wAAAAAA//////// + //////8AAAAAAf//////////////AAAAAAP//////////////gAAAAAD//////////////4AAAAAB/// + ///////////+AAAAAA///////////////gAAAAAf//////////////4AAAAAP//////////////8AAAA + AH///////////////AAAAAD///////////////wAAAAB///////////////8AAAAA/////////////// + /AAAAAf///////////////gAAAAP///////////////4AAAAH///////////////+AAAAD////////// + //////gAAAA////////////////4AAAAf///////////////+AAAAP////////////////gAAAH///// + ///////////wAAAD////////////////8AAAA/////////////////AAAAf////////////////wAAAP + ////////////////8AAAD////////////wAAD/AAAB////////////AAAAAAAAA////////////gAAAA + AAAAP///////////gAAAAAAAAH///////////wAAAAAAAAD///////////4AAAAAAAAB///////////8 + AAAAAAAAAP///////////AAAAAAAAAAf//////////gAAAAAAAAAB//////////wAAAAAAAAAAD///// + ////8AAAAAAAAAAAP////////+AAAAAAAAAAAA/////////gAAAAAAAAAAAD////////wAAAAAAAAAAA + AP///////8AAAAAAAAAAAAAf///////AAAAAAAAAAAAAD///////gAAAAAAAAAAAAAP//////4AAAAAA + AAAAAAAB//////+AAAAAAAAAAAAAAP//////gAAAAAAAAAAAAAB//////4AAAAAAAAAAAAAAP/////+A + AAAAAAAAAAAAAB//////gAAAAAAAAAAAAAAf/////4AAAAAAAAAAAAAAD/////+AAAAAAAAAAAAAAA// + ////gAAAAAAAAAAAAAAP/////4AAAAAAAAAAAAAAB/////+AAAAAAAAAAAAAAAf/////gAAAAAAAAAAA + AAAH/////4AAAAAAAAAAAAAAB/////+AAAAAAAAAAAAAAAP/////gAAAAAAAAAAAAAAD/////4AAAAAA + AAAAAAAAA/////+AAAAAAAAAAAAAAAP/////wAAAAAAAAAAAAAAD/////8AAAAAAAAAAAAAAA//////A + AAAAAAAAAAAAAAP/////4AAAAAAAAAAAAAAD/////+AAAAAAAAAAAAAAB//////gAAAAAAAAAAAAAAf/ + ////8AAAAAAAAAAAAAAH//////AAAAAAAAAAAAAAD//////4AAAAAAAAAAAAAA//////+AAAAAAAAAAA + AAAP//////wAAAAAAAAAAAAAH//////8AAAAAAAAAAAAAB///////gAAAAAAAAAAAAAf//////4AAAAA + AAAAAAAAP///////AAAAAAAAAAAAAH///////4AAAAAAAAAAAAB///////+AAAAAAAAAAAAA//////// + wAAAAAAAAAAAAf///////+AAAAAAAAAAAAP////////wAAAAAAAAAAAH////////+AAAAAAAAAAAH/// + //////4AAAAAAAAAAD//////////AAAAAAAAAAD//////////8AAAAAAAAAB///////////4AAAAAAAA + B////////////wAAAAAAAB//////////////AAAAAAB///////////////8AAAAB//////////////// + +AAAD//////////////////gAH//////////////////////////////iVBORw0KGgoAAAANSUhEUgAA + AQAAAAEACAYAAABccqhmAAAKPWlDQ1BpY2MAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4BUaaIS + kgChhBgSQOyIqMCIoiKCFRkUccDREZCxIoqFQbH3AXkIKOPgKDZU3g/eGn2z5r03b/avvfY5Z53vnH0+ + AEZgsESahaoBZEoV8ogAHzw2Lh4ndwMKVCCBA4BAmC0LifSPAgDg+/Hw7IgAH/gCBODNbUAAAG7YBIbh + OPx/UBfK5AoAJAwApovE2UIApBAAMnIVMgUAMgoA7KR0mQIAJQAAWx4bFw+AagEAO2WSTwMAdtIk9wIA + tihTKgJAowBAJsoUiQDQDgBYl6MUiwCwYAAoypGIcwGwmwBgkqHMlABg7wCAnSkWZAMQGABgohALUwEI + 9gDAkEdF8AAIMwEojJSveNJXXCHOUwAA8LJki+WSlFQFbiG0xB1cXbl4oDg3Q6xQ2IQJhOkCuQjnZWXK + BNLFAJMzAwCARnZEgA/O9+M5O7g6O9s42jp8taj/GvyLiI2L/5c/r8IBAQCE0/VF+7O8rBoA7hgAtvGL + lrQdoGUNgNb9L5rJHgDVQoDmq1/Nw+H78fBUhULmZmeXm5trKxELbYWpX/X5nwl/AV/1s+X78fDf14P7 + ipMFygwFHhHggwuzMrKUcjxbJhCKcZs/HvHfLvzzd0yLECeL5WKpUIxHS8S5EmkKzsuSiiQKSZYUl0j/ + k4l/s+wPmLxrAGDVfgb2QltQu8oG7JcuILDogCXsAgDkd9+CqdEQBgAxBoOTdw8AMPmb/x1oGQCg2ZIU + HACAFxGFC5XynMkYAQCACDRQBTZogz4YgwXYgCO4gDt4gR/MhlCIgjhYAEJIhUyQQy4shVVQBCWwEbZC + FeyGWqiHRjgCLXACzsIFuALX4BY8gF4YgOcwCm9gHEEQMsJEWIg2YoCYItaII8JFZiF+SDASgcQhiUgK + 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 + +QAAAABJRU5ErkJggg== + + + \ No newline at end of file diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/Preview/ModelPreview.vb b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Preview/ModelPreview.vb new file mode 100644 index 0000000..85b4b8b --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Preview/ModelPreview.vb @@ -0,0 +1,341 @@ +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 + +Namespace PreviewN + + Public Class ModelPreview + + Public Event WandUpdateView() + + Private WithEvents glControl1 As GLControl + 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 myPressedKeys As New List(Of Keys) + Private isDeactivated As Boolean = False + Private ReadOnly myModels As New Dictionary(Of Object3D, Renderer) + + Public Property RenderWhenWindowsIsInactive As Boolean = False + Public Property EnableCameraControlling As Boolean = True + Public Property Scaling As Single = 500.0F + Public Property ClearColor As Color = Color.CornflowerBlue + + Public ReadOnly Property PressedKeys As IReadOnlyList(Of Keys) + Get + Return myPressedKeys + End Get + 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 + + Private ReadOnly Property IsStrgPressed As Boolean + Get + Return myPressedKeys.Contains(Keys.ControlKey) + End Get + End Property + + Private ReadOnly Property IsShiftPressed As Boolean + Get + Return myPressedKeys.Contains(Keys.ShiftKey) + End Get + End Property + + Public Property IsMouseDown As Boolean + Get + Return _isMouseDown + End Get + Set(value As Boolean) + _isMouseDown = value + glControl1.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) + Me.SuspendLayout() + + InitializeComponent() + DoubleBuffered = True + + 'glControl1 + Me.glControl1 = New GLControl + Me.glControl1.BackColor = Color.Black + Me.glControl1.Location = New Point(0, 0) + Me.glControl1.MinimumSize = New Size(600, 120) + Me.glControl1.Name = "glControl1" + Me.glControl1.Anchor = AnchorStyles.Left Or AnchorStyles.Top Or AnchorStyles.Right Or AnchorStyles.Bottom + Me.glControl1.Location = New Point(0, 0) + Me.glControl1.Size = Me.ClientSize + Me.glControl1.TabIndex = 0 + Me.glControl1.TabStop = False + Me.glControl1.VSync = False + Me.Controls.Add(Me.glControl1) + Me.ResumeLayout(False) + AddHandler Windows.Media.CompositionTarget.Rendering, AddressOf CompositionTarget_Rendering + + Scaling = scale + + 'Toolkit.Init() + + glControl1.CreateControl() + AddHandler glControl1.MouseWheel, AddressOf glControl1_Wheel + ProjMatrix = Matrix4.CreatePerspectiveFieldOfView(FOV, glControl1.Width / glControl1.Height, 100.0F, 100000.0F) + glControl1.Enabled = False + MyCamera.SetCameraMode(CameraMode.FLY, camMtx) + MyCamera.UpdateMatrix(camMtx) + + Me.ResumeLayout() + + For Each obj As Object3D In objs + AddModel(obj) + Next + End Sub + + Public Sub UpdateOrbitCamera() + If Camera.IsOrbitCamera Then + Camera.UpdateOrbitCamera(camMtx) + End If + End Sub + + Public Sub UpdateView() + glControl1.Invalidate() + 'glControl1.Update() + 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 + glControl1.Enabled = True + RenderModels() + glControl1.Invalidate() + 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(sender As Object, e As EventArgs) Handles glControl1.Load + 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 CompositionTarget_Rendering(sender As Object, e As EventArgs) + If Not isDeactivated OrElse RenderWhenWindowsIsInactive Then + RaiseEvent WandUpdateView() + glControl1.Invalidate() + End If + End Sub + + Public Sub HandlesOnPaint(sender As Object, e As PaintEventArgs) Handles glControl1.Paint + If EnableCameraControlling Then + MoveCameraViaWASDQE() + End If + + GL.ClearColor(ClearColor) + + GL.Clear(ClearBufferMask.ColorBufferBit Or ClearBufferMask.DepthBufferBit) + + 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 + + glControl1.SwapBuffers() + + 'If Not IsMouseDown AndAlso obj3d IsNot Nothing Then + ' e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias + ' e.Graphics.DrawString(GetModelInfoAsString, New Font(FontFamily.GenericSerif, 10), New SolidBrush(Panel1.ForeColor), New Drawing.Point(10, 10)) + 'End If + End Sub + + Private Function GetModelInfoAsString() As String + Dim matsCount As Long = 0 + Dim facesCount As Long = 0 + Dim vertsCount As Long = 0 + Dim vcCount As Long = 0 + Dim uvCount As Long = 0 + + For Each obj3d As Object3D In myModels.Keys + matsCount += obj3d.Materials.Count + For Each m As Mesh In obj3d.Meshes + vertsCount += m.Vertices.Count + facesCount += m.Faces.Count + vcCount += m.VertexColors.Count + uvCount += m.UVs.Count + Next + Next + + Return String.Format("Materials:{0}{1} +Faces:{0}{0}{2} +Vertices:{0}{3} +Vertex Colors{0}{4} +UVs:{0}{0}{5}", + vbTab, matsCount, facesCount, vertsCount, vcCount, uvCount) + End Function + + Private Sub glControl1_Resize(sender As Object, e As EventArgs) Handles glControl1.Resize + glControl1.Context.Update(glControl1.WindowInfo) + GL.Viewport(0, 0, glControl1.Width, glControl1.Height) + ProjMatrix = Matrix4.CreatePerspectiveFieldOfView(FOV, glControl1.Width / glControl1.Height, 100.0F, 100000.0F) + glControl1.Invalidate() + End Sub + + Private Sub glControl1_Wheel(sender As Object, e As MouseEventArgs) + MyCamera.ResetMouseStuff() + MyCamera.UpdateCameraMatrixWithScrollWheel(CInt(Math.Truncate(e.Delta * (If(IsShiftPressed, 3.5F, 1.5F)))), camMtx) + savedCamPos = MyCamera.Position + glControl1.Invalidate() + End Sub + + Private Sub glControl1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) 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 MouseEventArgs) Handles glControl1.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 + glControl1.Invalidate() + End If + End Sub + + Public Sub HandlesOnKeyDown(sender As Object, e As KeyEventArgs) Handles glControl1.KeyDown + If Not myPressedKeys.Contains(e.KeyCode) Then myPressedKeys.Add(e.KeyCode) + End Sub + + Public Sub HandlesOnKeyUp(sender As Object, e As KeyEventArgs) Handles MyBase.KeyUp + If myPressedKeys.Contains(e.KeyCode) Then myPressedKeys.Remove(e.KeyCode) + 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) + + For Each k As Keys In myPressedKeys + If allowCamMove Then + Select Case k + Case Keys.W + 'camera.Move(moveSpeed, moveSpeed, camMtx) + MyCamera.UpdateCameraMatrixWithScrollWheel(moveSpeed, camMtx) + savedCamPos = MyCamera.Position + Case Keys.S + 'camera.Move(-moveSpeed, -moveSpeed, camMtx) + MyCamera.UpdateCameraMatrixWithScrollWheel(-moveSpeed, camMtx) + savedCamPos = MyCamera.Position + Case Keys.A + 'camera.Move(-moveSpeed, 0, camMtx) + MyCamera.UpdateCameraOffsetDirectly(-moveSpeed, 0, camMtx) + Case Keys.D + 'camera.Move(moveSpeed, 0, camMtx) + MyCamera.UpdateCameraOffsetDirectly(moveSpeed, 0, camMtx) + Case Keys.E + 'camera.Move(0, -moveSpeed, camMtx) + MyCamera.UpdateCameraOffsetDirectly(0, -moveSpeed, camMtx) + Case Keys.Q + 'camera.Move(0, moveSpeed, camMtx) + MyCamera.UpdateCameraOffsetDirectly(0, moveSpeed, camMtx) + End Select + End If + Next + End Sub + + Private Sub Camera_NeedSelectedObject(e As Camera.NeedSelectedObjectEventArgs) Handles MyCamera.NeedSelectedObject + e.Points = Nothing + 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 diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/Rendering/BoundingBox.vb b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Rendering/BoundingBox.vb new file mode 100644 index 0000000..edbd8d4 --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Rendering/BoundingBox.vb @@ -0,0 +1,105 @@ +Imports System.Drawing +Imports OpenTK +Imports OpenTK.Graphics.OpenGL + +Namespace RenderingN + + Public Class BoundingBox + + Public Shared Sub DrawSolid(scale As System.Numerics.Vector3, rot As System.Numerics.Quaternion, pos As System.Numerics.Vector3, color As Color, upper As System.Numerics.Vector3, lower As System.Numerics.Vector3) + GL.Disable(EnableCap.Blend) + GL.Disable(EnableCap.Texture2D) + GL.Disable(EnableCap.AlphaTest) + GL.PushMatrix() + GL.Translate(pos.X, pos.Y, pos.Z) + GL.Rotate(rot.X, 1, 0, 0) + GL.Rotate(rot.Y, 0, 1, 0) + GL.Rotate(rot.Z, 0, 0, 1) + GL.Scale(scale.X, scale.Y, scale.Z) + + GL.Begin(PrimitiveType.Quads) + GL.Color4(color) + + GL.Vertex3(upper.X, upper.Y, lower.Z) ' Top-right of top face + GL.Vertex3(lower.X, upper.Y, lower.Z) ' Top-left of top face + GL.Vertex3(lower.X, upper.Y, upper.Z) ' Bottom-left of top face + GL.Vertex3(upper.X, upper.Y, upper.Z) ' Bottom-right of top face + + GL.Vertex3(upper.X, lower.Y, lower.Z) ' Top-right of bottom face + GL.Vertex3(lower.X, lower.Y, lower.Z) ' Top-left of bottom face + GL.Vertex3(lower.X, lower.Y, upper.Z) ' Bottom-left of bottom face + GL.Vertex3(upper.X, lower.Y, upper.Z) ' Bottom-right of bottom face + + GL.Vertex3(upper.X, upper.Y, upper.Z) ' Top-Right of front face + GL.Vertex3(lower.X, upper.Y, upper.Z) ' Top-left of front face + GL.Vertex3(lower.X, lower.Y, upper.Z) ' Bottom-left of front face + GL.Vertex3(upper.X, lower.Y, upper.Z) ' Bottom-right of front face + + GL.Vertex3(upper.X, lower.Y, lower.Z) ' Bottom-Left of back face + GL.Vertex3(lower.X, lower.Y, lower.Z) ' Bottom-Right of back face + GL.Vertex3(lower.X, upper.Y, lower.Z) ' Top-Right of back face + GL.Vertex3(upper.X, upper.Y, lower.Z) ' Top-Left of back face + + GL.Vertex3(lower.X, upper.Y, upper.Z) ' Top-Right of left face + GL.Vertex3(lower.X, upper.Y, lower.Z) ' Top-Left of left face + GL.Vertex3(lower.X, lower.Y, lower.Z) ' Bottom-Left of left face + GL.Vertex3(lower.X, lower.Y, upper.Z) ' Bottom-Right of left face + + GL.Vertex3(upper.X, upper.Y, upper.Z) ' Top-Right of left face + GL.Vertex3(upper.X, upper.Y, lower.Z) ' Top-Left of left face + GL.Vertex3(upper.X, lower.Y, lower.Z) ' Bottom-Left of left face + GL.Vertex3(upper.X, lower.Y, upper.Z) ' Bottom-Right of left face + + GL.Color4(Color.White) + GL.End() + GL.PopMatrix() + GL.Enable(EnableCap.Blend) + GL.Enable(EnableCap.Texture2D) + GL.Enable(EnableCap.AlphaTest) + End Sub + + Public Shared Sub Draw(scale As Numerics.Vector3, rot As Numerics.Quaternion, pos As Numerics.Vector3, color As Color, upper As Numerics.Vector3, lower As Numerics.Vector3) + GL.Disable(EnableCap.Blend) + GL.Disable(EnableCap.Texture2D) + GL.Disable(EnableCap.AlphaTest) + GL.PushMatrix() + GL.Translate(pos.X, pos.Y, pos.Z) + GL.Rotate(rot.X, 1, 0, 0) + GL.Rotate(rot.Y, 0, 1, 0) + GL.Rotate(rot.Z, 0, 0, 1) + GL.Scale(scale.X, scale.Y, scale.Z) + + GL.Begin(PrimitiveType.LineLoop) + GL.Color4(color) + + GL.Vertex3(upper.X, upper.Y, lower.Z) ' 1 + GL.Vertex3(lower.X, upper.Y, lower.Z) ' 2 + GL.Vertex3(lower.X, upper.Y, upper.Z) ' 3 + GL.Vertex3(upper.X, upper.Y, lower.Z) ' 1 + GL.Vertex3(upper.X, upper.Y, upper.Z) ' 4 + GL.Vertex3(lower.X, upper.Y, upper.Z) ' 3 + + GL.Vertex3(lower.X, lower.Y, upper.Z) ' 7 + GL.Vertex3(lower.X, lower.Y, lower.Z) ' 6 + GL.Vertex3(upper.X, lower.Y, lower.Z) ' 5 + GL.Vertex3(lower.X, lower.Y, upper.Z) ' 7 + GL.Vertex3(upper.X, lower.Y, upper.Z) ' 8 + GL.Vertex3(upper.X, lower.Y, lower.Z) ' 5 + + GL.Vertex3(lower.X, upper.Y, lower.Z) ' 2 + GL.Vertex3(lower.X, lower.Y, lower.Z) ' 6 + GL.Vertex3(lower.X, upper.Y, upper.Z) ' 3 + GL.Vertex3(upper.X, lower.Y, upper.Z) ' 8 + GL.Vertex3(upper.X, upper.Y, upper.Z) ' 4 + GL.Vertex3(upper.X, lower.Y, lower.Z) ' 5 + + GL.Color4(Color.White) + GL.End() + GL.PopMatrix() + GL.Enable(EnableCap.Blend) + GL.Enable(EnableCap.Texture2D) + GL.Enable(EnableCap.AlphaTest) + End Sub + End Class + +End Namespace diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/Rendering/ContentPipe.vb b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Rendering/ContentPipe.vb new file mode 100644 index 0000000..8e0d289 --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Rendering/ContentPipe.vb @@ -0,0 +1,33 @@ +Imports System +Imports OpenTK +Imports OpenTK.Graphics.OpenGL +Imports System.Drawing +Imports System.Drawing.Imaging + +Namespace RenderingN + + Public Class ContentPipe + + Public Shared Function LoadTexture(filepath As String) As Integer + Dim bitmap As New Bitmap(filepath) + Return LoadTexture(bitmap) + End Function + + Public Shared Function LoadTexture(bitmap As Bitmap) As Integer + Dim id As Integer = GL.GenTexture() + LoadTexture(bitmap, id) + Return id + End Function + + Public Shared Sub LoadTexture(bitmap As Bitmap, id As Integer) + Dim bmpData As BitmapData = bitmap.LockBits(New Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, Imaging.PixelFormat.Format32bppArgb) + GL.BindTexture(TextureTarget.Texture2D, id) + GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bitmap.Width, bitmap.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bmpData.Scan0) + bitmap.UnlockBits(bmpData) + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, CInt(Math.Truncate(TextureMinFilter.Linear))) + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, CInt(Math.Truncate(TextureMagFilter.Linear))) + End Sub + + End Class + +End Namespace diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/Rendering/RenderMode.vb b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Rendering/RenderMode.vb new file mode 100644 index 0000000..0205862 --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Rendering/RenderMode.vb @@ -0,0 +1,10 @@ +Namespace RenderingN + + Public Enum RenderMode As Byte + None = &H0 + Fill = &H1 + Outline = &H2 + FillOutline = Fill Or Outline + End Enum + +End Namespace diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/Rendering/Renderer.vb b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Rendering/Renderer.vb new file mode 100644 index 0000000..86eb404 --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/Rendering/Renderer.vb @@ -0,0 +1,456 @@ +Imports System.Drawing +Imports System.Threading +Imports System.Windows.Forms +Imports OpenTK +Imports OpenTK.Graphics.OpenGL +Imports Pilz.S3DFileParser + +Namespace RenderingN + + Public Class Renderer + + Private obj3d As Object3D + Private dicTextureIDs As New Dictionary(Of Image, Integer) + Private dicColorIDs As New Dictionary(Of Color, Integer) + Private emptyTexture As Bitmap = Nothing + Private lineTexture As Bitmap = Nothing + Private selectedLineTexture As Bitmap = Nothing + Public Property ModelScaling As Single = 1.0F + Public ReadOnly Property HasRendered As Boolean = False + Public ReadOnly Property SelectedElements As List(Of Object) + + Private ReadOnly Property VertexBuffers As New Dictionary(Of Mesh, Integer) + Private ReadOnly Property IndicesBuffers As New Dictionary(Of Mesh, List(Of Integer)) + Private ReadOnly Property UVBuffers As New Dictionary(Of Mesh, Integer) + Private ReadOnly Property VertexColorBuffers As New Dictionary(Of Mesh, Integer) + Private ReadOnly Property NormalBuffers As New Dictionary(Of Mesh, Integer) + + Public ReadOnly Property Model As Object3D + Get + Return obj3d + End Get + End Property + + Public Sub New(obj3d As Object3D) + Me.obj3d = obj3d.ToOneMesh + + 'Set Texture used for faces without texture + emptyTexture = ColorToTexture(Color.LightGray) + + 'Set Texture used for lines + lineTexture = ColorToTexture(Color.Black) + + 'Set Texture used for lines of selected faces + selectedLineTexture = ColorToTexture(Color.Orange) + End Sub + + Private Function ColorToTexture(color As Color) As Image + Dim tex As New Bitmap(1, 1) + tex.SetPixel(0, 0, color) + Return tex + End Function + + ''' + ''' Updates the Data of a Vertex in the buffer. + ''' + ''' The Mesh where the Vertex is listed. + ''' The Vertex to update. + Public Sub UpdateVertexData(m As Mesh, v As Vertex) + GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBuffers(m)) + GL.BufferSubData(BufferTarget.ArrayBuffer, CType(m.Vertices.IndexOf(v) * Vector3.SizeInBytes, IntPtr), Vector3.SizeInBytes, New Vector3(v.X, v.Y, v.Z)) + End Sub + + ''' + ''' Updates the Data of a Normal in the buffer. + ''' + ''' The Mesh where the Vertex is listed. + ''' The Normal to update. + Public Sub UpdateNormalData(m As Mesh, n As Normal) + GL.BindBuffer(BufferTarget.ArrayBuffer, NormalBuffers(m)) + GL.BufferSubData(BufferTarget.ArrayBuffer, CType(m.Normals.IndexOf(n) * Vector3.SizeInBytes, IntPtr), Vector3.SizeInBytes, New Vector3(n.X, n.Y, n.Z)) + End Sub + + ''' + ''' Updates the Data of a Vertex Color in the buffer. + ''' + ''' The Mesh where the Vertex is listed. + ''' The Vertex Color to update. + Public Sub UpdateVertexColorData(m As Mesh, vc As VertexColor) + GL.BindBuffer(BufferTarget.ArrayBuffer, VertexColorBuffers(m)) + GL.BufferSubData(BufferTarget.ArrayBuffer, CType(m.VertexColors.IndexOf(vc) * Vector4.SizeInBytes, IntPtr), Vector4.SizeInBytes, New Vector4(vc.R, vc.G, vc.B, vc.A)) + End Sub + + ''' + ''' Updates the Data of a UV in the buffer. + ''' + ''' The Mesh where the Vertex is listed. + ''' The UV to update. + Public Sub UpdateUVData(m As Mesh, uv As UV) + GL.BindBuffer(BufferTarget.ArrayBuffer, UVBuffers(m)) + GL.BufferSubData(BufferTarget.ArrayBuffer, CType(m.UVs.IndexOf(uv) * Vector2.SizeInBytes, IntPtr), Vector2.SizeInBytes, New Vector2(uv.U, uv.V)) + End Sub + + ''' + ''' Updates the indicies of a face in the buffer. + ''' + ''' The Mesh where the Vertex is listed. + ''' The Face to update. + Public Sub UpdateFaceIndicies(m As Mesh, f As Face) + Dim faceIndex As Integer = m.Faces.IndexOf(f) + Dim uintlen As Byte = Len(New UInteger) + Dim indicies As New Vector3(m.Vertices.IndexOf(f.Points(0).Vertex), + m.Vertices.IndexOf(f.Points(1).Vertex), + m.Vertices.IndexOf(f.Points(2).Vertex)) + + GL.BindBuffer(BufferTarget.ArrayBuffer, IndicesBuffers(m)(faceIndex)) + GL.BufferSubData(BufferTarget.ArrayBuffer, CType(uintlen * faceIndex, IntPtr), uintlen, indicies) + End Sub + + ''' + ''' Replace an Image with a new one. + ''' + ''' + ''' + Public Sub UpdateTexture(oldImage As Image, newImage As Image) + If dicTextureIDs.ContainsKey(oldImage) Then + Dim id As Integer = dicTextureIDs(oldImage) + dicTextureIDs.Remove(oldImage) + dicTextureIDs.Add(newImage, id) + ContentPipe.LoadTexture(newImage, id) + End If + End Sub + + ''' + ''' Updates an Image. + ''' + ''' + Public Sub UpdateTexture(image As Image) + If dicTextureIDs.ContainsKey(image) Then + ContentPipe.LoadTexture(dicTextureIDs(image)) + End If + End Sub + + ''' + ''' Creates the Buffers and store the requied Data. + ''' + Public Sub RenderModel() + ReleaseBuffers() + + For Each mesh As Mesh In obj3d.Meshes + + Dim nibo As New List(Of Integer) + Dim enablecols As Boolean = mesh.VertexColors.Count > 0 + Dim enablenorms As Boolean = (Not enablecols) AndAlso mesh.Normals.Count > 0 + Dim verts As New List(Of Vector3) + Dim uvs As New List(Of Vector2) + Dim cols As New List(Of Vector4) + Dim norms As New List(Of Vector3) + Dim curvi As ULong = 0 + IndicesBuffers.Add(mesh, nibo) + + For i As Integer = 0 To mesh.Faces.Count - 1 + With mesh.Faces(i) + Dim indices As New List(Of UInteger) + For Each p As S3DFileParser.Point In .Points + indices.Add(curvi) + curvi += 1 + + If verts IsNot Nothing Then + verts.Add(New Vector3(p.Vertex.X, p.Vertex.Y, p.Vertex.Z)) + Else + verts.Add(New Vector3(0, 0, 0)) + End If + + If p.UV IsNot Nothing Then + uvs.Add(New Vector2(p.UV.U, p.UV.V)) + Else + uvs.Add(New Vector2(0, 0)) + End If + + If enablecols AndAlso p.VertexColor IsNot Nothing Then + cols.Add(New Vector4(p.VertexColor.R, p.VertexColor.G, p.VertexColor.B, p.VertexColor.A)) + Else + cols.Add(New Vector4(1, 1, 1, 1)) + End If + + If enablenorms AndAlso p.Normal IsNot Nothing Then + norms.Add(New Vector3(p.Normal.X, p.Normal.Y, p.Normal.Z)) + Else + norms.Add(New Vector3(1, 1, 1)) + End If + Next + + nibo.Add(GL.GenBuffer) + GL.BindBuffer(BufferTarget.ElementArrayBuffer, nibo(i)) + GL.BufferData( + BufferTarget.ElementArrayBuffer, + CType(Len(New UInteger) * indices.Count, IntPtr), + indices.ToArray, + BufferUsageHint.StaticDraw) + + If .Material?.Image IsNot Nothing Then + If Not dicTextureIDs.ContainsKey(.Material.Image) Then + dicTextureIDs.Add(.Material.Image, ContentPipe.LoadTexture(.Material.Image)) + End If + ElseIf .Material?.Color IsNot Nothing Then + If Not dicColorIDs.ContainsKey(.Material.Color) Then + dicColorIDs.Add(.Material.Color, ContentPipe.LoadTexture(ColorToTexture(.Material.Color))) + End If + Else + If Not dicTextureIDs.ContainsKey(emptyTexture) Then + dicTextureIDs.Add(emptyTexture, ContentPipe.LoadTexture(emptyTexture)) + End If + End If + End With + Next + + Dim nvbo As Integer = GL.GenBuffer + VertexBuffers.Add(mesh, nvbo) + GL.BindBuffer(BufferTarget.ArrayBuffer, nvbo) + GL.BufferData( + BufferTarget.ArrayBuffer, + CType(Vector3.SizeInBytes * verts.Count, IntPtr), + verts.ToArray, + BufferUsageHint.StaticDraw + ) + + Dim ntbo As Integer = GL.GenBuffer + UVBuffers.Add(mesh, ntbo) + GL.BindBuffer(BufferTarget.ArrayBuffer, ntbo) + GL.BufferData( + BufferTarget.ArrayBuffer, + CType(Vector2.SizeInBytes * uvs.Count, IntPtr), + uvs.ToArray, + BufferUsageHint.StaticDraw + ) + + If enablecols Then + Dim ncbo As Integer = GL.GenBuffer + VertexColorBuffers.Add(mesh, ncbo) + GL.BindBuffer(BufferTarget.ArrayBuffer, ncbo) + GL.BufferData( + BufferTarget.ArrayBuffer, + CType(Vector4.SizeInBytes * cols.Count, IntPtr), + cols.ToArray, + BufferUsageHint.StaticDraw + ) + End If + + If enablenorms Then + Dim nnbo As Integer = GL.GenBuffer + NormalBuffers.Add(mesh, nnbo) + GL.BindBuffer(BufferTarget.ArrayBuffer, nnbo) + GL.BufferData( + BufferTarget.ArrayBuffer, + CType(Vector3.SizeInBytes * norms.Count, IntPtr), + norms.ToArray, + BufferUsageHint.StaticDraw + ) + End If + + Next + + If Not dicTextureIDs.ContainsKey(lineTexture) Then + dicTextureIDs.Add(lineTexture, ContentPipe.LoadTexture(lineTexture)) + End If + + _HasRendered = True + End Sub + + Public Sub DrawModel(mode As RenderMode) + DrawModel(mode, Vector3.Zero, Quaternion.Identity, New Vector3(ModelScaling, ModelScaling, ModelScaling)) + End Sub + Public Sub DrawModel(mode As RenderMode, pos As Vector3, rot As Quaternion) + DrawModel(mode, pos, rot, New Vector3(ModelScaling, ModelScaling, ModelScaling)) + End Sub + Public Sub DrawModel(mode As RenderMode, pos As Vector3, rot As Quaternion, scale As Vector3) + If mode = RenderMode.None Then Return + If Not _HasRendered Then Return + + GL.PushMatrix() + GL.Translate(pos.X, pos.Y, pos.Z) + GL.Rotate(rot.X, 1, 0, 0) + GL.Rotate(rot.Y, 0, 1, 0) + GL.Rotate(rot.Z, 0, 0, 1) + GL.Scale(scale) 'GL.Scale(scale.X, scale.Y, scale.Z) + GL.EnableClientState(ArrayCap.VertexArray) + GL.EnableClientState(ArrayCap.TextureCoordArray) + + For Each mesh As Mesh In obj3d.Meshes + If VertexColorBuffers.ContainsKey(mesh) Then + GL.EnableClientState(ArrayCap.ColorArray) + ElseIf NormalBuffers.ContainsKey(mesh) Then + GL.EnableClientState(ArrayCap.NormalArray) + End If + + GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBuffers(mesh)) + GL.VertexPointer(3, VertexPointerType.Float, 0, IntPtr.Zero) + + GL.BindBuffer(BufferTarget.ArrayBuffer, UVBuffers(mesh)) + GL.TexCoordPointer(2, TexCoordPointerType.Float, 0, IntPtr.Zero) + + If VertexColorBuffers.ContainsKey(mesh) Then + GL.BindBuffer(BufferTarget.ArrayBuffer, VertexColorBuffers(mesh)) + GL.ColorPointer(4, ColorPointerType.Float, 0, IntPtr.Zero) + ElseIf NormalBuffers.ContainsKey(mesh) Then + GL.BindBuffer(BufferTarget.ArrayBuffer, NormalBuffers(mesh)) + GL.NormalPointer(NormalPointerType.Float, 0, IntPtr.Zero) + End If + + For i As Integer = 0 To mesh.Faces.Count - 1 + Dim l As Face = mesh.Faces(i) + + GL.BindBuffer(BufferTarget.ElementArrayBuffer, IndicesBuffers(mesh)(i)) + + Dim texID As Integer + Dim isEmptyTexture As Boolean = l.Material?.Image Is Nothing + Dim isEmptyColor As Boolean = l.Material?.Color Is Nothing + + If (mode And RenderMode.Fill) = RenderMode.Fill Then + texID = If(isEmptyTexture, If(isEmptyColor, dicTextureIDs(emptyTexture), dicColorIDs(l.Material.Color)), dicTextureIDs(l.Material.Image)) + + GL.BindTexture(TextureTarget.Texture2D, texID) + + If Not isEmptyTexture Then + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, l.Material.Wrap.X) + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, l.Material.Wrap.Y) + End If + + GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill) + + GL.DrawElements(PrimitiveType.Triangles, l.Points.Count, + DrawElementsType.UnsignedInt, IntPtr.Zero) + + End If + + If (mode And RenderMode.Outline) = RenderMode.Outline Then + + If (mode And RenderMode.Fill) = RenderMode.Fill Then + texID = dicTextureIDs(lineTexture) + GL.BindTexture(TextureTarget.Texture2D, texID) + Else + texID = If(isEmptyTexture, If(isEmptyColor, dicTextureIDs(emptyTexture), dicColorIDs(l.Material.Color)), dicTextureIDs(l.Material.Image)) + GL.BindTexture(TextureTarget.Texture2D, texID) + + If Not isEmptyTexture Then + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, l.Material.Wrap.X) + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, l.Material.Wrap.Y) + End If + End If + + GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line) + + GL.DrawElements(PrimitiveType.Triangles, l.Points.Count, + DrawElementsType.UnsignedInt, IntPtr.Zero) + + End If + Next + + GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill) 'Reset for RenderEngineOld + + If VertexColorBuffers.ContainsKey(mesh) Then + GL.DisableClientState(ArrayCap.ColorArray) + ElseIf NormalBuffers.ContainsKey(mesh) Then + GL.DisableClientState(ArrayCap.NormalArray) + End If + Next + + GL.DisableClientState(ArrayCap.VertexArray) + GL.DisableClientState(ArrayCap.TextureCoordArray) + GL.PopMatrix() + End Sub + + Public Sub DrawFacePicking() + DrawFacePicking(Vector3.Zero, Quaternion.Identity, New Vector3(ModelScaling, ModelScaling, ModelScaling)) + End Sub + Public Sub DrawFacePicking(pos As Vector3, rot As Quaternion) + DrawFacePicking(pos, rot, New Vector3(ModelScaling, ModelScaling, ModelScaling)) + End Sub + Public Sub DrawFacePicking(pos As Vector3, rot As Quaternion, scale As Vector3) + If Not _HasRendered Then Return + + GL.PushMatrix() + GL.Translate(pos.X, pos.Y, pos.Z) + GL.Rotate(rot.X, 1, 0, 0) + GL.Rotate(rot.Y, 0, 1, 0) + GL.Rotate(rot.Z, 0, 0, 1) + GL.Scale(scale) + GL.EnableClientState(ArrayCap.VertexArray) + + For iMesh As Integer = 0 To obj3d.Meshes.Count - 1 + Dim mesh As Mesh = obj3d.Meshes(iMesh) + + GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBuffers(mesh)) + GL.VertexPointer(3, VertexPointerType.Float, 0, IntPtr.Zero) + + For iFace As Integer = 0 To mesh.Faces.Count - 1 + Dim l As Face = mesh.Faces(iFace) + + GL.BindBuffer(BufferTarget.ElementArrayBuffer, IndicesBuffers(mesh)(iFace)) + + GL.Color4(Color.FromArgb(&H20000000 + (iMesh << 16) + iFace)) 'Color: "2f ff xx xx" -> where 'f' = mesh index and where 'x' is face index + + GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill) + + GL.DrawElements(PrimitiveType.Triangles, l.Points.Count, + DrawElementsType.UnsignedInt, IntPtr.Zero) + Next + + GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill) + Next + + GL.DisableClientState(ArrayCap.VertexArray) + GL.PopMatrix() + End Sub + + Public Sub ReleaseBuffers() + If Not HasRendered Then Return + + For Each kvp As KeyValuePair(Of Mesh, Integer) In VertexBuffers + GL.DeleteBuffer(kvp.Value) + Next + VertexBuffers.Clear() + + For Each kvp As KeyValuePair(Of Mesh, Integer) In UVBuffers + GL.DeleteBuffer(kvp.Value) + Next + UVBuffers.Clear() + + For Each kvp As KeyValuePair(Of Mesh, Integer) In VertexColorBuffers + GL.DeleteBuffer(kvp.Value) + Next + VertexColorBuffers.Clear() + + For Each kvp As KeyValuePair(Of Mesh, Integer) In NormalBuffers + GL.DeleteBuffer(kvp.Value) + Next + NormalBuffers.Clear() + + For Each kvp As KeyValuePair(Of Mesh, List(Of Integer)) In IndicesBuffers + For Each i As Integer In kvp.Value + GL.DeleteBuffer(i) + Next + kvp.Value.Clear() + Next + IndicesBuffers.Clear() + + For Each kvp As KeyValuePair(Of Image, Integer) In dicTextureIDs + GL.DeleteBuffer(kvp.Value) + Next + dicTextureIDs.Clear() + + For Each kvp As KeyValuePair(Of Color, Integer) In dicColorIDs + GL.DeleteBuffer(kvp.Value) + Next + dicColorIDs.Clear() + + _HasRendered = False + End Sub + + Protected Overrides Sub Finalize() + 'ReleaseBuffers() + End Sub + + End Class + +End Namespace diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/app.config b/Pilz.Drawing.Drawing3D.OpenGLRenderer/app.config new file mode 100644 index 0000000..d4f722e --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Pilz.Drawing.Drawing3D.OpenGLRenderer/packages.config b/Pilz.Drawing.Drawing3D.OpenGLRenderer/packages.config new file mode 100644 index 0000000..d8280d7 --- /dev/null +++ b/Pilz.Drawing.Drawing3D.OpenGLRenderer/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Pilz.IO/ManagedPipes/ManagedPipeServer.vb b/Pilz.IO/ManagedPipes/ManagedPipeServer.vb index 9d50580..54222fe 100644 --- a/Pilz.IO/ManagedPipes/ManagedPipeServer.vb +++ b/Pilz.IO/ManagedPipes/ManagedPipeServer.vb @@ -4,8 +4,8 @@ Imports Pilz.Threading Public Class ManagedPipeServer : Inherits ManagedPipe - 'Pro Verbindung(sanfrage) wird ein Client-Objekt generiert, das den Datenaustausch dieser Verbindung abwickelt - Private _Clients As New List(Of ManagedPipeClient) + 'Pro Verbindung (Anfrage) wird ein Client-Objekt generiert, das den Datenaustausch dieser Verbindung abwickelt + Public ReadOnly Property Clients As New List(Of ManagedPipeClient) Private ReadOnly pipeName As String = "" Private ReadOnly maxNumbersOfServerInstances As Integer Private numberOfStartedServerInstances As Integer = 0 @@ -70,22 +70,16 @@ Public Class ManagedPipeServer : Inherits ManagedPipe OnStatusMessage(e) End Sub -#End Region '_Clients-Ereignisverarbeitung +#End Region Public Overrides Function SendAsnyc(bytes() As Byte) As Task Return Task.Run(Sub() Send(bytes)) End Function Public Overrides Sub Send(data As Byte()) - Console.WriteLine("Sending Data ...") - - 'OnRetriveData(New DataEventargs(data)) ' anzeigen - - For Each client As ManagedPipeClient In _Clients ' an alle versenden + For Each client As ManagedPipeClient In _Clients 'an alle versenden client.Send(data) Next - - Console.WriteLine("Data send!") End Sub Protected Overrides Sub Dispose(ByVal disposing As Boolean) diff --git a/Pilz.IO/Pilz.IO.vbproj b/Pilz.IO/Pilz.IO.vbproj index d70fe2d..bdc16cc 100644 --- a/Pilz.IO/Pilz.IO.vbproj +++ b/Pilz.IO/Pilz.IO.vbproj @@ -128,7 +128,7 @@ {d9c8655e-4f1c-4348-a51c-ab00fd9a14bb} - CrossThreads + Pilz.Threading diff --git a/Pilz.LicenseHelper/AsposeModifyInMemory.cs b/Pilz.LicenseHelper/AsposeModifyInMemory.cs new file mode 100644 index 0000000..ce93850 --- /dev/null +++ b/Pilz.LicenseHelper/AsposeModifyInMemory.cs @@ -0,0 +1,185 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Text; +using System.Xml; + +namespace Pilz.LicenseHelper +{ + public static class AsposeModifyInMemory + { + private static string AsposeList = "Aspose.3D.dll, Aspose.BarCode.dll, Aspose.BarCode.Compact.dll, Aspose.BarCode.WPF.dll, Aspose.Cells.GridDesktop.dll, Aspose.Cells.GridWeb.dll, Aspose.CAD.dll, Aspose.Cells.dll, Aspose.Diagram.dll, Aspose.Email.dll, Aspose.Imaging.dll, Aspose.Note.dll, Aspose.OCR.dll, Aspose.Pdf.dll, Aspose.Slides.dll, Aspose.Tasks.dll, Aspose.Words.dll"; + + public static void ActivateMemoryPatching() + { + Assembly[] arr = AppDomain.CurrentDomain.GetAssemblies(); + foreach (Assembly assembly in arr) + { + if (AsposeList.IndexOf(assembly.FullName.Split(',')[0] + ".dll") != -1) + ActivateForAssembly(assembly); + } + AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(ActivateOnLoad); + } + + private static void ActivateOnLoad(object sender, AssemblyLoadEventArgs e) + { + if (AsposeList.IndexOf(e.LoadedAssembly.FullName.Split(',')[0] + ".dll") != -1) + ActivateForAssembly(e.LoadedAssembly); + } + + private static void ActivateForAssembly(Assembly assembly) + { + MethodInfo miLicensed1 = typeof(AsposeModifyInMemory).GetMethod("InvokeMe1", BindingFlags.NonPublic | BindingFlags.Static); + MethodInfo miLicensed2 = typeof(AsposeModifyInMemory).GetMethod("InvokeMe2", BindingFlags.NonPublic | BindingFlags.Static); + MethodInfo miEvaluation = null; + + Dictionary miDict = new Dictionary() + { + {"System.DateTime" , miLicensed1}, + {"System.Xml.XmlElement", miLicensed2} + }; + + Type[] arrType = null; + bool isFound = false; + int nCount = 0; + + try + { + arrType = assembly.GetTypes(); + } + catch (ReflectionTypeLoadException err) + { + arrType = err.Types; + } + + + foreach (Type type in arrType) + { + if (isFound) break; + + if (type == null) continue; + + MethodInfo[] arrMInfo = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Static); + + foreach (MethodInfo info in arrMInfo) + { + if (isFound) break; + + try + { + string strMethod = info.ToString(); + if ((strMethod.IndexOf("(System.Xml.XmlElement, System.String)") > 0) && (miDict.ContainsKey(info.ReturnType.ToString()))) + { + miEvaluation = info; + MemoryPatching(miEvaluation, miDict[miEvaluation.ReturnType.ToString()]); + nCount++; + + if ((assembly.FullName.IndexOf("Aspose.3D") != -1) && (nCount == 2)) + { + isFound = true; + break; + } + } + } + catch + { + throw new InvalidOperationException("MemoryPatching for \"" + assembly.FullName + "\" failed !"); + } + } + } + + String[] aParts = assembly.FullName.Split(','); + string fName = aParts[0]; + if (fName.IndexOf("Aspose.BarCode.") != -1) + fName = "Aspose.BarCode"; + else if (fName.IndexOf("Aspose.3D") != -1) + fName = "Aspose.ThreeD"; + + try + { + Type type2 = assembly.GetType(fName + ".License"); + MethodInfo mi = type2.GetMethod("SetLicense", new Type[] { typeof(Stream) }); + string LData = "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPExpY2Vuc2U+CiAgPERhdGE+CiAgICA8TGljZW5zZWRUbz5MaWNlbnNlZTwvTGljZW5zZWRUbz4KICAgIDxFbWFpbFRvPmxpY2Vuc2VlQGVtYWlsLmNvbTwvRW1haWxUbz4KICAgIDxMaWNlbnNlVHlwZT5EZXZlbG9wZXIgT0VNPC9MaWNlbnNlVHlwZT4KICAgIDxMaWNlbnNlTm90ZT5MaW1pdGVkIHRvIDEwMDAgZGV2ZWxvcGVyLCB1bmxpbWl0ZWQgcGh5c2ljYWwgbG9jYXRpb25zPC9MaWNlbnNlTm90ZT4KICAgIDxPcmRlcklEPjc4NDM3ODU3Nzg1PC9PcmRlcklEPgogICAgPFVzZXJJRD4xMTk3ODkyNDM3OTwvVXNlcklEPgogICAgPE9FTT5UaGlzIGlzIGEgcmVkaXN0cmlidXRhYmxlIGxpY2Vuc2U8L09FTT4KICAgIDxQcm9kdWN0cz4KICAgICAgPFByb2R1Y3Q+QXNwb3NlLlRvdGFsIFByb2R1Y3QgRmFtaWx5PC9Qcm9kdWN0PgogICAgPC9Qcm9kdWN0cz4KICAgIDxFZGl0aW9uVHlwZT5FbnRlcnByaXNlPC9FZGl0aW9uVHlwZT4KICAgIDxTZXJpYWxOdW1iZXI+e0YyQjk3MDQ1LTFCMjktNEIzRi1CRDUzLTYwMUVGRkExNUFBOX08L1NlcmlhbE51bWJlcj4KICAgIDxTdWJzY3JpcHRpb25FeHBpcnk+MjA5OTEyMzE8L1N1YnNjcmlwdGlvbkV4cGlyeT4KICAgIDxMaWNlbnNlVmVyc2lvbj4zLjA8L0xpY2Vuc2VWZXJzaW9uPgogIDwvRGF0YT4KICA8U2lnbmF0dXJlPlFYTndiM05sTGxSdmRHRnNJRkJ5YjJSMVkzUWdSbUZ0YVd4NTwvU2lnbmF0dXJlPgo8L0xpY2Vuc2U+"; + Stream stream = new MemoryStream(Convert.FromBase64String(LData)); + stream.Seek(0, SeekOrigin.Begin); + mi.Invoke(Activator.CreateInstance(type2, null), new Stream[] { stream }); + } + catch + { + throw new InvalidOperationException("SetLicense for \"" + assembly.FullName + "\" failed !"); + } + + } + + + private static DateTime InvokeMe1(XmlElement element, string name) + { + return DateTime.MaxValue; + } + + + private static XmlElement InvokeMe2(XmlElement element, string name) + { + if (element.LocalName == "License") + { + string License64 = "PERhdGE+PExpY2Vuc2VkVG8+R3JvdXBEb2NzPC9MaWNlbnNlZFRvPjxMaWNlbnNlVHlwZT5TaXRlIE9FTTwvTGljZW5zZVR5cGU+PExpY2Vuc2VOb3RlPkxpbWl0ZWQgdG8gMTAgZGV2ZWxvcGVyczwvTGljZW5zZU5vdGU+PE9yZGVySUQ+MTMwNzI0MDQwODQ5PC9PcmRlcklEPjxPRU0+VGhpcyBpcyBhIHJlZGlzdHJpYnV0YWJsZSBsaWNlbnNlPC9PRU0+PFByb2R1Y3RzPjxQcm9kdWN0PkFzcG9zZS5Ub3RhbDwvUHJvZHVjdD48L1Byb2R1Y3RzPjxFZGl0aW9uVHlwZT5FbnRlcnByaXNlPC9FZGl0aW9uVHlwZT48U2VyaWFsTnVtYmVyPjliNTc5NTAxLTUyNjEtNDIyMC04NjcwLWZjMmQ4Y2NkZDkwYzwvU2VyaWFsTnVtYmVyPjxTdWJzY3JpcHRpb25FeHBpcnk+MjAxNDA3MjQ8L1N1YnNjcmlwdGlvbkV4cGlyeT48TGljZW5zZVZlcnNpb24+Mi4yPC9MaWNlbnNlVmVyc2lvbj48L0RhdGE+PFNpZ25hdHVyZT5udFpocmRoL3I0QS81ZFpsU2dWYnhac0hYSFBxSjZ5UVVYa0RvaW4vS2lVZWhUUWZET0lQdHdzUlR2NmRTUVplOVdXekNnV3RGdkdROWpmR2QySmF4YUQvbkx1ZEk2R0VVajhqeVhUMG4vbWRrMEF1WVZNYlBXRjJYd3dSTnFlTmRrblYyQjhrZVFwbDJ2RzZVbnhxS2J6VVFxS2Rhc1pzZ2w1Q0xqSFVEWms9PC9TaWduYXR1cmU+"; + element.InnerXml = new UTF8Encoding().GetString(Convert.FromBase64String(License64)); + } + + if (element.LocalName == "BlackList") + { + string BlackList64 = "PERhdGE+PC9EYXRhPjxTaWduYXR1cmU+cUJwMEx1cEVoM1ZnOWJjeS8vbUVXUk9KRWZmczRlY25iTHQxYlNhanU2NjY5RHlad09FakJ1eEdBdVBxS1hyd0x5bmZ5VWplYUNGQ0QxSkh2RVUxVUl5eXJOTnBSMXc2NXJIOUFyUCtFbE1lVCtIQkZ4NFMzckFVMnd6dkxPZnhGeU9DQ0dGQ2UraTdiSHlGQk44WHp6R1UwdGRPMGR1RTFoRTQ5M1RNY3pRPTwvU2lnbmF0dXJlPg=="; + element.InnerXml = new UTF8Encoding().GetString(Convert.FromBase64String(BlackList64)); + } + + XmlNodeList elementsByTagName = element.GetElementsByTagName(name); + if (elementsByTagName.Count <= 0) + { + return null; + } + + return (XmlElement)elementsByTagName[0]; + } + + + private static unsafe void MemoryPatching(MethodBase miEvaluation, MethodBase miLicensed) + { + IntPtr IntPtrEval = GetMemoryAddress(miEvaluation); + IntPtr IntPtrLicensed = GetMemoryAddress(miLicensed); + + if (IntPtr.Size == 8) + *((long*)IntPtrEval.ToPointer()) = *((long*)IntPtrLicensed.ToPointer()); + else + *((int*)IntPtrEval.ToPointer()) = *((int*)IntPtrLicensed.ToPointer()); + + } + + + private static unsafe IntPtr GetMemoryAddress(MethodBase mb) + { + RuntimeHelpers.PrepareMethod(mb.MethodHandle); + + if ((Environment.Version.Major >= 4) || ((Environment.Version.Major == 2) && (Environment.Version.MinorRevision >= 3053))) + { + return new IntPtr(((int*)mb.MethodHandle.Value.ToPointer() + 2)); + } + + UInt64* location = (UInt64*)(mb.MethodHandle.Value.ToPointer()); + int index = (int)(((*location) >> 32) & 0xFF); + if (IntPtr.Size == 8) + { + ulong* classStart = (ulong*)mb.DeclaringType.TypeHandle.Value.ToPointer(); + ulong* address = classStart + index + 10; + return new IntPtr(address); + } + else + { + uint* classStart = (uint*)mb.DeclaringType.TypeHandle.Value.ToPointer(); + uint* address = classStart + index + 10; + return new IntPtr(address); + } + } + } +} diff --git a/Pilz.LicenseHelper/Pilz.LicenseHelper.csproj b/Pilz.LicenseHelper/Pilz.LicenseHelper.csproj new file mode 100644 index 0000000..bd103e8 --- /dev/null +++ b/Pilz.LicenseHelper/Pilz.LicenseHelper.csproj @@ -0,0 +1,49 @@ + + + + + Debug + AnyCPU + {67593FF7-C1D1-4529-98C4-61CBD0615F08} + Library + Properties + Pilz.LicenseHelper + Pilz.LicenseHelper + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Pilz.LicenseHelper/Properties/AssemblyInfo.cs b/Pilz.LicenseHelper/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..0d2d071 --- /dev/null +++ b/Pilz.LicenseHelper/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die einer Assembly zugeordnet sind. +[assembly: AssemblyTitle("LicenseHelper")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("DRSN")] +[assembly: AssemblyProduct("LicenseHelper")] +[assembly: AssemblyCopyright("Copyright © DRSN 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly +// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von +// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("67593ff7-c1d1-4529-98c4-61cbd0615f08")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, +// indem Sie "*" wie unten gezeigt eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Pilz.Simple3DFileParser/App.config b/Pilz.Simple3DFileParser/App.config new file mode 100644 index 0000000..bc3672d --- /dev/null +++ b/Pilz.Simple3DFileParser/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Pilz.Simple3DFileParser/FileParser/Aspose3DLoader.vb b/Pilz.Simple3DFileParser/FileParser/Aspose3DLoader.vb new file mode 100644 index 0000000..67806f0 --- /dev/null +++ b/Pilz.Simple3DFileParser/FileParser/Aspose3DLoader.vb @@ -0,0 +1,250 @@ +Imports System.Globalization +Imports System.IO +Imports System.Threading +Imports Aspose.ThreeD +Imports Aspose.ThreeD.Entities +Imports Aspose.ThreeD.Formats +Imports Aspose.ThreeD.Shading +Imports Aspose.ThreeD.Utilities + +Namespace Aspose3DModule + + Public Class Aspose3DLoader + + Private Shared hasActivatedMemoryPatching As Boolean = False + + Private Shared Sub ActivateMemoryPatching() + If Not hasActivatedMemoryPatching Then + LicenseHelper.AsposeModifyInMemory.ActivateMemoryPatching() + hasActivatedMemoryPatching = True + End If + End Sub + + Public Shared Function FromFile(fileName As String, LoadMaterials As Boolean, UpAxis As UpAxis) As Object3D + ActivateMemoryPatching() + + 'Create new Model + Dim obj3d As New Object3D + + 'Create new temporary CultureInfo + Dim curThread As Thread = Thread.CurrentThread + Dim curCultInfo As CultureInfo = curThread.CurrentCulture + Dim newCultInfo As New CultureInfo(curCultInfo.Name) + newCultInfo.NumberFormat.NumberDecimalSeparator = "." + newCultInfo.NumberFormat.PercentDecimalSeparator = "." + newCultInfo.NumberFormat.CurrencyDecimalSeparator = "." + newCultInfo.NumberFormat.NumberGroupSeparator = "," + newCultInfo.NumberFormat.PercentGroupSeparator = "," + newCultInfo.NumberFormat.CurrencyGroupSeparator = "," + curThread.CurrentCulture = newCultInfo + + 'Load Model from file + Dim scene As New Scene(fileName) + + 'Reset Cultur-Info + curThread.CurrentCulture = curCultInfo + + 'Triangulate the Model + PolygonModifier.Triangulate(scene) + + 'Create Dictionary for Materials + Dim dicMaterials As New Dictionary(Of Aspose.ThreeD.Shading.Material, Material) + + 'Create List of all avaiable Map-States + Dim MapNames As String() = {Aspose.ThreeD.Shading.Material.MapDiffuse, Aspose.ThreeD.Shading.Material.MapAmbient, Aspose.ThreeD.Shading.Material.MapSpecular, Aspose.ThreeD.Shading.Material.MapEmissive, Aspose.ThreeD.Shading.Material.MapNormal} + Dim ColorNames As String() = {"DiffuseColor", "AmbientColor", "SpecularColor", "EmissiveColor"} + + For Each node As Node In scene.RootNode.ChildNodes + + 'Add new Materials, if not added + For Each mat As Aspose.ThreeD.Shading.Material In node.Materials + If Not dicMaterials.ContainsKey(mat) Then + + 'Create new Material + Dim newMat As New Material + + 'Get TextureBase + Dim texBase As TextureBase = Nothing + Dim curmnindex As Byte = 0 + Do While texBase Is Nothing AndAlso curmnindex < MapNames.Length + texBase = mat.GetTexture(MapNames(curmnindex)) + curmnindex += 1 + Loop + + If texBase IsNot Nothing Then + If LoadMaterials Then + 'Get Texture Image + Dim imgFile As String = texBase.GetPropertyValue("FileName") + imgFile = imgFile.Replace("/", "\") + + 'Load and set Image + If imgFile <> "" Then + Dim fs As New FileStream(imgFile, FileMode.Open, FileAccess.Read) + newMat.Image = Image.FromStream(fs) + fs.Close() + End If + End If + End If + + 'Get Texture Color + Dim texcol As Vector3? = Nothing + Dim curcnindex As Byte = 0 + Do While texcol Is Nothing AndAlso curcnindex < ColorNames.Length + texcol = mat.GetPropertyValue(ColorNames(curcnindex)) + curcnindex += 1 + Loop + + If texcol IsNot Nothing Then + newMat.Color = Color.FromArgb(texcol?.x, texcol?.y, texcol?.z) + End If + + 'Add Material to Object3D + obj3d.Materials.Add(mat.Name, newMat) + + 'Add Dictionary-Entry + dicMaterials.Add(mat, newMat) + + End If + Next + + 'Get Aspose-Mesh + Dim curMesh As Entities.Mesh = node.GetEntity(Of Entities.Mesh) + + If curMesh IsNot Nothing Then + + 'Create new Mesh + Dim newMesh As New Mesh + + 'Create Vertices + For Each vert As Vector4 In curMesh.ControlPoints + 'Create new Vertex + Dim newVert As New Vertex + + 'Set Vertex Data + newVert.X = vert.x + newVert.Y = vert.y + newVert.Z = vert.z + + 'Add new Vertex + newMesh.Vertices.Add(newVert) + Next + + 'Create Normals + Dim veNormals As VertexElementNormal = curMesh.GetElement(VertexElementType.Normal) + If veNormals IsNot Nothing Then + For Each n As Vector4 In veNormals.Data + 'Create new Normal + Dim newNormal As New Normal + + 'Set Normal Data + newNormal.X = n.x + newNormal.Y = n.y + newNormal.Z = n.z + + 'Add new Normal + newMesh.Normals.Add(newNormal) + Next + End If + + 'Create Normals + Dim veUVs As VertexElementUV = curMesh.GetElement(VertexElementType.UV) + If veUVs IsNot Nothing Then + For Each uv As Vector4 In veUVs.Data + 'Create new UV + Dim newUV As New UV + + 'Set UV Data + newUV.U = uv.x + newUV.V = uv.y + + 'Add new UV + newMesh.UVs.Add(newUV) + Next + End If + + 'Create Normals + Dim veVertexColor As VertexElementVertexColor = curMesh.GetElement(VertexElementType.VertexColor) + If veVertexColor IsNot Nothing Then + For Each n As Vector4 In veVertexColor.Data + 'Create new Normal + Dim newVC As New VertexColor + + 'Set Normal Data + newVC.R = n.x + newVC.G = n.y + newVC.B = n.z + newVC.A = n.w + + 'Add new Normal + newMesh.VertexColors.Add(newVC) + Next + End If + + 'Get Material-Indicies + Dim veMaterials As VertexElementMaterial = curMesh.GetElement(VertexElementType.Material) + + 'Definde Index for VertexElement.Indicies + Dim veIndex As Integer = 0 + + 'Build Polygones + For iPoly = 0 To curMesh.Polygons.Count - 1 + 'Get current Polygon + Dim poly As Integer() = curMesh.Polygons(iPoly) + + 'Create new Face + Dim f As New Face + + 'Set Texture, if avaiable + If veMaterials IsNot Nothing Then + f.Material = dicMaterials(node.Materials(veMaterials.Indices(iPoly))) + ElseIf node.Material IsNot Nothing Then + f.Material = dicMaterials(node.Material) + End If + + For Each index As Integer In poly + 'Create new Point + Dim p As New Point + + 'Set Vertex + p.Vertex = newMesh.Vertices(index) + + 'Set Normal + If veNormals IsNot Nothing Then + p.Normal = newMesh.Normals(veNormals.Indices(veIndex)) + End If + + 'Set UV + If veUVs IsNot Nothing Then + p.UV = newMesh.UVs(veUVs.Indices(veIndex)) + End If + + 'Set Vertex Color + If veVertexColor IsNot Nothing Then + p.VertexColor = newMesh.VertexColors(veVertexColor.Indices(veIndex)) + End If + + 'Add new Point + f.Points.Add(p) + + 'Increment VertexElementIndicies-Index + veIndex += 1 + Next + + 'Add new Face + newMesh.Faces.Add(f) + Next + + 'Add new Mesh + obj3d.Meshes.Add(newMesh) + + End If + + Next + + 'Return the new Object3D + Return obj3d + End Function + + End Class + +End Namespace diff --git a/Pilz.Simple3DFileParser/FileParser/AssimpLoader.vb b/Pilz.Simple3DFileParser/FileParser/AssimpLoader.vb new file mode 100644 index 0000000..f5df5f5 --- /dev/null +++ b/Pilz.Simple3DFileParser/FileParser/AssimpLoader.vb @@ -0,0 +1,391 @@ +Imports System.IO +Imports Assimp +Imports Assimp.Unmanaged + +Namespace AssimpModule + + Public Class AssimpLoader + + Public Shared PathToAssimpLib32 As String = "Assimp32.dll" + Public Shared PathToAssimpLib64 As String = "Assimp64.dll" + + Friend Shared Sub LoadAssimpLibs() + If Not AssimpLibrary.Instance.IsLibraryLoaded Then + AssimpLibrary.Instance.LoadLibrary(PathToAssimpLib32, PathToAssimpLib64) + End If + End Sub + + Public Shared Function FromFile(fileName As String, LoadMaterials As Boolean, UpAxis As UpAxis) As Object3D + Dim LoadedImages As New Dictionary(Of String, Image) + Dim newObj As New Object3D + Dim daeMdl As Scene = Nothing + Dim ac As New AssimpContext + Dim channelIndicies As New Dictionary(Of Material, Integer) + + daeMdl = ac.ImportFile(fileName, PostProcessPreset.TargetRealTimeMaximumQuality Or PostProcessSteps.Triangulate) + + For Each et As EmbeddedTexture In daeMdl.Textures + If et.HasCompressedData Then + Dim newMat As New Material + + Dim ms As New MemoryStream(et.CompressedData) + newMat.Image = Image.FromStream(ms) + ms.Close() + + newObj.Materials.Add("tex_" & daeMdl.Textures.IndexOf(et), newMat) + End If + Next + + For Each mat As Assimp.Material In daeMdl.Materials + Dim newMat As New Material + Dim texSlot As TextureSlot? = Nothing + Dim col4d As Color4D? = Nothing + + newMat.Opacity = mat.Opacity + + Select Case True + Case mat.HasTextureNormal + texSlot = mat.TextureNormal + Case mat.HasTextureDiffuse + texSlot = mat.TextureDiffuse + Case mat.HasTextureAmbient + texSlot = mat.TextureAmbient + Case mat.HasTextureSpecular + texSlot = mat.TextureSpecular + End Select + + Select Case True + Case mat.HasColorDiffuse + col4d = mat.ColorDiffuse + Case mat.HasColorAmbient + col4d = mat.ColorAmbient + Case mat.HasColorSpecular + col4d = mat.ColorSpecular + End Select + + If texSlot IsNot Nothing Then + Dim filePath As String = texSlot.Value.FilePath + + If LoadMaterials Then + If filePath <> "" Then + Dim combiPath As String = Path.Combine(Path.GetDirectoryName(fileName), filePath) + If File.Exists(combiPath) Then + newMat.Image = LoadImage(combiPath, LoadedImages) + ElseIf File.Exists(filePath) Then + newMat.Image = LoadImage(filePath, LoadedImages) + End If + ElseIf texSlot.Value.TextureIndex > -1 AndAlso daeMdl.Textures.Count > texSlot.Value.TextureIndex Then + Dim et As EmbeddedTexture = daeMdl.Textures(texSlot.Value.TextureIndex) + If et.HasCompressedData Then + Dim ms As New MemoryStream(et.CompressedData) + newMat.Image = Image.FromStream(ms) + ms.Close() + End If + End If + End If + + channelIndicies.Add(newMat, texSlot.Value.UVIndex) + End If + + If col4d IsNot Nothing Then + newMat.Color = Color.FromArgb(col4d.Value.R * 255, col4d.Value.G * 255, col4d.Value.B * 255) + End If + + newObj.Materials.Add(mat.Name, newMat) + Next + + Dim newMesh As New Mesh + newObj.Meshes.Add(newMesh) + + Dim dicVertices As New Dictionary(Of Vector3D, Vertex) + Dim dicNormals As New Dictionary(Of Vector3D, Normal) + Dim dicUVs As New Dictionary(Of Vector3D, UV) + Dim dicVertexColors As New Dictionary(Of Color4D, VertexColor) + + For Each m As Assimp.Mesh In daeMdl.Meshes + Dim curMat As Material + If m.MaterialIndex > -1 AndAlso newObj.Materials.Count > m.MaterialIndex Then + curMat = newObj.Materials.ElementAt(m.MaterialIndex).Value + Else + curMat = Nothing + End If + + For Each n As Vector3D In m.Normals + If Not dicNormals.ContainsKey(n) Then + Dim newNormal As New Normal + + Select Case UpAxis + Case UpAxis.Y + newNormal.X = n.X + newNormal.Y = n.Y + newNormal.Z = n.Z + Case UpAxis.Z + newNormal.X = n.Y + newNormal.Y = n.Z + newNormal.Z = n.X + End Select + + newMesh.Normals.Add(newNormal) + dicNormals.Add(n, newNormal) + End If + Next + + For Each v As Vector3D In m.Vertices + If Not dicVertices.ContainsKey(v) Then + Dim newVert As New Vertex + + Select Case UpAxis + Case UpAxis.Y + newVert.X = v.X + newVert.Y = v.Y + newVert.Z = v.Z + Case UpAxis.Z + newVert.X = v.Y + newVert.Y = v.Z + newVert.Z = v.X + End Select + + newMesh.Vertices.Add(newVert) + dicVertices.Add(v, newVert) + End If + Next + + For Each uvList As List(Of Vector3D) In m.TextureCoordinateChannels + For Each uv As Vector3D In uvList + If Not dicUVs.ContainsKey(uv) Then + Dim newUV As New UV + + newUV.U = uv.X + newUV.V = uv.Y + + newMesh.UVs.Add(newUV) + dicUVs.Add(uv, newUV) + End If + Next + Next + + For Each vcList As List(Of Color4D) In m.VertexColorChannels + For Each vc As Color4D In vcList + If Not dicVertexColors.ContainsKey(vc) Then + Dim newVC As New VertexColor + + newVC.R = vc.R + newVC.G = vc.G + newVC.B = vc.B + newVC.A = vc.A + + newMesh.VertexColors.Add(newVC) + dicVertexColors.Add(vc, newVC) + End If + Next + Next + + For Each f As Assimp.Face In m.Faces + If f.HasIndices Then + Dim newFace As New Face With {.Material = curMat} + + For Each index As Integer In f.Indices + If index > -1 Then + Dim newPoint As New Point + + If m.HasVertices Then + newPoint.Vertex = dicVertices(m.Vertices(index)) + End If + + If m.HasNormals Then + newPoint.Normal = dicNormals(m.Normals(index)) + End If + + If curMat IsNot Nothing AndAlso channelIndicies.ContainsKey(curMat) Then + Dim tkey As Integer = channelIndicies(curMat) + + If m.HasTextureCoords(tkey) Then + newPoint.UV = dicUVs(m.TextureCoordinateChannels(tkey)(index)) + End If + + If m.HasVertexColors(tkey) Then + newPoint.VertexColor = dicVertexColors(m.VertexColorChannels(tkey)(index)) + End If + End If + + newFace.Points.Add(newPoint) + End If + Next + + If newFace.Points.Count = 3 Then + newMesh.Faces.Add(newFace) + End If + End If + Next + Next + + Return newObj + End Function + + Public Shared Sub ToFile(fileName As String, obj As Object3D) + Dim mdl As New Scene + Dim dicMatIndex As New Dictionary(Of Material, Integer) + + Dim texDir As String = "" + If obj.Materials.Count > 0 Then + texDir = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName)) + If Not Directory.Exists(texDir) Then + Directory.CreateDirectory(texDir) + End If + End If + + For Each kvp As KeyValuePair(Of String, Material) In obj.Materials + Dim mat As New Assimp.Material + + mat.Name = If(kvp.Key <> "", kvp.Key, "_" & mdl.Materials.Count) + mat.Opacity = mat.Opacity + + Dim texslot As New TextureSlot + texslot.TextureIndex = mdl.Textures.Count + texslot.TextureType = TextureType.Diffuse + texslot.UVIndex = 0 + + Dim ms As New MemoryStream + kvp.Value.Image.Save(ms, Imaging.ImageFormat.Png) + 'Dim tex As New EmbeddedTexture("png", ms.GetBuffer) + ms.Close() + + If kvp.Value.Image IsNot Nothing Then + texslot.FilePath = Path.Combine(texDir, mat.Name & ".png") + File.WriteAllBytes(texslot.FilePath, ms.GetBuffer) + End If + + 'mdl.Textures.Add(tex) + mat.AddMaterialTexture(texslot) + mdl.Materials.Add(mat) + + If kvp.Value.Color IsNot Nothing Then + With kvp.Value.Color.Value + mat.ColorDiffuse = New Color4D(.R / 255, .G / 255, .B / 255, 1) + End With + End If + + dicMatIndex.Add(kvp.Value, mdl.Materials.Count - 1) + Next + + Dim dicTexMesh As New Dictionary(Of Material, Assimp.Mesh) + Dim dicMeshDicVertIndex As New Dictionary(Of Assimp.Mesh, Dictionary(Of Vertex, Integer)) + Dim dicCounter As New Dictionary(Of Assimp.Mesh, Integer) + + For Each mesh As Mesh In obj.Meshes + For Each f As Face In mesh.Faces + Dim m As Assimp.Mesh + + If dicTexMesh.ContainsKey(f.Material) Then + m = dicTexMesh(f.Material) + Else + m = New Assimp.Mesh("Mesh_" & mdl.MeshCount + 1) + m.PrimitiveType = PrimitiveType.Triangle + If dicMatIndex.ContainsKey(f.Material) Then + m.MaterialIndex = dicMatIndex(f.Material) + End If + mdl.Meshes.Add(m) + dicTexMesh.Add(f.Material, m) + dicMeshDicVertIndex.Add(m, New Dictionary(Of Vertex, Integer)) + dicCounter.Add(m, 0) + End If + + Dim newFace As New Assimp.Face + + For Each p As Point In f.Points + newFace.Indices.Add(dicCounter(m)) + + If p.Vertex IsNot Nothing Then + Dim vert As New Vector3D + vert.X = p.Vertex.X + vert.Y = p.Vertex.Y + vert.Z = p.Vertex.Z + m.Vertices.Add(vert) + Else + m.Vertices.Add(New Vector3D(0, 0, 0)) + End If + + If p.Normal IsNot Nothing Then + Dim norm As New Vector3D + norm.X = p.Normal.X + norm.Y = p.Normal.Y + norm.Z = p.Normal.Z + m.Normals.Add(norm) + Else + m.Normals.Add(New Vector3D(0, 0, 0)) + End If + + 'If p.UV IsNot Nothing Then + ' Dim uv As New Vector3D + ' uv.X = p.UV.U + ' uv.Y = p.UV.V + ' m.TextureCoordinateChannels(0).Add(uv) + 'Else + ' m.TextureCoordinateChannels(0).Add(New Vector3D(0, 0, 0)) + 'End If + + 'If p.VertexColor IsNot Nothing Then + ' Dim vc As New Color4D + ' vc.R = p.VertexColor.R + ' vc.G = p.VertexColor.G + ' vc.B = p.VertexColor.B + ' vc.A = p.VertexColor.A + ' m.VertexColorChannels(0).Add(vc) + 'Else + ' m.VertexColorChannels(0).Add(New Color4D(0, 0, 0, 0)) + 'End If + + dicCounter(m) += 1 + Next + + m.Faces.Add(newFace) + Next + Next + + 'Add Root Node + mdl.RootNode = New Node(Path.GetFileName(fileName)) + + 'Add Mesh Indicies + For i As Integer = 0 To mdl.MeshCount - 1 + mdl.RootNode.MeshIndices.Add(i) + Next + + Dim ac As New AssimpContext + + Dim formatID As String = "" + Dim myExt As String = Path.GetExtension(fileName).ToLower.Substring(1) + For Each efd As ExportFormatDescription In ac.GetSupportedExportFormats + If myExt = efd.FileExtension Then + formatID = efd.FormatId + Exit For + End If + Next + + ac.ExportFile(mdl, fileName, formatID) + End Sub + + Private Shared Function LoadImage(fileName As String, loadedImages As Dictionary(Of String, Image)) As Image + If File.Exists(fileName) Then + If loadedImages.ContainsKey(fileName) Then + Return loadedImages(fileName) + Else + Dim fs As New FileStream(fileName, FileMode.Open, FileAccess.Read) + Dim img As Image = Image.FromStream(fs) + fs.Close() + + For Each kvp In loadedImages + If IsTheSameAs(img, kvp.Value) Then + Return kvp.Value + End If + Next + + loadedImages.Add(fileName, img) + Return img + End If + End If + Return Nothing + End Function + + End Class + +End Namespace diff --git a/Pilz.Simple3DFileParser/FileParser/Obj.vb b/Pilz.Simple3DFileParser/FileParser/Obj.vb new file mode 100644 index 0000000..bb28d11 --- /dev/null +++ b/Pilz.Simple3DFileParser/FileParser/Obj.vb @@ -0,0 +1,391 @@ +Imports System.Globalization +Imports System.IO +Imports System.Threading +Imports Pilz.S3DFileParser.Exceptions + +Namespace ObjModule + + Public Class ObjFile + + Public Shared Function FromFile(FileName As String, LoadMaterials As Boolean, UpAxis As UpAxis) As Object3D + Dim curThread As Thread = Thread.CurrentThread + Dim curCultInfo As CultureInfo = curThread.CurrentCulture + Dim newCultInfo As New CultureInfo(curCultInfo.Name) + newCultInfo.NumberFormat.NumberDecimalSeparator = "." + newCultInfo.NumberFormat.PercentDecimalSeparator = "." + newCultInfo.NumberFormat.CurrencyDecimalSeparator = "." + newCultInfo.NumberFormat.NumberGroupSeparator = "," + newCultInfo.NumberFormat.PercentGroupSeparator = "," + newCultInfo.NumberFormat.CurrencyGroupSeparator = "," + curThread.CurrentCulture = newCultInfo + + Dim newObj As New Object3D + Dim newMesh As New Mesh + Dim curObjPath As String = Path.GetDirectoryName(FileName) + + Dim mtllibs As New Dictionary(Of String, MaterialLib) + + Dim curMaterialLib As MaterialLib = Nothing + Dim curMaterial As Material = Nothing + + Dim srObj As New StreamReader(FileName, Text.Encoding.ASCII) + Dim line As String = "" + + Do Until srObj.EndOfStream + line = srObj.ReadLine.Trim + + If line <> "" Then + + Select Case True + Case line.StartsWith("mtllib ") + Dim name As String = line.Substring(7) + + If Not mtllibs.ContainsKey(name) Then + Dim mtlfile As String = Path.Combine(curObjPath, name) + If Not File.Exists(mtlfile) Then Throw New MaterialException("Material Library not found!") + + Dim newmtl As New MaterialLib + newmtl.FromFile(mtlfile, LoadMaterials) + mtllibs.Add(name, newmtl) + curMaterialLib = newmtl + + For Each kvp As KeyValuePair(Of String, Material) In curMaterialLib.Materials + If Not newObj.Materials.ContainsKey(kvp.Key) Then newObj.Materials.Add(kvp.Key, kvp.Value) + Next + Else + curMaterialLib = mtllibs(name) + End If + + Case line.StartsWith("usemtl ") + curMaterial = curMaterialLib.Materials(line.Substring(7)) + + Case line.StartsWith("v ") + If line.Contains("nan") Then line = line.Replace("nan", "0") + Dim splitXYZ() As String = line.Substring(2).Split(" "c) + + Dim tX As Double = Convert.ToDouble(splitXYZ(0)) + Dim tY As Double = Convert.ToDouble(splitXYZ(1)) + Dim tZ As Double = Convert.ToDouble(splitXYZ(2)) + + Dim v As New Vertex + Select Case UpAxis + Case UpAxis.Y + v.X = tX + v.Y = tY + v.Z = tZ + Case UpAxis.Z + v.X = tY + v.Y = tZ + v.Z = tX + End Select + newMesh.Vertices.Add(v) + + Case line.StartsWith("vt ") + Dim uvstr() As String = line.Substring(3).Split(" "c) + Dim uv As New UV With { + .U = Convert.ToSingle(uvstr(0)), + .V = Convert.ToSingle(uvstr(1))} + newMesh.UVs.Add(uv) + + Case line.StartsWith("vn ") + Dim splitXYZ() As String = line.Substring(3).Split(" "c) + + Dim tX As Single = Convert.ToSingle(splitXYZ(0)) + Dim tY As Single = Convert.ToSingle(splitXYZ(1)) + Dim tZ As Single = Convert.ToSingle(splitXYZ(2)) + + Dim n As New Normal + Select Case UpAxis + Case UpAxis.Y + n.X = tX + n.Y = tY + n.Z = tZ + Case UpAxis.Z + n.X = tZ + n.Y = tY + n.Z = tX + End Select + newMesh.Normals.Add(n) + + Case line.StartsWith("vc ") + Dim splitRGB() As String = line.Substring(3).Split(" "c) + + Dim tX As Single = Convert.ToSingle(splitRGB(0)) + Dim tY As Single = Convert.ToSingle(splitRGB(1)) + Dim tZ As Single = Convert.ToSingle(splitRGB(2)) + + Dim vc As New VertexColor + Select Case UpAxis + Case UpAxis.Y + vc.R = tX + vc.G = tY + vc.B = tZ + Case UpAxis.Z + vc.R = tY + vc.G = tZ + vc.B = tX + End Select + newMesh.VertexColors.Add(vc) + + Case line.StartsWith("f ") + Dim tri As New Face With {.Material = curMaterial} + + For Each xyz As String In line.Substring(2).Split(" "c) + xyz = xyz.Trim + If xyz = "" Then Continue For + + Dim splitsub() As String = Nothing + Dim p As New Point + + Select Case True + Case xyz.Contains("/") + splitsub = xyz.Split("/"c) + Case xyz.Contains("\") + splitsub = xyz.Split("\"c) + Case Else + splitsub = {0, 0, 0} + End Select + + Dim v1 As String = splitsub(0) + Dim v2 As String = splitsub(1) + Dim v3 As String = splitsub(2) + + If v1 <> "" Then + p.Vertex = newMesh.Vertices(Convert.ToInt32(v1) - 1) + End If + + If v2 <> "" Then + p.UV = newMesh.UVs(Convert.ToInt32(v2) - 1) + Else + Dim newUV As New UV With {.U = 0, .V = 0} + p.UV = newUV + newMesh.UVs.Add(newUV) + End If + + If v3 <> "" Then + p.Normal = newMesh.Normals(Convert.ToInt32(v3) - 1) + End If + + If splitsub.Count > 3 Then + Dim v4 As String = splitsub(3) + If v4 <> "" Then p.VertexColor = newMesh.VertexColors(Convert.ToInt32(v4) - 1) + End If + + tri.Points.Add(p) + Next + + newMesh.Faces.Add(tri) + + End Select + + End If + + Loop + newObj.Meshes.Add(newMesh) + + curThread.CurrentCulture = curCultInfo + + srObj.Close() + Return newObj + End Function + + Public Shared Sub ToFile(FileName As String, obj As Object3D) + Dim fs As New FileStream(FileName, FileMode.Create, FileAccess.ReadWrite) + Dim sw As New StreamWriter(fs, Text.Encoding.ASCII) + + If obj.Materials.Count > 0 Then + Dim mtlName As String = Path.GetFileNameWithoutExtension(FileName) & ".mtl" + Dim mtlFile As String = Path.Combine(Path.GetDirectoryName(FileName), mtlName) + sw.WriteLine($"mtllib {mtlName}") + MaterialLib.ToFile(mtlFile, obj) + End If + + Dim curVertCount As Integer = 1 + Dim curUVCount As Integer = 1 + Dim curNormCount As Integer = 1 + Dim curVertColCount As Integer = 1 + + For Each m As Mesh In obj.Meshes + + For Each vert As Vertex In m.Vertices + sw.WriteLine($"v {vert.X.ToString.Replace(",", ".")} {vert.Y.ToString.Replace(",", ".")} {vert.Z.ToString.Replace(",", ".")}") + Next + + For Each uv As UV In m.UVs + sw.WriteLine($"vt {uv.U.ToString.Replace(",", ".")} {uv.V.ToString.Replace(",", ".")}") + Next + + For Each norm As Normal In m.Normals + sw.WriteLine($"vn {norm.X.ToString.Replace(",", ".")} {norm.Y.ToString.Replace(",", ".")} {norm.Z.ToString.Replace(",", ".")}") + Next + + For Each vertcol As VertexColor In m.VertexColors + sw.WriteLine($"vc {vertcol.R.ToString.Replace(",", ".")} {vertcol.G.ToString.Replace(",", ".")} {vertcol.B.ToString.Replace(",", ".")}") + Next + + Dim curMtl As Material = Nothing + + For Each f As Face In m.Faces + If curMtl IsNot f.Material Then + curMtl = f.Material + sw.WriteLine($"usemtl _{GetIndexOfMaterialInList(obj, curMtl)}") + End If + + sw.Write("f") + + For Each p As Point In f.Points + sw.Write(" ") + sw.Write(curVertCount + m.Vertices.IndexOf(p.Vertex)) + + sw.Write("/") + If p.UV IsNot Nothing Then sw.Write(curUVCount + m.UVs.IndexOf(p.UV)) + + sw.Write("/") + If p.Normal IsNot Nothing Then sw.Write(curNormCount + m.Normals.IndexOf(p.Normal)) + + If m.VertexColors.Count > 0 Then + sw.Write("/") + If p.VertexColor IsNot Nothing Then sw.Write(curVertColCount + m.VertexColors.IndexOf(p.VertexColor)) + End If + Next + + sw.WriteLine() + Next + + curVertCount += m.Vertices.Count + curUVCount += m.UVs.Count + curNormCount += m.Normals.Count + curVertColCount += m.VertexColors.Count + Next + + sw.Flush() + fs.Close() + End Sub + + Public Shared Function GetIndexOfMaterialInList(obj As Object3D, matToFind As Material) As Integer + For Index As Integer = 0 To obj.Materials.Count - 1 + If obj.Materials.ElementAt(Index).Value.Equals(matToFind) Then + Return Index + End If + Next + Return -1 + End Function + + End Class + + Public Class MaterialLib + + Public ReadOnly Property Materials As New Dictionary(Of String, Material) + Private ReadOnly LoadedImages As New Dictionary(Of String, Image) + + Public Sub FromFile(fileName As String, LoadMaterials As Boolean) + LoadedImages.Clear() + + Dim curMatLibPath As String = Path.GetDirectoryName(fileName) + + Dim curMat As Material = Nothing + Dim curName As String = "" + + Dim srMtl As New StreamReader(fileName, Text.Encoding.ASCII) + Dim line As String = "" + + Do Until srMtl.EndOfStream + line = srMtl.ReadLine + + Select Case True + Case line.StartsWith("newmtl ") + curMat = New Material + curName = line.Substring(7) + Materials.Add(curName, curMat) + + Case line.ToLower.StartsWith("kd ") + Dim splitColor() As String = line.Substring(3).Split(" "c) + Dim col As Color = Color.FromArgb( + Convert.ToSingle(Math.Round(255 * splitColor(0))), + Convert.ToSingle(Math.Round(255 * splitColor(1))), + Convert.ToSingle(Math.Round(255 * splitColor(2)))) + curMat.Color = col + + Case line.ToLower.StartsWith("d ") + curMat.Opacity = Convert.ToSingle(line.Substring(2)) + + Case line.ToLower.StartsWith("tr ") + curMat.Opacity = 1 - Convert.ToSingle(line.Substring(2)) + + Case line.ToLower.StartsWith("map_kd ") + If LoadMaterials Then + Dim mtlpath As String = line.Substring(7) + Dim combipath As String = Path.Combine(curMatLibPath, line.Substring(7)) + Dim imgfile As String + + If File.Exists(combipath) Then + imgfile = combipath + ElseIf File.Exists(line.Substring(7)) Then + imgfile = mtlpath + Else + imgfile = "" + End If + + If imgfile <> "" Then + If LoadedImages.ContainsKey(imgfile) Then + curMat.Image = LoadedImages(imgfile) + Else + Dim fs As New FileStream(imgfile, FileMode.Open, FileAccess.Read) + curMat.Image = Image.FromStream(fs) + fs.Close() + Dim imgExists As Boolean = False + For Each kvp In LoadedImages + If Not imgExists AndAlso IsTheSameAs(kvp.Value, curMat.Image) Then + curMat.Image = kvp.Value + imgExists = True + End If + Next + If Not imgExists Then + LoadedImages.Add(imgfile, curMat.Image) + End If + End If + End If + End If + + End Select + Loop + + srMtl.Close() + End Sub + + Public Shared Sub ToFile(fileName As String, obj As Object3D) + Dim fs As New FileStream(fileName, FileMode.Create, FileAccess.ReadWrite) + Dim sw As New StreamWriter(fs, Text.Encoding.ASCII) + Dim imgDirName As String = Path.GetFileNameWithoutExtension(fileName) + Dim imgDirFull As String = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName)) + + For Each kvp As KeyValuePair(Of String, Material) In obj.Materials + Dim mat As Material = kvp.Value + Dim name As String = "_" & ObjFile.GetIndexOfMaterialInList(obj, mat) + sw.WriteLine($"newmtl {name}") + + If mat.Color IsNot Nothing Then + sw.WriteLine($"kd {mat.Color.Value.R.ToString.Replace(",", ".")} {mat.Color.Value.G.ToString.Replace(",", ".")} {mat.Color.Value.B.ToString.Replace(",", ".")}") + End If + + If mat.Opacity IsNot Nothing Then + sw.WriteLine($"d {mat.Opacity.Value.ToString.Replace(",", ".")}") + End If + + If mat.Image IsNot Nothing Then + Dim imgFile As String = name & ".png" + + If Not Directory.Exists(imgDirFull) Then Directory.CreateDirectory(imgDirFull) + mat.Image.Save(Path.Combine(imgDirFull, imgFile), Imaging.ImageFormat.Png) + + sw.WriteLine($"map_kd {Path.Combine(imgDirName, imgFile)}") + End If + Next + + sw.Flush() + fs.Close() + End Sub + + End Class + +End Namespace \ No newline at end of file diff --git a/Pilz.Simple3DFileParser/Model/Face.vb b/Pilz.Simple3DFileParser/Model/Face.vb new file mode 100644 index 0000000..09497ce --- /dev/null +++ b/Pilz.Simple3DFileParser/Model/Face.vb @@ -0,0 +1,5 @@ +Public Class Face + Public ReadOnly Property Points As New List(Of Point) + Public Property Material As Material = Nothing + Public Property Tag As Object = Nothing +End Class diff --git a/Pilz.Simple3DFileParser/Model/Interfaces.vb b/Pilz.Simple3DFileParser/Model/Interfaces.vb new file mode 100644 index 0000000..05bac76 --- /dev/null +++ b/Pilz.Simple3DFileParser/Model/Interfaces.vb @@ -0,0 +1,6 @@ +Public Interface IToObject3D + + Function ToObject3D() As Object3D + Function ToObject3DAsync() As Task(Of Object3D) + +End Interface diff --git a/Pilz.Simple3DFileParser/Model/Material.vb b/Pilz.Simple3DFileParser/Model/Material.vb new file mode 100644 index 0000000..1b755b6 --- /dev/null +++ b/Pilz.Simple3DFileParser/Model/Material.vb @@ -0,0 +1,25 @@ +Imports System.Numerics + +Public Class Material + Implements IComparable + + Public Property Image As Image = Nothing + Public Property Color As Color? = Nothing + Public Property Opacity As Single? = Nothing + Public Property Wrap As New Vector2(10497, 10497) + Public Property Scale As New Vector2(1.0F, 1.0F) + Public Property Tag As Object = Nothing + + Public Function CompareTo(obj As Object) As Integer Implements IComparable.CompareTo + If obj IsNot Nothing Then + If obj Is Me Then + Return 0 + Else + Return -1 + End If + Else + Return 1 + End If + End Function + +End Class diff --git a/Pilz.Simple3DFileParser/Model/Mesh.vb b/Pilz.Simple3DFileParser/Model/Mesh.vb new file mode 100644 index 0000000..53dfa0b --- /dev/null +++ b/Pilz.Simple3DFileParser/Model/Mesh.vb @@ -0,0 +1,41 @@ +Imports System.Numerics + +Public Class Mesh + + Public ReadOnly Property Vertices As New List(Of Vertex) + Public ReadOnly Property Normals As New List(Of Normal) + Public ReadOnly Property UVs As New List(Of UV) + Public ReadOnly Property VertexColors As New List(Of VertexColor) + Public ReadOnly Property Faces As New List(Of Face) + + Friend Function GetCenterModelAvg() As Vector3 + Dim avgX As Integer = 0 + Dim avgY As Integer = 0 + Dim avgZ As Integer = 0 + + For Each v As Vertex In Vertices + avgX += v.X + avgY += v.Y + avgZ += v.Z + Next + + Return New Vector3(avgX, avgY, avgZ) + End Function + + Public Sub CenterModel() + Dim avg As Vector3 = GetCenterModelAvg() + + avg /= New Vector3(Vertices.Count) + + CenterModel(avg) + End Sub + + Public Sub CenterModel(avg As Vector3) + For Each v As Vertex In Vertices + v.X -= avg.X + v.Y -= avg.Y + v.Z -= avg.Z + Next + End Sub + +End Class \ No newline at end of file diff --git a/Pilz.Simple3DFileParser/Model/ModelBoundaries.vb b/Pilz.Simple3DFileParser/Model/ModelBoundaries.vb new file mode 100644 index 0000000..ea4495d --- /dev/null +++ b/Pilz.Simple3DFileParser/Model/ModelBoundaries.vb @@ -0,0 +1,11 @@ +Imports System.Numerics + +Public Class ModelBoundaries + Public ReadOnly Upper As Vector3 + Public ReadOnly Lower As Vector3 + + Public Sub New(upper As Vector3, lower As Vector3) + Me.Upper = upper + Me.Lower = lower + End Sub +End Class diff --git a/Pilz.Simple3DFileParser/Model/Normal.vb b/Pilz.Simple3DFileParser/Model/Normal.vb new file mode 100644 index 0000000..e855cb2 --- /dev/null +++ b/Pilz.Simple3DFileParser/Model/Normal.vb @@ -0,0 +1,5 @@ +Public Class Normal + Public Property X As Single = 0 + Public Property Y As Single = 0 + Public Property Z As Single = 0 +End Class diff --git a/Pilz.Simple3DFileParser/Model/Object3D.vb b/Pilz.Simple3DFileParser/Model/Object3D.vb new file mode 100644 index 0000000..52e5aa8 --- /dev/null +++ b/Pilz.Simple3DFileParser/Model/Object3D.vb @@ -0,0 +1,200 @@ +Imports System.IO +Imports System.Numerics + +Public Class Object3D + + Public ReadOnly Property Meshes As New List(Of Mesh) + Public ReadOnly Property Materials As New Dictionary(Of String, Material) + Public Property Shading As New Shading + + Public Sub ScaleModel(factor As Single) + For Each m As Mesh In Meshes + For Each v As Vertex In m.Vertices + v.X *= factor + v.Y *= factor + v.Z *= factor + Next + Next + End Sub + + Public Sub OffsetModel(off As Vector3) + For Each m As Mesh In Meshes + For Each v As Vertex In m.Vertices + v.X += off.X + v.Y += off.Y + v.Z += off.Z + Next + Next + End Sub + + Public Function GetBoundaries() As ModelBoundaries + Dim maxX As Single? = Nothing + Dim maxY As Single? = Nothing + Dim maxZ As Single? = Nothing + Dim minX As Single? = Nothing + Dim minY As Single? = Nothing + Dim minZ As Single? = Nothing + + For Each m As Mesh In Meshes + For Each vert As Vertex In m.Vertices + If maxX Is Nothing OrElse vert.X > maxX Then maxX = vert.X + If maxY Is Nothing OrElse vert.Y > maxY Then maxY = vert.Y + If maxZ Is Nothing OrElse vert.Z > maxZ Then maxZ = vert.Z + If minX Is Nothing OrElse vert.X < minX Then minX = vert.X + If minY Is Nothing OrElse vert.Y < minY Then minY = vert.Y + If minZ Is Nothing OrElse vert.Z < minZ Then minZ = vert.Z + Next + Next + + If maxX Is Nothing Then maxX = 0 + If maxY Is Nothing Then maxY = 0 + If maxZ Is Nothing Then maxZ = 0 + If minX Is Nothing Then minX = 0 + If minY Is Nothing Then minY = 0 + If minZ Is Nothing Then minZ = 0 + + Return New ModelBoundaries(New Vector3(maxX, maxY, maxZ), + New Vector3(minX, minY, minZ)) + End Function + + Public Sub SetNullVertices() + Dim newVert As New Vertex With {.X = 0, .Y = 0, .Z = 0} + Dim nullCounter As Integer + + For Each m As Mesh In Meshes + nullCounter = 0 + + For Each f As Face In m.Faces + For Each p As Point In f.Points + If p.Vertex Is Nothing Then + p.Vertex = newVert + nullCounter += 1 + End If + Next + Next + + If nullCounter > 0 Then + m.Vertices.Add(newVert) + End If + Next + End Sub + + Public Sub SetNullUVs() + Dim newUV As New UV With {.U = 0, .V = 0} + Dim nullCounter As Integer + + For Each m As Mesh In Meshes + nullCounter = 0 + + For Each f As Face In m.Faces + For Each p As Point In f.Points + If p.UV Is Nothing Then + p.UV = newUV + nullCounter += 1 + End If + Next + Next + + If nullCounter > 0 Then + m.UVs.Add(newUV) + End If + Next + End Sub + + Public Sub SetNullNormals() + Dim newNormal As New Normal With {.X = 0, .Y = 0, .Z = 1} + Dim nullCounter As Integer + + For Each m As Mesh In Meshes + nullCounter = 0 + + For Each f As Face In m.Faces + For Each p As Point In f.Points + If p.Normal Is Nothing Then + p.Normal = newNormal + nullCounter += 1 + End If + Next + Next + + If nullCounter > 0 Then + m.Normals.Add(newNormal) + End If + Next + End Sub + + Public Sub RemoveUnusedMaterials() + 'Dim usedMats As New List(Of Material) + 'Dim unusedMats As New List(Of String) + + 'For Each f As Face In Faces + ' If Not usedMats.Contains(f.Material) Then + ' usedMats.Add(f.Material) + ' End If + 'Next + + 'For Each kvp As KeyValuePair(Of String, Material) In Materials + ' If Not usedMats.Contains(kvp.Value) Then + ' unusedMats.Add(kvp.Key) + ' End If + 'Next + + 'For Each k As String In unusedMats + ' Materials.Remove(k) + 'Next + End Sub + + Public Function ToOneMesh() As Object3D + Dim newObject3D As New Object3D + Dim newMesh As New Mesh + + For Each mat As KeyValuePair(Of String, Material) In Materials + newObject3D.Materials.Add(mat.Key, mat.Value) + Next + + For Each m As Mesh In Meshes + For Each v As Vertex In m.Vertices + newMesh.Vertices.Add(v) + Next + + For Each vc As VertexColor In m.VertexColors + newMesh.VertexColors.Add(vc) + Next + + For Each n As Normal In m.Normals + newMesh.Normals.Add(n) + Next + + For Each uv As UV In m.UVs + newMesh.UVs.Add(uv) + Next + + For Each f As Face In m.Faces + newMesh.Faces.Add(f) + Next + Next + + newObject3D.Meshes.Add(newMesh) + Return newObject3D + End Function + + Public Sub CenterModel() + Dim avg As Vector3 = Vector3.Zero + Dim vertsCount As ULong = 0 + + For Each m As Mesh In Meshes + avg += m.GetCenterModelAvg + vertsCount += m.Vertices.Count + Next + + avg /= vertsCount + + CenterModel(avg) + End Sub + Public Sub CenterModel(avg As Vector3) + For Each m As Mesh In Meshes + m.CenterModel(avg) + Next + End Sub + +End Class diff --git a/Pilz.Simple3DFileParser/Model/Point.vb b/Pilz.Simple3DFileParser/Model/Point.vb new file mode 100644 index 0000000..2760f7f --- /dev/null +++ b/Pilz.Simple3DFileParser/Model/Point.vb @@ -0,0 +1,6 @@ +Public Class Point + Public Property Vertex As Vertex = Nothing + Public Property UV As UV = Nothing + Public Property VertexColor As VertexColor = Nothing + Public Property Normal As Normal = Nothing +End Class diff --git a/Pilz.Simple3DFileParser/Model/Shading.vb b/Pilz.Simple3DFileParser/Model/Shading.vb new file mode 100644 index 0000000..b69447b --- /dev/null +++ b/Pilz.Simple3DFileParser/Model/Shading.vb @@ -0,0 +1,5 @@ +Public Class Shading + Public Property AmbientColor As Color = Color.FromArgb(&HFFFFFFFF) + Public Property DiffuseColor As Color = Color.FromArgb(&HFF7F7F7F) + Public Property DiffusePosition As Vertex = Nothing +End Class diff --git a/Pilz.Simple3DFileParser/Model/UV.vb b/Pilz.Simple3DFileParser/Model/UV.vb new file mode 100644 index 0000000..74de128 --- /dev/null +++ b/Pilz.Simple3DFileParser/Model/UV.vb @@ -0,0 +1,4 @@ +Public Class UV + Public Property U As Single = 0 + Public Property V As Single = 0 +End Class diff --git a/Pilz.Simple3DFileParser/Model/UpAxis.vb b/Pilz.Simple3DFileParser/Model/UpAxis.vb new file mode 100644 index 0000000..1e309de --- /dev/null +++ b/Pilz.Simple3DFileParser/Model/UpAxis.vb @@ -0,0 +1,4 @@ +Public Enum UpAxis + Y + Z +End Enum diff --git a/Pilz.Simple3DFileParser/Model/Vertex.vb b/Pilz.Simple3DFileParser/Model/Vertex.vb new file mode 100644 index 0000000..d1b4d1e --- /dev/null +++ b/Pilz.Simple3DFileParser/Model/Vertex.vb @@ -0,0 +1,5 @@ +Public Class Vertex + Public Property X As Double = 0 + Public Property Y As Double = 0 + Public Property Z As Double = 0 +End Class diff --git a/Pilz.Simple3DFileParser/Model/VertexColor.vb b/Pilz.Simple3DFileParser/Model/VertexColor.vb new file mode 100644 index 0000000..0d41404 --- /dev/null +++ b/Pilz.Simple3DFileParser/Model/VertexColor.vb @@ -0,0 +1,6 @@ +Public Class VertexColor + Public Property R As Single = 1 + Public Property G As Single = 1 + Public Property B As Single = 1 + Public Property A As Single = 1 +End Class diff --git a/Pilz.Simple3DFileParser/My Project/Application.Designer.vb b/Pilz.Simple3DFileParser/My Project/Application.Designer.vb new file mode 100644 index 0000000..8ab460b --- /dev/null +++ b/Pilz.Simple3DFileParser/My Project/Application.Designer.vb @@ -0,0 +1,13 @@ +'------------------------------------------------------------------------------ +' +' Dieser Code wurde von einem Tool generiert. +' Laufzeitversion:4.0.30319.42000 +' +' Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +' der Code erneut generiert wird. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + diff --git a/Pilz.Simple3DFileParser/My Project/Application.myapp b/Pilz.Simple3DFileParser/My Project/Application.myapp new file mode 100644 index 0000000..1243847 --- /dev/null +++ b/Pilz.Simple3DFileParser/My Project/Application.myapp @@ -0,0 +1,11 @@ + + + true + Form1 + false + 0 + true + 0 + 0 + true + diff --git a/Pilz.Simple3DFileParser/My Project/AssemblyInfo.vb b/Pilz.Simple3DFileParser/My Project/AssemblyInfo.vb new file mode 100644 index 0000000..d6dd9e2 --- /dev/null +++ b/Pilz.Simple3DFileParser/My Project/AssemblyInfo.vb @@ -0,0 +1,35 @@ +Imports System +Imports System.Reflection +Imports System.Runtime.InteropServices + +' Allgemeine Informationen über eine Assembly werden über die folgenden +' Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +' die einer Assembly zugeordnet sind. + +' Werte der Assemblyattribute überprüfen + + + + + + + + + + +'Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird. + + +' Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +' +' Hauptversion +' Nebenversion +' Buildnummer +' Revision +' +' Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, +' übernehmen, indem Sie "*" eingeben: +' + + + diff --git a/Pilz.Simple3DFileParser/My Project/Resources.Designer.vb b/Pilz.Simple3DFileParser/My Project/Resources.Designer.vb new file mode 100644 index 0000000..0832c08 --- /dev/null +++ b/Pilz.Simple3DFileParser/My Project/Resources.Designer.vb @@ -0,0 +1,63 @@ +'------------------------------------------------------------------------------ +' +' Dieser Code wurde von einem Tool generiert. +' Laufzeitversion:4.0.30319.42000 +' +' Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +' der Code erneut generiert wird. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + +Imports System + +Namespace My.Resources + + 'Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + '-Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + 'Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + 'mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + ''' + ''' Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + ''' + _ + Friend Module Resources + + Private resourceMan As Global.System.Resources.ResourceManager + + Private resourceCulture As Global.System.Globalization.CultureInfo + + ''' + ''' Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + ''' + _ + Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager + Get + If Object.ReferenceEquals(resourceMan, Nothing) Then + Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("Pilz.S3DFileParser.Resources", GetType(Resources).Assembly) + resourceMan = temp + End If + Return resourceMan + End Get + End Property + + ''' + ''' Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + ''' Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + ''' + _ + Friend Property Culture() As Global.System.Globalization.CultureInfo + Get + Return resourceCulture + End Get + Set + resourceCulture = value + End Set + End Property + End Module +End Namespace diff --git a/Pilz.Simple3DFileParser/My Project/Resources.resx b/Pilz.Simple3DFileParser/My Project/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/Pilz.Simple3DFileParser/My Project/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Pilz.Simple3DFileParser/My Project/Settings.Designer.vb b/Pilz.Simple3DFileParser/My Project/Settings.Designer.vb new file mode 100644 index 0000000..60c5980 --- /dev/null +++ b/Pilz.Simple3DFileParser/My Project/Settings.Designer.vb @@ -0,0 +1,73 @@ +'------------------------------------------------------------------------------ +' +' Dieser Code wurde von einem Tool generiert. +' Laufzeitversion:4.0.30319.42000 +' +' Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +' der Code erneut generiert wird. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + + +Namespace My + + _ + Partial Friend NotInheritable Class MySettings + Inherits Global.System.Configuration.ApplicationSettingsBase + + Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()),MySettings) + +#Region "Automatische My.Settings-Speicherfunktion" +#If _MyType = "WindowsForms" Then + Private Shared addedHandler As Boolean + + Private Shared addedHandlerLockObject As New Object + + _ + Private Shared Sub AutoSaveSettings(sender As Global.System.Object, e As Global.System.EventArgs) + If My.Application.SaveMySettingsOnExit Then + My.Settings.Save() + End If + End Sub +#End If +#End Region + + Public Shared ReadOnly Property [Default]() As MySettings + Get + +#If _MyType = "WindowsForms" Then + If Not addedHandler Then + SyncLock addedHandlerLockObject + If Not addedHandler Then + AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings + addedHandler = True + End If + End SyncLock + End If +#End If + Return defaultInstance + End Get + End Property + End Class +End Namespace + +Namespace My + + _ + Friend Module MySettingsProperty + + _ + Friend ReadOnly Property Settings() As Global.Pilz.S3DFileParser.My.MySettings + Get + Return Global.Pilz.S3DFileParser.My.MySettings.Default + End Get + End Property + End Module +End Namespace diff --git a/Pilz.Simple3DFileParser/My Project/Settings.settings b/Pilz.Simple3DFileParser/My Project/Settings.settings new file mode 100644 index 0000000..85b890b --- /dev/null +++ b/Pilz.Simple3DFileParser/My Project/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Pilz.Simple3DFileParser/Other/Exceptions.vb b/Pilz.Simple3DFileParser/Other/Exceptions.vb new file mode 100644 index 0000000..df3a620 --- /dev/null +++ b/Pilz.Simple3DFileParser/Other/Exceptions.vb @@ -0,0 +1,14 @@ +Namespace Exceptions + + Public Class MaterialException + Inherits Exception + + Public Sub New() + MyBase.New + End Sub + Public Sub New(message As String) + MyBase.New(message) + End Sub + End Class + +End Namespace diff --git a/Pilz.Simple3DFileParser/Other/Extensions.vb b/Pilz.Simple3DFileParser/Other/Extensions.vb new file mode 100644 index 0000000..59da39b --- /dev/null +++ b/Pilz.Simple3DFileParser/Other/Extensions.vb @@ -0,0 +1,26 @@ +Imports System.IO +Imports System.Runtime.CompilerServices + +Friend Module Extensions + + + Public Function GetPropertyValue(base As Object, propertyName As String) As Object + Return base?.GetType.GetProperty(propertyName, Reflection.BindingFlags.Public Or Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Static)?.GetValue(base) + End Function + + + Public Function IsTheSameAs(base As Bitmap, image As Bitmap) As Boolean + If base.Size <> image.Size Then Return False + + For y As Integer = 0 To base.Height - 1 + For x As Integer = 0 To base.Width - 1 + Dim p1 As Color = base.GetPixel(x, y) + Dim p2 As Color = image.GetPixel(x, y) + If p1 <> p2 Then Return False + Next + Next + + Return True + End Function + +End Module diff --git a/Pilz.Simple3DFileParser/Other/LoaderModule.vb b/Pilz.Simple3DFileParser/Other/LoaderModule.vb new file mode 100644 index 0000000..a34a287 --- /dev/null +++ b/Pilz.Simple3DFileParser/Other/LoaderModule.vb @@ -0,0 +1,144 @@ +Imports System.Reflection +Imports Assimp.Unmanaged + +Public Class File3DLoaderModule + + Public Delegate Function LoaderAction(fileName As String, options As LoaderOptions) As Object3D + Public Delegate Sub ExporterAction(obj As Object3D, fileName As String) + + Private Shared _LoaderModules As File3DLoaderModule() = Nothing + Private Shared _ExporterModules As File3DLoaderModule() = Nothing + + Private ReadOnly method As [Delegate] = Nothing + Public ReadOnly Property Name As String + Public ReadOnly Property SupportedFormats As IReadOnlyDictionary(Of String, String) + + Public Sub New(name As String, method As LoaderAction, supportedFormats As IReadOnlyDictionary(Of String, String)) + Me.Name = name + Me.method = method + Me.SupportedFormats = supportedFormats + End Sub + + Public Sub New(name As String, method As ExporterAction, supportedFormats As IReadOnlyDictionary(Of String, String)) + Me.Name = name + Me.method = method + Me.SupportedFormats = supportedFormats + End Sub + + Public Function InvokeAsync(obj As Object3D, fileName As String) As Task + Return Task.Run(Sub() Invoke(obj, fileName)) + End Function + + Public Sub Invoke(obj As Object3D, fileName As String) + method.Method.Invoke(Nothing, {obj, fileName}) + End Sub + + Public Function InvokeAsync(fileName As String, options As LoaderOptions) As Task(Of Object3D) + Return Task.Run(Function() Invoke(fileName, options)) + End Function + + Public Function Invoke(fileName As String, options As LoaderOptions) As Object3D + Return method.Method.Invoke(Nothing, {fileName, options}) + End Function + + Public Shared ReadOnly Property LoaderModules As File3DLoaderModule() + Get + If _LoaderModules Is Nothing Then + _LoaderModules = GetLoaderModules() + End If + Return _LoaderModules + End Get + End Property + + Public Shared ReadOnly Property ExporterModules As File3DLoaderModule() + Get + If _ExporterModules Is Nothing Then + _ExporterModules = GetExporterModules() + End If + Return _ExporterModules + End Get + End Property + + Private Shared Function GetLoaderModules() As File3DLoaderModule() + Dim list As New List(Of File3DLoaderModule) + + list.Add(New File3DLoaderModule("Simple File Parser", + AddressOf LoadViaSimpleFileParser, + New Dictionary(Of String, String) From {{"obj", "OBJ"}})) + + AssimpModule.AssimpLoader.LoadAssimpLibs() + Dim exts As New Dictionary(Of String, String) + For Each fd As Assimp.ExportFormatDescription In AssimpLibrary.Instance.GetExportFormatDescriptions + If Not exts.ContainsKey(fd.FileExtension) Then exts.Add(fd.FileExtension, fd.FormatId & " - " & fd.Description) + Next + + list.Add(New File3DLoaderModule("Assimp", + AddressOf LoadViaAssimp, + exts)) + + list.Add(New File3DLoaderModule("Aspose.3D", + AddressOf LoadViaAspose3D, + New Dictionary(Of String, String) From { + {"obj", "OBJ"}, + {"dae", "DAE"}, + {"fbx", "FBX"}, + {"stl", "STL"}, + {"3ds", "3DS"}, + {"3d", "3D"}, + {"gltf", "glTF"}, + {"drc", "DRC"}, + {"rvm", "RVM"}, + {"pdf", "PDF"}, + {"x", "X"}, + {"jt", "JT"}, + {"dfx", "DFX"}, + {"ply", "PLY"}, + {"3mf", "3MF"}, + {"ase", "ASE"}})) + + Return list.ToArray + End Function + + Private Shared Function GetExporterModules() As File3DLoaderModule() + Dim list As New List(Of File3DLoaderModule) + + list.Add(New File3DLoaderModule("Simple File Parser", + AddressOf ExportViaSimpleFileParser, + New Dictionary(Of String, String) From {{"obj", "OBJ"}})) + + AssimpModule.AssimpLoader.LoadAssimpLibs() + Dim exts As New Dictionary(Of String, String) + For Each fd As Assimp.ExportFormatDescription In AssimpLibrary.Instance.GetExportFormatDescriptions + If Not exts.ContainsKey(fd.FileExtension) Then exts.Add(fd.FileExtension, fd.FormatId & " - " & fd.Description) + Next + + list.Add(New File3DLoaderModule("Assimp", + AddressOf ExportViaAssimp, + exts)) + + Return list.ToArray + End Function + + Private Shared Function LoadViaSimpleFileParser(fileName As String, options As LoaderOptions) As Object3D + Return ObjModule.ObjFile.FromFile(fileName, options.LoadMaterials, options.UpAxis) + End Function + + Private Shared Function LoadViaAssimp(fileName As String, options As LoaderOptions) As Object3D + AssimpModule.AssimpLoader.LoadAssimpLibs() + Return AssimpModule.AssimpLoader.FromFile(fileName, options.LoadMaterials, options.UpAxis) + End Function + + Private Shared Function LoadViaAspose3D(fileName As String, options As LoaderOptions) As Object3D + Return Aspose3DModule.Aspose3DLoader.FromFile(fileName, options.LoadMaterials, options.UpAxis) + End Function + + Private Shared Sub ExportViaSimpleFileParser(o As Object3D, fileName As String) + ObjModule.ObjFile.ToFile(fileName, o) + End Sub + + Private Shared Sub ExportViaAssimp(o As Object3D, fileName As String) + AssimpModule.AssimpLoader.LoadAssimpLibs() + AssimpModule.AssimpLoader.ToFile(fileName, o) + End Sub + +End Class diff --git a/Pilz.Simple3DFileParser/Other/LoaderOptions.vb b/Pilz.Simple3DFileParser/Other/LoaderOptions.vb new file mode 100644 index 0000000..a41d785 --- /dev/null +++ b/Pilz.Simple3DFileParser/Other/LoaderOptions.vb @@ -0,0 +1,14 @@ +Public Class LoaderOptions + + Public Property LoadMaterials As Boolean = False + Public Property UpAxis As UpAxis = False + + Public Sub New() + End Sub + + Public Sub New(loadMaterials As Boolean, upAxis As UpAxis) + Me.LoadMaterials = loadMaterials + Me.UpAxis = upAxis + End Sub + +End Class diff --git a/Pilz.Simple3DFileParser/Pilz.Simple3DFileParser.vbproj b/Pilz.Simple3DFileParser/Pilz.Simple3DFileParser.vbproj new file mode 100644 index 0000000..058d877 --- /dev/null +++ b/Pilz.Simple3DFileParser/Pilz.Simple3DFileParser.vbproj @@ -0,0 +1,154 @@ + + + + + Debug + AnyCPU + {AC955819-7910-450C-940C-7C1989483D4B} + Library + + + Pilz.S3DFileParser + Pilz.Simple3DFileParser + 512 + Windows + v4.5 + + + + + AnyCPU + true + full + true + true + bin\Debug\ + Pilz.Simple3DFileParser.xml + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + AnyCPU + pdbonly + false + true + true + bin\Release\ + Pilz.Simple3DFileParser.xml + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + On + + + Binary + + + Off + + + On + + + + ..\packages\Aspose.3D.18.4.0\lib\net40\Aspose.3D.dll + + + False + ..\Shared Libs\AssimpNet.dll + + + ..\..\..\DLL's\ColladaSchema.dll + + + + + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\portable-net45+win8+wp8+wpa81\System.Numerics.Vectors.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + Application.myapp + + + True + True + Resources.resx + + + True + Settings.settings + True + + + + + + VbMyResourcesResXFileCodeGenerator + Resources.Designer.vb + My.Resources + Designer + + + + + MyApplicationCodeGenerator + Application.Designer.vb + + + SettingsSingleFileGenerator + My + Settings.Designer.vb + + + + + + + {67593ff7-c1d1-4529-98c4-61cbd0615f08} + Pilz.LicenseHelper + + + + \ No newline at end of file diff --git a/Pilz.Simple3DFileParser/packages.config b/Pilz.Simple3DFileParser/packages.config new file mode 100644 index 0000000..8267bb7 --- /dev/null +++ b/Pilz.Simple3DFileParser/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/Pilz.Threading/CrossThreadsInvokeing.vb b/Pilz.Threading/CrossThreadsInvokeing.vb index a37f0ae..a43f643 100644 --- a/Pilz.Threading/CrossThreadsInvokeing.vb +++ b/Pilz.Threading/CrossThreadsInvokeing.vb @@ -16,15 +16,17 @@ Imports System.Windows.Forms Public Class CrossThreadsInvokeing Public Shared Sub RunAsync(Of T1, T2, T3)(ByVal Action As Action(Of T1, T2, T3), ByVal Arg1 As T1, ByVal Arg2 As T2, ByVal Arg3 As T3) - ' Aufruf von Action.EndInvoke() gewährleisten, indem er als Callback-Argument mitgegeben wird Action.BeginInvoke(Arg1, Arg2, Arg3, AddressOf Action.EndInvoke, Nothing) End Sub + Public Shared Sub RunAsync(Of T1, T2)(ByVal Action As Action(Of T1, T2), ByVal Arg1 As T1, ByVal Arg2 As T2) Action.BeginInvoke(Arg1, Arg2, AddressOf Action.EndInvoke, Nothing) End Sub + Public Shared Sub RunAsync(Of T1)(ByVal Action As Action(Of T1), ByVal Arg1 As T1) Action.BeginInvoke(Arg1, AddressOf Action.EndInvoke, Nothing) End Sub + Public Shared Sub RunAsync(ByVal Action As Action) Action.BeginInvoke(AddressOf Action.EndInvoke, Nothing) End Sub @@ -32,14 +34,6 @@ Public Class CrossThreadsInvokeing Private Shared Function GuiCrossInvoke(ByVal Action As [Delegate], ByVal ParamArray Args() As Object) As Boolean Dim frms As FormCollection = Application.OpenForms - 'If frms.Count = 0 Then - ' 'wenn kein Form mehr da ist, so tun, als ob das Invoking ausgeführt wäre - ' Return True - 'ElseIf frms(0).InvokeRequired Then - 'frms(0).BeginInvoke(Action, Args) - 'Return True - 'End If - If frms.Count > 0 AndAlso frms(0).InvokeRequired Then frms(0).BeginInvoke(Action, Args) Return True @@ -49,15 +43,17 @@ Public Class CrossThreadsInvokeing End Function Public Shared Sub RunGui(Of T1, T2, T3)(ByVal Action As Action(Of T1, T2, T3), ByVal Arg1 As T1, ByVal Arg2 As T2, ByVal Arg3 As T3) - 'falls Invoking nicht erforderlich, die Action direkt ausführen If Not GuiCrossInvoke(Action, Arg1, Arg2, Arg3) Then Action(Arg1, Arg2, Arg3) End Sub + Public Shared Sub RunGui(Of T1, T2)(ByVal Action As Action(Of T1, T2), ByVal Arg1 As T1, ByVal Arg2 As T2) If Not GuiCrossInvoke(Action, Arg1, Arg2) Then Action(Arg1, Arg2) End Sub + Public Shared Sub RunGui(Of T1)(ByVal Action As Action(Of T1), ByVal Arg1 As T1) If Not GuiCrossInvoke(Action, Arg1) Then Action(Arg1) End Sub + Public Shared Sub RunGui(ByVal Action As Action) If Not GuiCrossInvoke(Action) Then Action() End Sub diff --git a/Pilz.UI/PaintingControl/DefaultDrawMethodes.vb b/Pilz.UI/PaintingControl/DefaultDrawMethodes.vb index 09bb875..d76539a 100644 --- a/Pilz.UI/PaintingControl/DefaultDrawMethodes.vb +++ b/Pilz.UI/PaintingControl/DefaultDrawMethodes.vb @@ -31,21 +31,33 @@ Public Class DefaultDrawMethodes Public Shared Sub DrawPicture(e As PaintingObjectPaintEventArgs) Dim obj As PaintingObject = e.PaintingObject Dim objImg As Image + Dim objImgSize As Size Dim result As RectangleF Dim image As Bitmap + Dim zoomf As SizeF + Dim hasNoParent As Boolean = e.PaintingObject.Parent Is Nothing + Dim syncObj As Object - SyncLock e.PaintingObject.Parent + If hasNoParent Then + zoomf = New SizeF(1, 1) + Static newSyncObj As New Object + syncObj = newSyncObj + Else + zoomf = e.PaintingObject.Parent.ZoomFactor + syncObj = e.PaintingObject.Parent + End If + + SyncLock syncObj If obj?.Image Is Nothing Then Return objImg = obj.Image + objImgSize = objImg.Size End SyncLock image = obj.BufferedImage - result = CalculateImageResolution(obj, objImg.Size) + result = CalculateImageResolution(obj, objImgSize, zoomf) If obj.ImageProperties.Rotate = 90 OrElse obj.ImageProperties.Rotate = 270 Then - result = CalculateImageResolution(obj, New SizeF(objImg.Size.Height, objImg.Size.Width)) - Else - result = result + result = CalculateImageResolution(obj, New SizeF(objImgSize.Height, objImgSize.Width), zoomf) End If If image Is Nothing Then @@ -71,7 +83,7 @@ Public Class DefaultDrawMethodes End If If needRescaleImageBecauseRot Then - result = CalculateImageResolution(obj, New SizeF(objImg.Size.Height, objImg.Size.Width)) + result = CalculateImageResolution(obj, New SizeF(objImgSize.Height, objImgSize.Width), zoomf) image = DrawToNewImage(image, result.Size) End If @@ -79,12 +91,15 @@ Public Class DefaultDrawMethodes End If If image IsNot Nothing Then - e.Graphics.DrawImageUnscaled(image, New Rectangle(New Point(obj.Location.X + result.Location.X - e.Offset.X, obj.Location.Y + result.Location.Y - e.Offset.Y), result.Size.ToSize)) + SyncLock syncObj + e.Graphics.DrawImageUnscaled(image, New Rectangle(New Point(obj.Location.X + result.Location.X - e.Offset.X, obj.Location.Y + result.Location.Y - e.Offset.Y), result.Size.ToSize)) + End SyncLock End If End Sub Private Shared Function DrawToNewImage(image As Bitmap, newSize As SizeF) As Bitmap - Dim bmp As New Bitmap(CInt(newSize.Width), CInt(newSize.Height)) + Dim bmp As New Bitmap(CInt(If(newSize.Width < 0, newSize.Width * -1, newSize.Width)), + CInt(If(newSize.Height < 0, newSize.Height * -1, newSize.Height))) Dim gimage As Graphics = Graphics.FromImage(bmp) gimage.SmoothingMode = SmoothingMode.HighQuality gimage.PixelOffsetMode = PixelOffsetMode.HighQuality @@ -103,10 +118,10 @@ Public Class DefaultDrawMethodes e.Graphics.DrawLine(p2, no, no + obj.Size) End Sub - Private Shared Function CalculateImageResolution(obj As PaintingObject, imageSize As SizeF) As RectangleF + Private Shared Function CalculateImageResolution(obj As PaintingObject, imageSize As SizeF, zoom As SizeF) As RectangleF Dim result As New RectangleF Dim objrect As New RectangleF(obj.Location, obj.Size) - Dim size As SizeF = imageSize + Dim size As SizeF = New SizeF(imageSize.Width * zoom.Width, imageSize.Height * zoom.Height) Dim clientRectangle As RectangleF = objrect Dim val As Single = clientRectangle.Width / size.Width diff --git a/Pilz.UI/PaintingControl/PaintingControl.vb b/Pilz.UI/PaintingControl/PaintingControl.vb index 5143f04..bbc72a7 100644 --- a/Pilz.UI/PaintingControl/PaintingControl.vb +++ b/Pilz.UI/PaintingControl/PaintingControl.vb @@ -107,6 +107,7 @@ Public Class PaintingControl Set If _ZoomFactor <> Value Then _ZoomFactor = Value + ResetAllBufferedImages() RaiseEvent ZoomFactorChanged(Me, New EventArgs) End If End Set @@ -116,6 +117,13 @@ Public Class PaintingControl DoubleBuffered = True End Sub + Private Sub ResetAllBufferedImages() + For Each ob As PaintingObject In PaintingObjects + ob.ResetImageBuffer() + Next + Refresh() + End Sub + Private Sub CheckKeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown, Me.KeyUp pressedShift = e.Shift pressedControl = e.Control @@ -166,6 +174,7 @@ Public Class PaintingControl End If Next End If + If AutoSingleSelection Then Dim objtosel As PaintingObject = curObjMouseDown If objtosel?.EnableSelection Then @@ -218,8 +227,10 @@ Public Class PaintingControl If _IsMovingObjects Then _IsMovingObjects = False + For Each obj As PaintingObject In GetSelectedObjects() + obj.RaiseMoved(New EventArgs) + Next AutoArrangeToGrid() - 'CalculateScrollValues() End If If curObjMouseDown IsNot Nothing Then @@ -304,43 +315,38 @@ Public Class PaintingControl End If Next End Sub + Private Sub UpdateObjectPositions(e As MouseEventArgs) UpdateObjectPositions(e, GetSelectedObjects) End Sub + Private Sub UpdateObjectPositions(e As MouseEventArgs, objs As IList(Of PaintingObject), Optional movedObjs As List(Of PaintingObject) = Nothing) If IsResizingObjs(objs) Then Return If movedObjs Is Nothing Then movedObjs = New List(Of PaintingObject) - Dim updateprocesses As New List(Of Task) SuspendDrawing() For Each obj As PaintingObject In objs - updateprocesses.Add(Task.Run( - Sub() - Dim sp As PointF = savedPos(obj) + Dim sp As PointF = savedPos(obj) - If Not movedObjs.Contains(obj) Then - UpdateObjectPosition(e, obj, sp) - movedObjs.Add(obj) - End If + If Not movedObjs.Contains(obj) Then + UpdateObjectPosition(e, obj, sp) + movedObjs.Add(obj) + End If - If obj.PinnedObjects.Count > 0 Then - UpdateObjectPositions(e, obj.PinnedObjects, movedObjs) - movedObjs.AddRange(obj.PinnedObjects.ToArray) - End If - End Sub)) - Next - - For Each a In updateprocesses - Do Until a.IsCompleted - Loop + If obj.PinnedObjects.Count > 0 Then + UpdateObjectPositions(e, obj.PinnedObjects, movedObjs) + movedObjs.AddRange(obj.PinnedObjects.ToArray) + End If Next ResumeDrawing(False) End Sub + Private Sub UpdateObjectPosition(e As MouseEventArgs, obj As PaintingObject, sp As PointF) obj.Location = New Point(e.X - sp.X + Offset.X, e.Y - sp.Y + Offset.Y) + obj.RaiseMoving(New EventArgs) End Sub Private Function IsResizingObjs(objs As IList(Of PaintingObject)) As Boolean @@ -355,19 +361,25 @@ Public Class PaintingControl End Function Public Function GetObject(p As PointF, Optional UseExtRect As Boolean = False) As PaintingObject - For Each obj As PaintingObject In PaintingObjects - If UseExtRect Then - If HelpfulDrawingFunctions.IsPointInRectangle(p, obj.RectangleExtended) Then - Return obj - End If - Else - If HelpfulDrawingFunctions.IsPointInRectangle(p, obj.Rectangle) Then - Return obj + Dim val As PaintingObject = Nothing + + For i As Integer = PaintingObjects.Count - 1 To 0 Step -1 + Dim obj As PaintingObject = PaintingObjects(i) + + If val Is Nothing Then + If UseExtRect Then + If HelpfulDrawingFunctions.IsPointInRectangle(p, obj.RectangleExtended) Then + val = obj + End If + Else + If HelpfulDrawingFunctions.IsPointInRectangle(p, obj.Rectangle) Then + val = obj + End If End If End If Next - Return Nothing + Return val End Function Public Function GetObjects(p As Point) As PaintingObject() @@ -439,46 +451,6 @@ Public Class PaintingControl MyBase.OnPaintBackground(e) End Sub - Private Function GetCurrentHashValue() As Integer - Dim hashes As New List(Of Integer) - - hashes.AddRange({Offset.X, - Offset.Y, - Size.Width, - Size.Height}) - - For Each p As PaintingObject In PaintingObjects - hashes.AddRange({p.Location.X, - p.Location.Y, - p.Size.Width, - p.Size.Height, - p.DrawMethodes.Count, - p.FillColor.ToArgb, - p.OutlineColor.ToArgb, - p.SelectionColor.ToArgb, - p.TextColor.ToArgb, - p.Type, - p.Text.GetHashCode / p.Text.Length, - p.Visible, - p.VerticalTextAlignment, - p.HorizontalTextAlignment}) - Next - - Dim hash As Integer = 0 - - For Each h As Integer In hashes - Try - hash += h - Catch ex As Exception - If h <> 0 AndAlso h <> 1 Then - hash /= h - End If - End Try - Next - - Return hash - End Function - Protected Overrides Sub OnPaint(e As PaintEventArgs) 'Do default Drawing Methode MyBase.OnPaint(e) @@ -579,6 +551,15 @@ Public Class PaintingControl End If End Sub + Public Function IsPinnedObject(o As PaintingObject) As Boolean + For Each obj As PaintingObject In PaintingObjects + If obj.PinnedObjects.Contains(o) Then + Return True + End If + Next + Return False + End Function + Public Sub AutoArrangeToGrid() If GridEnabled Then For Each obj As PaintingObject In GetSelectedObjects() diff --git a/Pilz.UI/PaintingControl/PaintingObject.vb b/Pilz.UI/PaintingControl/PaintingObject.vb index 5ceaa73..97c90d8 100644 --- a/Pilz.UI/PaintingControl/PaintingObject.vb +++ b/Pilz.UI/PaintingControl/PaintingObject.vb @@ -47,6 +47,7 @@ Imports Newtonsoft.Json Public Property MouseTransparency As Boolean = False Public ReadOnly Property Layering As New PaintingObjectLayering(Me) Public ReadOnly Property PaintingObjects As New PaintingObjectList(_Parent) With {.EnableRaisingEvents = False} + Public ReadOnly Property ErrorsAtDrawing As ULong = 0 Public Event MouseClick(sender As PaintingObject, e As MouseEventArgs) Public Event MouseDown(sender As PaintingObject, e As MouseEventArgs) @@ -56,6 +57,8 @@ Imports Newtonsoft.Json Public Event Paint(sender As PaintingObject, e As PaintEventArgs) Public Event ParentChanged(sender As PaintingObject, e As EventArgs) Public Event VisibleChanged(sender As PaintingObject, e As EventArgs) + Public Event Moved(sender As PaintingObject, e As EventArgs) + Public Event Moving(sender As PaintingObject, e As EventArgs) Public Sub New() End Sub @@ -69,21 +72,27 @@ Imports Newtonsoft.Json Me.DrawMethodes.AddRange(drawMethodes) End Sub - Public Sub RaiseMouseClick(e As MouseEventArgs) + Friend Sub RaiseMouseClick(e As MouseEventArgs) RaiseEvent MouseClick(Me, e) End Sub - Public Sub RaiseMouseDown(e As MouseEventArgs) + Friend Sub RaiseMouseDown(e As MouseEventArgs) RaiseEvent MouseDown(Me, e) End Sub - Public Sub RaiseMouseUp(e As MouseEventArgs) + Friend Sub RaiseMouseUp(e As MouseEventArgs) RaiseEvent MouseUp(Me, e) End Sub - Public Sub RaiseMouseMove(e As MouseEventArgs) + Friend Sub RaiseMouseMove(e As MouseEventArgs) RaiseEvent MouseMove(Me, e) End Sub Private Sub RaisePaint(e As PaintEventArgs) RaiseEvent Paint(Me, e) End Sub + Friend Sub RaiseMoved(e As EventArgs) + RaiseEvent Moved(Me, e) + End Sub + Friend Sub RaiseMoving(e As EventArgs) + RaiseEvent Moving(Me, e) + End Sub Public Property Type As PaintingObjectType Get @@ -376,16 +385,22 @@ Imports Newtonsoft.Json End Set End Property - Public ReadOnly Property Right As Integer + Public Property Right As Integer Get Return X + Width End Get + Set(value As Integer) + X = value - Width + End Set End Property - Public ReadOnly Property Bottom() As Integer + Public Property Bottom() As Integer Get Return Y + Height End Get + Set(value As Integer) + Y = value - Height + End Set End Property Public Property EnableResize As Boolean @@ -439,7 +454,11 @@ Imports Newtonsoft.Json Dim poevargs As New PaintingObjectPaintEventArgs(Me, g, offset) For Each dm As DelegateDrawPaintingObjectMethode In DrawMethodes - dm?.Invoke(poevargs) + Try + dm?.Invoke(poevargs) + Catch ex As Exception + _ErrorsAtDrawing += 1 + End Try Next If Selected AndAlso DrawSelectionMethode IsNot Nothing Then @@ -454,20 +473,27 @@ Imports Newtonsoft.Json Public Function Clone(includePinnedObject As Boolean) As Object Dim obj As New PaintingObject - Dim t As Type = Me.GetType - Dim blackField As New List(Of String) From { + Dim metype As Type = Me.GetType + Dim blackField As String() = { NameOf(_PinnedObjects), NameOf(resizeEngine), NameOf(_Parent), - NameOf(BufferedImage) + NameOf(BufferedImage), + NameOf(_ImageProperties) } - Dim fields As FieldInfo() = t.GetFields(BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.IgnoreCase Or BindingFlags.Instance) - For Each field As FieldInfo In fields - If Not blackField.Contains(field.Name) Then - field.SetValue(obj, field.GetValue(Me)) - End If - Next + Dim copyFields = + Sub(source As Object, dest As Object, blackFields As String(), t As Type) + Dim fields As New List(Of FieldInfo)(t.GetFields(BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.IgnoreCase Or BindingFlags.Instance)) + For Each field As FieldInfo In fields + If Not blackFields.Contains(field.Name) Then + field.SetValue(dest, field.GetValue(source)) + End If + Next + End Sub + + copyFields(Me, obj, blackField, metype) + copyfields(ImageProperties, obj.ImageProperties, {}, ImageProperties.GetType) If includePinnedObject Then obj.PinnedObjects.AddRange(PinnedObjects) diff --git a/Pilz.UI/PaintingControl/PaintingObjectResizing.vb b/Pilz.UI/PaintingControl/PaintingObjectResizing.vb index 002e303..76f1b9a 100644 --- a/Pilz.UI/PaintingControl/PaintingObjectResizing.vb +++ b/Pilz.UI/PaintingControl/PaintingObjectResizing.vb @@ -95,8 +95,12 @@ Imports Pilz.Drawing ElseIf Not mMouseDown Then - Dim eX As Integer = e.X - mObj.X + mObj.Parent.Offset.X - Dim eY As Integer = e.Y - mObj.Y + mObj.Parent.Offset.Y + Dim eXo As Integer = e.X + Dim eYo As Integer = e.Y + Dim eXwo As Integer = eXo - mObj.X + Dim eYwo As Integer = eYo - mObj.Y + Dim eX As Integer = eXwo + mObj.Parent.Offset.X + Dim eY As Integer = eYwo + mObj.Parent.Offset.Y Dim eLocation As New Point(eX, eY) Dim extRect As RectangleF = mObj.RectangleExtended Dim oldRect As RectangleF = mObj.Rectangle @@ -108,8 +112,9 @@ Imports Pilz.Drawing newRect.Height = (extRect.Height - oldRect.Height) / 2 Dim setToNone As Boolean = False + Dim isOnTop As Boolean = mObj.Parent.GetObject(New PointF(eXo, eYo), True) Is mObj - If Enabled Then + If Enabled AndAlso isOnTop Then Select Case True Case HelpfulDrawingFunctions.IsPointInRectangle(eLocation, New Rectangle(newRect.X, newRect.Y, newRect.Width, newRect.Height)) mObj.Cursor = Cursors.SizeNWSE diff --git a/Pilz.sln b/Pilz.sln index f366730..aba4084 100644 --- a/Pilz.sln +++ b/Pilz.sln @@ -23,6 +23,12 @@ Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Pilz.Configuration", "Pilz. EndProject Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Pilz.Reflection.PluginSystem", "Pilz.Reflection.PluginSystem\Pilz.Reflection.PluginSystem.vbproj", "{F7975470-4CA3-4FAB-BB6A-A3AF3978ABB7}" EndProject +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Pilz.Drawing.Drawing3D.OpenGLFactory", "Pilz.Drawing.Drawing3D.OpenGLRenderer\Pilz.Drawing.Drawing3D.OpenGLFactory.vbproj", "{5E9F0B0A-F7B8-49A9-80FC-6DFE0D44CC84}" +EndProject +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Pilz.Simple3DFileParser", "Pilz.Simple3DFileParser\Pilz.Simple3DFileParser.vbproj", "{AC955819-7910-450C-940C-7C1989483D4B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pilz.LicenseHelper", "Pilz.LicenseHelper\Pilz.LicenseHelper.csproj", "{67593FF7-C1D1-4529-98C4-61CBD0615F08}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -111,6 +117,30 @@ Global {F7975470-4CA3-4FAB-BB6A-A3AF3978ABB7}.Release|Any CPU.Build.0 = Release|Any CPU {F7975470-4CA3-4FAB-BB6A-A3AF3978ABB7}.Release|x86.ActiveCfg = Release|Any CPU {F7975470-4CA3-4FAB-BB6A-A3AF3978ABB7}.Release|x86.Build.0 = Release|Any CPU + {5E9F0B0A-F7B8-49A9-80FC-6DFE0D44CC84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5E9F0B0A-F7B8-49A9-80FC-6DFE0D44CC84}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5E9F0B0A-F7B8-49A9-80FC-6DFE0D44CC84}.Debug|x86.ActiveCfg = Debug|Any CPU + {5E9F0B0A-F7B8-49A9-80FC-6DFE0D44CC84}.Debug|x86.Build.0 = Debug|Any CPU + {5E9F0B0A-F7B8-49A9-80FC-6DFE0D44CC84}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5E9F0B0A-F7B8-49A9-80FC-6DFE0D44CC84}.Release|Any CPU.Build.0 = Release|Any CPU + {5E9F0B0A-F7B8-49A9-80FC-6DFE0D44CC84}.Release|x86.ActiveCfg = Release|Any CPU + {5E9F0B0A-F7B8-49A9-80FC-6DFE0D44CC84}.Release|x86.Build.0 = Release|Any CPU + {AC955819-7910-450C-940C-7C1989483D4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AC955819-7910-450C-940C-7C1989483D4B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AC955819-7910-450C-940C-7C1989483D4B}.Debug|x86.ActiveCfg = Debug|Any CPU + {AC955819-7910-450C-940C-7C1989483D4B}.Debug|x86.Build.0 = Debug|Any CPU + {AC955819-7910-450C-940C-7C1989483D4B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AC955819-7910-450C-940C-7C1989483D4B}.Release|Any CPU.Build.0 = Release|Any CPU + {AC955819-7910-450C-940C-7C1989483D4B}.Release|x86.ActiveCfg = Release|Any CPU + {AC955819-7910-450C-940C-7C1989483D4B}.Release|x86.Build.0 = Release|Any CPU + {67593FF7-C1D1-4529-98C4-61CBD0615F08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {67593FF7-C1D1-4529-98C4-61CBD0615F08}.Debug|Any CPU.Build.0 = Debug|Any CPU + {67593FF7-C1D1-4529-98C4-61CBD0615F08}.Debug|x86.ActiveCfg = Debug|Any CPU + {67593FF7-C1D1-4529-98C4-61CBD0615F08}.Debug|x86.Build.0 = Debug|Any CPU + {67593FF7-C1D1-4529-98C4-61CBD0615F08}.Release|Any CPU.ActiveCfg = Release|Any CPU + {67593FF7-C1D1-4529-98C4-61CBD0615F08}.Release|Any CPU.Build.0 = Release|Any CPU + {67593FF7-C1D1-4529-98C4-61CBD0615F08}.Release|x86.ActiveCfg = Release|Any CPU + {67593FF7-C1D1-4529-98C4-61CBD0615F08}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE