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

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4. END
  5. Attribute VB_Name = "ObjFacePlane"
  6. Attribute VB_Creatable = False
  7. Attribute VB_Exposed = False
  8. Option Explicit
  9.  
  10. ' This class is intended for polygons that make up
  11. ' a solid. Light entering and exiting the solid is
  12. ' refracted.
  13. '
  14. ' For this to work correctly, you must orient the
  15. ' point in the polygonal faces so the normal
  16. ' between Point1 --> Point2 is outward pointing.
  17. '
  18. ' If you want to make a flat surface with no
  19. ' interior (like a thin sheet of glass), set
  20. ' N1 = N2 = 1.
  21.  
  22. Private Point1 As Point3D   ' Point on plane.
  23. Private Point2 As Point3D   ' Normal = P2 - P1.
  24.  
  25. Private HitX As Single
  26. Private HitY As Single
  27. Private HitZ As Single
  28.  
  29. Private Kar As Single
  30. Private Kag As Single
  31. Private Kab As Single
  32.  
  33. Private Kdr As Single
  34. Private Kdg As Single
  35. Private Kdb As Single
  36.  
  37. Private SpecN As Single
  38. Private Ks As Single
  39.  
  40. Private Krr As Single
  41. Private Krg As Single
  42. Private Krb As Single
  43.  
  44. Private Nt As Single
  45. Private N1 As Single   ' Index of refraction outside the object.
  46. Private N2 As Single   ' Index of refraction inside the object.
  47. Private Ktr As Single
  48. Private Ktg As Single
  49. Private Ktb As Single
  50.  
  51. Private IsReflective As Boolean
  52. Private IsTransparent As Boolean
  53.  
  54. ' ************************************************
  55. ' Apply a transformation matrix to the plane.
  56. ' ************************************************
  57. Public Sub Apply(M() As Single)
  58.     ' Transform the point and normal.
  59.     m3Apply Point1.coord, M, Point1.trans
  60.     m3Apply Point2.coord, M, Point2.trans
  61. End Sub
  62. ' ************************************************
  63. ' Return the red, green, and blue components of
  64. ' the surface at the hit position.
  65. ' ************************************************
  66. Public Sub HitColor(depth As Integer, Objects As Collection, R As Integer, G As Integer, B As Integer)
  67. Dim nx As Single
  68. Dim ny As Single
  69. Dim nz As Single
  70. Dim lx As Single
  71. Dim ly As Single
  72. Dim lz As Single
  73. Dim Vx As Single
  74. Dim Vy As Single
  75. Dim Vz As Single
  76. Dim rx As Single
  77. Dim ry As Single
  78. Dim rz As Single
  79. Dim n_len As Single
  80. Dim l_len As Single
  81. Dim v_len As Single
  82. Dim r_len As Single
  83. Dim NdotL As Single
  84. Dim RdotV As Single
  85. Dim NdotV As Single
  86. Dim r_dif As Single
  87. Dim g_dif As Single
  88. Dim b_dif As Single
  89. Dim r_amb As Single
  90. Dim g_amb As Single
  91. Dim b_amb As Single
  92. Dim spec As Single
  93. Dim r_ref As Single
  94. Dim g_ref As Single
  95. Dim b_ref As Single
  96. Dim r1 As Integer
  97. Dim g1 As Integer
  98. Dim b1 As Integer
  99. Dim mx As Single
  100. Dim my As Single
  101. Dim mz As Single
  102. Dim LdotV As Single
  103. Dim r_trd As Single
  104. Dim g_trd As Single
  105. Dim b_trd As Single
  106. Dim r_tra As Single
  107. Dim g_tra As Single
  108. Dim b_tra As Single
  109. Dim tx As Single
  110. Dim ty As Single
  111. Dim tz As Single
  112. Dim n_ratio As Single
  113. Dim cos2 As Single
  114. Dim cos1 As Single
  115. Dim cos_factor As Single
  116. Dim NdotT As Single
  117. Dim NdotT_Nt As Single
  118. Dim hit_x As Single
  119. Dim hit_y As Single
  120. Dim hit_z As Single
  121. Dim i As Integer
  122. Dim dist As Single
  123. Dim shadowed As Boolean
  124. Dim rlng As Long
  125. Dim glng As Long
  126. Dim blng As Long
  127.  
  128.     hit_x = HitX
  129.     hit_y = HitY
  130.     hit_z = HitZ
  131.     
  132.     ' *******************************
  133.     ' * Compute local contributions *
  134.     ' *******************************
  135.     
  136.     ' Find the unit vector pointing toward the light.
  137.     lx = LightSource.trans(1) - hit_x
  138.     ly = LightSource.trans(2) - hit_y
  139.     lz = LightSource.trans(3) - hit_z
  140.     l_len = Sqr(lx * lx + ly * ly + lz * lz)
  141.     lx = lx / l_len
  142.     ly = ly / l_len
  143.     lz = lz / l_len
  144.     ' We will use l_len later as the distance from
  145.     ' the light to the surface.
  146.  
  147.     ' Find the surface unit normal.
  148.     nx = Point2.trans(1) - Point1.trans(1)
  149.     ny = Point2.trans(2) - Point1.trans(2)
  150.     nz = Point2.trans(3) - Point1.trans(3)
  151.     n_len = Sqr(nx * nx + ny * ny + nz * nz)
  152.     nx = nx / n_len
  153.     ny = ny / n_len
  154.     nz = nz / n_len
  155.     
  156.     ' See if the light shines directly on the surface.
  157.     If Not shadowed Then
  158.         For i = 1 To Objects.Count
  159.             dist = Objects.Item(i).RayDistance( _
  160.                 LightSource.trans(1), _
  161.                 LightSource.trans(2), _
  162.                 LightSource.trans(3), _
  163.                 -lx, -ly, -lz)
  164.             If dist < l_len - 0.1 Then Exit For
  165.         Next i
  166.         shadowed = (i <= Objects.Count)
  167.     End If
  168.     
  169.     ' Find vector R in the mirror direction.
  170.     NdotL = nx * lx + ny * ly + nz * lz
  171.     rx = 2 * nx * NdotL - lx
  172.     ry = 2 * ny * NdotL - ly
  173.     rz = 2 * nz * NdotL - lz
  174.     
  175.     ' Find the vector V from the surface to the
  176.     ' viewpoint.
  177.     Vx = EyeX - hit_x
  178.     Vy = EyeY - hit_y
  179.     Vz = EyeZ - hit_z
  180.     v_len = Sqr(Vx * Vx + Vy * Vy + Vz * Vz)
  181.     Vx = Vx / v_len
  182.     Vy = Vy / v_len
  183.     Vz = Vz / v_len
  184.  
  185.     ' Calculate the part due to diffuse reflection.
  186.     If shadowed Then NdotL = -1
  187.     If NdotL < 0 Then
  188.         ' The light does not hit the surface.
  189.         r_dif = 0
  190.         g_dif = 0
  191.         b_dif = 0
  192.         spec = 0
  193.     Else
  194.         r_dif = Kdr * NdotL
  195.         g_dif = Kdg * NdotL
  196.         b_dif = Kdb * NdotL
  197.         
  198.         ' Calculate the part due to specular reflection.
  199.         RdotV = rx * Vx + ry * Vy + rz * Vz
  200.         If RdotV < 0 Then
  201.             spec = 0
  202.         Else
  203.             spec = Ks * RdotV ^ SpecN
  204.         End If
  205.     End If
  206.     
  207.     ' Calculate the part due to ambient light.
  208.     r_amb = LightIar * Kar
  209.     g_amb = LightIag * Kag
  210.     b_amb = LightIab * Kab
  211.  
  212.     ' **********************************
  213.     ' * Compute reflected contribution *
  214.     ' **********************************
  215.     NdotV = nx * Vx + ny * Vy + nz * Vz
  216.     r_ref = 0
  217.     g_ref = 0
  218.     b_ref = 0
  219.     If IsReflective And depth > 1 Then
  220.         ' Find vector M in the direction of reflection.
  221.         mx = 2 * nx * NdotV - Vx
  222.         my = 2 * ny * NdotV - Vy
  223.         mz = 2 * nz * NdotV - Vz
  224.         
  225.         TraceRay depth - 1, hit_x, hit_y, hit_z, mx, my, mz, r1, g1, b1
  226.         r_ref = Krr * r1
  227.         g_ref = Krg * g1
  228.         b_ref = Krb * b1
  229.     End If
  230.     
  231.     ' **********************************
  232.     ' * Compute refracted contribution *
  233.     ' **********************************
  234.     r_trd = 0
  235.     g_trd = 0
  236.     b_trd = 0
  237.     r_tra = 0
  238.     g_tra = 0
  239.     b_tra = 0
  240.     If IsTransparent Then
  241.         ' Find the transmission vector T.
  242.         If NdotV > 0 Then
  243.             ' The ray is entering this object.
  244.             cos1 = NdotV
  245.         Else
  246.             ' The ray is exiting this object.
  247.             cos1 = -NdotV
  248.         End If
  249.         n_ratio = N1 / N2
  250.         cos2 = Sqr(1 - (1 - cos1 * cos1) * n_ratio * n_ratio)
  251.         cos_factor = cos2 - cos1 * n_ratio
  252.         tx = -Vx * n_ratio - cos_factor * nx
  253.         ty = -Vy * n_ratio - cos_factor * ny
  254.         tz = -Vz * n_ratio - cos_factor * nz
  255.         
  256.         ' If LdotV < 0, the viewpoint and light are on
  257.         ' opposite sides of the surface. In that case
  258.         ' there is direct transmitted light and no
  259.         ' specular reflection.
  260.         '
  261.         ' If LdotV > 0, the viewpoint and light are on
  262.         ' the same side of the surface. Then there
  263.         ' is specular reflection and no direct
  264.         ' transmitted light.
  265.         LdotV = lx * Vx + ly * Vy + lz * Vz
  266.         
  267.         ' Find the directly transmitted component.
  268.         If LdotV < 0 Then
  269.             NdotT = nx * tx + ny * ty + nz * tz
  270.             NdotT_Nt = NdotT ^ Nt
  271.             r_trd = Ktr * NdotT_Nt
  272.             g_trd = Ktg * NdotT_Nt
  273.             b_trd = Ktb * NdotT_Nt
  274.         End If
  275.     
  276.         ' Find the indirectly transmitted component.
  277.         If depth > 1 Then
  278.             TraceRay depth - 1, hit_x, hit_y, hit_z, tx, ty, tz, r1, g1, b1
  279.             r_tra = Ktr * r1
  280.             g_tra = Ktg * g1
  281.             b_tra = Ktb * b1
  282.         End If
  283.     End If
  284.     
  285.     ' See how intense to make the color.
  286.     ' Some of the reflections may be close to
  287.     ' the light source so these values can get big.
  288.     rlng = r_amb + _
  289.         LightIir / (l_len + LightKdist) * _
  290.             (r_dif + spec) + _
  291.         r_ref + r_tra + r_trd
  292.     glng = g_amb + _
  293.         LightIig / (l_len + LightKdist) * _
  294.             (g_dif + spec) + _
  295.         g_ref + g_tra + g_trd
  296.     blng = b_amb + _
  297.         LightIib / (l_len + LightKdist) * _
  298.             (b_dif + spec) + _
  299.         b_ref + b_tra + b_trd
  300.     If rlng > 255 Then rlng = 255
  301.     If glng > 255 Then glng = 255
  302.     If blng > 255 Then blng = 255
  303.     R = rlng
  304.     G = glng
  305.     B = blng
  306. End Sub
  307.  
  308. ' ************************************************
  309. ' Set constants for transmitted light.
  310. ' ************************************************
  311. Sub SetKt(n As Single, n_1 As Single, n_2 As Single, R As Single, G As Single, B As Single)
  312.     Nt = n
  313.     N1 = n_1
  314.     N2 = n_2
  315.     Ktr = R
  316.     Ktg = G
  317.     Ktb = B
  318.     IsTransparent = (R > 0 Or G > 0 Or B > 0)
  319. End Sub
  320.  
  321.  
  322. ' ************************************************
  323. ' Set constants for reflected light.
  324. ' ************************************************
  325. Sub SetKr(R As Single, G As Single, B As Single)
  326.     Krr = R
  327.     Krg = G
  328.     Krb = B
  329.     IsReflective = (R > 0 Or G > 0 Or B > 0)
  330. End Sub
  331.  
  332.  
  333. ' ************************************************
  334. ' Compute the distance from point (px, py, pz)
  335. ' along vector <vx, vy, vz> to the plane.
  336. '
  337. ' Save the point of intersection in
  338. ' (HitX, HitY, HitZ) for later use.
  339. ' ************************************************
  340. Public Function RayDistance(px As Single, py As Single, pz As Single, Vx As Single, Vy As Single, Vz As Single) As Single
  341. Dim A As Single
  342. Dim B As Single
  343. Dim C As Single
  344. Dim D As Single
  345. Dim nx As Single
  346. Dim ny As Single
  347. Dim nz As Single
  348. Dim denom As Single
  349. Dim t As Single
  350.  
  351.     ' Recompute the normal vector.
  352.     nx = Point2.trans(1) - Point1.trans(1)
  353.     ny = Point2.trans(2) - Point1.trans(2)
  354.     nz = Point2.trans(3) - Point1.trans(3)
  355.     
  356.     ' Compute the plane's parameters.
  357.     A = nx
  358.     B = ny
  359.     C = nz
  360.     D = -(nx * Point1.trans(1) + _
  361.           ny * Point1.trans(2) + _
  362.           nz * Point1.trans(3))
  363.  
  364.     ' If the denominator = 0, the ray is parallel
  365.     ' to the plane so there's no intersection.
  366.     denom = A * Vx + B * Vy + C * Vz
  367.     If denom = 0 Then
  368.         RayDistance = INFINITY
  369.         Exit Function
  370.     End If
  371.     
  372.     ' Solve for t.
  373.     t = -(A * px + B * py + C * pz + D) / denom
  374.  
  375.     ' If t < 0 then the intersection is behind the
  376.     ' center of projection so not of interest.
  377.     If t < 0.001 Then
  378.         RayDistance = INFINITY
  379.         Exit Function
  380.     End If
  381.     
  382.     ' Compute the actual hit location.
  383.     HitX = px + t * Vx
  384.     HitY = py + t * Vy
  385.     HitZ = pz + t * Vz
  386.     
  387.     ' Compute the distance from (px, py, pz).
  388.     A = px - HitX
  389.     B = py - HitY
  390.     C = pz - HitZ
  391.     RayDistance = Sqr(A * A + B * B + C * C)
  392. End Function
  393.  
  394. ' ************************************************
  395. ' Set the points. Point2 = Point1 + normal vector.
  396. ' ************************************************
  397. Public Sub Initialize(Cx As Single, Cy As Single, Cz As Single, Vx As Single, Vy As Single, Vz As Single)
  398.     Point1.coord(1) = Cx
  399.     Point1.coord(2) = Cy
  400.     Point1.coord(3) = Cz
  401.     Point1.coord(4) = 1
  402.     Point2.coord(1) = Cx + Vx
  403.     Point2.coord(2) = Cy + Vy
  404.     Point2.coord(3) = Cz + Vz
  405.     Point2.coord(4) = 1
  406. End Sub
  407.  
  408.  
  409. ' ************************************************
  410. ' Set N and Ks for specular reflection.
  411. ' ************************************************
  412. Sub SetSpec(n As Single, s As Single)
  413.     SpecN = n
  414.     Ks = s
  415. End Sub
  416.  
  417. ' ************************************************
  418. ' Return the latest Hit location.
  419. ' ************************************************
  420. Public Sub HitLocation(x As Single, y As Single, z As Single)
  421.     x = HitX
  422.     y = HitY
  423.     z = HitZ
  424. End Sub
  425.  
  426. ' ************************************************
  427. ' Set constants for diffuse reflection.
  428. ' ************************************************
  429. Sub SetKd(R As Single, G As Single, B As Single)
  430.     Kdr = R
  431.     Kdg = G
  432.     Kdb = B
  433. End Sub
  434.  
  435. ' ************************************************
  436. ' Set constants for ambient light.
  437. ' ************************************************
  438. Sub SetKa(R As Single, G As Single, B As Single)
  439.     Kar = R
  440.     Kag = G
  441.     Kab = B
  442. End Sub
  443.  
  444.  
  445.  
  446. ' ************************************************
  447. ' Initialize N1 and N2 to default values.
  448. ' ************************************************
  449. Private Sub Class_Initialize()
  450.     N1 = 1
  451.     N2 = 1
  452. End Sub
  453.  
  454.