home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / pplane / d3dutils.cpp < prev    next >
C/C++ Source or Header  |  1997-07-14  |  18KB  |  724 lines

  1. /*
  2. **-----------------------------------------------------------------------------
  3. ** Name:    D3DUtils.cpp
  4. ** Purpose: Various D3D utility functions
  5. ** Notes:
  6. **
  7. ** Copyright (c) 1995 - 1997 by Microsoft, all rights reserved.
  8. **-----------------------------------------------------------------------------
  9. */
  10.  
  11. // Note:  Must Define D3D_OVERLOADS to get C++ version of D3DMATRIX
  12. #define D3D_OVERLOADS
  13. #include <float.h>
  14. #include <math.h>
  15.  
  16. #include "d3dutils.h"
  17.  
  18. const float pi = 3.141592654f;
  19.  
  20. /*
  21. **-----------------------------------------------------------------------------
  22. ** Functions
  23. **-----------------------------------------------------------------------------
  24. */
  25.  
  26. /*
  27. **-----------------------------------------------------------------------------
  28. **  Name:       ZeroMatrix
  29. **  Purpose:    sets D3D matrix to all 0's
  30. **-----------------------------------------------------------------------------
  31. */
  32.  
  33. D3DMATRIX 
  34. ZeroMatrix(void)
  35. {
  36.     D3DMATRIX ret;
  37.     for (int i=0; i<4; i++) {
  38.         for (int j=0; j<4; j++) {
  39.             ret(i, j) = 0.0f;
  40.         }
  41.     }
  42.     return ret;
  43. } // end ZeroMatrix
  44.  
  45. /*
  46. **-----------------------------------------------------------------------------
  47. **  Name:       IdentityMatrix
  48. **  Purpose:    sets D3D matrix to Identiy (1's on diagonal, zero's elsewhere)
  49. **-----------------------------------------------------------------------------
  50. */
  51.  
  52. D3DMATRIX
  53. IdentityMatrix(void)
  54. {
  55.     D3DMATRIX ret;
  56.     for (int i=0; i<4; i++) {
  57.         for (int j=0; j<4; j++)    {
  58.             ret(i, j) = 0.0f;
  59.         }
  60.         ret(i,i) = 1.0f;
  61.     }
  62.     return ret;
  63. } // end IdentityMatrix
  64.   
  65. /*
  66. **-----------------------------------------------------------------------------
  67. **  Name:       ProjectionMatrix
  68. **  Purpose:    sets Projection matrix from fov, near and far planes
  69. **  Notes:        
  70. **        1. fov is in radians.
  71. **        2. See Blinn, "A Trip Down the Graphics Pipeline" pg 188 for details.
  72. **-----------------------------------------------------------------------------
  73. */
  74.  
  75. D3DMATRIX 
  76. ProjectionMatrix(const float near_plane, 
  77.                  const float far_plane, 
  78.                  const float fov)
  79. {
  80.     float    c, s, Q;
  81.  
  82.     c = (float) cos(fov*0.5);
  83.     s = (float) sin(fov*0.5);
  84.     Q = s/(1.0f - near_plane/far_plane);
  85.  
  86.     D3DMATRIX ret = ZeroMatrix();
  87.     ret(0, 0) = c;
  88.     ret(1, 1) = c;
  89.     ret(2, 2) = Q;
  90.     ret(3, 2) = -Q*near_plane;
  91.     ret(2, 3) = s;
  92.     return ret;
  93. }    // end ProjectionMatrix
  94.  
  95. /*
  96. **-----------------------------------------------------------------------------
  97. **  Name:       ViewMatrix
  98. **  Purpose:    Controls where the camara is.
  99. **  Notes:        
  100. **        1. Note the roll parameter is in radians and rools the viewpoint
  101. **            around the viewing direction
  102. **-----------------------------------------------------------------------------
  103. */
  104.  
  105. D3DMATRIX
  106. ViewMatrix(const D3DVECTOR& from, 
  107.            const D3DVECTOR& at, 
  108.            const D3DVECTOR& world_up, 
  109.            const float roll)
  110. {
  111.     D3DMATRIX view = IdentityMatrix();
  112.     D3DVECTOR up, right, view_dir;
  113.  
  114.     view_dir = Normalize(at - from);
  115.     right = CrossProduct(world_up, view_dir);
  116.     up = CrossProduct(view_dir, right);
  117.  
  118.     right = Normalize(right);
  119.     up = Normalize(up);
  120.     
  121.     view(0, 0) = right.x;
  122.     view(1, 0) = right.y;
  123.     view(2, 0) = right.z;
  124.     view(0, 1) = up.x;
  125.     view(1, 1) = up.y;
  126.     view(2, 1) = up.z;
  127.     view(0, 2) = view_dir.x;
  128.     view(1, 2) = view_dir.y;
  129.     view(2, 2) = view_dir.z;
  130.     
  131.     view(3, 0) = -DotProduct(right, from);
  132.     view(3, 1) = -DotProduct(up, from);
  133.     view(3, 2) = -DotProduct(view_dir, from);
  134.  
  135.     // Set roll
  136.     if (roll != 0.0f) {
  137.         view = MatrixMult(RotateZMatrix(-roll), view);
  138.     }
  139.  
  140.     return view;
  141. } // end ViewMatrix
  142.  
  143. /*
  144. **-----------------------------------------------------------------------------
  145. **  Name:       RotateXMatrix
  146. **  Purpose:    Rotate matrix about X axis
  147. **-----------------------------------------------------------------------------
  148. */
  149.  
  150. D3DMATRIX
  151. RotateXMatrix(const float rads)
  152. {
  153.     float    cosine, sine;
  154.  
  155.     cosine = (float) cos(rads);
  156.     sine = (float) sin(rads);
  157.     D3DMATRIX ret = IdentityMatrix();
  158.     ret(1,1) = cosine;
  159.     ret(2,2) = cosine;
  160.     ret(1,2) = -sine;
  161.     ret(2,1) = sine;
  162.     return ret;
  163. } // end RotateXMatrix
  164.  
  165. /*
  166. **-----------------------------------------------------------------------------
  167. **  Name:       RotateYMatrix
  168. **  Purpose:    Rotate matrix about Y axis
  169. **-----------------------------------------------------------------------------
  170. */
  171.  
  172. D3DMATRIX
  173. RotateYMatrix(const float rads)
  174. {
  175.     float    cosine, sine;
  176.  
  177.     cosine = (float) cos(rads);
  178.     sine = (float) sin(rads);
  179.     D3DMATRIX ret = IdentityMatrix();
  180.     ret(0,0) = cosine;
  181.     ret(2,2) = cosine;
  182.     ret(0,2) = sine;
  183.     ret(2,0) = -sine;
  184.     return ret;
  185. } // end RotateY
  186.   
  187. /*
  188. **-----------------------------------------------------------------------------
  189. **  Name:       RotateZMatrix
  190. **  Purpose:    Rotate matrix about Z axis
  191. **-----------------------------------------------------------------------------
  192. */
  193.  
  194. D3DMATRIX
  195. RotateZMatrix(const float rads)
  196. {
  197.     float    cosine, sine;
  198.  
  199.     cosine = (float) cos(rads);
  200.     sine = (float) sin(rads);
  201.     D3DMATRIX ret = IdentityMatrix();
  202.     ret(0,0) = cosine;
  203.     ret(1,1) = cosine;
  204.     ret(0,1) = -sine;
  205.     ret(1,0) = sine;
  206.     return ret;
  207. } // end RotateZMatrix
  208.  
  209. /*
  210. **-----------------------------------------------------------------------------
  211. **  Name:       TranslateMatrix
  212. **  Purpose:    Returns matrix to translate by (dx, dy, dz)
  213. **-----------------------------------------------------------------------------
  214. */
  215.  
  216. D3DMATRIX 
  217. TranslateMatrix(const float dx, const float dy, const float dz)
  218. {
  219.     D3DMATRIX ret = IdentityMatrix();
  220.     ret(3, 0) = dx;
  221.     ret(3, 1) = dy;
  222.     ret(3, 2) = dz;
  223.     return ret;
  224. } // end TranslateMatrix
  225.  
  226. /*
  227. **-----------------------------------------------------------------------------
  228. **  Name:       TranslateMatrix
  229. **  Purpose:    Returns matrix to translate by v
  230. **-----------------------------------------------------------------------------
  231. */
  232.  
  233. D3DMATRIX 
  234. TranslateMatrix(const D3DVECTOR& v)
  235. {
  236.     D3DMATRIX ret = IdentityMatrix();
  237.     ret(3, 0) = v[0];
  238.     ret(3, 1) = v[1];
  239.     ret(3, 2) = v[2];
  240.     return ret;
  241. } // end TranslateMatrix
  242.  
  243. /*
  244. **-----------------------------------------------------------------------------
  245. **  Name:       ScaleMatrix
  246. **  Purpose:    scale matrix (uniform)
  247. **-----------------------------------------------------------------------------
  248. */
  249.  
  250. D3DMATRIX 
  251. ScaleMatrix(const float size)
  252. {
  253.     D3DMATRIX ret = IdentityMatrix();
  254.     ret(0, 0) = size;
  255.     ret(1, 1) = size;
  256.     ret(2, 2) = size;
  257.     return ret;
  258. } // end ScaleMatrix
  259.   
  260. /*
  261. **-----------------------------------------------------------------------------
  262. **  Name:       ScaleMatrix
  263. **  Purpose:    scale matrix
  264. **-----------------------------------------------------------------------------
  265. */
  266.  
  267. D3DMATRIX 
  268. ScaleMatrix(const float a, const float b, const float c)
  269. {
  270.     D3DMATRIX ret = IdentityMatrix();
  271.     ret(0, 0) = a;
  272.     ret(1, 1) = b;
  273.     ret(2, 2) = c;
  274.     return ret;
  275. } // end ScaleMatrix
  276.   
  277. /*
  278. **-----------------------------------------------------------------------------
  279. **  Name:       ScaleMatrix
  280. **  Purpose:    scale matrix
  281. **-----------------------------------------------------------------------------
  282. */
  283.  
  284. D3DMATRIX 
  285. ScaleMatrix(const D3DVECTOR& v)
  286. {
  287.     D3DMATRIX ret = IdentityMatrix();
  288.     ret(0, 0) = v.x;
  289.     ret(1, 1) = v.y;
  290.     ret(2, 2) = v.z;
  291.     return ret;
  292. } // end ScaleMatrix
  293.  
  294. /*
  295. **-----------------------------------------------------------------------------
  296. **  Name:       MatrixMult
  297. **  Purpose:    [C] = [A] * [B]
  298. **-----------------------------------------------------------------------------
  299. */
  300.  
  301. D3DMATRIX
  302. MatrixMult(const D3DMATRIX & a, const D3DMATRIX & b)
  303. {
  304.     D3DMATRIX ret = ZeroMatrix();
  305.  
  306.     for (int i=0; i<4; i++) {
  307.         for (int j=0; j<4; j++) {
  308.             for (int k=0; k<4; k++) {
  309.                 ret(i, j) += a(k, j) * b(i, k);
  310.             }
  311.         }
  312.     }
  313.     return ret;
  314. } // end MatrixMult
  315.  
  316. /*
  317. **-----------------------------------------------------------------------------
  318. **  Name:       TransformVector
  319. **  Purpose:    V' = V * [M]
  320. **-----------------------------------------------------------------------------
  321. */
  322.  
  323. D3DVECTOR 
  324. TransformVector(const D3DVECTOR& v, const D3DMATRIX & m)
  325. {
  326.     float    hvec[4];
  327.  
  328.     for (int i=0; i<4; i++) {
  329.         hvec[i] = 0.0f;
  330.         for (int j=0; j<4; j++) {
  331.             if (j==3) {
  332.                 hvec[i] += m(j, i);
  333.             } else {
  334.                 hvec[i] += v[j] * m(j, i);
  335.             }
  336.         }
  337.     }
  338.     D3DVECTOR ret(hvec[0]/hvec[3], hvec[1]/hvec[3], hvec[2]/hvec[3]);
  339.  
  340.     return ret;
  341. } // end TransformVector
  342.  
  343. /*
  344. **-----------------------------------------------------------------------------
  345. **  Name:       TransformNormal
  346. **  Purpose:    N' = N * [M]
  347. **-----------------------------------------------------------------------------
  348. */
  349.  
  350. D3DVECTOR
  351. TransformNormal(const D3DVECTOR& v, const D3DMATRIX & mat)
  352. {
  353.     D3DMATRIX    m;
  354.  
  355.     m = MatrixInverse(mat);
  356.     m = MatrixTranspose(m);
  357.     return TransformVector(v, m);
  358. }  // end TransformNormal
  359.  
  360. /*
  361. **-----------------------------------------------------------------------------
  362. **  Name:       MatrixInverse
  363. **  Purpose:    Creates the inverse of a 4x4 matrix
  364. **-----------------------------------------------------------------------------
  365. */
  366.  
  367. static void    lubksb(D3DMATRIX & a, int *indx, float *b);
  368. static void ludcmp(D3DMATRIX & a, int *indx, float *d);
  369.  
  370. D3DMATRIX   
  371. MatrixInverse(const D3DMATRIX & m)
  372. {
  373.     D3DMATRIX    n, y;
  374.     int            i, j, indx[4];
  375.     float        d, col[4];
  376.  
  377.     n = m;
  378.     ludcmp(n, indx, &d);
  379.  
  380.     for (j=0; j<4; j++) {
  381.         for (i=0; i<4; i++) {
  382.             col[i] = 0.0f;
  383.         }
  384.         col[j] = 1.0f;
  385.         lubksb(n, indx, col);
  386.         for (i=0; i<4; i++) {
  387.             y(i, j) = col[i];
  388.         }
  389.     }
  390.     return y;
  391. } // end MatrixInverse
  392.  
  393. /*
  394. **-----------------------------------------------------------------------------
  395. **  Name:       lubksb
  396. **  Purpose:    backward subsitution
  397. **-----------------------------------------------------------------------------
  398. */
  399.  
  400. static void 
  401. lubksb(D3DMATRIX & a, int *indx, float *b)
  402. {
  403.     int        i, j, ii=-1, ip;
  404.     float    sum;
  405.  
  406.     for (i=0; i<4; i++) {
  407.         ip = indx[i];
  408.         sum = b[ip];
  409.         b[ip] = b[i];
  410.         if (ii>=0) {
  411.             for (j=ii; j<=i-1; j++) {
  412.                 sum -= a(i, j) * b[j];
  413.             }
  414.         } else if (sum != 0.0) {
  415.             ii = i;
  416.         }
  417.         b[i] = sum;
  418.     }
  419.     for (i=3; i>=0; i--) {
  420.         sum = b[i];
  421.         for (j=i+1; j<4; j++) {
  422.             sum -= a(i, j) * b[j];
  423.         }
  424.         b[i] = sum/a(i, i);
  425.     }
  426. } // end lubksb
  427.  
  428. /*
  429. **-----------------------------------------------------------------------------
  430. **  Name:       ludcmp
  431. **  Purpose:    LU decomposition
  432. **-----------------------------------------------------------------------------
  433. */
  434.  
  435. static void 
  436. ludcmp(D3DMATRIX & a, int *indx, float *d)
  437. {
  438.     float    vv[4];               /* implicit scale for each row */
  439.     float    big, dum, sum, tmp;
  440.     int        i, imax, j, k;
  441.  
  442.     *d = 1.0f;
  443.     for (i=0; i<4; i++) {
  444.         big = 0.0f;
  445.         for (j=0; j<4; j++) {
  446.             if ((tmp = (float) fabs(a(i, j))) > big) {
  447.                 big = tmp;
  448.             }
  449.         }
  450.         /*
  451.         if (big == 0.0f) {
  452.             printf("ludcmp(): singular matrix found...\n");
  453.             exit(1);
  454.         }
  455.         */
  456.         vv[i] = 1.0f/big;
  457.     }
  458.     for (j=0; j<4; j++) {
  459.         for (i=0; i<j; i++) {
  460.             sum = a(i, j);
  461.             for (k=0; k<i; k++) {
  462.                 sum -= a(i, k) * a(k, j);
  463.             }
  464.             a(i, j) = sum;
  465.         }
  466.         big = 0.0f;
  467.         for (i=j; i<4; i++) {
  468.             sum = a(i, j);
  469.             for (k=0; k<j; k++) {
  470.                 sum -= a(i, k)*a(k, j);
  471.             }
  472.             a(i, j) = sum;
  473.             if ((dum = vv[i] * (float)fabs(sum)) >= big) {
  474.                 big = dum;
  475.                 imax = i;
  476.             }
  477.         }
  478.         if (j != imax) {
  479.             for (k=0; k<4; k++) {
  480.                 dum = a(imax, k);
  481.                 a(imax, k) = a(j, k);
  482.                 a(j, k) = dum;
  483.             }
  484.             *d = -(*d);
  485.             vv[imax] = vv[j];
  486.         }
  487.         indx[j] = imax;
  488.         if (a(j, j) == 0.0f) {
  489.             a(j, j) = 1.0e-20f;      /* can be 0.0 also... */
  490.         }
  491.         if (j != 3) {
  492.             dum = 1.0f/a(j, j);
  493.             for (i=j+1; i<4; i++) {
  494.                 a(i, j) *= dum;
  495.             }
  496.         }
  497.     }
  498. } // end ludcmp
  499.   
  500. /*
  501. **-----------------------------------------------------------------------------
  502. **  Name:       Matrix Transpose
  503. **  Purpose:    [M] = [M]'
  504. **-----------------------------------------------------------------------------
  505. */
  506.  
  507. D3DMATRIX 
  508. MatrixTranspose(const D3DMATRIX & m)
  509. {
  510.     D3DMATRIX    ret;
  511.     int            i, j;
  512.  
  513.     for (i=0; i<4; i++) {
  514.         for (j=0; j<4; j++) {
  515.             ret(i, j) = m(j, i);
  516.         }
  517.     }
  518.  
  519.     return ret;
  520. } // end MatrixTranspose
  521.  
  522. /*
  523.     Class Methods
  524. */
  525.  
  526. /*
  527. **-----------------------------------------------------------------------------
  528. **  Name:       Light::Light
  529. **  Purpose:    Constructor
  530. **-----------------------------------------------------------------------------
  531. */
  532.  
  533. Light::Light(LPDIRECT3D2 lpD3D)
  534. {
  535.     memset(&light, 0, sizeof(D3DLIGHT2));
  536.     light.dwSize = sizeof(D3DLIGHT2);
  537.     lpD3D->CreateLight(&lpD3DLight, NULL);
  538.     changed = 1;
  539.  
  540.     // default to no attenuation with distance
  541.     light.dvAttenuation0 = 1.0f;
  542.     light.dvAttenuation1 = 0.0f;
  543.     light.dvAttenuation2 = 0.0f;
  544.     // default to no max distance
  545.     light.dvRange = D3DLIGHT_RANGE_MAX;
  546.     // default to linear ramp from inner to outer cone
  547.     light.dvFalloff = 1.0f;
  548.     // default to on
  549.     light.dwFlags = D3DLIGHT_ACTIVE;
  550. } // end of Light::Light
  551.  
  552. /*
  553. **-----------------------------------------------------------------------------
  554. **  Name:       Light::~Light
  555. **  Purpose:    Destructor
  556. **-----------------------------------------------------------------------------
  557. */
  558.  
  559. Light::~Light()
  560. {
  561.     if (lpD3DLight) {
  562.         lpD3DLight->Release();
  563.         lpD3DLight = NULL;
  564.     }
  565. } // end Light::~Light
  566.   
  567. /*
  568. **-----------------------------------------------------------------------------
  569. **  Name:       PointLight::PointLight
  570. **  Purpose:    Constructor
  571. **-----------------------------------------------------------------------------
  572. */
  573.  
  574. PointLight::PointLight(LPDIRECT3D2        lpD3D, 
  575.                        const D3DVECTOR&    color, 
  576.                        const D3DVECTOR&    position) : Light(lpD3D)
  577. {
  578.     light.dltType = D3DLIGHT_POINT;
  579.     light.dcvColor.r = color[0];
  580.     light.dcvColor.g = color[1];
  581.     light.dcvColor.b = color[2];
  582.     light.dvPosition.x = position[0];
  583.     light.dvPosition.y = position[1];
  584.     light.dvPosition.z = position[2];
  585.  
  586.     changed = 1;
  587. } // end PointLight::PointLight
  588.   
  589. /*
  590. **-----------------------------------------------------------------------------
  591. **  Name:       SpotLight::SpotLight
  592. **  Purpose:    Constructor
  593. **-----------------------------------------------------------------------------
  594. */
  595.  
  596. SpotLight::SpotLight(LPDIRECT3D2        lpD3D, 
  597.                      const D3DVECTOR&    color, 
  598.                      const D3DVECTOR&    position, 
  599.                      const D3DVECTOR&    direction, 
  600.                      const float        umbra_angle,
  601.                      const float        penumbra_angle) : Light(lpD3D)
  602. {
  603.     light.dltType = D3DLIGHT_SPOT;
  604.     light.dcvColor.r = color[0];
  605.     light.dcvColor.g = color[1];
  606.     light.dcvColor.b = color[2];
  607.     light.dvPosition.x = position[0];
  608.     light.dvPosition.y = position[1];
  609.     light.dvPosition.z = position[2];
  610.     light.dvDirection.x = direction[0];
  611.     light.dvDirection.y = direction[1];
  612.     light.dvDirection.z = direction[2];
  613.     light.dvTheta = umbra_angle;
  614.     light.dvPhi = penumbra_angle;
  615.  
  616.     changed = 1;
  617. } // end of SpotLight::SpotLight
  618.   
  619. /*
  620. **-----------------------------------------------------------------------------
  621. **  Name:       DirectionalLight::DirectionalLight
  622. **  Purpose:    Constructor
  623. **-----------------------------------------------------------------------------
  624. */
  625.  
  626. DirectionalLight::DirectionalLight(LPDIRECT3D2        lpD3D, 
  627.                                    const D3DVECTOR&    color, 
  628.                                    const D3DVECTOR&    direction) : Light(lpD3D)
  629. {
  630.     light.dltType = D3DLIGHT_DIRECTIONAL;
  631.     light.dcvColor.r = color[0];
  632.     light.dcvColor.g = color[1];
  633.     light.dcvColor.b = color[2];
  634.     light.dvDirection.x = direction[0];
  635.     light.dvDirection.y = direction[1];
  636.     light.dvDirection.z = direction[2];
  637.  
  638.     changed = 1;
  639. }    // end of DirectionalLight::DirectionalLight
  640.  
  641. /*
  642. **-----------------------------------------------------------------------------
  643. **  Name:       ParallelLight::ParallelLight
  644. **  Purpose:    Constructor
  645. **-----------------------------------------------------------------------------
  646. */
  647.  
  648. ParallelPointLight::ParallelPointLight(LPDIRECT3D2            lpD3D, 
  649.                                        const D3DVECTOR&    color, 
  650.                                        const D3DVECTOR&    position) : Light(lpD3D)
  651. {
  652.     light.dltType = D3DLIGHT_PARALLELPOINT;
  653.     light.dcvColor.r = color[0];
  654.     light.dcvColor.g = color[1];
  655.     light.dcvColor.b = color[2];
  656.     light.dvPosition.x = position[0];
  657.     light.dvPosition.y = position[1];
  658.     light.dvPosition.z = position[2];
  659.  
  660.     changed = 1;
  661. } // end of ParallelPointLight::ParallelPointLight constructor
  662.  
  663. /*
  664. **-----------------------------------------------------------------------------
  665. **  Name:       Material::Material
  666. **  Purpose:    Constructor
  667. **-----------------------------------------------------------------------------
  668. */
  669.  
  670. Material::Material(LPDIRECT3D2 lpD3D, LPDIRECT3DDEVICE2 lpDev)
  671. {
  672.     memset(&Mat, 0, sizeof(D3DMATERIAL));
  673.     Mat.dwSize = sizeof(D3DMATERIAL);
  674.  
  675.     // leave the default material black
  676.  
  677.     Mat.dwRampSize = 16;
  678.     Mat.diffuse.a = 1.0f;
  679.  
  680.     lpD3D->CreateMaterial(&lpMat, NULL);
  681.     lpMat->SetMaterial(&Mat);
  682.     lpMat->GetHandle(lpDev, &hMat);
  683.  
  684.     changed = 1;
  685.     Set();
  686. } // end of Material::Material
  687.   
  688. /*
  689. **-----------------------------------------------------------------------------
  690. **  Name:       Material::~Material
  691. **  Purpose:    Destructor
  692. **-----------------------------------------------------------------------------
  693. */
  694.  
  695. Material::~Material()
  696. {
  697.     if (lpMat) {
  698.         lpMat->Release();
  699.         lpMat = NULL;
  700.     }
  701. } // end of Material::~Material
  702.   
  703. /*
  704. **-----------------------------------------------------------------------------
  705. **  Name:       rnd
  706. **  Purpose:    Returns a random number (float) in the range [0.0 - 1.0]
  707. **-----------------------------------------------------------------------------
  708. */
  709.  
  710. float 
  711. rnd(void)
  712. {
  713.     return float(rand())/RAND_MAX;
  714. }    // end of rnd()
  715.  
  716.  
  717. /*
  718. **-----------------------------------------------------------------------------
  719. **  end of File
  720. **-----------------------------------------------------------------------------
  721. */
  722.  
  723.  
  724.