home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / OldSrc / CH13 / SRC / OBJPLAR2.CLS < prev    next >
Encoding:
Text File  |  1996-04-12  |  12.6 KB  |  462 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. ' 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.     ' Find the vector V from the surface to the
  157.     ' viewpoint.
  158.     Vx = EyeX - hit_x
  159.     Vy = EyeY - hit_y
  160.     Vz = EyeZ - hit_z
  161.     v_len = Sqr(Vx * Vx + Vy * Vy + Vz * Vz)
  162.     Vx = Vx / v_len
  163.     Vy = Vy / v_len
  164.     Vz = Vz / v_len
  165.  
  166.     ' See if the light shines on the back of the
  167.     ' plane. I.e. if the center of projection
  168.     ' and light source lie on the same side.
  169.     NdotL = nx * lx + ny * ly + nz * lz
  170.     NdotV = nx * Vx + ny * Vy + nz * Vz
  171.     shadowed = (NdotL * NdotV < 0)
  172.     
  173.     ' Treat backface planes as normal planes.
  174.     NdotL = Abs(NdotL)
  175.  
  176.     ' See if the light shines directly on the surface.
  177.     If Not shadowed Then
  178.         For i = 1 To Objects.Count
  179.             dist = Objects.Item(i).RayDistance( _
  180.                 LightSource.trans(1), _
  181.                 LightSource.trans(2), _
  182.                 LightSource.trans(3), _
  183.                 -lx, -ly, -lz)
  184.             If dist < l_len - 0.1 Then Exit For
  185.         Next i
  186.         shadowed = (i <= Objects.Count)
  187.     End If
  188.     
  189.     ' Find vector R in the mirror direction.
  190.     rx = 2 * nx * NdotL - lx
  191.     ry = 2 * ny * NdotL - ly
  192.     rz = 2 * nz * NdotL - lz
  193.     
  194.     ' Calculate the part due to diffuse reflection.
  195.     If shadowed Then NdotL = -1
  196.     If NdotL < 0 Then
  197.         ' The light does not hit the surface.
  198.         r_dif = 0
  199.         g_dif = 0
  200.         b_dif = 0
  201.         spec = 0
  202.     Else
  203.         r_dif = Kdr * NdotL
  204.         g_dif = Kdg * NdotL
  205.         b_dif = Kdb * NdotL
  206.         
  207.         ' Calculate the part due to specular reflection.
  208.         RdotV = rx * Vx + ry * Vy + rz * Vz
  209.         If RdotV < 0 Then
  210.             spec = 0
  211.         Else
  212.             spec = Ks * RdotV ^ SpecN
  213.         End If
  214.     End If
  215.     
  216.     ' Calculate the part due to ambient light.
  217.     r_amb = LightIar * Kar
  218.     g_amb = LightIag * Kag
  219.     b_amb = LightIab * Kab
  220.  
  221.     ' **********************************
  222.     ' * Compute reflected contribution *
  223.     ' **********************************
  224.     r_ref = 0
  225.     g_ref = 0
  226.     b_ref = 0
  227.     If IsReflective And depth > 1 Then
  228.         ' Find vector M in the direction of reflection.
  229.         mx = 2 * nx * NdotV - Vx
  230.         my = 2 * ny * NdotV - Vy
  231.         mz = 2 * nz * NdotV - Vz
  232.         
  233.         TraceRay depth - 1, hit_x, hit_y, hit_z, mx, my, mz, r1, g1, b1
  234.         r_ref = Krr * r1
  235.         g_ref = Krg * g1
  236.         b_ref = Krb * b1
  237.     End If
  238.     
  239.     ' **********************************
  240.     ' * Compute refracted contribution *
  241.     ' **********************************
  242.     r_trd = 0
  243.     g_trd = 0
  244.     b_trd = 0
  245.     r_tra = 0
  246.     g_tra = 0
  247.     b_tra = 0
  248.     If IsTransparent Then
  249.         ' Find the transmission vector T.
  250.         If NdotV > 0 Then
  251.             ' The ray is entering this object.
  252.             cos1 = NdotV
  253.         Else
  254.             ' The ray is exiting this object.
  255.             cos1 = -NdotV
  256.         End If
  257.         n_ratio = N1 / N2
  258.         cos2 = Sqr(1 - (1 - cos1 * cos1) * n_ratio * n_ratio)
  259.         cos_factor = cos2 - cos1 * n_ratio
  260.         tx = -Vx * n_ratio - cos_factor * nx
  261.         ty = -Vy * n_ratio - cos_factor * ny
  262.         tz = -Vz * n_ratio - cos_factor * nz
  263.         
  264.         ' If LdotV < 0, the viewpoint and light are on
  265.         ' opposite sides of the surface. In that case
  266.         ' there is direct transmitted light and no
  267.         ' specular reflection.
  268.         '
  269.         ' If LdotV > 0, the viewpoint and light are on
  270.         ' the same side of the surface. Then there
  271.         ' is specular reflection and no direct
  272.         ' transmitted light.
  273.         LdotV = lx * Vx + ly * Vy + lz * Vz
  274.         
  275.         ' Find the directly transmitted component.
  276.         If LdotV < 0 Then
  277.             NdotT = nx * tx + ny * ty + nz * tz
  278.             NdotT_Nt = NdotT ^ Nt
  279.             r_trd = Ktr * NdotT_Nt
  280.             g_trd = Ktg * NdotT_Nt
  281.             b_trd = Ktb * NdotT_Nt
  282.         End If
  283.     
  284.         ' Find the indirectly transmitted component.
  285.         If depth > 1 Then
  286.             TraceRay depth - 1, hit_x, hit_y, hit_z, tx, ty, tz, r1, g1, b1
  287.             r_tra = Ktr * r1
  288.             g_tra = Ktg * g1
  289.             b_tra = Ktb * b1
  290.         End If
  291.     End If
  292.     
  293.     ' See how intense to make the color.
  294.     ' Some of the reflections may be close to
  295.     ' the light source so these values can get big.
  296.     rlng = r_amb + _
  297.         LightIir / (l_len + LightKdist) * _
  298.             (r_dif + spec) + _
  299.         r_ref + r_tra + r_trd
  300.     glng = g_amb + _
  301.         LightIig / (l_len + LightKdist) * _
  302.             (g_dif + spec) + _
  303.         g_ref + g_tra + g_trd
  304.     blng = b_amb + _
  305.         LightIib / (l_len + LightKdist) * _
  306.             (b_dif + spec) + _
  307.         b_ref + b_tra + b_trd
  308.     If rlng > 255 Then rlng = 255
  309.     If glng > 255 Then glng = 255
  310.     If blng > 255 Then blng = 255
  311.     R = rlng
  312.     G = glng
  313.     B = blng
  314. End Sub
  315.  
  316. ' ************************************************
  317. ' Set constants for transmitted light.
  318. ' ************************************************
  319. Sub SetKt(n As Single, n_1 As Single, n_2 As Single, R As Single, G As Single, B As Single)
  320.     Nt = n
  321.     N1 = n_1
  322.     N2 = n_2
  323.     Ktr = R
  324.     Ktg = G
  325.     Ktb = B
  326.     IsTransparent = (R > 0 Or G > 0 Or B > 0)
  327. End Sub
  328.  
  329.  
  330. ' ************************************************
  331. ' Set constants for reflected light.
  332. ' ************************************************
  333. Sub SetKr(R As Single, G As Single, B As Single)
  334.     Krr = R
  335.     Krg = G
  336.     Krb = B
  337.     IsReflective = (R > 0 Or G > 0 Or B > 0)
  338. End Sub
  339.  
  340.  
  341. ' ************************************************
  342. ' Compute the distance from point (px, py, pz)
  343. ' along vector <vx, vy, vz> to the plane.
  344. '
  345. ' Save the point of intersection in
  346. ' (HitX, HitY, HitZ) for later use.
  347. ' ************************************************
  348. Public Function RayDistance(px As Single, py As Single, pz As Single, Vx As Single, Vy As Single, Vz As Single) As Single
  349. Dim A As Single
  350. Dim B As Single
  351. Dim C As Single
  352. Dim D As Single
  353. Dim nx As Single
  354. Dim ny As Single
  355. Dim nz As Single
  356. Dim denom As Single
  357. Dim t As Single
  358.  
  359.     ' Recompute the normal vector.
  360.     nx = Point2.trans(1) - Point1.trans(1)
  361.     ny = Point2.trans(2) - Point1.trans(2)
  362.     nz = Point2.trans(3) - Point1.trans(3)
  363.     
  364.     ' Compute the plane's parameters.
  365.     A = nx
  366.     B = ny
  367.     C = nz
  368.     D = -(nx * Point1.trans(1) + _
  369.           ny * Point1.trans(2) + _
  370.           nz * Point1.trans(3))
  371.  
  372.     ' If the denominator = 0, the ray is parallel
  373.     ' to the plane so there's no intersection.
  374.     denom = A * Vx + B * Vy + C * Vz
  375.     If denom = 0 Then
  376.         RayDistance = INFINITY
  377.         Exit Function
  378.     End If
  379.     
  380.     ' Solve for t.
  381.     t = -(A * px + B * py + C * pz + D) / denom
  382.  
  383.     ' If t < 0 then the intersection is behind the
  384.     ' center of projection so not of interest.
  385.     If t < 0.001 Then
  386.         RayDistance = INFINITY
  387.         Exit Function
  388.     End If
  389.     
  390.     ' Compute the actual hit location.
  391.     HitX = px + t * Vx
  392.     HitY = py + t * Vy
  393.     HitZ = pz + t * Vz
  394.     
  395.     ' Compute the distance from (px, py, pz).
  396.     A = px - HitX
  397.     B = py - HitY
  398.     C = pz - HitZ
  399.     RayDistance = Sqr(A * A + B * B + C * C)
  400. End Function
  401.  
  402. ' ************************************************
  403. ' Set the points. Point2 = Point1 + normal vector.
  404. ' ************************************************
  405. Public Sub Initialize(Cx As Single, Cy As Single, Cz As Single, Vx As Single, Vy As Single, Vz As Single)
  406.     Point1.coord(1) = Cx
  407.     Point1.coord(2) = Cy
  408.     Point1.coord(3) = Cz
  409.     Point1.coord(4) = 1
  410.     Point2.coord(1) = Cx + Vx
  411.     Point2.coord(2) = Cy + Vy
  412.     Point2.coord(3) = Cz + Vz
  413.     Point2.coord(4) = 1
  414. End Sub
  415.  
  416.  
  417. ' ************************************************
  418. ' Set N and Ks for specular reflection.
  419. ' ************************************************
  420. Sub SetSpec(n As Single, s As Single)
  421.     SpecN = n
  422.     Ks = s
  423. End Sub
  424.  
  425. ' ************************************************
  426. ' Return the latest Hit location.
  427. ' ************************************************
  428. Public Sub HitLocation(x As Single, y As Single, z As Single)
  429.     x = HitX
  430.     y = HitY
  431.     z = HitZ
  432. End Sub
  433.  
  434. ' ************************************************
  435. ' Set constants for diffuse reflection.
  436. ' ************************************************
  437. Sub SetKd(R As Single, G As Single, B As Single)
  438.     Kdr = R
  439.     Kdg = G
  440.     Kdb = B
  441. End Sub
  442.  
  443. ' ************************************************
  444. ' Set constants for ambient light.
  445. ' ************************************************
  446. Sub SetKa(R As Single, G As Single, B As Single)
  447.     Kar = R
  448.     Kag = G
  449.     Kab = B
  450. End Sub
  451.  
  452.  
  453.  
  454. ' ************************************************
  455. ' Initialize N1 and N2 to default values.
  456. ' ************************************************
  457. Private Sub Class_Initialize()
  458.     N1 = 1
  459.     N2 = 1
  460. End Sub
  461.  
  462.