home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / OldSrc / CH13 / SRC / OBJPLA.CLS < prev    next >
Encoding:
Text File  |  1996-04-10  |  7.5 KB  |  280 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. ' ************************************************
  29. ' Apply a transformation matrix to the plane.
  30. ' ************************************************
  31. Public Sub Apply(M() As Single)
  32.     ' Transform the point and normal.
  33.     m3Apply Point1.coord, M, Point1.trans
  34.     m3Apply Point2.coord, M, Point2.trans
  35. End Sub
  36. ' ************************************************
  37. ' Return the red, green, and blue components of
  38. ' the surface at the hit position.
  39. ' ************************************************
  40. Public Sub HitColor(Objects As Collection, R As Integer, G As Integer, B As Integer)
  41. Dim nx As Single
  42. Dim ny As Single
  43. Dim nz As Single
  44. Dim lx As Single
  45. Dim ly As Single
  46. Dim lz As Single
  47. Dim Vx As Single
  48. Dim Vy As Single
  49. Dim Vz As Single
  50. Dim rx As Single
  51. Dim ry As Single
  52. Dim rz As Single
  53. Dim n_len As Single
  54. Dim l_len As Single
  55. Dim v_len As Single
  56. Dim r_len As Single
  57. Dim NdotL As Single
  58. Dim RdotV As Single
  59. Dim NdotV As Single
  60. Dim r_dif As Single
  61. Dim g_dif As Single
  62. Dim b_dif As Single
  63. Dim r_amb As Single
  64. Dim g_amb As Single
  65. Dim b_amb As Single
  66. Dim spec As Single
  67. Dim i As Integer
  68. Dim dist As Single
  69. Dim shadowed As Boolean
  70.  
  71.     ' Find the unit vector pointing toward the light.
  72.     lx = LightSource.trans(1) - HitX
  73.     ly = LightSource.trans(2) - HitY
  74.     lz = LightSource.trans(3) - HitZ
  75.     l_len = Sqr(lx * lx + ly * ly + lz * lz)
  76.     lx = lx / l_len
  77.     ly = ly / l_len
  78.     lz = lz / l_len
  79.     ' We will use l_len later as the distance from
  80.     ' the light to the surface.
  81.  
  82.     ' Find the surface unit normal.
  83.     nx = Point2.trans(1) - Point1.trans(1)
  84.     ny = Point2.trans(2) - Point1.trans(2)
  85.     nz = Point2.trans(3) - Point1.trans(3)
  86.     n_len = Sqr(nx * nx + ny * ny + nz * nz)
  87.     nx = nx / n_len
  88.     ny = ny / n_len
  89.     nz = nz / n_len
  90.     
  91.     ' Find the vector V from the surface to the
  92.     ' viewpoint.
  93.     Vx = EyeX - HitX
  94.     Vy = EyeY - HitY
  95.     Vz = EyeZ - HitZ
  96.     v_len = Sqr(Vx * Vx + Vy * Vy + Vz * Vz)
  97.     Vx = Vx / v_len
  98.     Vy = Vy / v_len
  99.     Vz = Vz / v_len
  100.  
  101.     ' See if the light shines on the back of the
  102.     ' plane. I.e. if the center of projection
  103.     ' and light source lie on the same side.
  104.     NdotL = nx * lx + ny * ly + nz * lz
  105.     NdotV = nx * Vx + ny * Vy + nz * Vz
  106.     shadowed = (NdotL * NdotV < 0)
  107.     
  108.     ' See if the light shines directly on the surface.
  109.     If Not shadowed Then
  110.         For i = 1 To Objects.Count
  111.             dist = Objects.Item(i).RayDistance( _
  112.                 LightSource.trans(1), _
  113.                 LightSource.trans(2), _
  114.                 LightSource.trans(3), _
  115.                 -lx, -ly, -lz)
  116.             If dist < l_len - 0.1 Then Exit For
  117.         Next i
  118.         shadowed = (i <= Objects.Count)
  119.     End If
  120.  
  121.     ' Calculate the part due to diffuse reflection.
  122.     If shadowed Then
  123.         ' The light does not hit the surface.
  124.         r_dif = 0
  125.         g_dif = 0
  126.         b_dif = 0
  127.         spec = 0
  128.     Else
  129.         ' Treat backface planes as normal planes.
  130.         NdotL = Abs(NdotL)
  131.         
  132.         r_dif = Kdr * NdotL
  133.         g_dif = Kdg * NdotL
  134.         b_dif = Kdb * NdotL
  135.         
  136.         ' Find vector R in the mirror direction.
  137.         rx = 2 * nx * NdotL - lx
  138.         ry = 2 * ny * NdotL - ly
  139.         rz = 2 * nz * NdotL - lz
  140.         
  141.         ' Calculate the part due to specular reflection.
  142.         RdotV = rx * Vx + ry * Vy + rz * Vz
  143.         If RdotV < 0 Then
  144.             spec = 0
  145.         Else
  146.             spec = Ks * RdotV ^ SpecN
  147.         End If
  148.     End If
  149.     
  150.     ' Calculate the part due to ambient light.
  151.     r_amb = LightIar * Kar
  152.     g_amb = LightIag * Kag
  153.     b_amb = LightIab * Kab
  154.     
  155.     ' See how intense to make the color.
  156.     R = r_amb + _
  157.         LightIir / (l_len + LightKdist) * _
  158.             (r_dif + spec)
  159.     G = g_amb + _
  160.         LightIig / (l_len + LightKdist) * _
  161.             (g_dif + spec)
  162.     B = b_amb + _
  163.         LightIib / (l_len + LightKdist) * _
  164.             (b_dif + spec)
  165. End Sub
  166.  
  167. ' ************************************************
  168. ' Compute the distance from point (px, py, pz)
  169. ' along vector <vx, vy, vz> to the plane.
  170. '
  171. ' Save the point of intersection in
  172. ' (HitX, HitY, HitZ) for later use.
  173. ' ************************************************
  174. Public Function RayDistance(px As Single, py As Single, pz As Single, Vx As Single, Vy As Single, Vz As Single) As Single
  175. Dim A As Single
  176. Dim B As Single
  177. Dim C As Single
  178. Dim D As Single
  179. Dim nx As Single
  180. Dim ny As Single
  181. Dim nz As Single
  182. Dim denom As Single
  183. Dim t As Single
  184.  
  185.     ' Recompute the normal vector.
  186.     nx = Point2.trans(1) - Point1.trans(1)
  187.     ny = Point2.trans(2) - Point1.trans(2)
  188.     nz = Point2.trans(3) - Point1.trans(3)
  189.     
  190.     ' Compute the plane's parameters.
  191.     A = nx
  192.     B = ny
  193.     C = nz
  194.     D = -(nx * Point1.trans(1) + _
  195.           ny * Point1.trans(2) + _
  196.           nz * Point1.trans(3))
  197.  
  198.     ' If the denominator = 0, the ray is parallel
  199.     ' to the plane so there's no intersection.
  200.     denom = A * Vx + B * Vy + C * Vz
  201.     If denom = 0 Then
  202.         RayDistance = INFINITY
  203.         Exit Function
  204.     End If
  205.     
  206.     ' Solve for t.
  207.     t = -(A * px + B * py + C * pz + D) / denom
  208.  
  209.     ' If t < 0 then the intersection is behind the
  210.     ' center of projection so not of interest.
  211.     If t < 0 Then
  212.         RayDistance = INFINITY
  213.         Exit Function
  214.     End If
  215.     
  216.     ' Compute the actual hit location.
  217.     HitX = px + t * Vx
  218.     HitY = py + t * Vy
  219.     HitZ = pz + t * Vz
  220.     
  221.     ' Compute the distance from (px, py, pz).
  222.     A = px - HitX
  223.     B = py - HitY
  224.     C = pz - HitZ
  225.     RayDistance = Sqr(A * A + B * B + C * C)
  226. End Function
  227.  
  228. ' ************************************************
  229. ' Set the points. Point2 = Point1 + normal vector.
  230. ' ************************************************
  231. Public Sub Initialize(Cx As Single, Cy As Single, Cz As Single, Vx As Single, Vy As Single, Vz As Single)
  232.     Point1.coord(1) = Cx
  233.     Point1.coord(2) = Cy
  234.     Point1.coord(3) = Cz
  235.     Point1.coord(4) = 1
  236.     Point2.coord(1) = Cx + Vx
  237.     Point2.coord(2) = Cy + Vy
  238.     Point2.coord(3) = Cz + Vz
  239.     Point2.coord(4) = 1
  240. End Sub
  241.  
  242.  
  243. ' ************************************************
  244. ' Set N and Ks for specular reflection.
  245. ' ************************************************
  246. Sub SetSpec(n As Single, s As Single)
  247.     SpecN = n
  248.     Ks = s
  249. End Sub
  250.  
  251. ' ************************************************
  252. ' Return the latest Hit location.
  253. ' ************************************************
  254. Public Sub HitLocation(x As Single, y As Single, z As Single)
  255.     x = HitX
  256.     y = HitY
  257.     z = HitZ
  258. End Sub
  259.  
  260. ' ************************************************
  261. ' Set constants for diffuse reflection.
  262. ' ************************************************
  263. Sub SetKd(R As Single, G As Single, B As Single)
  264.     Kdr = R
  265.     Kdg = G
  266.     Kdb = B
  267. End Sub
  268.  
  269. ' ************************************************
  270. ' Set constants for ambient light.
  271. ' ************************************************
  272. Sub SetKa(R As Single, G As Single, B As Single)
  273.     Kar = R
  274.     Kag = G
  275.     Kab = B
  276. End Sub
  277.  
  278.  
  279.  
  280.