home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / OldSrc / CH13 / SRC / OBJPLAR.CLS < prev    next >
Encoding:
Text File  |  1996-04-11  |  9.0 KB  |  340 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4. END
  5. Attribute VB_Name = "ObjPlane"
  6. Attribute VB_Creatable = False
  7. Attribute VB_Exposed = False
  8. Option Explicit
  9.  
  10. Private Point1 As Point3D   ' Point on plane.
  11. Private Point2 As Point3D   ' Normal = P2 - P1.
  12.  
  13. Private HitX As Single
  14. Private HitY As Single
  15. Private HitZ As Single
  16.  
  17. Private Kar As Single
  18. Private Kag As Single
  19. Private Kab As Single
  20.  
  21. Private Kdr As Single
  22. Private Kdg As Single
  23. Private Kdb As Single
  24.  
  25. Private SpecN As Single
  26. Private Ks As Single
  27.  
  28. Private Krr As Single
  29. Private Krg As Single
  30. Private Krb As Single
  31.  
  32. ' ************************************************
  33. ' Apply a transformation matrix to the plane.
  34. ' ************************************************
  35. Public Sub Apply(M() As Single)
  36.     ' Transform the point and normal.
  37.     m3Apply Point1.coord, M, Point1.trans
  38.     m3Apply Point2.coord, M, Point2.trans
  39. End Sub
  40. ' ************************************************
  41. ' Return the red, green, and blue components of
  42. ' the surface at the hit position.
  43. ' ************************************************
  44. Public Sub HitColor(depth As Integer, Objects As Collection, R As Integer, G As Integer, B As Integer)
  45. Dim nx As Single
  46. Dim ny As Single
  47. Dim nz As Single
  48. Dim lx As Single
  49. Dim ly As Single
  50. Dim lz As Single
  51. Dim Vx As Single
  52. Dim Vy As Single
  53. Dim Vz As Single
  54. Dim rx As Single
  55. Dim ry As Single
  56. Dim rz As Single
  57. Dim n_len As Single
  58. Dim l_len As Single
  59. Dim v_len As Single
  60. Dim r_len As Single
  61. Dim NdotL As Single
  62. Dim RdotV As Single
  63. Dim NdotV As Single
  64. Dim r_dif As Single
  65. Dim g_dif As Single
  66. Dim b_dif As Single
  67. Dim r_amb As Single
  68. Dim g_amb As Single
  69. Dim b_amb As Single
  70. Dim spec As Single
  71. Dim r_ref As Single
  72. Dim g_ref As Single
  73. Dim b_ref As Single
  74. Dim r1 As Integer
  75. Dim g1 As Integer
  76. Dim b1 As Integer
  77. Dim mx As Single
  78. Dim my As Single
  79. Dim mz As Single
  80. Dim i As Integer
  81. Dim dist As Single
  82. Dim shadowed As Boolean
  83. Dim rlng As Long
  84. Dim glng As Long
  85. Dim blng As Long
  86.  
  87.     ' *******************************
  88.     ' * Compute local contributions *
  89.     ' *******************************
  90.     
  91.     ' Find the unit vector pointing toward the light.
  92.     lx = LightSource.trans(1) - HitX
  93.     ly = LightSource.trans(2) - HitY
  94.     lz = LightSource.trans(3) - HitZ
  95.     l_len = Sqr(lx * lx + ly * ly + lz * lz)
  96.     lx = lx / l_len
  97.     ly = ly / l_len
  98.     lz = lz / l_len
  99.     ' We will use l_len later as the distance from
  100.     ' the light to the surface.
  101.  
  102.     ' Find the surface unit normal.
  103.     nx = Point2.trans(1) - Point1.trans(1)
  104.     ny = Point2.trans(2) - Point1.trans(2)
  105.     nz = Point2.trans(3) - Point1.trans(3)
  106.     n_len = Sqr(nx * nx + ny * ny + nz * nz)
  107.     nx = nx / n_len
  108.     ny = ny / n_len
  109.     nz = nz / n_len
  110.     
  111.     ' Find the vector V from the surface to the
  112.     ' viewpoint.
  113.     Vx = EyeX - HitX
  114.     Vy = EyeY - HitY
  115.     Vz = EyeZ - HitZ
  116.     v_len = Sqr(Vx * Vx + Vy * Vy + Vz * Vz)
  117.     Vx = Vx / v_len
  118.     Vy = Vy / v_len
  119.     Vz = Vz / v_len
  120.  
  121.     ' See if the light shines on the back of the
  122.     ' plane. I.e. if the center of projection
  123.     ' and light source lie on the same side.
  124.     NdotL = nx * lx + ny * ly + nz * lz
  125.     NdotV = nx * Vx + ny * Vy + nz * Vz
  126.     shadowed = (NdotL * NdotV < 0)
  127.     
  128.     ' Treat backface planes as normal planes.
  129.     NdotL = Abs(NdotL)
  130.     
  131.     ' Find vector R in the mirror direction.
  132.     rx = 2 * nx * NdotL - lx
  133.     ry = 2 * ny * NdotL - ly
  134.     rz = 2 * nz * NdotL - lz
  135.     
  136.     ' See if the light shines directly on the surface.
  137.     If Not shadowed Then
  138.         For i = 1 To Objects.Count
  139.             dist = Objects.Item(i).RayDistance( _
  140.                 LightSource.trans(1), _
  141.                 LightSource.trans(2), _
  142.                 LightSource.trans(3), _
  143.                 -lx, -ly, -lz)
  144.             If dist < l_len - 0.1 Then Exit For
  145.         Next i
  146.         shadowed = (i <= Objects.Count)
  147.     End If
  148.     
  149.     ' Calculate the part due to diffuse reflection.
  150.     If shadowed Then
  151.         ' The light does not hit the surface.
  152.         r_dif = 0
  153.         g_dif = 0
  154.         b_dif = 0
  155.         spec = 0
  156.     Else
  157.         r_dif = Kdr * NdotL
  158.         g_dif = Kdg * NdotL
  159.         b_dif = Kdb * NdotL
  160.                 
  161.         ' Calculate the part due to specular reflection.
  162.         RdotV = rx * Vx + ry * Vy + rz * Vz
  163.         If RdotV < 0 Then
  164.             spec = 0
  165.         Else
  166.             spec = Ks * RdotV ^ SpecN
  167.         End If
  168.     End If
  169.     
  170.     ' Calculate the part due to ambient light.
  171.     r_amb = LightIar * Kar
  172.     g_amb = LightIag * Kag
  173.     b_amb = LightIab * Kab
  174.     
  175.     ' **********************************
  176.     ' * Compute reflected contribution *
  177.     ' **********************************
  178.     ' Find vector M in the direction of reflection.
  179.     mx = 2 * nx * NdotV - Vx
  180.     my = 2 * ny * NdotV - Vy
  181.     mz = 2 * nz * NdotV - Vz
  182.     
  183.     If depth > 1 Then
  184.         TraceRay depth - 1, HitX, HitY, HitZ, mx, my, mz, r1, g1, b1
  185.         r_ref = Krr * r1
  186.         g_ref = Krg * g1
  187.         b_ref = Krb * b1
  188.     Else
  189.         r_ref = 0
  190.         g_ref = 0
  191.         b_ref = 0
  192.     End If
  193.     
  194.     ' See how intense to make the color.
  195.     ' Some of the reflections may be close to
  196.     ' the light source so these values can get big.
  197.     rlng = r_amb + _
  198.         LightIir / (l_len + LightKdist) * _
  199.             (r_dif + spec) + _
  200.         r_ref
  201.     glng = g_amb + _
  202.         LightIig / (l_len + LightKdist) * _
  203.             (g_dif + spec) + _
  204.         g_ref
  205.     blng = b_amb + _
  206.         LightIib / (l_len + LightKdist) * _
  207.             (b_dif + spec) + _
  208.         b_ref
  209.     If rlng > 255 Then rlng = 255
  210.     If glng > 255 Then glng = 255
  211.     If blng > 255 Then blng = 255
  212.     R = rlng
  213.     G = glng
  214.     B = blng
  215. End Sub
  216.  
  217. ' ************************************************
  218. ' Set constants for reflected light.
  219. ' ************************************************
  220. Sub SetKr(R As Single, G As Single, B As Single)
  221.     Krr = R
  222.     Krg = G
  223.     Krb = B
  224. End Sub
  225.  
  226.  
  227. ' ************************************************
  228. ' Compute the distance from point (px, py, pz)
  229. ' along vector <vx, vy, vz> to the plane.
  230. '
  231. ' Save the point of intersection in
  232. ' (HitX, HitY, HitZ) for later use.
  233. ' ************************************************
  234. Public Function RayDistance(px As Single, py As Single, pz As Single, Vx As Single, Vy As Single, Vz As Single) As Single
  235. Dim A As Single
  236. Dim B As Single
  237. Dim C As Single
  238. Dim D As Single
  239. Dim nx As Single
  240. Dim ny As Single
  241. Dim nz As Single
  242. Dim denom As Single
  243. Dim t As Single
  244.  
  245.     ' Recompute the normal vector.
  246.     nx = Point2.trans(1) - Point1.trans(1)
  247.     ny = Point2.trans(2) - Point1.trans(2)
  248.     nz = Point2.trans(3) - Point1.trans(3)
  249.     
  250.     ' Compute the plane's parameters.
  251.     A = nx
  252.     B = ny
  253.     C = nz
  254.     D = -(nx * Point1.trans(1) + _
  255.           ny * Point1.trans(2) + _
  256.           nz * Point1.trans(3))
  257.  
  258.     ' If the denominator = 0, the ray is parallel
  259.     ' to the plane so there's no intersection.
  260.     denom = A * Vx + B * Vy + C * Vz
  261.     If denom = 0 Then
  262.         RayDistance = INFINITY
  263.         Exit Function
  264.     End If
  265.     
  266.     ' Solve for t.
  267.     t = -(A * px + B * py + C * pz + D) / denom
  268.  
  269.     ' If t < 0 then the intersection is behind the
  270.     ' center of projection so not of interest.
  271.     If t < 0.001 Then
  272.         RayDistance = INFINITY
  273.         Exit Function
  274.     End If
  275.     
  276.     ' Compute the actual hit location.
  277.     HitX = px + t * Vx
  278.     HitY = py + t * Vy
  279.     HitZ = pz + t * Vz
  280.     
  281.     ' Compute the distance from (px, py, pz).
  282.     A = px - HitX
  283.     B = py - HitY
  284.     C = pz - HitZ
  285.     RayDistance = Sqr(A * A + B * B + C * C)
  286. End Function
  287.  
  288. ' ************************************************
  289. ' Set the points. Point2 = Point1 + normal vector.
  290. ' ************************************************
  291. Public Sub Initialize(Cx As Single, Cy As Single, Cz As Single, Vx As Single, Vy As Single, Vz As Single)
  292.     Point1.coord(1) = Cx
  293.     Point1.coord(2) = Cy
  294.     Point1.coord(3) = Cz
  295.     Point1.coord(4) = 1
  296.     Point2.coord(1) = Cx + Vx
  297.     Point2.coord(2) = Cy + Vy
  298.     Point2.coord(3) = Cz + Vz
  299.     Point2.coord(4) = 1
  300. End Sub
  301.  
  302.  
  303. ' ************************************************
  304. ' Set N and Ks for specular reflection.
  305. ' ************************************************
  306. Sub SetSpec(n As Single, s As Single)
  307.     SpecN = n
  308.     Ks = s
  309. End Sub
  310.  
  311. ' ************************************************
  312. ' Return the latest Hit location.
  313. ' ************************************************
  314. Public Sub HitLocation(x As Single, y As Single, z As Single)
  315.     x = HitX
  316.     y = HitY
  317.     z = HitZ
  318. End Sub
  319.  
  320. ' ************************************************
  321. ' Set constants for diffuse reflection.
  322. ' ************************************************
  323. Sub SetKd(R As Single, G As Single, B As Single)
  324.     Kdr = R
  325.     Kdg = G
  326.     Kdb = B
  327. End Sub
  328.  
  329. ' ************************************************
  330. ' Set constants for ambient light.
  331. ' ************************************************
  332. Sub SetKa(R As Single, G As Single, B As Single)
  333.     Kar = R
  334.     Kag = G
  335.     Kab = B
  336. End Sub
  337.  
  338.  
  339.  
  340.