home *** CD-ROM | disk | FTP | other *** search
/ Planet Source Code Jumbo …e CD Visual Basic 1 to 7 / 3_2004-2005.ISO / Data / Zips / A_3D_Engin178818912004.psc / Application.cls < prev   
Text File  |  2004-09-01  |  63KB  |  1,303 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4.   Persistable = 0  'NotPersistable
  5.   DataBindingBehavior = 0  'vbNone
  6.   DataSourceBehavior  = 0  'vbNone
  7.   MTSTransactionMode  = 0  'NotAnMTSObject
  8. END
  9. Attribute VB_Name = "Application"
  10. Attribute VB_GlobalNameSpace = False
  11. Attribute VB_Creatable = True
  12. Attribute VB_PredeclaredId = False
  13. Attribute VB_Exposed = False
  14. Option Explicit
  15.  
  16. ' Define the name of this class/module for error-trap reporting.
  17. Private Const mc_ModuleName As String = "Peters3DEngine7.Application"
  18.  
  19. ' ============================
  20. ' Simulation State / Settings.
  21. ' ============================
  22. Public GameState As String
  23. Private m_blnVideoFullScreen As Boolean
  24. Private m_blnDetailClipBoundary As Boolean
  25. Private m_blnDetailPartialPolygons As Boolean
  26. Private m_blnDetailPolygonsOutside As Boolean
  27. Private m_blnDetailLCDScreen As Boolean
  28. Private m_intDetailDrawMode As Integer
  29. Private m_blnDetailEdgedFaces As Boolean
  30. Private m_blnDetailDayMode As Boolean
  31. Private m_blnDetailShadows As Boolean
  32. Private m_intInputMouseSensitivity As Integer
  33. Private m_blnIgnoreEvent As Boolean
  34.  
  35. ' This is where most of the drawing occurs.
  36. ' =========================================
  37. Public WithEvents m_frmCanvas As frmCanvas
  38. Attribute m_frmCanvas.VB_VarHelpID = -1
  39. Private WithEvents m_frmSettings As frmSettings
  40. Attribute m_frmSettings.VB_VarHelpID = -1
  41.  
  42.  
  43. ' This big-fat array holds ALL 3D objects in this aplication!
  44. ' (Arrays are much faster than VB Classes & Collections)
  45. ' ===========================================================
  46. Private m_AllObjects()          As mdr3DObject
  47. Private m_Primitives()          As mdrPrimitive
  48.  
  49. Private m_Camera                As mdr3DTargetCamera
  50. Private m_matViewOrientation    As mdrMatrix4
  51. Private m_matViewMapping        As mdrMatrix4
  52. Private m_matViewPort           As mdrMatrix4
  53.  
  54. Private m_PlayerOne             As mdrPlayer
  55.  
  56. Private m_blnMouseCapture As Boolean
  57. Private m_RenderOptions As Integer ' Temporary rendering options.
  58.  
  59. Private Sub Init_MIDISoundtrack()
  60.  
  61.     ' ==========================================
  62.     ' Init. Multimedia Control & Open MIDI File.
  63.     ' ==========================================
  64.     With m_frmCanvas.MMControl1
  65.         .Visible = False
  66.         .DeviceType = "Sequencer"
  67.         .FileName = App.Path & "\Europe - The Final Countdown.mid"
  68.         .UpdateInterval = 1
  69.         .Command = "OPEN"
  70. '        .From = 575
  71. '        .To = 630
  72.         .Command = "PLAY"
  73.     End With
  74.     
  75. End Sub
  76. Private Sub DoMasterReset()
  77.     
  78.     ' =======================================
  79.     ' General Settings. Change these for fun!
  80.     ' =======================================
  81.     m_blnDetailClipBoundary = True
  82.     m_intInputMouseSensitivity = 16
  83.     m_blnDetailLCDScreen = True
  84.     m_blnVideoFullScreen = True
  85.     m_blnDetailClipBoundary = False
  86.     m_intDetailDrawMode = 1 ' << Wireframe, Flat, Gouraud.
  87.     m_blnDetailEdgedFaces = True
  88.     m_blnDetailDayMode = False
  89.     m_blnDetailShadows = False
  90.     
  91.     ' ====================
  92.     ' Setup form / canvas.
  93.     ' ====================
  94.     m_frmCanvas.ScaleMode = vbPixels
  95.     
  96.     ' ====================================
  97.     ' Load Animation Scene from Text File.
  98.     ' ====================================
  99.     Call ReadAnimationFile
  100.     
  101.     ' ==========================================
  102.     ' This routine is used to load some objects.
  103.     ' ==========================================
  104.     Dim objTestGrid As mdr3DObject
  105.     Dim obj3DStudio As mdr3DObject
  106.     
  107.     ' ================
  108.     ' Load "TestGrid".
  109.     ' ================
  110.     objTestGrid = LoadGroundGrid()
  111.     objTestGrid.ID = "TestGrid"
  112.     objTestGrid.Class = "GeometryDots"
  113.     objTestGrid.Caption = "TestGrid"
  114.     objTestGrid.Description = "TestGrid"
  115.     objTestGrid.UniformScale = 1
  116.     
  117.     
  118.     ' Load "3DStudio" Text.
  119.     ' =====================
  120.     obj3DStudio = mDirectXParser2.LoadXFile(App.Path & "\xFiles\3DStudio_only.X")
  121.     obj3DStudio.ID = "3DStudio_only.X"
  122.     obj3DStudio.Class = "Geometry"
  123.     obj3DStudio.Caption = "3DStudio_only.X"
  124.     obj3DStudio.Description = "3DStudio_only.X"
  125.     obj3DStudio.UniformScale = 1
  126.     obj3DStudio.WorldPosition.Y = 16
  127.  
  128.  
  129.     ' ==============================
  130.     ' Reserve space for the objects.
  131.     ' ==============================
  132.     ReDim m_AllObjects(1) As mdr3DObject
  133.           m_AllObjects(0) = objTestGrid
  134.           m_AllObjects(1) = obj3DStudio
  135.     
  136.     
  137.     ' ===============================
  138.     ' Reset Camera / Player Position.
  139.     ' ===============================
  140.     m_PlayerOne.WorldPosition.X = 0
  141.     m_PlayerOne.WorldPosition.Y = 0
  142.     m_PlayerOne.WorldPosition.Z = -2000
  143.     m_PlayerOne.VPN.X = 0
  144.     m_PlayerOne.VPN.Y = 0
  145.     m_PlayerOne.VPN.Z = -1
  146.     
  147.     m_Camera.FreeCamera = False
  148.     
  149.     m_Camera.WorldPosition.X = 0
  150.     m_Camera.WorldPosition.Y = 0
  151.     m_Camera.WorldPosition.Z = -2000
  152.     m_Camera.WorldPosition.w = 1
  153.     
  154.     m_Camera.LookAtPoint.X = 0
  155.     m_Camera.LookAtPoint.Y = 0
  156.     m_Camera.LookAtPoint.Z = -2001
  157.     m_Camera.LookAtPoint.w = 1
  158.     
  159.     m_Camera.VPN.X = 0
  160.     m_Camera.VPN.Y = 0
  161.     m_Camera.VPN.Z = 1
  162.     m_Camera.VPN.w = 1
  163.     
  164.     m_Camera.VUP.X = 0
  165.     m_Camera.VUP.Y = 1
  166.     m_Camera.VUP.Z = 0
  167.     m_Camera.VUP.w = 1#
  168.     
  169.     ' Remember: PRP is specified in Camera Coordinates.
  170.     m_Camera.PRP.X = 0 ' u
  171.     m_Camera.PRP.Y = 0 ' v
  172.     m_Camera.PRP.Z = 2.666 ' n << Change this value to distort the perspective!
  173.     m_Camera.PRP.Z = 1.333
  174.     m_Camera.PRP.w = 1#
  175.     
  176.     
  177.     ' ==========================================================================
  178.     ' The UV coordinate system is our 'virtual window' into the 3D world.
  179.     ' --------------------------------------------------------------------------
  180.     ' All objects in our scene are clipped to this 'virtual window'. After we
  181.     ' have finished doing all the 3D calculations, we then transform everything
  182.     ' within this 'virtual window' into the 'actual window'; this is our Windows
  183.     ' Form. If the 'virtual window' is a perfect square, then we need to make
  184.     ' sure the form we are drawing too is also a perfect square, otherwise we'll
  185.     ' get an image that looks squashed. The normal aspect ratio of a computer
  186.     ' monitor is 1:1.333  Some typicaly ratios are 640x480, 800x600, 1024x768
  187.     '   Example: 1024 / 768 = 1.333
  188.     ' For this reason, I often make the 'virtual window' the same shape as our
  189.     ' form by making it the same aspect ratio.
  190.     ' ==========================================================================
  191.     m_Camera.Umin = (-1 + m_Camera.UPan) * 1.333
  192.     m_Camera.Umax = (1 + m_Camera.UPan) * 1.333
  193.     m_Camera.Vmin = -1 + m_Camera.VPan
  194.     m_Camera.Vmax = 1 + m_Camera.VPan
  195.     
  196.     m_Camera.ClipNear = 0
  197.     m_Camera.ClipFar = -2048 ' (any negative number)
  198.         
  199.     ' =================================================================
  200.     ' The ViewPort (VP) bounds must be specified in pixels (not twips).
  201.     ' -----------------------------------------------------------------
  202.     ' Typicall values are as follows:
  203.     '       VPXmin = 0
  204.     '       VPXmax = 1024
  205.     '       VPYmin = 0
  206.     '       VPYmax = 768
  207.     ' Note: I usually put a 128 pixel border around this for testing
  208.     '       the clipping procedure.
  209.     ' =================================================================
  210.     m_Camera.VPXmin = 0
  211.     m_Camera.VPXmax = m_frmCanvas.ScaleWidth
  212.     m_Camera.VPYmin = m_frmCanvas.ScaleHeight
  213.     m_Camera.VPYmax = 0
  214.         
  215. End Sub
  216.  
  217. Private Sub DoOutputStatistics(withHandle As Form, DayMode As Boolean)
  218.  
  219.     Dim lngTempOnly As Long
  220.     Dim curTemp64BitInteger As Currency
  221.     Dim lngColBright As Long
  222.     Dim lngColDim As Long
  223.     
  224.     
  225.     If DayMode = True Then
  226.         lngColBright = RGB(0, 0, 255)
  227.         lngColDim = RGB(160, 160, 255)
  228.     Else
  229.         lngColBright = RGB(255, 0, 0)
  230.         lngColDim = RGB(128, 0, 0)
  231.     End If
  232.     
  233.     
  234.     ' Update debug & info. counters (conditionally compiled)
  235.     ' NOTE: Putting this part in the display loop, isn't really a great idea, it slows things down.
  236.     #If g_blnCompiledDebugInfo = True Then
  237.     
  238.         withHandle.Font = "Courier"
  239.         withHandle.FontSize = 7
  240.         withHandle.FontBold = False
  241.         withHandle.ForeColor = lngColDim
  242.         withHandle.CurrentY = withHandle.ScaleTop
  243.         withHandle.CurrentX = withHandle.ScaleLeft
  244.  
  245.         lngTempOnly = g_lngMultiplicationCount + g_lngDivisionCount + g_lngAdditionCount + g_lngSubtractionCount + g_lngSquareRootCount
  246.         If lngTempOnly = 0 Then lngTempOnly = 1
  247.         
  248.         withHandle.Print "Multiplications /frame : " & Format(g_lngMultiplicationCount, "###,000,000") & "  " & Format(g_lngMultiplicationCount / lngTempOnly, "00%")
  249.         withHandle.Print "Divisions              : " & Format(g_lngDivisionCount, "###,000,000") & "  " & Format(g_lngDivisionCount / lngTempOnly, "00%")
  250.         withHandle.Print "Additions              : " & Format(g_lngAdditionCount, "###,000,000") & "  " & Format(g_lngAdditionCount / lngTempOnly, "00%")
  251.         withHandle.Print "Subtractions           : " & Format(g_lngSubtractionCount, "###,000,000") & "  " & Format(g_lngSubtractionCount / lngTempOnly, "00%")
  252.         withHandle.Print "Square Roots           : " & Format(g_lngSquareRootCount, "###,000,000") & "  " & Format(g_lngSquareRootCount / lngTempOnly, "00%")
  253.         withHandle.ForeColor = lngColBright
  254.         withHandle.Print "Polygons Drawn         : " & Format(g_lngPolygonCount, "###,000,000")
  255.         withHandle.ForeColor = lngColDim
  256.         
  257.         curTemp64BitInteger = (GetPerformanceCounter - g_curFramePerfCount) / g_curPerformanceFrequency
  258.         withHandle.Print "Frame Draw Time (sec.) : " & curTemp64BitInteger
  259.         
  260.         withHandle.ForeColor = lngColBright
  261.         withHandle.Print "Frame Rate (approx.)   : " & Format(1 / curTemp64BitInteger, "#,##0.0")
  262.         
  263.     #End If
  264.  
  265. End Sub
  266.  
  267. Private Sub DoUpdateSettingsWindow()
  268.  
  269.     If (m_frmSettings Is Nothing) Then Exit Sub
  270.     If m_frmSettings.IsFormLoaded = False Then Exit Sub
  271.     
  272.     With m_frmSettings
  273.         .txtCameraX.Text = m_Camera.WorldPosition.X
  274.         .txtCameraY.Text = m_Camera.WorldPosition.Y
  275.         .txtCameraZ.Text = m_Camera.WorldPosition.Z
  276.         
  277.         .txtClipNear.Text = m_Camera.ClipNear
  278.         .txtClipFar.Text = m_Camera.ClipFar
  279.         
  280.         .txtDocResWidth.Text = m_Camera.VPXmax - m_Camera.VPXmin
  281.         .txtDocResHeight.Text = m_Camera.VPYmin - m_Camera.VPYmax
  282.         
  283.         .txtFOV.Text = m_Camera.FOV
  284.         .txtZoom.Text = m_Camera.Zoom
  285.         .txtPRPz.Text = m_Camera.PRP.Z
  286.         
  287.     End With
  288.     
  289. End Sub
  290.  
  291. Private Sub PrintAnimationText(FontSize As Integer, Text As String)
  292.  
  293.     m_frmCanvas.Font = "Arial Bold"
  294.     m_frmCanvas.FontSize = FontSize
  295.     If m_blnDetailDayMode = True Then
  296.         m_frmCanvas.ForeColor = vbBlack
  297.     Else
  298.         m_frmCanvas.ForeColor = vbWhite
  299.     End If
  300.     
  301.     Dim sngTextWidth As Single
  302.     Dim sngTextHeight As Single
  303.     
  304.     sngTextWidth = m_frmCanvas.TextWidth(Text)
  305.     sngTextHeight = m_frmCanvas.TextHeight(Text)
  306.     
  307.     m_frmCanvas.CurrentX = (m_frmCanvas.ScaleWidth - sngTextWidth) / 2
  308.     m_frmCanvas.CurrentY = (m_frmCanvas.ScaleHeight - sngTextHeight) / 2
  309.     
  310.     m_frmCanvas.Print Text
  311.     
  312. End Sub
  313.  
  314. Private Sub zTest()
  315.  
  316.     Dim intObject As Integer
  317.     Dim intPart As Integer
  318.     Dim intFace As Integer
  319.     
  320.     For intObject = LBound(m_AllObjects) To (UBound(m_AllObjects) - 1)
  321.     
  322.         For intPart = 0 To UBound(m_AllObjects(intObject).Parts)
  323.             For intFace = 0 To UBound(m_AllObjects(intObject).Parts(intPart).Faces)
  324.             
  325.             Next intFace
  326.         Next intPart
  327.     Next intObject
  328.  
  329. End Sub
  330.  
  331. Private Function LoadGroundGrid() As mdr3DObject
  332.     
  333.     Dim sngX As Double
  334.     Dim sngY As Double
  335.     Dim sngZ As Double
  336.     Dim lngVertexCount As Long
  337.     
  338.     ReDim LoadGroundGrid.Parts(0)
  339.     
  340.     Const sngMax = 1000!
  341.     Const sngStep = 100!
  342.     
  343.     For sngZ = -sngMax To sngMax Step sngStep
  344.         For sngX = -sngMax To sngMax Step sngStep
  345.             For sngY = 0 To sngMax Step sngStep
  346.                 With LoadGroundGrid.Parts(0)
  347.                     If (Abs(sngX) = sngMax) And (Abs(sngY) = sngMax) Then
  348.                         ReDim Preserve LoadGroundGrid.Parts(0).Vertices(lngVertexCount)
  349.                         .Vertices(lngVertexCount).Pxyz.X = sngX
  350.                         .Vertices(lngVertexCount).Pxyz.Y = sngY
  351.                         .Vertices(lngVertexCount).Pxyz.Z = sngZ
  352.                         .Vertices(lngVertexCount).Pxyz.w = 1
  353.                         .Vertices(lngVertexCount).RGB_Red = 255: .Vertices(lngVertexCount).RGB_Green = 127: .Vertices(lngVertexCount).RGB_Blue = 127
  354.                         lngVertexCount = lngVertexCount + 1
  355.                     ElseIf (Abs(sngY) = sngMax) And (Abs(sngZ) = sngMax) Then
  356.                         ReDim Preserve LoadGroundGrid.Parts(0).Vertices(lngVertexCount)
  357.                         .Vertices(lngVertexCount).Pxyz.X = sngX
  358.                         .Vertices(lngVertexCount).Pxyz.Y = sngY
  359.                         .Vertices(lngVertexCount).Pxyz.Z = sngZ
  360.                         .Vertices(lngVertexCount).Pxyz.w = 1
  361.                         .Vertices(lngVertexCount).RGB_Red = 127: .Vertices(lngVertexCount).RGB_Green = 255: .Vertices(lngVertexCount).RGB_Blue = 127
  362.                         lngVertexCount = lngVertexCount + 1
  363.                     ElseIf (Abs(sngX) = sngMax) And (Abs(sngZ) = sngMax) Then
  364.                         ReDim Preserve LoadGroundGrid.Parts(0).Vertices(lngVertexCount)
  365.                         .Vertices(lngVertexCount).Pxyz.X = sngX
  366.                         .Vertices(lngVertexCount).Pxyz.Y = sngY
  367.                         .Vertices(lngVertexCount).Pxyz.Z = sngZ
  368.                         .Vertices(lngVertexCount).Pxyz.w = 1
  369.                         .Vertices(lngVertexCount).RGB_Red = 127: .Vertices(lngVertexCount).RGB_Green = 127: .Vertices(lngVertexCount).RGB_Blue = 255
  370.                         lngVertexCount = lngVertexCount + 1
  371.                     ElseIf (sngX = 0) Then
  372.                         ReDim Preserve LoadGroundGrid.Parts(0).Vertices(lngVertexCount)
  373.                         .Vertices(lngVertexCount).Pxyz.X = sngX
  374.                         .Vertices(lngVertexCount).Pxyz.Y = sngY
  375.                         .Vertices(lngVertexCount).Pxyz.Z = sngZ
  376.                         .Vertices(lngVertexCount).Pxyz.w = 1
  377.                         .Vertices(lngVertexCount).RGB_Red = 255: .Vertices(lngVertexCount).RGB_Green = 0: .Vertices(lngVertexCount).RGB_Blue = 0
  378.                         lngVertexCount = lngVertexCount + 1
  379.                     ElseIf (sngY = 0) Then
  380.                         ReDim Preserve LoadGroundGrid.Parts(0).Vertices(lngVertexCount)
  381.                         .Vertices(lngVertexCount).Pxyz.X = sngX ' Rnd * (sngMax * 2) - sngMax 'sngX
  382.                         .Vertices(lngVertexCount).Pxyz.Y = sngY
  383.                         .Vertices(lngVertexCount).Pxyz.Z = sngZ ' Rnd * (sngMax * 2) - sngMax 'sngZ
  384.                         .Vertices(lngVertexCount).Pxyz.w = 1
  385.                         .Vertices(lngVertexCount).RGB_Red = 0: .Vertices(lngVertexCount).RGB_Green = 255: .Vertices(lngVertexCount).RGB_Blue = 0
  386.                         lngVertexCount = lngVertexCount + 1
  387.                     ElseIf (sngZ = 0) Then
  388.                         ReDim Preserve LoadGroundGrid.Parts(0).Vertices(lngVertexCount)
  389.                         .Vertices(lngVertexCount).Pxyz.X = sngX
  390.                         .Vertices(lngVertexCount).Pxyz.Y = sngY
  391.                         .Vertices(lngVertexCount).Pxyz.Z = sngZ
  392.                         .Vertices(lngVertexCount).Pxyz.w = 1
  393.                         .Vertices(lngVertexCount).RGB_Red = 127: .Vertices(lngVertexCount).RGB_Green = 127: .Vertices(lngVertexCount).RGB_Blue = 255
  394.                         lngVertexCount = lngVertexCount + 1
  395.                     End If
  396.                 End With
  397.             Next sngY
  398.         Next sngX
  399.     Next sngZ
  400.         
  401. End Function
  402.  
  403. Private Sub RefreshF5()
  404.     
  405.     #If g_blnCompiledDebugInfo = True Then
  406.         ' Reset debug/info. counters (conditionally compiled)
  407.         g_lngMultiplicationCount = 0
  408.         g_lngDivisionCount = 0
  409.         g_lngAdditionCount = 0
  410.         g_lngSubtractionCount = 0
  411.         g_lngSquareRootCount = 0
  412.         g_lngPolygonCount = 0
  413.         g_curFramePerfCount = GetPerformanceCounter
  414.     #End If
  415.     
  416.     ' =================
  417.     ' Erase the screen.
  418.     ' =================
  419.     If m_blnDetailDayMode = True Then
  420.         m_frmCanvas.BackColor = vbWhite
  421.     Else
  422.         m_frmCanvas.BackColor = vbBlack
  423.     End If
  424.     m_frmCanvas.Cls
  425.     
  426.     
  427.     ' =================================================
  428.     ' Place a 128 pixel border around the viewing area.
  429.     ' =================================================
  430.     If m_blnVideoFullScreen = True Then
  431.         m_Camera.VPXmin = m_frmCanvas.ScaleLeft
  432.         m_Camera.VPXmax = m_frmCanvas.ScaleWidth
  433.         m_Camera.VPYmin = m_frmCanvas.ScaleHeight
  434.         m_Camera.VPYmax = m_frmCanvas.ScaleTop
  435.     Else
  436.         m_Camera.VPXmin = m_frmCanvas.ScaleLeft + 64
  437.         m_Camera.VPXmax = m_frmCanvas.ScaleWidth - 64
  438.         m_Camera.VPYmin = m_frmCanvas.ScaleHeight - 64
  439.         m_Camera.VPYmax = m_frmCanvas.ScaleTop + 128
  440.     End If
  441.     
  442.     
  443.     m_Camera.WorldPosition = m_PlayerOne.WorldPosition
  444.     Call DoSetDrawingParamaters(m_Camera)
  445.     m_Camera.FOV = ConvertRad2Deg(2 * Atn((m_Camera.Umax - m_Camera.Umin) / m_Camera.PRP.Z))
  446.     m_Camera.Zoom = Round(1 / Tan(ConvertDeg2Rad(m_Camera.FOV) / 2), 5)
  447.     
  448.     
  449.     ' =======================================================
  450.     ' Map canonical view volume into 3D viewport view volume.
  451.     ' =======================================================
  452.     With m_frmCanvas
  453.         m_matViewPort = Matrix_vv3dv(m_frmCanvas, m_Camera.VPXmin, m_Camera.VPXmax, m_Camera.VPYmin, m_Camera.VPYmax, -1, 0, m_blnDetailClipBoundary, m_blnDetailDayMode)
  454.     End With
  455.     
  456.     ' =====================================================================================
  457.     ' Draw shadows first. Note: To draw shadows, you have to traverse through the render
  458.     ' pipeline twice, thus slowing everything down and doubling the number of calculations.
  459.     ' =====================================================================================
  460.     If (m_blnDetailShadows = True) And (m_Camera.WorldPosition.Y > 0) Then
  461.         m_RenderOptions = 1
  462.         Call RenderPipeline0
  463.     End If
  464.     
  465.     ' ==============
  466.     ' Draw normally.
  467.     ' ==============
  468.     m_RenderOptions = 0
  469.     Call RenderPipeline0
  470.     
  471.     
  472.     ' ==========================================
  473.     ' Output some text to the screen. (optional)
  474.     ' ==========================================
  475.     Call DoOutputStatistics(m_frmCanvas, m_blnDetailDayMode)
  476.     
  477.     
  478.     ' ==============================================
  479.     ' Update settings window, but only if it's open.
  480.     ' ==============================================
  481.     Call DoUpdateSettingsWindow
  482.     
  483.  
  484.     Screen.MousePointer = vbDefault
  485.  
  486. End Sub
  487.  
  488. Private Sub RenderPipeline0()
  489.  
  490.     On Error GoTo errTrap
  491.     
  492.     Dim intObject As Integer
  493.     For intObject = LBound(m_AllObjects) To UBound(m_AllObjects)
  494.         With m_AllObjects(intObject)
  495.             
  496.             ' Draw each Part within the 3DObject.
  497.             Dim lngPart As Long
  498.             For lngPart = 0 To UBound(.Parts)
  499.             
  500.                 Dim vectLight As mdrVector4
  501.                 vectLight.X = -64
  502.                 vectLight.Y = 128
  503.                 vectLight.Z = 256
  504.                 vectLight.w = 1
  505.                 
  506.                 Dim vectPlaneEq As mdrVector4
  507.                 vectPlaneEq.X = 0
  508.                 vectPlaneEq.Y = 100
  509.                 vectPlaneEq.Z = 0
  510.                 vectPlaneEq.w = 1
  511.                 
  512.                 Dim matShadow As mdrMatrix4
  513.                 matShadow = MatrixShadow(vectLight, vectPlaneEq)
  514.                 
  515.                 Dim matOutput As mdrMatrix4
  516.                 Dim matWorld As mdrMatrix4
  517.                 matOutput = MatrixIdentity()
  518.                 
  519.                 .Parts(lngPart).IdentityMatrix = MatrixIdentity
  520.                 matOutput = MakeWorldMatrix(.Parts(lngPart).IdentityMatrix, .WorldPosition, 0, 0, 0, .UniformScale)
  521.                 
  522.                 If m_RenderOptions <> 0 Then matOutput = MatrixMultiply(matOutput, matShadow)
  523.                 matOutput = MatrixMultiply(matOutput, m_matViewOrientation)
  524.                 matOutput = MatrixMultiply(matOutput, m_matViewMapping)
  525.                 
  526.                 ' For each vertex in the Part, recalculate.
  527.                 Dim blnClipMe As Boolean
  528.                 Dim sngW As Double
  529.                 
  530.                 Dim intJ As Integer
  531.                 For intJ = 0 To UBound(.Parts(lngPart).Vertices)
  532.                     
  533.                     With .Parts(lngPart).Vertices(intJ)
  534.                         
  535.                         ' Do some heavy number crunching here.
  536.                         .Wxyz = MatrixMultiplyVector(matOutput, .Pxyz)
  537.                         
  538.                         .Clipped = False
  539.                         sngW = .Wxyz.w
  540.                         If sngW > 0 Then
  541.                             ' W is positive.
  542.                             If (.Wxyz.X < -sngW) Or (.Wxyz.X > sngW) Then .Clipped = True
  543.                             If (.Wxyz.Y < -sngW) Or (.Wxyz.Y > sngW) Then .Clipped = True
  544.                             If (.Wxyz.Z < -sngW) Or (.Wxyz.Z > 0) Then .Clipped = True
  545.                         Else
  546.                             ' W is negative
  547.                             If (.Wxyz.X < -sngW) Or (.Wxyz.X > sngW) Then .Clipped = True
  548.                             If (.Wxyz.Y < -sngW) Or (.Wxyz.Y > sngW) Then .Clipped = True
  549.                             If (.Wxyz.Z < -sngW) Or (.Wxyz.Z > 0) Then .Clipped = True
  550.                         End If
  551.                         
  552.                         If (.Clipped = False) Then
  553.                             .Brightness = Abs(1 - .Wxyz.w)
  554.                             If .Brightness > 1 Then .Brightness = 1
  555.                         End If
  556.                         
  557.                     End With
  558.                 Next intJ
  559.                 
  560.                 
  561.             ' ==========================
  562.             ' >>> Clip Polygons Here <<<
  563.             ' ==========================
  564. ''            Call DoClipping(.Parts(lngPart))
  565.             
  566.             
  567. SkipOver:
  568.             Next lngPart
  569.             
  570. '            m_matViewPort = MatrixIdentity
  571.             ' Convert canonical view volume into 3D viewport view volume.
  572.             ' ClipSpace -> ViewPort (ie. to pixels)
  573.             On Error GoTo errTrap2
  574.             For lngPart = 0 To UBound(.Parts)
  575.                 For intJ = 0 To UBound(.Parts(lngPart).Vertices)
  576.                     With .Parts(lngPart).Vertices(intJ)
  577.                         .Txyz = MatrixMultiplyVector(m_matViewPort, .Wxyz)
  578. '                        .Txyz.Y = -.Txyz.Y
  579.                     End With
  580.                 Next intJ
  581. SkipOver2:
  582.             Next lngPart
  583.  
  584.             
  585.             ' Convert from 4D down to 3D
  586.             ' ==========================
  587.             Call Convert4Dto3D(m_AllObjects(intObject))
  588.             
  589.             
  590.             ' ==============
  591.             ' Draw 3D Object
  592.             ' ==============
  593.             Select Case m_AllObjects(intObject).Class
  594.                 Case "GeometryDots"
  595.                     Call Draw_DotsOnly(m_AllObjects(intObject))
  596.                 
  597.                 Case Else
  598.                     Call Draw_SimpleWireframe(m_AllObjects(intObject))
  599.                     
  600.             End Select
  601.             
  602.             
  603. ''            ' Display Hollowed Lines
  604. ''            m_frmCanvas.DrawMode = vbCopyPen
  605. ''            m_frmCanvas.DrawStyle = vbDot
  606. ''            m_frmCanvas.DrawWidth = 1
  607. ''            m_frmCanvas.ForeColor = RGB(0, 128, 0)
  608. ''            Call Draw_SimpleWireframeH(m_AllObjects(intObject), -1)
  609. ''
  610. ''            m_frmCanvas.DrawMode = vbCopyPen
  611. ''            m_frmCanvas.DrawStyle = vbSolid
  612. ''            m_frmCanvas.DrawWidth = 8
  613. ''            m_frmCanvas.ForeColor = RGB(0, 0, 0)
  614. ''            Call Draw_SimpleWireframeH(m_AllObjects(intObject), 1)
  615. ''
  616. ''            m_frmCanvas.DrawMode = vbCopyPen
  617. ''            m_frmCanvas.DrawStyle = vbSolid
  618. ''            m_frmCanvas.DrawWidth = 1
  619. ''            m_frmCanvas.ForeColor = RGB(0, 255, 0)
  620. ''            Call Draw_SimpleWireframeH(m_AllObjects(intObject), 1)
  621. '            m_frmCanvas.Refresh
  622.             
  623.         End With
  624.     Next intObject
  625.     
  626.     
  627.     Exit Sub
  628. errTrap:
  629.     Resume SkipOver
  630.     
  631. errTrap2:
  632.     Resume SkipOver2
  633.     
  634. End Sub
  635.  
  636. Private Sub RenderPipeline00()
  637.    
  638.    ' =======================================================================================
  639.    ' -------------------[ Double-Zero is the default wire-frame renderer ]------------------
  640.    '
  641.    ' * Backfaces are included. Nothing complicated.
  642.    ' * Worse-case rendering used to measure performance against improved rendering piplines.
  643.    ' =======================================================================================
  644.    On Error GoTo errTrap
  645.    
  646.     Dim intObject As Integer
  647.     Dim lngPart As Long
  648.     Dim lngFace As Long
  649.     Dim matOutput As mdrMatrix4
  650.     Dim matWorld As mdrMatrix4
  651.     Dim matIWorld As mdrMatrix4
  652.     Dim vectLight As mdrVector4
  653.     Dim vectPlaneEq As mdrVector4
  654.     Dim matShadow As mdrMatrix4
  655.     Dim blnClipMe As Boolean
  656.     Dim sngW As Double
  657.     Dim intJ As Integer
  658.     Dim vectCamera As mdrVector4
  659.     Dim vectVertex As mdrVector4
  660.     Dim lngIndex0 As Long, lngIndex1 As Long, lngIndex2 As Long
  661.     Dim vect0 As mdrVector4, vect1 As mdrVector4, vect2 As mdrVector4
  662.     Dim sngDotProduct As Single
  663.     
  664.     For intObject = LBound(m_AllObjects) To (UBound(m_AllObjects))
  665.         With m_AllObjects(intObject)
  666.             
  667.             ' Draw each Part within the 3DObject.
  668.             For lngPart = 0 To UBound(.Parts)
  669.             
  670.                 matWorld = MakeWorldMatrix(.Parts(lngPart).IdentityMatrix, .WorldPosition, 0, 0, 0, 1)
  671. '                matIWorld = MatrixInverse(matWorld)
  672. '                vectCamera = MatrixMultiplyVector(matIWorld, m_Camera.WorldPosition)
  673.                 
  674.                 matOutput = MatrixMultiply(matWorld, m_matViewOrientation)
  675.                 matOutput = MatrixMultiply(matOutput, m_matViewMapping)
  676.                 matOutput = MatrixMultiply(matOutput, m_matViewPort)
  677.                 
  678.                 ' Draw each polygon for the given polyhedra.
  679.                 For lngFace = 0 To UBound(.Parts(lngPart).Faces)
  680.                 
  681.                     lngIndex0 = .Parts(lngPart).Faces(lngFace)(0)
  682.                     lngIndex1 = .Parts(lngPart).Faces(lngFace)(1)
  683.                     lngIndex2 = .Parts(lngPart).Faces(lngFace)(2)
  684.                     
  685.                     vect0 = .Parts(lngPart).Vertices(lngIndex0).Pxyz
  686.                     vect1 = .Parts(lngPart).Vertices(lngIndex1).Pxyz
  687.                     vect2 = .Parts(lngPart).Vertices(lngIndex2).Pxyz
  688.                     
  689.                     .Parts(lngPart).Vertices(lngIndex0).Txyz = MatrixMultiplyVector(matOutput, .Parts(lngPart).Vertices(lngIndex0).Pxyz)
  690.                     .Parts(lngPart).Vertices(lngIndex1).Txyz = MatrixMultiplyVector(matOutput, .Parts(lngPart).Vertices(lngIndex1).Pxyz)
  691.                     .Parts(lngPart).Vertices(lngIndex2).Txyz = MatrixMultiplyVector(matOutput, .Parts(lngPart).Vertices(lngIndex2).Pxyz)
  692.                     
  693.                     .Parts(lngPart).Vertices(lngIndex0).Txyz.X = .Parts(lngPart).Vertices(lngIndex0).Txyz.X / .Parts(lngPart).Vertices(lngIndex0).Txyz.w
  694.                     .Parts(lngPart).Vertices(lngIndex0).Txyz.Y = .Parts(lngPart).Vertices(lngIndex0).Txyz.Y / .Parts(lngPart).Vertices(lngIndex0).Txyz.w
  695.                     .Parts(lngPart).Vertices(lngIndex0).Txyz.Z = .Parts(lngPart).Vertices(lngIndex0).Txyz.Z / .Parts(lngPart).Vertices(lngIndex0).Txyz.w
  696.                     
  697.                     .Parts(lngPart).Vertices(lngIndex1).Txyz.X = .Parts(lngPart).Vertices(lngIndex1).Txyz.X / .Parts(lngPart).Vertices(lngIndex1).Txyz.w
  698.                     .Parts(lngPart).Vertices(lngIndex1).Txyz.Y = .Parts(lngPart).Vertices(lngIndex1).Txyz.Y / .Parts(lngPart).Vertices(lngIndex1).Txyz.w
  699.                     .Parts(lngPart).Vertices(lngIndex1).Txyz.Z = .Parts(lngPart).Vertices(lngIndex1).Txyz.Z / .Parts(lngPart).Vertices(lngIndex1).Txyz.w
  700.                     
  701.                     .Parts(lngPart).Vertices(lngIndex2).Txyz.X = .Parts(lngPart).Vertices(lngIndex2).Txyz.X / .Parts(lngPart).Vertices(lngIndex2).Txyz.w
  702.                     .Parts(lngPart).Vertices(lngIndex2).Txyz.Y = .Parts(lngPart).Vertices(lngIndex2).Txyz.Y / .Parts(lngPart).Vertices(lngIndex2).Txyz.w
  703.                     .Parts(lngPart).Vertices(lngIndex2).Txyz.Z = .Parts(lngPart).Vertices(lngIndex2).Txyz.Z / .Parts(lngPart).Vertices(lngIndex2).Txyz.w
  704.                     
  705.                     vect0 = .Parts(lngPart).Vertices(lngIndex0).Txyz
  706.                     vect1 = .Parts(lngPart).Vertices(lngIndex1).Txyz
  707.                     vect2 = .Parts(lngPart).Vertices(lngIndex2).Txyz
  708.                     
  709.                     Call DrawFlatTriangle(m_frmCanvas, vect0.X, vect0.Y, vect1.X, vect1.Y, vect2.X, vect2.Y, RGB(0, 0, 255), -1, vbSolid, vbFSSolid)
  710.                     g_lngPolygonCount = g_lngPolygonCount + 1
  711.                     
  712.                 Next lngFace
  713. ResumePoint:
  714.             Next lngPart
  715.         End With
  716.     Next intObject
  717.     
  718.     Exit Sub
  719. errTrap:
  720.     Resume ResumePoint
  721.    
  722. End Sub
  723. Private Sub Draw_SimpleWireframe(withObject As mdr3DObject)
  724.     
  725.     ' Displays 3D usin Simple Wireframe
  726.  
  727.     On Error GoTo errTrap
  728.  
  729.     Dim intN As Long, intJ As Long, intK As Long
  730.     Dim blnClipped As Boolean
  731.     Dim intClipCount As Integer
  732.  
  733.     Dim lngIndex0 As Long
  734.     Dim vect0 As mdrVector4
  735.     Dim Red0 As Double
  736.     Dim Green0 As Double
  737.     Dim Blue0 As Double
  738.     Dim sngBrightness0 As Double
  739.     
  740.     Dim lngIndex1 As Long
  741.     Dim vect1 As mdrVector4
  742.     Dim Red1 As Double
  743.     Dim Green1 As Double
  744.     Dim Blue1 As Double
  745.     Dim sngBrightness1 As Double
  746.     
  747.     Dim lngIndex2 As Long
  748.     Dim vect2 As mdrVector4
  749.     Dim Red2 As Double
  750.     Dim Green2 As Double
  751.     Dim Blue2 As Double
  752.     Dim sngBrightness2 As Double
  753.  
  754.     
  755.     If m_blnDetailLCDScreen = True Then
  756.         m_frmCanvas.DrawWidth = 2
  757.     Else
  758.         m_frmCanvas.DrawWidth = 1
  759.     End If
  760.     If m_intDetailDrawMode <> 0 Then m_frmCanvas.DrawWidth = 1
  761.     
  762.     With withObject
  763.  
  764.         ' Draw each object's polyhedra
  765.         For intN = 0 To UBound(.Parts)
  766.             m_frmCanvas.ForeColor = vbBlack
  767.             
  768.             ' Draw each polygon for the given polyhedra.
  769.             For intJ = 0 To UBound(.Parts(intN).Faces)
  770.  
  771.                 If .Parts(intN).Selected = True Then
  772.                     m_frmCanvas.ForeColor = vbWhite
  773.                 End If
  774.  
  775.                 With .Parts(intN)
  776.                 
  777.                     lngIndex0 = .Faces(intJ)(0)
  778.                     lngIndex1 = .Faces(intJ)(1)
  779.                     lngIndex2 = .Faces(intJ)(2)
  780.                     
  781.                     ' Enough faces for a Triangle?
  782.                     If (UBound(.Faces(intJ)) > 1) Then
  783.                     
  784.                         ' Should the triangle be clipped?
  785.                         blnClipped = False
  786.                         blnClipped = blnClipped Or .Vertices(lngIndex0).Clipped
  787.                         blnClipped = blnClipped Or .Vertices(lngIndex1).Clipped
  788.                         blnClipped = blnClipped Or .Vertices(lngIndex2).Clipped
  789.                         
  790.                         intClipCount = 0
  791.                         If .Vertices(lngIndex0).Clipped = True Then intClipCount = intClipCount + 1
  792.                         If .Vertices(lngIndex1).Clipped = True Then intClipCount = intClipCount + 1
  793.                         If .Vertices(lngIndex2).Clipped = True Then intClipCount = intClipCount + 1
  794.                         
  795.                         If blnClipped = True Then
  796.                             vect0 = .Vertices(lngIndex0).Txyz
  797.                             vect1 = .Vertices(lngIndex1).Txyz
  798.                             vect2 = .Vertices(lngIndex2).Txyz
  799.                             If intClipCount = 3 Then
  800.                                 If m_blnDetailPolygonsOutside = True Then
  801.                                     Call DrawFlatTriangle(m_frmCanvas, vect0.X, vect0.Y, vect1.X, vect1.Y, vect2.X, vect2.Y, RGB(64, 32, 32), 0, vbSolid, vbFSTransparent)
  802.                                 End If
  803.                             Else
  804.                                 If m_blnDetailPartialPolygons = True Then
  805.                                     Call DrawFlatTriangle(m_frmCanvas, vect0.X, vect0.Y, vect1.X, vect1.Y, vect2.X, vect2.Y, RGB(255, 128, 0), 0, vbSolid, vbFSTransparent)
  806.                                 End If
  807.                             End If
  808.                             
  809.                         Else
  810.                             vect0 = .Vertices(lngIndex0).Txyz
  811.                             vect1 = .Vertices(lngIndex1).Txyz
  812.                             vect2 = .Vertices(lngIndex2).Txyz
  813.                             
  814.                             ' ==================
  815.                             ' Back-Face Culling.
  816.                             ' ==================
  817.                             Dim vectA As mdrVector4, vectB As mdrVector4, vectC As mdrVector4
  818.                             vectA = .Vertices(lngIndex0).Txyz
  819.                             vectB = .Vertices(lngIndex1).Txyz
  820.                             vectC = .Vertices(lngIndex2).Txyz
  821.  
  822.                             Dim sngDotProduct As Single
  823.                             sngDotProduct = IsBackFace(m_Camera.PRP, vectA, vectB, vectC)
  824.                             If sngDotProduct < 0 Then
  825.                                 
  826. ' Update debug & info. counters (conditionally compiled)
  827. #If g_blnCompiledDebugInfo = True Then
  828.     g_lngPolygonCount = g_lngPolygonCount + 1
  829. #End If
  830.  
  831.                                 If m_RenderOptions = 0 Then
  832.                                 
  833.                                     ' ============================================================================================
  834.                                     ' This colour part is much more complicated that it needs to be. You could probably delete all
  835.                                     ' this colour stuff and it would not effect the program at all.
  836.                                     ' ============================================================================================
  837.                                     Dim sngRed0 As Single, sngGreen0 As Single, sngBlue0 As Single
  838.                                     sngBrightness0 = .Vertices(lngIndex0).Brightness
  839.                                     If m_blnDetailDayMode = True Then
  840.                                         Call HSV2(sngRed0, sngGreen0, sngBlue0, 360 * sngBrightness0 * 12, sngBrightness0, 1)
  841.                                     Else
  842.                                         Call HSV2(sngRed0, sngGreen0, sngBlue0, 360 * sngBrightness0 * 12, 1, sngBrightness0)
  843.                                     End If
  844.                                     Red0 = 255 * sngRed0
  845.                                     Green0 = 255 * sngGreen0
  846.                                     Blue0 = 255 * sngBlue0
  847.  
  848.                                     Dim sngRed1 As Single, sngGreen1 As Single, sngBlue1 As Single
  849.                                     sngBrightness1 = .Vertices(lngIndex1).Brightness
  850.                                     If m_blnDetailDayMode = True Then
  851.                                         Call HSV2(sngRed1, sngGreen1, sngBlue1, 360 * sngBrightness1 * 12, sngBrightness1, 1)
  852.                                     Else
  853.                                         Call HSV2(sngRed1, sngGreen1, sngBlue1, 360 * sngBrightness1 * 12, 1, sngBrightness1)
  854.                                     End If
  855.                                     Red1 = 255 * sngRed1
  856.                                     Green1 = 255 * sngGreen1
  857.                                     Blue1 = 255 * sngBlue1
  858.  
  859.                                     Dim sngRed2 As Single, sngGreen2 As Single, sngBlue2 As Single
  860.                                     sngBrightness2 = .Vertices(lngIndex2).Brightness
  861.                                     If m_blnDetailDayMode = True Then
  862.                                         Call HSV2(sngRed2, sngGreen2, sngBlue2, 360 * sngBrightness2 * 12, sngBrightness2, 1)
  863.                                     Else
  864.                                         Call HSV2(sngRed2, sngGreen2, sngBlue2, 360 * sngBrightness2 * 12, 1, sngBrightness2)
  865.                                     End If
  866.                                     Red2 = 255 * sngRed2
  867.                                     Green2 = 255 * sngGreen2
  868.                                     Blue2 = 255 * sngBlue2
  869.                                     
  870.                                     Dim sngRedAvg As Single
  871.                                     Dim sngGrnAvg As Single
  872.                                     Dim sngBluAvg As Single
  873.                                     sngRedAvg = (Red0 + Red1 + Red2) / 3
  874.                                     sngGrnAvg = (Green0 + Green1 + Green2) / 3
  875.                                     sngBluAvg = (Blue0 + Blue1 + Blue2) / 3
  876.                                     
  877.                                     ' Draw Wireframe.
  878.                                     If m_intDetailDrawMode = 0 Then
  879.                                         Call DrawFlatTriangle(m_frmCanvas, vect0.X, vect0.Y, vect1.X, vect1.Y, vect2.X, vect2.Y, RGB(sngRedAvg * 0.9, sngGrnAvg * 0.9, sngBluAvg * 0.9), RGB(sngRedAvg, sngGrnAvg, sngBluAvg), vbSolid, vbFSTransparent)
  880.                                     End If
  881.                                     
  882.                                     ' Flat-Shaded Polygon
  883.                                     If m_intDetailDrawMode = 1 Then
  884.                                         If m_blnDetailEdgedFaces = True Then
  885.                                             Call DrawFlatTriangle(m_frmCanvas, vect0.X, vect0.Y, vect1.X, vect1.Y, vect2.X, vect2.Y, RGB(sngRedAvg * 0.9, sngGrnAvg * 0.9, sngBluAvg * 0.9), RGB(sngRedAvg, sngGrnAvg, sngBluAvg), vbSolid, vbFSSolid)
  886.                                         Else
  887.                                             Call DrawFlatTriangle(m_frmCanvas, vect0.X, vect0.Y, vect1.X, vect1.Y, vect2.X, vect2.Y, 0, RGB(sngRedAvg, sngGrnAvg, sngBluAvg), vbInvisible, vbFSSolid)
  888.                                         End If
  889.                                     End If
  890.                                     
  891.                                     ' Gouraud Shaded
  892.                                     If m_intDetailDrawMode = 2 Then
  893.                                         Call DrawTriangle(m_frmCanvas, vect0.X, vect0.Y, vect1.X, vect1.Y, vect2.X, vect2.Y, Red0, Green0, Blue0, Red1, Green1, Blue1, Red2, Green2, Blue2)
  894.                                         If m_blnDetailEdgedFaces = True Then
  895.                                             Call DrawFlatTriangle(m_frmCanvas, vect0.X, vect0.Y, vect1.X, vect1.Y, vect2.X, vect2.Y, RGB(sngRedAvg * 0.9, sngGrnAvg * 0.9, sngBluAvg * 0.9), RGB(sngRedAvg, sngGrnAvg, sngBluAvg), vbSolid, vbFSTransparent)
  896.                                         End If
  897.                                     End If
  898.                                     
  899.                                 Else
  900.                                     ' Draw Shadow..
  901.                                     If m_intDetailDrawMode <> 0 Then ' if wireframe
  902.                                         Call DrawFlatTriangle(m_frmCanvas, vect0.X, vect0.Y, vect1.X, vect1.Y, vect2.X, vect2.Y, RGB(1, 1, 1), RGB(Blue0, Blue0, Blue0), vbSolid, vbFSSolid)
  903.                                     Else
  904.                                         Call DrawFlatTriangle(m_frmCanvas, vect0.X, vect0.Y, vect1.X, vect1.Y, vect2.X, vect2.Y, RGB(1, 1, 1), RGB(Blue0, Blue0, Blue0), vbSolid, vbFSTransparent)
  905.                                     End If
  906.                                 End If
  907.                             Else
  908.                                 'Call DrawFlatTriangle(m_frmCanvas, vect0.X, vect0.Y, vect1.X, vect1.Y, vect2.X, vect2.Y, RGB(0, 128, 0), -1, vbDot, vbFSSolid)
  909.                             End If
  910.                             
  911.                         End If ' Clipped=False
  912.                     End If ' Enough faces for a Triangle?
  913.                 End With
  914. SkipOver1:
  915.             Next intJ
  916.         Next intN
  917.     End With
  918.     
  919.     Exit Sub
  920. errTrap:
  921.     Select Case Err.Number
  922.         Case 9 ' Subscript Error
  923.             Resume SkipOver1
  924.  
  925.         Case Else
  926.             MsgBox Err.Number & " - " & Err.Description, vbCritical
  927.             ' Do nothing
  928.  
  929.     End Select
  930.     
  931. End Sub
  932.  
  933. Private Sub Draw_DotsOnly(withObject As mdr3DObject)
  934.     
  935.     Dim intPart As Long, intVertex As Long
  936.     Dim blnClipped As Boolean
  937.     Dim intClipCount As Integer
  938.  
  939.     Dim lngIndex0 As Long
  940.     Dim vect0 As mdrVector4
  941.     Dim Red0 As Double
  942.     Dim Green0 As Double
  943.     Dim Blue0 As Double
  944.     Dim sngBrightness0 As Double
  945.     
  946.     Dim sngX As Single
  947.     Dim sngY As Single
  948.     
  949.     If m_blnDetailLCDScreen = True Then
  950.         m_frmCanvas.DrawWidth = 4
  951.     Else
  952.         m_frmCanvas.DrawWidth = 1
  953.     End If
  954.     
  955.     With withObject
  956.  
  957.         ' Draw each object's part.
  958.         For intPart = 0 To UBound(.Parts)
  959.         
  960.             ' Loop through all vertices for the part.
  961.             For intVertex = 0 To UBound(.Parts(intPart).Vertices)
  962.             
  963.                 If .Parts(intPart).Vertices(intVertex).Clipped = False Then
  964.                 
  965.                     If m_blnDetailDayMode = True Then
  966.                         sngBrightness0 = 1 - .Parts(intPart).Vertices(intVertex).Brightness
  967.                     Else
  968.                         sngBrightness0 = .Parts(intPart).Vertices(intVertex).Brightness
  969.                     End If
  970.                     
  971.                     Red0 = .Parts(intPart).Vertices(intVertex).RGB_Red * sngBrightness0
  972.                     Green0 = .Parts(intPart).Vertices(intVertex).RGB_Green * sngBrightness0
  973.                     Blue0 = .Parts(intPart).Vertices(intVertex).RGB_Blue * sngBrightness0
  974.                     
  975.                     sngX = .Parts(intPart).Vertices(intVertex).Txyz.X
  976.                     sngY = .Parts(intPart).Vertices(intVertex).Txyz.Y
  977.                     
  978.                     m_frmCanvas.PSet (sngX, sngY), RGB(Red0, Green0, Blue0)
  979.                     
  980.                 End If
  981.                 
  982.             Next intVertex
  983.         Next intPart
  984.         
  985.     End With
  986.         
  987. End Sub
  988.  
  989. Private Sub Convert4Dto3D(p_3DObject As mdr3DObject)
  990.  
  991.     On Error GoTo errTrap
  992.     
  993.     Dim lngN As Long, lngJ As Long
  994.     
  995.     With p_3DObject
  996.     
  997.         ' For each object, calculate it's Parts
  998.         For lngN = 0 To UBound(.Parts)
  999.         
  1000.             For lngJ = 0 To UBound(.Parts(lngN).Vertices)
  1001.                 With .Parts(lngN).Vertices(lngJ)
  1002.                         
  1003.                         ' Ignore invalid co-ordinates
  1004.                         If (.Txyz.w = 0) = False Then
  1005.                             ' Convert from 4D down to 3D
  1006.                             ' ==========================
  1007.                             ' Apply the Perspective transformation by converting 4 dimensions down to
  1008.                             ' 3 dimensions, by dividing the x, y & z co-ordinates with w. Don't forget the w
  1009.                             ' value was previous calculated using the 'MatrixPerspective' routine.
  1010.                             ' I personally like to call this part of the code, 'dimensionally downshifting'.
  1011.                             .Txyz.X = .Txyz.X / .Txyz.w
  1012.                             .Txyz.Y = .Txyz.Y / .Txyz.w
  1013.                             .Txyz.Z = .Txyz.Z / .Txyz.w
  1014.                             
  1015. ' Update debug & info. counters (conditionally compiled)
  1016. #If g_blnCompiledDebugInfo = True Then
  1017.     ' Probably a bad idea to have this code here in a loop... oh well.
  1018.     g_lngDivisionCount = g_lngDivisionCount + 3
  1019. #End If
  1020.                             
  1021.                     End If
  1022.                 End With
  1023. SkipPointA:
  1024.             Next lngJ ' .Parts(lngN).Vertices
  1025.         Next lngN ' .Parts
  1026.     End With ' p_3DObject
  1027.     
  1028.     
  1029.     Exit Sub
  1030. errTrap:
  1031.     Select Case Err.Number
  1032.         Case 9 ' Subscript out of range
  1033.             Resume SkipPointA
  1034.             
  1035.         Case Else
  1036.             MsgBox Err.Number & " - " & Err.Description, vbExclamation
  1037.             
  1038.     End Select
  1039.     
  1040. End Sub
  1041.  
  1042. Private Sub DoSetDrawingParamaters(p_Camera As mdr3DTargetCamera)
  1043.     
  1044.     ' ======================================================================================
  1045.     '                       *** Synthetic [Virtual] Camera Values ***
  1046.     ' The four basic Viewing Parameters that define the View Reference Coordinates (VRC).
  1047.     ' They are all specified in World Coordinates (WC) except PRP; this is specified in VRC.
  1048.     '                       *** Synthetic [Virtual] Camera Values ***
  1049.     '
  1050.     ' ======================================================================================
  1051.     Dim vectVRP As mdrVector4   ' View Reference Point (VRP) - The world position of the virtual camera AND the virtual film!
  1052.     Dim vectVPN As mdrVector4   ' View Plane Normal (VPN) - The direction that the virtual camera is pointing "away from"!
  1053.     Dim vectPRP As mdrVector4   ' Projection Reference Point (PRP), also known as Centre Of Projection (COP) - This is the distance between the virtual camera's film, and the pin-hole lens of the virtual camera.
  1054.     Dim vectVUP As mdrVector4   ' View UP direction (VUP) - Which way is up? This is used for tilting (or not tilting) the camera.
  1055.     
  1056.     
  1057.     ' ====================================================
  1058.     ' Define the View Reference Point (VRP)
  1059.     ' This is defined in the World Coordinate (WC) system.
  1060.     ' ====================================================
  1061.     vectVRP = p_Camera.WorldPosition
  1062.     
  1063.     
  1064.     If p_Camera.FreeCamera = True Then
  1065.         ' Programmer is responsible for creating and rotating View Plane Normal (VPN) manually.
  1066.         ' This is a last minute hack... I'll probably clean this up a little so that I'm not
  1067.         ' mixing up cameras with human players; their code should be kept separate. Note, this
  1068.         ' is a 'camera' routine, not a 'human player' routine.
  1069.         vectVPN = m_PlayerOne.VPN
  1070.     Else
  1071.         ' =============================================================================================================
  1072.         ' Subtract the Camera's world position (VRP) from the 'LookingAt' point to give us the View Plane Normal (VPN).
  1073.         ' In this application, the VPN points in the opposite direction that the camera is facing!! I said, Opposite!
  1074.         ' Fig. 6.14 to 6.16
  1075.         ' =============================================================================================================
  1076.         vectVPN = VectorSubtract(vectVRP, p_Camera.LookAtPoint)
  1077.     End If
  1078.     If (vectVPN.X = 0) And (vectVPN.Y = 0) And (vectVPN.Z = 0) Then
  1079.         vectVPN.X = 0# ' Do not allow VPN to be all zero's (shouldn't happen anyway, but still check)
  1080.         vectVPN.Y = 0#
  1081.         vectVPN.Z = 1#
  1082.     End If
  1083.     
  1084.     
  1085.     ' ==============================================================================================
  1086.     ' PRP is specified in the View Reference Coordinate system (and NOT the world coordinate system)
  1087.     ' ==============================================================================================
  1088.     vectPRP = p_Camera.PRP
  1089.     
  1090.     
  1091.     ' ==================================================================================
  1092.     ' The VUP vector is usually x=0,y=1,z=0. This is used to tilt the camera.
  1093.     ' If you had a camera firmly mounted on the handle bars of a motorcycle, you would
  1094.     ' expect to see the camera tilt when the motorcycle rounded the corners.
  1095.     ' (To achieve this, multiply the vectVUP vector with a rotation matrix)
  1096.     ' ==================================================================================
  1097.     vectVUP = p_Camera.VUP
  1098.     
  1099.     ' ============================================================================
  1100.     ' View Orientation.
  1101.     ' ============================================================================
  1102.     m_matViewOrientation = MatrixViewOrientation(vectVPN, vectVUP, vectVRP)
  1103.     
  1104.     
  1105.     ' ============================================================================
  1106.     ' Map projection view volume into canonical view volume suitable for clipping.
  1107.     ' ============================================================================
  1108.     m_matViewMapping = MatrixViewMapping_Per(p_Camera)
  1109.     
  1110.     
  1111. End Sub
  1112. Public Sub ShowApplication()
  1113.     
  1114.     ' Create the Canvas window (which is now 'owned' by the Application class.)
  1115.     If (m_frmCanvas Is Nothing) Then
  1116.     
  1117.         Set m_frmCanvas = New frmCanvas
  1118.         Load m_frmCanvas
  1119.         m_frmCanvas.Show
  1120.         
  1121.     End If
  1122.     
  1123. End Sub
  1124.  
  1125.  
  1126. Private Sub m_frmCanvas_OnAnimate()
  1127.     
  1128.     ' ===========================================================================
  1129.     ' The entire program is controlled from here.
  1130.     ' --------------------------------------------
  1131.     ' The game is always in a known state (ie. the GameState). If you program in
  1132.     ' this manner, you will be able to expand your game as time goes on without
  1133.     ' the headache of increasing the complexity (a common problem with newbie's).
  1134.     ' Each "game state" can have it's own "sub-state". That is, when the game is
  1135.     ' in "run_game" state, I could then sub-divide this state into various parts
  1136.     ' such as "do enemies", "do A.I", "do check for collisions" and so on.
  1137.     ' ===========================================================================
  1138.     Select Case Me.GameState
  1139.         Case ""
  1140.             ' ==========================================
  1141.             ' Master Reset - first time program has run.
  1142.             ' ==========================================
  1143.             Call DoMasterReset
  1144.             Call GetMouseInput(m_intInputMouseSensitivity, Me.GameState, m_PlayerOne, m_Camera, m_frmCanvas)
  1145.             
  1146.             Me.GameState = "run_demo"
  1147.             
  1148.             ' ======================================================================================
  1149.             ' Initilize the MIDI Soundtrack.
  1150.             ' This will also initilize the 'Sequencer' timer that will double-up as a Timer control.
  1151.             ' The Multimedia Control helps us Synchronize the Music to the action... very cool!
  1152.             ' ======================================================================================
  1153.             Call Init_MIDISoundtrack
  1154.             m_frmCanvas.lblPleaseWait.Visible = False
  1155.             m_frmCanvas.TimerDoAnimation.Enabled = False
  1156.         
  1157.         
  1158.         Case "show_settings"
  1159.             Me.GameState = "settings"
  1160.             If m_frmSettings Is Nothing Then Set m_frmSettings = New frmSettings
  1161.             m_frmSettings.Show vbModeless, m_frmCanvas
  1162.             
  1163.             m_frmSettings.chkVideoFullScreen.Value = m_blnVideoFullScreen
  1164.             m_frmSettings.chkDetailClipBoundry.Value = m_blnDetailClipBoundary
  1165.             m_frmSettings.chkDetailEdgedFaces.Value = m_blnDetailEdgedFaces
  1166.             m_frmSettings.chkDetailDayMode.Value = m_blnDetailDayMode
  1167.             m_frmSettings.chkDetailShadows.Value = m_blnDetailShadows
  1168.             m_frmSettings.chkDetailPartialPolygons.Value = m_blnDetailPartialPolygons
  1169.             m_frmSettings.chkDetailPolygonsOutside.Value = m_blnDetailPolygonsOutside
  1170.             m_frmSettings.chkDetailLCDScreen.Value = m_blnDetailLCDScreen
  1171.             m_frmSettings.optDetailDrawMode.Item(rmSettings.chkDetaiting m_frmSItem(rmSettings.chkDetaiting m_frmSItem(rmSettings.chkDetaiting m_frmSItem(rmSettings.chkDetaiting m_frmSItem(rliting m_frmSItem(rmSettsing m_frmSItem(rliti em(rmSettings.chkDetaitio( ettings.chkDebDg Red2 = 255 * =====F&:sS
  1172.             'S
  1173.   ra' routineSettings.chk======   _Per(p_Camera_frmSettings.chkDetailPolygonsOuttin=
  1174.   show_sett
  1175.              uvl         m_frmSett e       If m_frmSettvate Sub DoSetDrawingParamaters(p_Camera As mdr3DTargetCamera)
  1176.     
  1177.     ' =====dr3DTargetl
  1178.     
  1179.     ' =====dr3DTargetl
  1180.     
  1181.     ' =====dr3DTargetl
  1182.     
  1183.     ' =====dr3DTargetl
  1184.     
  1185.   ===
  1186.   oi ThePrzlygonoolean
  1187.     Dim intClipCouetailIf m_frmSettings Is Nothing T oi ThePrzlygonoolean     If m_frmSet oi ThePrzlygrtiblnDetailClipBoundary
  1188.             m_frmSet(blnDetfrmSettinontrol.
  1189.           F_Per(p_Camera)
  1190.  x)
  1191.     ' ===    ng m_frmSItem(rliting m_frmSIte F_Per(p_Camera)
  1192.  x)VUP As mdrVector4   ' View l sparrrrr' ===    ng m_frmSItem(rliting m_frmSIte F_Per(p_Camera)
  1193.  x)VUP As mdrVector4   ' Vieulle, sngG    rack.rld position (V sngBluAvg0---         **=====m6*.C sngBluAvg0---             s    (p_Camera)
  1194.           ' ========eta          lipCouetailIf m_frmSettings Is Nothingt = 255 * =====F&:sS
  1195.             'S
  1196.   ra' routineSettings.chk=====+iSSolid)
  1197.      ,===dr3DTaSphtoe
  1198.      ,===dr3DTaSpht===========================
  1199.             ' Initilize the MIDI Soundtrack.
  1200.       tp tilt .P As mdrVector4   ' View l spau      m_frmCanvas.PSetnvaGObject As mdr3DObject)
  1201.     icr3DObjec  Il ' =======    ' Initilize the MIDIt      o seePSetnvaGObject As mdr3nhtect Aois uAs mdr3nhtect Aois uAs mdr3nhtect Aois uAs md2IDIt      o seePSetnvaGObject As mdr3nhtects    (p_Camer=======ehtects    (p_Camer===kVRP) - ThrY===W) OrAs t                         .undtrack.
  1202.             ' This will also initilize the 'Sequencer' timer that will double-up as aquencer'up 1,          .undize the 'Sequencer' timer thattttttc the 'Se(2O === As mdroM't ftor is usual(2O === As mdog This  thattttttc the 'Se(2O ===ing     (tc the 'Se( oiean
  1203.     Dim 'Sequeo!lean     If m_frmSet oi ThePrz as aquencer'up 1,          .undize the 'SequenV sngBluAvg0-----------=_frmSePSN)
  1204.  
  1205. =============================
  1206.             ' Inilue k=====+iSSohtects +     EVUP, vas window (whict"(sL                 sngVUP As mdrVec_frmN'ocn.Enablt(0---              o sr  EVUP, vas === d======== End If
  1207.                         
  1208.                Next intPart
  1209.         
  1210.     E.Value = m_blnD.raseWait.Visible = False
  1211.             m_frmCanvas.TteApplication()
  1212.     
  1213.     ' Create theLu ' Fig. 6.14 to 6.16
  1214.         ' ===============================mSIte  m_frmCanvas.TteA)KvaGObj--         **=====m6*.C sngBl' Fig.o====bj--tCall DraN mdr3nhtect AoirmCanvas.PSetlue = m_blnD.raseWidth m============================
  1215.  vValue = m_blnDetailShadows
  1216.    hole lens of the virtual camera.
  1217.     Dim vectVUP As mdrVector4   ' View UP direction (VUP) - Which way is up      een
  1218.             m_f     =================ual c========ual c==== pointing "awayPart)                
  1219.     End Select
  1220.   
  1221.     pointitheLu ' , sngra.
  1222.     Dim vectVUP As mdrVector4   ' View UP direction (VUP) - Which way is up      een
  1223.   mePrz as aqtCliptlize t m_frmSet oi    =================ual c========ual c==== pointing-----
  1224.     ' The game- Whi=ap:
  1225.     Sel                     .Txyz.Z  ' The gaQ
  1226.     D===========ual c========uaI couldsp n sub-divier1
  1227.  
  1228.         ndize P) - Which r)a (.TxyzwNe
  1229.   =======uaI couldsp n sub-dquencer'up 1, uaI couldsp n sub-dquencer'u-divMt=====ictor4 time goeInilueiduencer'u-dicer'u-dicer'u-dicer'u-dicerctos(intVexyz.X = .Txyz.X / .Txyz.w
  1230.             ===ictor4 t , sngtt enemies", "do A.I", "do c ,yste' ,.I", "do c ,yste' ,.I", "do c ,yste' ,.I",frmSePlygon -=====, Opposite!
  1231.       )
  1232.          uvl        mSettvateeeeeeeetings.......................yste# o c ,yste' ,.I",frmSePlygon -=====, Opposite!
  1233.       )_demo"nvaGOb= m_bte# o c ,yste' ,.I",   downe.rate. Note, this
  1234. V   alse
  1235.   G*=====oieagon       downe.1I t e kleaseWait.VisibleBiaD========== = vbSolile = Fal   ' r3DTaSph Note,       gon ngs.cSph NoteectVPrdzr==========
  1236.     ' TentVexyz.X = .a.Y *A = .P    wyngle  m_frmCanvte,       gon ngs.cSph  End Selecz.X / .Txyz.w
  1237.             ===ictor4 t , sngtt enemies",lefrmSIc  G*=====oieagon       downe.1I t e kleaseWait.Vi                           ' ===d_t e kleasao  gon n_t e kleasao  gon n_t e kleasao  gonee        on n e kleasaosett
  1238.     er
  1239.   
  1240.     f<e,Y(p_C As Longle"Bz.w Casaopo"ct2.X, vect2.Y,,,,,,S_t e kleasao  u- Which way i   f"ay i   f"ay i   f"ay i   f"ay i   f"ay i   f"ay i     f"ay i    ouble====iiRoi Thh' =====dr3DTs ' ==p ' ======5 * s  f"ay i(art).Vertl_C As uoa ' ==p ' ======5    
  1241.     ' =====drQ      
  1242.     ' =====drQ     =====em2
  1243.     Dim e ae4 to  Dim e ae4 to  Dim e ae4 to  Dim e ae4 to  Dim e a     ' Initilize the     ========CouetailIfl'em2
  1244.     Dim e ae4 to  Di=====intVexyanvas.PSetlue = m_blnD.raPSetlue = m_
  1245. slnD.raPSetlue = m_
  1246. slnD.raPSetlue = m_
  1247. slnD.raPSetlue = m_
  1248. slnD.raPSetlue = m_
  1249. slnD.ra=====eV  _
  1250. slnf==eV mem_
  1251. s... s ae4 to  Dim e ae4=====eVtyz.X =         **=====m6*.C P) - ThrY===W)sd1 Asc( + Red1 ng tilize the MIDIt      o seePSetnvaGObjeRe the ' This is defined in  = 255 * sngonee   S  D   Dlositesao      mSettvateeGlrr S)m_Plett.llll==W)sd1 Asc( + Red1 Objec  Il ' ====!lIfl'em2
  1252.     Dim e ae4=============================
  1253.     m_matViewmct0.Y, IDrqlnD.raPSetlue==================================================
  1254.     m  Dim e ae4 to  Dim e ae4 to  Dim e ae4 to  Dim e a     is uAs md2IDIt   le a     is uAs md2IDIt   le a     is uAs md2IDIt   le a     is uAs md2IDIt   le a     is uAs md2IDIt   le a     is p' m_mdIfl'em2
  1255.     Dim e ae4 to  Di=====intVexyanv Dim vectPlaneEq As mdrVector4r    lrzlygrtiblnDetailCli'easi     is uAs md2ID    * s  f"ay i(artc etl + Red1 ng tilizeSProduct = IsBack0 As mdrVector4
  1256.   C As Lo.Parts(/===          
  1257.        p
  1258.   C ASe( rtc etl + Red1 ng tililector4(e Lo.P      rtack0 As mdBlue0 = 255ng tilizeSProduct = Inir   Sel             HroduGeect
  1259.    aces(ll*=====_mdIflroduGeect      uGeectt2         As Loar0 = 255ng SProdued1 n. 6.14 to 6.16
  1260.         ' =============  uAs mesub-dquencer'u-dimesssso 6.16
  1261.         ' r"5ng SProdued1 n. 6.14 to 6.16
  1262.        qndex0).Txyz.Z qndex0).Txyz.Z qngPart).Vertices(lngIndex2).Txyz.Y / .Parts(lngPart).Vertices(lngIndex2).Txyz.w
  1263.                A.Z qneer'up 1, utpcTr= qneer'usu+ect1.X, ttvateeGlrr S)m_Plett.l      cDim e ae4=====eVtyz.X =         **=====m6*.C P) - ThrY===W)sd1 Asc( + Red1 ng tilize the MIDIt      o seePSetnvaGOOOOOMIDIt     .Z qngPart).Vertices(lngIndex2).Txyz. _intInightness1, 1)
  1264.     ePart=====Inilue k=====+iSSohtects +  o'P) - lble
  1265.     Diall DrawF=ssntIn(.Y, Red0, Green0, Blue0, Red1, Green1     (p_C As Longle"Bz.w Casaopo"ct2.X, vecn_
  1266. qndex0).ii            =Inilue km oe = F
  1267.     ' =====drQ      
  1268.       =Inilue km oe          ' ===Inilue km oe  ============probaeeeeeeeeeeer          l.eeeeeeeeobaeeeeeeeeeeer eeeer          l.eeeeeeeeobaeeeeeeeeeeer eee=lb-dquencerYObjec.....).Txyz Sin".eeer eeeCou      l.eeeeeeeeobaeeeeeeeyz. _intInightness1, 1)
  1269.     ePart=====Inilue k=====+iSSohtects +  o'P) - lble
  1270.     Diall DrawF=ssntIn(.Y, Red0, Green0, Blue0, Red1, Green1     (p_C Aseeeer      lkAseeeeeeeeee f intC ==p es
  1271. r    ngra.
  1272.    gParntIn(.Y, Red0, Greee 9 ' cs,d0, Greee 9 ' C) excendex2).       
  1273.       32), 0, vbSolid, DimeInightnesl_1, Green1     (p_C Aseeeer      lkAseeeeeeeeee f intC ==p es
  1274. r    ngra.
  1275.    gParntIn(.Y, Red0, Greee 9 ' cs,d0, Greee 9 ' C) excpnv DimeSetnvaGObject As mdr3DObject)
  1276.  e=======frBmmcC) l2  ePart=====InnnnnnnnseeeeeeeCamer=======ehtects    (p_Camer==If m_= cePar  phPartialU.X = .mdr3DObjoi ThePrzorBmmcC)t Su   (p_C Aseeel=======ual c= le a     is uAsc= le Su   (p_Ce(p_Ce(p_e' ,.I",frmSePlPc=====frBmmcC) l2  ePart==========uaP) l2  ePart==========uaP) l) l2  ePart====xl(2O === As ======   _Per(p_C  ra' ro
  1277.         ' This is!ne a     is uAs md2IDIt   l uAs md2IDIt   l uAs md2IDIt   l uAs mN(r=======ehteA"llllllllllloeelllllUriaaaaaaaaaauAs md2is!ne YeagoparntIn(.Yt====xlC  ra' ro
  1278.         ' This is!neai  End r gaRGB(sngRaBu.eeeee 0, Greeeplication()
  1279. laaaaaaauAs md2s is!neai  EnaaaauAs e4 to  DimWmr=======eht eeeer y====C As Longle"BlGrue Th6.16
  1280.  IfTh6.16
  1281.  IfTheht eeeer=eeer y====mesub-dquteee
  1282.    -dqu"===C As LctVPN.X = 0) And (vectVPN.Y = 0) And (vectVPN.Z = 0) Then
  1283.         vectVPN.X = 0# ' D     'ir   .dctVRP  eeeer      P  eeeer      P  eeeer      P  eeeer      P  eeeer       P awF=ssntIn(.Y, Red0, Green0, Blue0, Red1, Green1   PSeVectorrheeeer eeeer=eeertorrheeeer eeRed0, Green0, Blue0, Red1, Green1   PSeVectorrheeee And (vecttttsYl'up 1, uaI coulds                             End If
  1284. en1   PS neen1  dex0).1  Dimcttt     
  1285. B)n
  1286.     
  1287.         Set m_frmt    lllr4   ' VieulleAs mda/ VieulleiDimcttt     
  1288. B)n
  1289.     
  1290.         Set m_frmt    lllr4   ' Vm_frerticeset m_frmt  plication()
  1291. laaaaaaauAs md2s tFalse
  1292.            ex0).Txyz.Z qnDoAnimation.Enabled =  am is contr qndexgnugh elygrtiblnDetailkS awF=ssntIntion()
  1293. laaaaaaauAs aaau2uf  - Which wDDDDDDus"FZAsc=Setlue_Ce(pztightness0)
  1294.       x0).T , gh elygrtiblnDe m_
  1295. slnD.ra=====eV m    to  DimWmr=======eht eeeer y====C As Longle"BlGrue Thm_frm1tu         MsgBox Err.Number &       MsgBox Err.Number &=====_mdIflroduGeecRz==========fhm_frhm_frhm_frhm_frhm_frhm_frhm_Gaodu!Red1,ngRedAvg, sngGrnAvg, WDetailatu         CouerA ====,====*.C P)o====,====*.C P)o====,====*.C P)o====,elate    m      Co   Co   Co===fhhhhhhhhhhhhhhh===D     'ir   .dctVRP  eeeer      P  eeeer      P  eeeer   Vi         ro        ro        ro        = p ' ======5         rrmSIte  
  1296. B)n
  1297.     
  1298.   r   Vi         reZ qWmr=======eht eeeerp  dex0).1 f  - Wh=eeertorrheeeer eeRed0, Green0, Blue0, Red1,  manner,=oar.;g_blnComystem.
  1299.     ' ==============  
  1300.     avg, sngGr 
  1301. r    ngra.
  1302.    gParntIn(.Y, Red0, Greee ,Mr==Dyz. _intIneer      P  eee_blnDetSllD.raPSetlue = m_
  1303. slnD.rai _iiiiiiiiitlue = ==ual c= le a     is uAsc= le Su   (p_Ce(p_Ce(p_e' ,C P)o====,===C P)l + Red1 ng tililector4(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e L(e