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

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4. END
  5. Attribute VB_Name = "ObjCylinder"
  6. Attribute VB_Creatable = False
  7. Attribute VB_Exposed = False
  8. Option Explicit
  9.  
  10. ' Point1 and Point2 are points at each end of the
  11. ' cylinder's axis.
  12. Private Point1 As Point3D
  13. Private Point2 As Point3D
  14. Private Radius As Single
  15.  
  16. ' The axis.
  17. Private Ax As Single
  18. Private Ay As Single
  19. Private Az As Single
  20.  
  21. ' The radii vectors.
  22. Private V1x As Single
  23. Private V1y As Single
  24. Private V1z As Single
  25. Private V2x As Single
  26. Private V2y As Single
  27. Private V2z As Single
  28.  
  29. Private HitX As Single
  30. Private HitY As Single
  31. Private HitZ As Single
  32. Private HitT As Single
  33.  
  34. Private Kar As Single
  35. Private Kag As Single
  36. Private Kab As Single
  37.  
  38. Private Kdr As Single
  39. Private Kdg As Single
  40. Private Kdb As Single
  41.  
  42. Private SpecN As Single
  43. Private Ks As Single
  44.  
  45. Private Krr As Single
  46. Private Krg As Single
  47. Private Krb As Single
  48.  
  49. ' ************************************************
  50. ' Apply a transformation matrix to the plane.
  51. ' ************************************************
  52. Public Sub Apply(M() As Single)
  53.     ' Transform the points.
  54.     m3Apply Point1.coord, M, Point1.trans
  55.     m3Apply Point2.coord, M, Point2.trans
  56. End Sub
  57.  
  58. ' ************************************************
  59. ' Return the red, green, and blue components of
  60. ' the surface at the hit position.
  61. ' ************************************************
  62. Public Sub HitColor(depth As Integer, Objects As Collection, R As Integer, G As Integer, B As Integer)
  63. Dim Vx As Single
  64. Dim Vy As Single
  65. Dim Vz As Single
  66. Dim nx As Single
  67. Dim ny As Single
  68. Dim nz As Single
  69. Dim lx As Single
  70. Dim ly As Single
  71. Dim lz As Single
  72. Dim rx As Single
  73. Dim ry As Single
  74. Dim rz As Single
  75. Dim n_len As Single
  76. Dim l_len As Single
  77. Dim v_len As Single
  78. Dim r_len As Single
  79. Dim NdotL As Single
  80. Dim RdotV As Single
  81. Dim NdotV As Single
  82. Dim r_dif As Single
  83. Dim g_dif As Single
  84. Dim b_dif As Single
  85. Dim r_amb As Single
  86. Dim g_amb As Single
  87. Dim b_amb As Single
  88. Dim spec As Single
  89. Dim r_ref As Single
  90. Dim g_ref As Single
  91. Dim b_ref As Single
  92. Dim r1 As Integer
  93. Dim g1 As Integer
  94. Dim b1 As Integer
  95. Dim mx As Single
  96. Dim my As Single
  97. Dim mz As Single
  98. Dim i As Integer
  99. Dim dist As Single
  100. Dim shadowed As Boolean
  101. Dim rlng As Long
  102. Dim glng As Long
  103. Dim blng As Long
  104.  
  105.     ' *******************************
  106.     ' * Compute local contributions *
  107.     ' *******************************
  108.     
  109.     ' Find the unit vector pointing toward the light.
  110.     lx = LightSource.trans(1) - HitX
  111.     ly = LightSource.trans(2) - HitY
  112.     lz = LightSource.trans(3) - HitZ
  113.     l_len = Sqr(lx * lx + ly * ly + lz * lz)
  114.     lx = lx / l_len
  115.     ly = ly / l_len
  116.     lz = lz / l_len
  117.     ' We will use l_len later as the distance from
  118.     ' the light to the surface.
  119.  
  120.     ' Find the surface unit normal.
  121.     Vx = Point2.trans(1) - Point1.trans(1)
  122.     Vy = Point2.trans(2) - Point1.trans(2)
  123.     Vz = Point2.trans(3) - Point1.trans(3)
  124.     nx = HitX - (Point1.trans(1) + HitT * Vx)
  125.     ny = HitY - (Point1.trans(2) + HitT * Vy)
  126.     nz = HitZ - (Point1.trans(3) + HitT * Vz)
  127.     n_len = Sqr(nx * nx + ny * ny + nz * nz)
  128.     nx = nx / n_len
  129.     ny = ny / n_len
  130.     nz = nz / n_len
  131.     
  132.     ' Find the vector V from the surface to the
  133.     ' viewpoint.
  134.     Vx = EyeX - HitX
  135.     Vy = EyeY - HitY
  136.     Vz = EyeZ - HitZ
  137.     v_len = Sqr(Vx * Vx + Vy * Vy + Vz * Vz)
  138.     Vx = Vx / v_len
  139.     Vy = Vy / v_len
  140.     Vz = Vz / v_len
  141.  
  142.     ' See if the light shines directly on the surface.
  143.     For i = 1 To Objects.Count
  144.         dist = Objects.Item(i).RayDistance( _
  145.             LightSource.trans(1), _
  146.             LightSource.trans(2), _
  147.             LightSource.trans(3), _
  148.             -lx, -ly, -lz)
  149.         If dist < l_len - 0.1 Then Exit For
  150.     Next i
  151.     shadowed = (i <= Objects.Count)
  152.  
  153.     ' Calculate the part due to diffuse reflection.
  154.     If shadowed Then
  155.         ' The light does not hit the surface.
  156.         r_dif = 0
  157.         g_dif = 0
  158.         b_dif = 0
  159.         spec = 0
  160.     Else
  161.         ' Treat backface planes as normal planes.
  162.         NdotL = Abs(nx * lx + ny * ly + nz * lz)
  163.         
  164.         r_dif = Kdr * NdotL
  165.         g_dif = Kdg * NdotL
  166.         b_dif = Kdb * NdotL
  167.         
  168.         ' Find vector R in the mirror direction.
  169.         rx = 2 * nx * NdotL - lx
  170.         ry = 2 * ny * NdotL - ly
  171.         rz = 2 * nz * NdotL - lz
  172.         
  173.         ' Calculate the part due to specular reflection.
  174.         RdotV = rx * Vx + ry * Vy + rz * Vz
  175.         If RdotV < 0 Then
  176.             spec = 0
  177.         Else
  178.             spec = Ks * RdotV ^ SpecN
  179.         End If
  180.     End If
  181.     
  182.     ' Calculate the part due to ambient light.
  183.     r_amb = LightIar * Kar
  184.     g_amb = LightIag * Kag
  185.     b_amb = LightIab * Kab
  186.     
  187.     ' **********************************
  188.     ' * Compute reflected contribution *
  189.     ' **********************************
  190.     ' Find vector M in the direction of reflection.
  191.     NdotV = nx * Vx + ny * Vy + nz * Vz
  192.     mx = 2 * nx * NdotV - Vx
  193.     my = 2 * ny * NdotV - Vy
  194.     mz = 2 * nz * NdotV - Vz
  195.     
  196.     If depth > 1 Then
  197.         TraceRay depth - 1, HitX, HitY, HitZ, mx, my, mz, r1, g1, b1
  198.         r_ref = Krr * r1
  199.         g_ref = Krg * g1
  200.         b_ref = Krb * b1
  201.     Else
  202.         r_ref = 0
  203.         g_ref = 0
  204.         b_ref = 0
  205.     End If
  206.     
  207.     ' See how intense to make the color.
  208.     ' Some of the reflections may be close to
  209.     ' the light source so these values can get big.
  210.     rlng = r_amb + _
  211.         LightIir / (l_len + LightKdist) * _
  212.             (r_dif + spec) + _
  213.         r_ref
  214.     glng = g_amb + _
  215.         LightIig / (l_len + LightKdist) * _
  216.             (g_dif + spec) + _
  217.         g_ref
  218.     blng = b_amb + _
  219.         LightIib / (l_len + LightKdist) * _
  220.             (b_dif + spec) + _
  221.         b_ref
  222.     If rlng > 255 Then rlng = 255
  223.     If glng > 255 Then glng = 255
  224.     If blng > 255 Then blng = 255
  225.     R = rlng
  226.     G = glng
  227.     B = blng
  228. End Sub
  229.  
  230. ' ************************************************
  231. ' Compute the distance from point (x3, y3, z3)
  232. ' along vector <wx, wy, wz> to the cylinder.
  233. '
  234. ' Save the point of intersection in
  235. ' (HitX, HitY, HitZ) for later use.
  236. ' ************************************************
  237. Public Function RayDistance(x3 As Single, y3 As Single, z3 As Single, Wx As Single, Wy As Single, Wz As Single) As Single
  238. Dim x1 As Single
  239. Dim y1 As Single
  240. Dim z1 As Single
  241. Dim Vx As Single
  242. Dim Vy As Single
  243. Dim Vz As Single
  244. Dim Vlen2 As Single
  245. Dim WdotV As Single
  246. Dim A As Single
  247. Dim B As Single
  248. Dim Cx As Single
  249. Dim Cy As Single
  250. Dim Cz As Single
  251. Dim dx As Single
  252. Dim dy As Single
  253. Dim dz As Single
  254. Dim A1 As Single
  255. Dim b1 As Single
  256. Dim C1 As Single
  257. Dim B24AC As Single
  258. Dim u1 As Single
  259. Dim u2 As Single
  260.  
  261.     ' Find the axis vector.
  262.     Vx = Point2.trans(1) - Point1.trans(1)
  263.     Vy = Point2.trans(2) - Point1.trans(2)
  264.     Vz = Point2.trans(3) - Point1.trans(3)
  265.     
  266.     ' Find A and B for t = A * u + B.
  267.     Vlen2 = Vx * Vx + Vy * Vy + Vz * Vz
  268.     WdotV = Wx * Vx + Wy * Vy + Wz * Vz
  269.     A = WdotV / Vlen2
  270.     
  271.     x1 = Point1.trans(1)
  272.     y1 = Point1.trans(2)
  273.     z1 = Point1.trans(3)
  274.     B = (Vx * (x3 - x1) + _
  275.          Vy * (y3 - y1) + _
  276.          Vz * (z3 - z1)) / Vlen2
  277.         
  278.     ' Solve for u.
  279.     Cx = Wx - Vx * A
  280.     Cy = Wy - Vy * A
  281.     Cz = Wz - Vz * A
  282.     dx = x3 - x1 - Vx * B
  283.     dy = y3 - y1 - Vy * B
  284.     dz = z3 - z1 - Vz * B
  285.     A1 = Cx * Cx + Cy * Cy + Cz * Cz
  286.     b1 = 2 * (Cx * dx + Cy * dy + Cz * dz)
  287.     C1 = dx * dx + dy * dy + dz * dz - Radius * Radius
  288.     ' Solve the quadratic A1*u^2 + B1*u + C1 = 0.
  289.     B24AC = b1 * b1 - 4 * A1 * C1
  290.     If B24AC < 0 Then
  291.         RayDistance = INFINITY
  292.         Exit Function
  293.     ElseIf B24AC = 0 Then
  294.         u1 = -b1 / 2 / A1
  295.     Else
  296.         B24AC = Sqr(B24AC)
  297.         u1 = (-b1 + B24AC) / 2 / A1
  298.         u2 = (-b1 - B24AC) / 2 / A1
  299.         ' Use only positive t values.
  300.         If u1 < 0.02 Then u1 = u2
  301.         If u2 < 0.02 Then u2 = u1
  302.         ' Use the smaller t value.
  303.         If u1 > u2 Then u1 = u2
  304.     End If
  305.     
  306.     ' If there is no positive u value, there's no
  307.     ' intersection in this direction.
  308.     If u1 < 0.02 Then
  309.         RayDistance = INFINITY
  310.         Exit Function
  311.     End If
  312.     
  313.     ' See where on the cylinder this is.
  314.     HitT = u1 * A + B
  315.     ' If this is not between Point1 and Point2,
  316.     ' ignore it.
  317.     If HitT < 0 Or HitT > 1 Then
  318.         RayDistance = INFINITY
  319.         Exit Function
  320.     End If
  321.     
  322.     ' Compute the actual hit location.
  323.     HitX = x3 + u1 * Wx
  324.     HitY = y3 + u1 * Wy
  325.     HitZ = z3 + u1 * Wz
  326.  
  327.     ' Compute the distance from (x3, y3, z3).
  328.     A1 = x3 - HitX
  329.     b1 = y3 - HitY
  330.     C1 = z3 - HitZ
  331.     RayDistance = Sqr(A1 * A1 + b1 * b1 + C1 * C1)
  332. End Function
  333.  
  334. ' ************************************************
  335. ' Initialize the data.
  336. ' ************************************************
  337. Public Sub Initialize(R As Single, p1x As Single, p1y As Single, p1z As Single, p2x As Single, p2y As Single, p2z As Single)
  338.     Radius = R
  339.     Point1.coord(1) = p1x
  340.     Point1.coord(2) = p1y
  341.     Point1.coord(3) = p1z
  342.     Point1.coord(4) = 1
  343.     Point2.coord(1) = p2x
  344.     Point2.coord(2) = p2y
  345.     Point2.coord(3) = p2z
  346.     Point2.coord(4) = 1
  347. End Sub
  348.  
  349.  
  350. ' ************************************************
  351. ' Set N and Ks for specular reflection.
  352. ' ************************************************
  353. Sub SetSpec(n As Single, s As Single)
  354.     SpecN = n
  355.     Ks = s
  356. End Sub
  357.  
  358. ' ************************************************
  359. ' Return the latest Hit location.
  360. ' ************************************************
  361. Public Sub HitLocation(x As Single, y As Single, z As Single)
  362.     x = HitX
  363.     y = HitY
  364.     z = HitZ
  365. End Sub
  366.  
  367. ' ************************************************
  368. ' Set constants for diffuse reflection.
  369. ' ************************************************
  370. Sub SetKd(R As Single, G As Single, B As Single)
  371.     Kdr = R
  372.     Kdg = G
  373.     Kdb = B
  374. End Sub
  375.  
  376. ' ************************************************
  377. ' Set constants for ambient light.
  378. ' ************************************************
  379. Sub SetKa(R As Single, G As Single, B As Single)
  380.     Kar = R
  381.     Kag = G
  382.     Kab = B
  383. End Sub
  384. ' ************************************************
  385. ' Set constants for reflected light.
  386. ' ************************************************
  387. Sub SetKr(R As Single, G As Single, B As Single)
  388.     Krr = R
  389.     Krg = G
  390.     Krb = B
  391. End Sub
  392.  
  393.  
  394.