home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / povsrc.sit / SOURCE / HFIELD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-03  |  25.9 KB  |  909 lines

  1. /****************************************************************************
  2. *                   hfield.c
  3. *
  4. *    This file implements the height field shape primitive.  The shape is
  5. *    implemented as a collection of triangles which are calculated as
  6. *    needed.  The basic intersection routine first computes the rays
  7. *    intersection with the box marking the limits of the shape, then
  8. *    follows the line from one intersection point to the other, testing the
  9. *    two triangles which form the pixel for an intersection with the ray at
  10. *    each step.
  11. *        height field added by Doug Muir
  12. *        with lots of advice and support from David Buck 
  13. *            and Drew Wells.
  14. *
  15. *  from Persistence of Vision Raytracer 
  16. *  Copyright 1992 Persistence of Vision Team
  17. *---------------------------------------------------------------------------
  18. *  Copying, distribution and legal info is in the file povlegal.doc which
  19. *  should be distributed with this file. If povlegal.doc is not available
  20. *  or for more info please contact:
  21. *
  22. *       Drew Wells [POV-Team Leader] 
  23. *       CIS: 73767,1244  Internet: 73767.1244@compuserve.com
  24. *       Phone: (213) 254-4041
  25. * This program is based on the popular DKB raytracer version 2.12.
  26. * DKBTrace was originally written by David K. Buck.
  27. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  28. *
  29. *****************************************************************************/
  30.  
  31.  
  32. #include "frame.h"
  33. #include "vector.h"
  34. #include "povproto.h"
  35.  
  36. #define sign(x) (((x) > 0.0) ? 1: (((x) == 0) ? 0: (-1)))
  37.  
  38. #ifndef min_value
  39. #define min_value(x,y) ((x) > (y) ? (y) : (x))
  40. #endif
  41. #ifndef max_value
  42. #define max_value(x,y) ((x) < (y) ? (y) : (x))
  43. #endif
  44.  
  45. METHODS Height_Field_Methods = {
  46.    Object_Intersect, All_HeightFld_Intersections,
  47.    Inside_HeightFld, HeightFld_Normal,
  48.    Copy_HeightFld,
  49.    Translate_HeightFld, Rotate_HeightFld,
  50.    Scale_HeightFld, Invert_HeightFld};
  51.  
  52. extern HEIGHT_FIELD *Get_Height_Field_Shape();
  53.  
  54. extern long Ray_Ht_Field_Tests, Ray_Ht_Field_Tests_Succeeded;
  55. extern long Ray_Ht_Field_Box_Tests, Ray_HField_Box_Tests_Succeeded;
  56. extern int Options;
  57.  
  58. int isdx, isdz, X_Dom;
  59. DBL Gdx, Gdy, Gdz;
  60. DBL Myx, Mxz, Mzx, Myz;
  61. INTERSECTION *Hf_Intersection;
  62. PRIOQ *Hf_Queue;
  63. RAY *RRay;
  64.  
  65. #define Get_Height(x, z, H_Field) ((DBL)(H_Field)->Map[(z)][(x)])
  66.  
  67. int Intersect_Pixel(x, z, Ray, H_Field, height1, height2)
  68. int x;
  69. int z;
  70. RAY *Ray;
  71. HEIGHT_FIELD *H_Field;
  72. DBL height1;
  73. DBL height2;
  74. {
  75.    VECTOR T1V1,T1V2,T1V3,T2V1,T2V2,T2V3,Local_Normal;
  76.    DBL pos1,pos2,dot,depth1,depth2,s,t,y1,y2,y3,y4;
  77.    DBL max_height, min_height;
  78.  
  79.    depth1 = HUGE_VAL;
  80.    depth2 = HUGE_VAL;
  81.  
  82.    y1 = Get_Height(x,z,H_Field);
  83.    y2 = Get_Height(x+1,z,H_Field);
  84.    y3 = Get_Height(x,z+1,H_Field);
  85.    y4 = Get_Height(x+1,z+1,H_Field);
  86.  
  87.    Make_Vector(&T1V1,(DBL)x,y1,(DBL)z);
  88.    Make_Vector(&T1V2,1.0,y2-y1,0.0);
  89.    Make_Vector(&T1V3,0.0,y3-y1,1.0);
  90.    Make_Vector(&T2V1,(DBL)(x+1),y4,(DBL)(z+1));
  91.    Make_Vector(&T2V2,-1.0,y3-y4,0.0);
  92.    Make_Vector(&T2V3,0.0,y2-y4,-1.0);
  93.  
  94.    /*
  95.      * first, we check to see if it is even possible for the ray to
  96.      * intersect the triangle.
  97.      */
  98.  
  99.    if((max_value(y1,max_value(y2,y3)) >= height1) && 
  100.       (min_value(y1,min_value(y2,y3)) <= height2))
  101.    {
  102.       VCross(Local_Normal,T1V3,T1V2);
  103.       VDot(dot,Local_Normal,Ray->Direction);
  104.  
  105.       if((dot > EPSILON) || (dot < -EPSILON))
  106.       {
  107.          VDot(pos1,Local_Normal,T1V1);
  108.  
  109.          VDot(pos2,Local_Normal,Ray->Initial);
  110.  
  111.          pos1 -= pos2;
  112.  
  113.          depth1 = pos1 / dot;
  114.  
  115.          if((depth1 > Small_Tolerance) && (depth1 < Max_Distance))
  116.          {
  117.             s = Ray->Initial.x+(depth1*Ray->Direction.x)-(DBL)x;
  118.             t = Ray->Initial.z+(depth1*Ray->Direction.z)-(DBL)z;
  119.  
  120.             if((s<-EPSILON) || (t<-EPSILON) || ((s+t)>1.0+EPSILON))
  121.                depth1 = HUGE_VAL;
  122.          }
  123.          else
  124.             depth1 = HUGE_VAL;
  125.       }
  126.    }
  127.  
  128.    /*
  129.      * first, we check to see if it is even possible for the ray to
  130.      * intersect the triangle.
  131.        Rewritten to get around Code Builder FP stack problem.
  132.        Original code:
  133.               if((max_value(y4,max_value(y2,y3)) >= height1) && 
  134.           (min_value(y4,min_value(y2,y3)) <= height2))            */
  135.  
  136.    max_height = max_value(y4,max_value(y2,y3));
  137.    min_height = min_value(y4,min_value(y2,y3));
  138.    if((max_height >= height1) && (min_height <= height2))
  139.    {
  140.       VCross(Local_Normal,T2V3,T2V2);
  141.       VDot(dot,Local_Normal,Ray->Direction);
  142.  
  143.       if((dot > EPSILON) || (dot < -EPSILON))
  144.       {
  145.          VDot(pos1,Local_Normal,T2V1);
  146.  
  147.          VDot(pos2,Local_Normal,Ray->Initial);
  148.          pos1 -= pos2;
  149.  
  150.          depth2 = pos1 / dot;
  151.  
  152.          if((depth2 > Small_Tolerance) && (depth2 < Max_Distance))
  153.          {
  154.             s = Ray->Initial.x+(depth2*Ray->Direction.x)-(DBL)x;
  155.             t = Ray->Initial.z+(depth2*Ray->Direction.z)-(DBL)z;
  156.  
  157.             if((s>1.0+EPSILON) || (t>1.0+EPSILON) || ((s+t)<1.0-EPSILON))
  158.                depth2 = HUGE_VAL;
  159.          }
  160.          else
  161.             depth2 = HUGE_VAL;
  162.       }
  163.    }
  164.  
  165.    if((depth1 >= Max_Distance) && (depth2 >= Max_Distance))
  166.       return(FALSE);
  167.  
  168.    if(depth2 < depth1) {
  169.       Hf_Intersection->Depth = depth2;
  170.       Hf_Intersection->Object = H_Field -> Parent_Object;
  171.       VScale (T1V1, RRay -> Direction, depth2);
  172.       VAdd (T1V1, T1V1, RRay -> Initial);
  173.       Hf_Intersection->Point = T1V1;
  174.       Hf_Intersection->Shape = (SHAPE *)H_Field;
  175.       pq_add (Hf_Queue, Hf_Intersection);
  176.    }
  177.    else {
  178.       Hf_Intersection->Depth = depth1;
  179.       Hf_Intersection->Object = H_Field -> Parent_Object;
  180.       VScale (T1V1, RRay -> Direction, depth1);
  181.       VAdd (T1V1, T1V1, RRay -> Initial);
  182.       Hf_Intersection->Point = T1V1;
  183.       Hf_Intersection->Shape = (SHAPE *)H_Field;
  184.       pq_add (Hf_Queue, Hf_Intersection);
  185.    }
  186.    Ray_Ht_Field_Tests_Succeeded++;
  187.    return(TRUE);
  188. }
  189.  
  190.    int Intersect_Sub_Block(Block, Ray, H_Field, start, end)
  191.       HF_BLOCK *Block;
  192. RAY *Ray;
  193. HEIGHT_FIELD *H_Field;
  194. VECTOR *start, *end;
  195. {
  196.    DBL y1, y2;
  197.    DBL sx, sy, sz, ex, ey, ez, f;
  198.    int ix, iz, length, i, x_size, z_size;
  199.  
  200.    if(min_value(start->y,end->y) > Block->max_y)
  201.       return(FALSE);
  202.  
  203.    if(max_value(start->y,end->y) < Block->min_y)
  204.       return(FALSE);
  205.  
  206.    sx = start->x;
  207.    sy = start->y;
  208.    sz = start->z;
  209.    ex = end->x;
  210.    ey = end->y;
  211.    ez = end->z;
  212.  
  213.    if(X_Dom)
  214.    {
  215.       if(isdx >= 0) {
  216.          f = floor(sx) - sx;
  217.          sx = floor(sx);
  218.          sy += Myx * f;
  219.          sz += Mzx * f;
  220.          ex = floor(ex);
  221.          ix = (int)sx;
  222.       }
  223.       else {
  224.          f = ceil(sx) - sx;
  225.          sx = ceil(sx);
  226.          sy += Myx * f;
  227.          sz += Mzx * f;
  228.          ex = ceil(ex);
  229.          ix = (int)sx - 1;
  230.       }
  231.  
  232.          length = 0.5 + fabs(ex - sx);
  233.  
  234.       if(isdz >= 0) {
  235.          f = sz - ceil(sz);
  236.          iz = (int)floor(sz);    
  237.       }
  238.       else {
  239.          f = floor(sz) - sz;
  240.          iz = (int)ceil(sz) - 1;
  241.       }
  242.  
  243.          if(Gdy >= 0.0) {
  244.             y1 = sy;
  245.             y2 = sy + Gdy;
  246.          }
  247.          else {
  248.             y1 = sy + Gdy;
  249.             y2 = sy;
  250.          }
  251.  
  252.          for(i=0;i<=length;i++) {
  253.             if(Intersect_Pixel(ix,iz,Ray,H_Field,y1,y2))
  254.                return(TRUE);
  255.             f += Gdz;
  256.             if(f>=0.0) {
  257.                iz += isdz;
  258.                if(Intersect_Pixel(ix,iz,Ray,H_Field,y1,y2))
  259.                   return(TRUE);
  260.                f -= 1.0;
  261.             }
  262.             ix += isdx;
  263.             y1 += Gdy;
  264.             y2 += Gdy;
  265.          }
  266.    }
  267.    else {
  268.  
  269.          if(isdz >= 0) {
  270.             f = floor(sz) - sz;
  271.             sz = floor(sz);
  272.             sy += Myz * f;
  273.             sx += Mxz * f;
  274.             ez = floor(ez);
  275.             iz = (int)sz;
  276.          }
  277.          else {
  278.             f = ceil(sz) - sz;
  279.             sz = ceil(sz);
  280.             sy += Myz * f;
  281.             sx += Mxz * f;
  282.             ez = ceil(ez);
  283.             iz = (int)sz - 1;
  284.          }                
  285.  
  286.          length = 0.5 + fabs(ez - sz);
  287.  
  288.       if(isdx >= 0) {
  289.          f = sx - ceil(sx);
  290.          ix = (int)floor(sx);
  291.       }
  292.       else {
  293.          f = floor(sx) - sx;
  294.          ix = (int)ceil(sx) - 1;
  295.       }
  296.  
  297.          if(Gdy >= 0.0) {
  298.             y1 = sy;
  299.             y2 = sy + Gdy;
  300.          }
  301.          else {
  302.             y1 = sy + Gdy;
  303.             y2 = sy;
  304.          }
  305.  
  306.          for(i=0;i<=length;i++) {
  307.             if(Intersect_Pixel(ix,iz,Ray,H_Field,y1,y2))
  308.                return(TRUE);
  309.             f += Gdx;
  310.             if(f>=0.0) {
  311.                ix += isdx;
  312.                if(Intersect_Pixel(ix,iz,Ray,H_Field,y1,y2))
  313.                   return(TRUE);
  314.                f -= 1.0;
  315.             }
  316.             iz += isdz;
  317.             y1 += Gdy;
  318.             y2 += Gdy;
  319.          }
  320.    }
  321.    return (FALSE);
  322. }
  323.  
  324. int Intersect_Hf_Node(Ray, H_Field, start, end)
  325. RAY *Ray;
  326. HEIGHT_FIELD *H_Field;
  327. VECTOR *start, *end;
  328. {
  329.    VECTOR *curr, *next, *temp, temp1, temp2;
  330.    DBL sx, sy, sz, ex, ey, ez, x, y, z;
  331.    DBL tnear, tfar, t, Block_Size, Inv_Blk_Size;
  332.    int ix, iz, x_size, z_size, length, i;
  333.  
  334.    x = sx = start->x;
  335.    y = sy = start->y;
  336.    z = sz = start->z;
  337.    ex = end->x;
  338.    ey = end->y;
  339.    ez = end->z;
  340.  
  341.    Block_Size = H_Field->Block_Size;
  342.    Inv_Blk_Size = H_Field->Inv_Blk_Size;
  343.  
  344.    x_size = abs((int)(ex*Inv_Blk_Size) - (int)(sx*Inv_Blk_Size));
  345.    z_size = abs((int)(ez*Inv_Blk_Size) - (int)(sz*Inv_Blk_Size));
  346.    length = x_size + z_size;
  347.  
  348.    curr = &temp1;
  349.    next = &temp2;
  350.    Make_Vector(curr, x, y, z);
  351.    t = 0.0;
  352.  
  353.    if(X_Dom)
  354.    {
  355.       if(isdx >= 0) {
  356.          ix = (int)floor(sx*Inv_Blk_Size);
  357.          tnear = Block_Size*(ix+1) - sx;
  358.  
  359.          if (isdz >= 0) {
  360.             iz = (int)floor(sz*Inv_Blk_Size);
  361.             tfar = Gdx * (Block_Size*(iz+1) - sz);
  362.          }
  363.          else {
  364.             iz = (int)ceil(sz*Inv_Blk_Size) - 1;
  365.             tfar = Gdx * (sz - Block_Size*(iz));
  366.          }                 
  367.          for (i = 0; i < length; i++) {
  368.             if(tnear < tfar) {
  369.                t = tnear;
  370.                x = sx + t;
  371.                y = sy + Myx * t;
  372.                z = sz + Mzx * t;
  373.                Make_Vector(next, x, y, z);
  374.                if(Intersect_Sub_Block(&(H_Field->Block[ix][iz]),Ray,H_Field,curr,next))
  375.                   return(TRUE);
  376.                temp = curr;
  377.                curr = next;
  378.                next = temp;
  379.                ix++;
  380.                tnear = Block_Size*(ix+1) - sx;
  381.             }
  382.             else {
  383.                t = tfar;
  384.                x = sx + t;
  385.                y = sy + Myx * t;
  386.                z = sz + Mzx * t;
  387.                Make_Vector(next, x, y, z);
  388.                if(Intersect_Sub_Block(&(H_Field->Block[ix][iz]),Ray,H_Field,curr,next))
  389.                   return(TRUE);
  390.                temp = curr;
  391.                curr = next;
  392.                next = temp;
  393.                iz += isdz;
  394.                if (isdz >= 0) 
  395.                   tfar = Gdx * (Block_Size*(iz+1) - sz);
  396.                else 
  397.                   tfar = Gdx * (sz - Block_Size*(iz));
  398.             }
  399.          }
  400.       }
  401.       else {                
  402.          ix = (int)ceil(sx*Inv_Blk_Size) - 1;
  403.          tnear = sx - Block_Size*(ix);
  404.  
  405.             if (isdz >= 0) {
  406.                iz = (int)floor(sz*Inv_Blk_Size);
  407.                tfar = Gdx * (Block_Size*(iz+1) - sz);
  408.             }
  409.             else {
  410.                iz = (int)ceil(sz*Inv_Blk_Size) - 1;
  411.                tfar = Gdx * (sz - Block_Size*(iz));
  412.             }
  413.  
  414.             for (i = 0; i < length; i++) {
  415.                if(tnear < tfar) {
  416.                   t = tnear;
  417.                   x = sx - t;
  418.                   y = sy - Myx * t;
  419.                   z = sz - Mzx * t;
  420.                   Make_Vector(next, x, y, z);
  421.                   if(Intersect_Sub_Block(&(H_Field->Block[ix][iz]),Ray,H_Field,curr,next))
  422.                      return(TRUE);
  423.                   temp = curr;
  424.                   curr = next;
  425.                   next = temp;
  426.                   ix--;
  427.                   tnear = sx - Block_Size*(ix);
  428.                }
  429.                else {
  430.                   t = tfar;
  431.                   x = sx - t;
  432.                   y = sy - Myx * t;
  433.                   z = sz - Mzx * t;
  434.                   Make_Vector(next, x, y, z);
  435.                   if(Intersect_Sub_Block(&(H_Field->Block[ix][iz]),Ray,H_Field,curr,next))
  436.                      return(TRUE);
  437.                   temp = curr;
  438.                   curr = next;
  439.                   next = temp;
  440.                   iz += isdz;
  441.                   if (isdz >= 0) 
  442.                      tfar = Gdx * (Block_Size*(iz+1) - sz);
  443.                   else 
  444.                      tfar = Gdx * (sz - Block_Size*(iz));
  445.                }
  446.             }
  447.       }                  
  448.    }
  449.    else {
  450.       if(isdz >= 0) {
  451.          iz = (int)floor(sz*Inv_Blk_Size);
  452.          tnear = Block_Size*(iz+1) - sz;
  453.  
  454.          if (isdx >= 0) {
  455.             ix = (int)floor(sx*Inv_Blk_Size);    
  456.             tfar = Gdz * (Block_Size*(ix+1) - sx);
  457.          }
  458.          else {
  459.             ix = (int)ceil(sx*Inv_Blk_Size) - 1;
  460.             tfar = Gdz * (sx - Block_Size*(ix));
  461.          }
  462.          for (i = 0; i < length; i++) {
  463.             if(tnear < tfar) {
  464.                t = tnear;
  465.                z = sz + t;
  466.                y = sy + Myz * t;
  467.                x = sx + Mxz * t;
  468.                Make_Vector(next, x, y, z);
  469.                if(Intersect_Sub_Block(&(H_Field->Block[ix][iz]),Ray,H_Field,curr,next))
  470.                   return(TRUE);
  471.                temp = curr;
  472.                curr = next;
  473.                next = temp;
  474.                iz++;
  475.                tnear = Block_Size*(iz+1) - sz;
  476.             }
  477.             else {
  478.                t = tfar;
  479.                z = sz + t;
  480.                y = sy + Myz * t;
  481.                x = sx + Mxz * t;
  482.                Make_Vector(next, x, y, z);
  483.                if(Intersect_Sub_Block(&(H_Field->Block[ix][iz]),Ray,H_Field,curr,next))
  484.                   return(TRUE);
  485.                temp = curr;
  486.                curr = next;
  487.                next = temp;
  488.                ix += isdx;
  489.                if (isdx >= 0) 
  490.                   tfar = Gdz * (Block_Size*(ix+1) - sx);
  491.                else 
  492.                   tfar = Gdz * (sx - Block_Size*(ix));
  493.             }
  494.          }
  495.       }
  496.       else {                
  497.          iz = (int)ceil(sz*Inv_Blk_Size) - 1;
  498.          tnear = sz - Block_Size*(iz);
  499.  
  500.             if (isdx >= 0) {
  501.                ix = (int)floor(sx*Inv_Blk_Size);
  502.                tfar = Gdz * (Block_Size*(ix+1) - sx);
  503.             }
  504.             else {
  505.                ix = (int)ceil(sx*Inv_Blk_Size) - 1;
  506.                tfar = Gdz * (sx - Block_Size*(ix));
  507.             }                        
  508.          for (i = 0; i < length; i++) {
  509.             if(tnear < tfar) {
  510.                t = tnear;
  511.                z = sz - t;
  512.                y = sy - Myz * t;
  513.                x = sx - Mxz * t;
  514.                Make_Vector(next, x, y, z);
  515.                if(Intersect_Sub_Block(&(H_Field->Block[ix][iz]),Ray,H_Field,curr,next))
  516.                   return(TRUE);
  517.                temp = curr;
  518.                curr = next;
  519.                next = temp;
  520.                iz--;
  521.                tnear = sz - Block_Size*iz;
  522.             }
  523.             else {
  524.                t = tfar;
  525.                z = sz - t;
  526.                y = sy - Myz * t;
  527.                x = sx - Mxz * t;
  528.                Make_Vector(next, x, y, z);
  529.                if(Intersect_Sub_Block(&(H_Field->Block[ix][iz]),Ray,H_Field,curr,next))
  530.                   return(TRUE);
  531.                temp = curr;
  532.                curr = next;
  533.                next = temp;
  534.                ix += isdx;
  535.                if (isdx >= 0) 
  536.                   tfar = Gdz * (Block_Size*(ix+1) - sx);
  537.                else 
  538.                   tfar = Gdz * (sx - Block_Size*(ix));
  539.             }
  540.          }
  541.       }                         
  542.    }
  543.    Make_Vector(next,ex,ey,ez);
  544.    if(isdx >= 0)
  545.       ix = (int)floor(ex*Inv_Blk_Size);
  546.    else
  547.       ix = (int)ceil(ex*Inv_Blk_Size) - 1;
  548.    if(isdz >= 0)
  549.       iz = (int)floor(ez*Inv_Blk_Size);
  550.    else
  551.       iz = (int)ceil(ez*Inv_Blk_Size) - 1;
  552.    if(Intersect_Sub_Block(&(H_Field->Block[ix][iz]),Ray,H_Field,curr,next))
  553.       return(TRUE);
  554.    return (FALSE);
  555. }
  556.  
  557. void Find_Hf_Min_Max(H_Field, Image, Image_Type)
  558. HEIGHT_FIELD *H_Field;
  559. IMAGE *Image;
  560. int Image_Type;
  561. {
  562.    int n, i, i2, j, j2, x, z, w, h, max_x, max_z, temp1, temp2;
  563.    DBL size;
  564.    DBL temp_y, Block_Size, Inv_Blk_Size;
  565.  
  566.    max_x = Image->iwidth;
  567.    if(Image_Type == POT) max_x = max_x/2;
  568.    max_z = Image->iheight;
  569.  
  570.    size = (DBL)max_value(max_x, max_z);
  571.    H_Field->Block_Size  = Block_Size = ceil(sqrt(size+1.0));
  572.    H_Field->Inv_Blk_Size = Inv_Blk_Size = 1.0/Block_Size;
  573.    n = (int)Block_Size;
  574.  
  575.    w = (int)ceil((Image->width+1.0)*Inv_Blk_Size);
  576.    h = (int)ceil((Image->height+1.0)*Inv_Blk_Size);
  577.  
  578.    H_Field->Map = (float **)calloc(max_z+1, sizeof(float *));
  579.    if (H_Field->Map == NULL)
  580.       fprintf(stderr,"Cannot allocate memory for height field\n");
  581.  
  582.    H_Field->Block = (HF_BLOCK **)calloc(w,sizeof(HF_BLOCK *));
  583.    if(H_Field->Block == NULL)
  584.       fprintf(stderr, "Cannot allocate memory for height field buffer\n");
  585.    for(i=0; i<w; i++) {
  586.       H_Field->Block[i] = (HF_BLOCK *)calloc(h,sizeof(HF_BLOCK));
  587.       if (H_Field->Block[i] == NULL)
  588.          fprintf(stderr, "Cannot allocate memory for height field buffer line\n");
  589.       for(j=0; j<h; j++) {
  590.          H_Field->Block[i][j].min_y = 65536.0;
  591.          H_Field->Block[i][j].max_y = 0.0;
  592.       }
  593.    }
  594.  
  595.    H_Field->Map[0] = (float *)calloc(max_x+1,sizeof(float));
  596.    if (H_Field->Map[0] == NULL)
  597.       fprintf(stderr,"Cannot allocate memory for height field\n");
  598.  
  599.    for(j=0; j < h; j++){
  600.       for(j2=0;(j2 <= n) && (j*n+j2 <= max_z);j2++){
  601.          z = j*n+j2;
  602.          if(j2!=0){
  603.             H_Field->Map[z] = (float *)calloc(max_x+1,sizeof(float));
  604.             if (H_Field->Map[z] == NULL)
  605.                fprintf(stderr, "Cannot allocate memory for height field\n");
  606.          }
  607.          for(i=0; i < w; i++){
  608.             for(i2=0;(i2 <= n)&&(i*n+i2 <= max_x);i2++){
  609.                x = i*n+i2;
  610.                if((x > 1) && (x < max_x - 1) && (z > 1) && (z < max_z - 1)) {
  611.                   switch(Image_Type) {
  612.                   case GIF:
  613.                      temp1 = Image->data.map_lines[max_z - z - 1][x];
  614.                      temp_y = (DBL)(temp1);
  615.                      break;
  616.                   case POT:
  617.                      temp1 = Image->data.map_lines[max_z - z - 1][x];
  618.                      temp2 = Image->data.map_lines[max_z - z - 1][x + max_x];
  619.                      temp_y = (DBL)((DBL)temp1 + (DBL)temp2/256.0);
  620.                      break;
  621.                   case TGA: 
  622.                      temp1 = Image->data.rgb_lines[max_z - z - 1].red[x];
  623.                      temp2 = Image->data.rgb_lines[max_z - z - 1].green[x];
  624.                      temp_y = (DBL)((DBL)temp1 + (DBL)temp2/256.0);
  625.                      break;
  626.                   }
  627.                   if (temp_y <= H_Field->bounding_box->bounds[0].y)
  628.                      H_Field->Map[z][x] = -10000.0;
  629.                   else
  630.                      H_Field->Map[z][x] = (float)temp_y;
  631.                }
  632.                else {
  633.                   temp_y = -10000.0;
  634.                   H_Field->Map[z][x] = (float)temp_y;
  635.                }
  636.  
  637.                   if(temp_y < H_Field->bounding_box->bounds[0].y)
  638.                      temp_y = H_Field->bounding_box->bounds[0].y;
  639.                if(temp_y < H_Field->Block[i][j].min_y)
  640.                   H_Field->Block[i][j].min_y = temp_y;
  641.                if(temp_y > H_Field->Block[i][j].max_y)
  642.                   H_Field->Block[i][j].max_y = temp_y;
  643.             }
  644.          }
  645.          if((z >= 0) && (z < max_z) && (j2!=n)) {
  646.             switch (Image_Type) {
  647.             case GIF: 
  648.                free(Image->data.map_lines[max_z - z - 1]); break;
  649.             case POT: 
  650.                free(Image->data.map_lines[max_z - z - 1]); break;
  651.             case TGA:
  652.                free(Image->data.rgb_lines[max_z - z - 1].blue);
  653.                free(Image->data.rgb_lines[max_z - z - 1].green);
  654.                free(Image->data.rgb_lines[max_z - z - 1].red);
  655.                break;
  656.             }
  657.          }
  658.       }
  659.    }
  660. }
  661.  
  662. int All_HeightFld_Intersections(Object, Ray, Depth_Queue)
  663. OBJECT *Object;
  664. RAY *Ray;    
  665. PRIOQ *Depth_Queue;
  666. {
  667.    VECTOR Temp1, Temp2, Test;
  668.    RAY Temp_Ray;
  669.    DBL depth1, depth2;
  670.    int ret_val = FALSE;
  671.    HEIGHT_FIELD *H_Field = (HEIGHT_FIELD *) Object;
  672.    INTERSECTION Local_Element;
  673.  
  674.    Ray_Ht_Field_Tests++;
  675.  
  676.    MInverseTransformVector(&(Temp_Ray.Initial),&(Ray->Initial),H_Field->Transformation);
  677.    MInvTransVector(&(Temp_Ray.Direction),&(Ray->Direction),H_Field->Transformation);
  678.  
  679.    if(!Intersect_Boxx(&Temp_Ray,H_Field->bounding_box,&depth1,&depth2))
  680.       return(FALSE);     
  681.  
  682.    /*    if(    fabs(depth1 - depth2) < Small_Tolerance) { Try EPSILON if next line doesn't work */
  683.  
  684.    if( depth1 == depth2) {
  685.       depth1 = 0.0;
  686.       VScale(Temp1,Temp_Ray.Direction,depth1);
  687.       VAdd(Temp1,Temp1,Temp_Ray.Initial);
  688.       VScale(Temp2,Temp_Ray.Direction,depth2);
  689.       VAdd(Temp2,Temp2,Temp_Ray.Initial);
  690.    }
  691.    else {
  692.       VScale(Temp1,Temp_Ray.Direction,depth1);
  693.       VAdd(Temp1,Temp1,Temp_Ray.Initial);
  694.       VScale(Temp2,Temp_Ray.Direction,depth2);
  695.       VAdd(Temp2,Temp2,Temp_Ray.Initial);        
  696.    }
  697.  
  698.       if(fabs(Temp_Ray.Direction.x) > EPSILON) {
  699.          Mzx = Temp_Ray.Direction.z/Temp_Ray.Direction.x;
  700.          Myx = Temp_Ray.Direction.y/Temp_Ray.Direction.x;
  701.       }
  702.       else {
  703.          Mzx = Temp_Ray.Direction.z/EPSILON;
  704.          Myx = Temp_Ray.Direction.y/EPSILON;
  705.       }
  706.    if(fabs(Temp_Ray.Direction.z) > EPSILON) {
  707.       Mxz = Temp_Ray.Direction.x/Temp_Ray.Direction.z;
  708.       Myz = Temp_Ray.Direction.y/Temp_Ray.Direction.z;
  709.    }
  710.    else {
  711.       Mxz = Temp_Ray.Direction.x/EPSILON;
  712.       Myz = Temp_Ray.Direction.y/EPSILON;
  713.    }
  714.  
  715.       Hf_Queue = Depth_Queue;
  716.    Hf_Intersection = &Local_Element;
  717.    RRay = Ray;
  718.  
  719.    isdx = sign(Temp_Ray.Direction.x);
  720.    isdz = sign(Temp_Ray.Direction.z);
  721.  
  722.    X_Dom = FALSE;
  723.    if(fabs(Temp_Ray.Direction.x) >= fabs(Temp_Ray.Direction.z))
  724.       X_Dom = TRUE;
  725.  
  726.    Gdx = fabs(Mxz);
  727.    Gdz = fabs(Mzx);
  728.    if(X_Dom) {
  729.       Gdy = Myx * (DBL)isdx;
  730.    }
  731.    else {
  732.       Gdy = Myz * (DBL)isdz;
  733.    }
  734.  
  735.       if(Intersect_Hf_Node(&Temp_Ray, H_Field, &Temp1, &Temp2))
  736.          ret_val = TRUE;
  737.    return(ret_val);
  738. }
  739.  
  740. int Inside_HeightFld (Test_Point, Object)
  741. VECTOR *Test_Point;
  742. OBJECT *Object;
  743. {
  744.    HEIGHT_FIELD *H_Field = (HEIGHT_FIELD *) Object;
  745.    int px, pz, dot1, dot2;
  746.    DBL x,z,y1,y2,y3;
  747.    VECTOR Local_Origin, Temp1, Temp2, Local_Normal, Test;
  748.  
  749.    MInverseTransformVector(&Test, Test_Point, H_Field->Transformation);
  750.  
  751.    px = (int)Test.x;
  752.    pz = (int)Test.z;
  753.    x = Test.x - (DBL)px;
  754.    z = Test.z - (DBL)pz;
  755.  
  756.    if((x+z)<1.0)
  757.    {
  758.       y1 = Get_Height(px,pz,H_Field);
  759.       y2 = Get_Height(px+1,pz,H_Field);
  760.       y3 = Get_Height(px,pz+1,H_Field);
  761.       Make_Vector(&Local_Origin,(DBL)px,y1,(DBL)pz);
  762.       Temp1.x = 1.0;
  763.       Temp1.z = 0.0;
  764.       Temp1.y = y2 - y1;
  765.       Temp2.x = 0.0;
  766.       Temp2.z = 1.0;
  767.       Temp2.y = y3 - y1;
  768.    }
  769.    else
  770.    {
  771.       px = ceil(Test.x);
  772.       pz = ceil(Test.z);
  773.       y1 = Get_Height(px,pz,H_Field);
  774.       y2 = Get_Height(px-1,pz,H_Field);
  775.       y3 = Get_Height(px,pz-1,H_Field);
  776.       Make_Vector(&Local_Origin,(DBL)px,y1,(DBL)pz);
  777.       Temp1.x = -1.0;
  778.       Temp1.z = 0.0;
  779.       Temp1.y = y2 - y1;
  780.       Temp2.x = 0.0;
  781.       Temp2.z = -1.0;
  782.       Temp2.y = y3 - y1;
  783.    }
  784.    VCross(Local_Normal,Temp2,Temp1);
  785.    if(Local_Normal.y < 0.0) {
  786.       VScale(Local_Normal,Local_Normal,-1.0);
  787.    }
  788.    VDot(dot1,Test,Local_Normal);
  789.    VDot(dot2,Local_Origin,Local_Normal);
  790.    if((dot1 < dot2) && (Test.y > (H_Field->bounding_box->bounds[0].y)+1.0))
  791.       return(TRUE);
  792.    return(FALSE);
  793. }
  794.  
  795. void HeightFld_Normal (Result, Object, Intersection_Point)
  796. OBJECT *Object;
  797. VECTOR *Result, *Intersection_Point;
  798. {
  799.    HEIGHT_FIELD *H_Field = (HEIGHT_FIELD *) Object;
  800.    int px,pz;
  801.    DBL x,z,y1,y2,y3;
  802.    VECTOR Local_Origin, Temp1, Temp2;
  803.  
  804.    MInverseTransformVector(&Local_Origin, Intersection_Point, H_Field->Transformation);
  805.  
  806.    px = (int)Local_Origin.x;
  807.    pz = (int)Local_Origin.z;
  808.    x = Local_Origin.x - (DBL)px;
  809.    z = Local_Origin.z - (DBL)pz;
  810.  
  811.    if((x+z)<=1)
  812.    {
  813.       y1 = Get_Height(px,pz,H_Field);
  814.       y2 = Get_Height(px+1,pz,H_Field);
  815.       y3 = Get_Height(px,pz+1,H_Field);
  816.       Temp1.x = 1.0;
  817.       Temp1.z = 0.0;
  818.       Temp1.y = y2 - y1;
  819.       Temp2.x = 0.0;
  820.       Temp2.z = 1.0;
  821.       Temp2.y = y3 - y1;
  822.    }
  823.    else
  824.    {
  825.       y1 = Get_Height(px+1,pz+1,H_Field);
  826.       y2 = Get_Height(px,pz+1,H_Field);
  827.       y3 = Get_Height(px+1,pz,H_Field);
  828.       Temp1.x = -1.0;
  829.       Temp1.z = 0.0;
  830.       Temp1.y = y2 - y1;
  831.       Temp2.x = 0.0;
  832.       Temp2.z = -1.0;
  833.       Temp2.y = y3 - y1;
  834.    }
  835.  
  836.    MTransVector(&Temp1,&Temp1,H_Field->Transformation);
  837.    MTransVector(&Temp2,&Temp2,H_Field->Transformation);
  838.    VCross(*Result, Temp2, Temp1);
  839.    VNormalize(*Result,*Result);
  840.    return;
  841. }
  842.  
  843. void *Copy_HeightFld (Object)
  844. OBJECT *Object;
  845. {
  846.    HEIGHT_FIELD *New_Shape;
  847.  
  848.    New_Shape = Get_Height_Field_Shape();
  849.    *New_Shape = * ((HEIGHT_FIELD *)Object);
  850.    New_Shape -> Next_Object = NULL;
  851.  
  852.    if (New_Shape->Shape_Texture != NULL)
  853.       New_Shape->Shape_Texture = Copy_Texture (New_Shape->Shape_Texture);
  854.  
  855.    return (New_Shape);
  856. }
  857.  
  858. void Translate_HeightFld (Object, Vector)
  859. OBJECT *Object;
  860. VECTOR *Vector;
  861. {
  862.    HEIGHT_FIELD *H_Field = (HEIGHT_FIELD *) Object;
  863.    TRANSFORMATION Transformation;
  864.  
  865.    if (! H_Field -> Transformation)
  866.       H_Field -> Transformation = Get_Transformation ();
  867.    Get_Translation_Transformation(&Transformation,Vector);
  868.    Compose_Transformations(H_Field->Transformation,&Transformation);
  869.  
  870.    Translate_Texture (&((HEIGHT_FIELD *) Object)->Shape_Texture, Vector);
  871. }
  872.  
  873. void Rotate_HeightFld (Object, Vector)
  874. OBJECT *Object;
  875. VECTOR *Vector;
  876. {
  877.    TRANSFORMATION Transformation;
  878.    HEIGHT_FIELD *H_Field = (HEIGHT_FIELD *)Object;
  879.  
  880.    if (! H_Field -> Transformation)
  881.       H_Field -> Transformation = Get_Transformation ();
  882.    Get_Rotation_Transformation(&Transformation,Vector);
  883.    Compose_Transformations(H_Field->Transformation,&Transformation);
  884.  
  885.    Rotate_Texture (&((HEIGHT_FIELD *) Object)->Shape_Texture, Vector);
  886. }
  887.  
  888. void Scale_HeightFld (Object, Vector)
  889. OBJECT *Object;
  890. VECTOR *Vector;
  891. {
  892.    HEIGHT_FIELD *H_Field = (HEIGHT_FIELD *) Object;
  893.    TRANSFORMATION Transformation;
  894.  
  895.    if (! H_Field -> Transformation)
  896.       H_Field -> Transformation = Get_Transformation ();
  897.    Get_Scaling_Transformation(&Transformation,Vector);
  898.    Compose_Transformations(H_Field->Transformation,&Transformation);
  899.  
  900.    Scale_Texture (&((HEIGHT_FIELD *) Object)->Shape_Texture, Vector);
  901. }
  902.  
  903. void Invert_HeightFld (Object)
  904. OBJECT *Object;
  905. {
  906.    return;
  907. }
  908.