home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / graphics / ftpovstc / addon2.c < prev    next >
C/C++ Source or Header  |  1994-05-25  |  20KB  |  855 lines

  1. /****************************************************************************
  2. *
  3. *  ATTENTION!!!
  4. *
  5. *  THIS FILE HAS BEEN MODIFIED!!! IT IS NOT PART OF THE OFFICAL
  6. *  POV-RAY 2.2 DISTRIBUTION!!!
  7. *
  8. *  THIS FILE IS PART OF "FASTER THAN POV-RAY" (VERSION 1.1),
  9. *  A SPED-UP VERSION OF POV-RAY 2.2. USE AT YOUR OWN RISK!!!!!!
  10. *
  11. *  New files: addon0.c, addon1.c, addon2.c, addon3.c, addon.h
  12. *
  13. *  The additional modules were written by Dieter Bayer.
  14. *
  15. *  Send comments, suggestions, bugs, ideas ... to:
  16. *
  17. *  dieter@cip.e-technik.uni-erlangen.de
  18. *
  19. *  All changed/added lines are enclosed in #ifdef DB_CODE ... #endif
  20. *
  21. *  The vista projection was taken from:
  22. *
  23. *    A. Hashimoto, T. Akimoto, K. Mase, and Y. Suenaga, 
  24. *    "Vista Ray-Tracing: High Speed Ray Tracing Using Perspective
  25. *    Projection Image", New Advances in Computer Graphics, Proceedings
  26. *    of CG International '89, R. A. Earnshaw, B. Wyvill (Eds.), 
  27. *    Springer, ..., pp. 549-560
  28. *
  29. *  The idea for the light buffer was taken from:
  30. *
  31. *    E. Haines and D. Greenberg, "The Light Buffer: A Shadow-Testing 
  32. *    Accelerator", IEEE CG&A, Vol. 6, No. 9, Sept. 1986, pp. 6-16
  33. *
  34. *****************************************************************************/
  35.  
  36. /****************************************************************************
  37. *  addon2.c
  38. *
  39. *  This module was written by Dieter Bayer.
  40. *
  41. *  This module contains functions used only for the light buffer.
  42. *
  43. *  01.03.1994 : Creation
  44. *
  45. *  29.04.1994 : Creation
  46. *
  47. ******************************************************************************/
  48.  
  49. #include "frame.h"
  50. #include "vector.h"
  51. #include "povproto.h"
  52. #include "addon.h"
  53.  
  54. #ifdef DB_CODE
  55.  
  56.  
  57. /*****************************************************************************
  58. * External variables
  59. ******************************************************************************/
  60.  
  61. extern FRAME Frame;
  62. extern unsigned long Quality_Flags;
  63. extern unsigned int Options, Extended_Options;
  64.  
  65. extern METHODS Bicubic_Patch_Methods;
  66. extern METHODS Blob_Methods;
  67. extern METHODS Box_Methods;
  68. extern METHODS Cone_Methods;
  69. extern METHODS Csg_Height_Field_Methods;
  70. extern METHODS CSG_Intersection_Methods;
  71. extern METHODS CSG_Merge_Methods;
  72. extern METHODS CSG_Union_Methods;
  73. extern METHODS Disc_Methods;
  74. extern METHODS Ellipsoid_Methods;
  75. extern METHODS Height_Field_Methods;
  76. extern METHODS Light_Source_Methods;
  77. extern METHODS Plane_Methods;
  78. extern METHODS Poly_Methods;
  79. extern METHODS Quadric_Methods;
  80. extern METHODS Smooth_Triangle_Methods;
  81. extern METHODS Sphere_Methods;
  82. extern METHODS Triangle_Methods;
  83.  
  84. extern OBJECT *Root_Object;
  85.  
  86. extern size_t Mem_Light_Buffers;
  87.  
  88.  
  89.  
  90. /*****************************************************************************
  91. * static variabls
  92. ******************************************************************************/
  93.  
  94. static VECTOR VIEW_VX1 = {-0.7071067812, 0.0, -0.7071067812};
  95. static VECTOR VIEW_VX2 = { 0.7071067812, 0.0, -0.7071067812};
  96. static VECTOR VIEW_VY1 = {0.0, -0.7071067812, -0.7071067812};
  97. static VECTOR VIEW_VY2 = {0.0,  0.7071067812, -0.7071067812};
  98. static DBL VIEW_DX1 = 0.0;
  99. static DBL VIEW_DX2 = 0.0;
  100. static DBL VIEW_DY1 = 0.0;
  101. static DBL VIEW_DY2 = 0.0;
  102.  
  103.  
  104.  
  105. /*****************************************************************************
  106. * static functions
  107. ******************************************************************************/
  108.  
  109. static void Calc_Points PARAMS((int Axis, OBJECT *Object, int *Number, VECTOR *Points, VECTOR *Origin));
  110.  
  111. static int BBox_Invisible PARAMS((int Axis, BBOX *Bounds, VECTOR *Origin));
  112.  
  113. static void Project_rectangle PARAMS((PROJECT *Project, VECTOR P1, VECTOR P2, VECTOR P3, VECTOR P4, int *visible));
  114. static void Project_triangle PARAMS((PROJECT *Project, VECTOR P1, VECTOR P2, VECTOR P3, int *visible));
  115. static void Project_Bbox PARAMS((PROJECT *Project, VECTOR *Points, int *visible));
  116. static void Project_Object PARAMS((PROJECT *Project, OBJECT *Object, int Axis, VECTOR *Origin));
  117.  
  118. static void Project_Bounding_Slab
  119.   PARAMS((int Axis, VECTOR *Origin, PROJECT *Project,
  120.       PROJECT_TREE_NODE **Entry, OBJECT *Object));
  121.  
  122.  
  123. /*****************************************************************************
  124. *
  125. * FUNCTION      : Calc_Points
  126. *
  127. * ARGUMENTS     : Axis   - Axis along the objects will be projected
  128. *                 Object - Object
  129. *                 Number - Number of points to project
  130. *                 Points - Points to project
  131. *                 Origin - Origin of current light source
  132. *
  133. * MODIFIED ARGS : Number, Points
  134. *
  135. * RETURN VALUE  : none
  136. *
  137. * AUTHOR        : Dieter Bayer, May 1994
  138. *
  139. * DESCRIPTION
  140. *
  141. *   Calculate the points to project depending on the object type,
  142. *   the light source position and the axis.
  143. *
  144. * CHANGES
  145. *
  146. *   -
  147. *
  148. ******************************************************************************/
  149.  
  150. static void Calc_Points(Axis, Object, Number, Points, Origin)
  151. int Axis;
  152. OBJECT *Object;
  153. int *Number;
  154. VECTOR *Points, *Origin;
  155. {
  156.   register int i;
  157.   DBL Direction;
  158.   VECTOR P[8];
  159.  
  160.   /* Get points depending on object's type */
  161.  
  162.   if ((Object->Methods == &Triangle_Methods) ||
  163.       (Object->Methods == &Smooth_Triangle_Methods))
  164.   {
  165.     if (Object->Methods == &Triangle_Methods)
  166.     {
  167.       *Number = 3;
  168.       P[0] = ((TRIANGLE *)Object)->P1;
  169.       P[1] = ((TRIANGLE *)Object)->P2;
  170.       P[2] = ((TRIANGLE *)Object)->P3;
  171.     }
  172.     if (Object->Methods == &Smooth_Triangle_Methods)
  173.     {
  174.       *Number = 3;
  175.       P[0] = ((SMOOTH_TRIANGLE *)Object)->P1;
  176.       P[1] = ((SMOOTH_TRIANGLE *)Object)->P2;
  177.       P[2] = ((SMOOTH_TRIANGLE *)Object)->P3;
  178.     }
  179.   }
  180.   else
  181.   {
  182.     *Number = 8;
  183.  
  184.     for (i = 0; i < *Number; i++)
  185.     {
  186.       P[i] = Object->Bounds.Lower_Left;
  187.  
  188.       P[i].x += ((i & 1) ? Object->Bounds.Lengths.x : 0.0);
  189.       P[i].y += ((i & 2) ? Object->Bounds.Lengths.y : 0.0);
  190.       P[i].z += ((i & 4) ? Object->Bounds.Lengths.z : 0.0);
  191.     }
  192.   }
  193.  
  194.   /* The points' coordinates need to be relative to the light source */
  195.  
  196.   for (i = 0; i < *Number; i++)
  197.   {
  198.     P[i].x -= Origin->x;
  199.     P[i].y -= Origin->y;
  200.     P[i].z -= Origin->z;
  201.   }
  202.  
  203.   /* Switch axes so that the specified axis becomes the +Z-axis */
  204.  
  205.   if ((Axis == XaxisP) || (Axis == YaxisP) || (Axis == ZaxisP))
  206.   {
  207.     Direction = +1.0;
  208.   }
  209.   else
  210.   {
  211.     Direction = -1.0;
  212.   }
  213.  
  214.   /* Modify points so that the new z direction is the projection axis */
  215.  
  216.   switch (Axis)
  217.   {
  218.     case XaxisP :
  219.     case XaxisM :
  220.  
  221.       for (i = 0; i < *Number; i++)
  222.       {
  223.     Points[i].x = P[i].y;
  224.     Points[i].y = P[i].z;
  225.     Points[i].z = P[i].x * Direction;
  226.       }
  227.       break;
  228.  
  229.     case YaxisP :
  230.     case YaxisM :
  231.  
  232.       for (i = 0; i < *Number; i++)
  233.       {
  234.     Points[i].x = P[i].x;
  235.     Points[i].y = P[i].z;
  236.     Points[i].z = P[i].y * Direction;
  237.       }
  238.       break;
  239.  
  240.     case ZaxisP :
  241.     case ZaxisM :
  242.  
  243.       for (i = 0; i < *Number; i++)
  244.       {
  245.     Points[i].x = P[i].x;
  246.     Points[i].y = P[i].y;
  247.     Points[i].z = P[i].z * Direction;
  248.       }
  249.       break;
  250.  
  251.     default :
  252.       Fatal_Error("Illegal axis in module addon2.\n");
  253.   }
  254. }
  255.  
  256.  
  257.  
  258. /*****************************************************************************
  259. *
  260. * FUNCTION      : BBox_Invisible
  261. *
  262. * ARGUMENTS     : Axis   - Axis along the objects will be projected
  263. *                 Bounds - Bounding box to test
  264. *                 Origin - Origin of current light source
  265. *
  266. * MODIFIED ARGS : none
  267. *
  268. * RETURN VALUE  : int - Flag if bounding box is totally invisble
  269. *
  270. * AUTHOR        : Dieter Bayer, May 1994
  271. *
  272. * DESCRIPTION
  273. *
  274. *   Do a quick test if a bounding box is totally invisble from the
  275. *   current light source in the specified axis direction.
  276. *
  277. * CHANGES
  278. *
  279. *   -
  280. *
  281. ******************************************************************************/
  282.  
  283. static int BBox_Invisible(Axis, Bounds, Origin)
  284. int Axis;
  285. BBOX *Bounds;
  286. VECTOR *Origin;
  287. {
  288.   switch (Axis)
  289.   {
  290.     case XaxisP :
  291.  
  292.       if (Bounds->Lower_Left.x + Bounds->Lengths.x < Origin->x) return(TRUE);
  293.       break;
  294.  
  295.     case XaxisM :
  296.  
  297.       if (Bounds->Lower_Left.x > Origin->x) return(TRUE);
  298.       break;
  299.  
  300.     case YaxisP :
  301.  
  302.       if (Bounds->Lower_Left.y + Bounds->Lengths.y < Origin->y) return(TRUE);
  303.       break;
  304.  
  305.     case YaxisM :
  306.  
  307.       if (Bounds->Lower_Left.y > Origin->y) return(TRUE);
  308.       break;
  309.  
  310.     case ZaxisP :
  311.  
  312.       if (Bounds->Lower_Left.z + Bounds->Lengths.z < Origin->z) return(TRUE);
  313.       break;
  314.  
  315.     case ZaxisM :
  316.  
  317.       if (Bounds->Lower_Left.z > Origin->z) return(TRUE);
  318.       break;
  319.  
  320.     default :
  321.       Fatal_Error("Illegal axis in module addon2.\n");
  322.   }
  323.  
  324.   return(FALSE);
  325. }
  326.  
  327.  
  328.  
  329. /*****************************************************************************
  330. *
  331. * FUNCTION      : Project_rectangle
  332. *
  333. * ARGUMENTS     : Project        - Rectangle's projection
  334. *                 P1, P2, P3, P4 - Rectangle's edges
  335. *                 visible        - Flag if rectangle is visible
  336. *
  337. * MODIFIED ARGS : Project, visible
  338. *
  339. * RETURN VALUE  : none
  340. *
  341. * AUTHOR        : Dieter Bayer, May 1994
  342. *
  343. * DESCRIPTION
  344. *
  345. *   Project a rectangle onto a light source.
  346. *
  347. * CHANGES
  348. *
  349. *   -
  350. *
  351. ******************************************************************************/
  352.  
  353. static void Project_rectangle(Project, P1, P2, P3, P4, visible)
  354. PROJECT *Project;
  355. VECTOR P1, P2, P3, P4;
  356. int *visible;
  357. {
  358.   VECTOR Points[MAX_CLIP_POINTS];
  359.   int i, number;
  360.   int x, y;
  361.  
  362.   /* Square totally invisible? */
  363.  
  364.   if ((P1.z <= 0.0) && (P2.z <= 0.0) && (P3.z <= 0.0) && (P4.z <= 0.0))
  365.     return;
  366.  
  367.   Points[0] = P1;
  368.   Points[1] = P2;
  369.   Points[2] = P3;
  370.   Points[3] = P4;
  371.  
  372.   number = 4;
  373.  
  374.   /* Clip square only if some quick tests say it's necessary.
  375.      Assuming that only a few squares need clipping this saves some time.
  376.      (I don't need to write fabs(P?.z) since the tests succeed anyway
  377.       if P?.z < 0. Hope the compiler doesn't change the tests' order!) */
  378.  
  379.   if ((P1.z < 0.0) || (P2.z < 0.0) || (P3.z < 0.0) || (P4.z < 0.0) ||
  380.       (fabs(P1.x) > (P1.z)) || (fabs(P1.y) > (P1.z)) ||
  381.       (fabs(P2.x) > (P2.z)) || (fabs(P2.y) > (P2.z)) ||
  382.       (fabs(P3.x) > (P3.z)) || (fabs(P3.y) > (P3.z)) ||
  383.       (fabs(P4.x) > (P4.z)) || (fabs(P4.y) > (P4.z)))
  384.   {
  385.     Clip_Polygon(Points, &number, &VIEW_VX1, &VIEW_VX2, &VIEW_VY1, &VIEW_VY2,
  386.                  VIEW_DX1,  VIEW_DX2,  VIEW_DY1,  VIEW_DY2);
  387.   }
  388.  
  389.   if (!number)
  390.     return;
  391.  
  392.   for (i = 0; i < number; i++)
  393.   {
  394.     if (Points[i].z < EPSILON)
  395.     {
  396.       Points[i].x = Points[i].y = 0.0;
  397.     }
  398.     else
  399.     {
  400.       Points[i].x = Points[i].x / Points[i].z;
  401.       Points[i].y = Points[i].y / Points[i].z;
  402.       if (fabs(Points[i].x) < EPSILON) Points[i].x = 0.0;
  403.       if (fabs(Points[i].y) < EPSILON) Points[i].y = 0.0;
  404.     }
  405.  
  406.     x = (int)(MAX_LB_ENTRY * Points[i].x);
  407.     y = (int)(MAX_LB_ENTRY * Points[i].y);
  408.  
  409.     if (x < Project->x1) Project->x1 = x;
  410.     if (x > Project->x2) Project->x2 = x;
  411.     if (y < Project->y1) Project->y1 = y;
  412.     if (y > Project->y2) Project->y2 = y;
  413.   }
  414.  
  415.   *visible = TRUE;
  416. }
  417.  
  418.  
  419.  
  420.  
  421. /*****************************************************************************
  422. *
  423. * FUNCTION      : Project_triangle
  424. *
  425. * ARGUMENTS     : Project    - Triangle's projection
  426. *                 P1, P2, P3 - Triangles's edges
  427. *                 visible    - Flag if triangle is visible
  428. *
  429. * MODIFIED ARGS : Project, visible
  430. *
  431. * RETURN VALUE  : none
  432. *
  433. * AUTHOR        : Dieter Bayer, May 1994
  434. *
  435. * DESCRIPTION
  436. *
  437. *   Project a triangle onto a light source.
  438. *
  439. * CHANGES
  440. *
  441. *   -
  442. *
  443. ******************************************************************************/
  444.  
  445. static void Project_triangle(Project, P1, P2, P3, visible)
  446. PROJECT *Project;
  447. VECTOR P1, P2, P3;
  448. int *visible;
  449. {
  450.   VECTOR Points[MAX_CLIP_POINTS];
  451.   int i, number;
  452.   int x, y;
  453.  
  454.   /* Triangle totally invisible? */
  455.  
  456.   if ((P1.z <= 0.0) && (P2.z <= 0.0) && (P3.z <= 0.0))
  457.     return;
  458.  
  459.   Points[0] = P1;
  460.   Points[1] = P2;
  461.   Points[2] = P3;
  462.  
  463.   number = 3;
  464.  
  465.   /* Clip triangle only if some quick tests say it's necessary.
  466.      Assuming that only a few triangles need clipping this saves some time.
  467.      (I don't need to write fabs(P?.z) since the tests succeed anyway
  468.       if P?.z < 0. Hope the compiler doesn't change the tests' order!) */
  469.  
  470.   if ((P1.z < 0.0) || (P2.z < 0.0) || (P3.z < 0.0) ||
  471.       (fabs(P1.x) > (P1.z)) || (fabs(P1.y) > (P1.z)) ||
  472.       (fabs(P2.x) > (P2.z)) || (fabs(P2.y) > (P2.z)) ||
  473.       (fabs(P3.x) > (P3.z)) || (fabs(P3.y) > (P3.z)))
  474.   {
  475.     Clip_Polygon(Points, &number, &VIEW_VX1, &VIEW_VX2, &VIEW_VY1, &VIEW_VY2,
  476.                    VIEW_DX1,  VIEW_DX2,  VIEW_DY1,  VIEW_DY2);
  477.   }
  478.  
  479.   if (!number)
  480.     return;
  481.  
  482.   for (i = 0; i < number; i++)
  483.   {
  484.     if (fabs(Points[i].z) < EPSILON)
  485.     {
  486.       Points[i].x = Points[i].y = 0.0;
  487.     }
  488.     else
  489.     {
  490.       Points[i].x = Points[i].x / Points[i].z;
  491.       Points[i].y = Points[i].y / Points[i].z;
  492.       if (fabs(Points[i].x) < EPSILON) Points[i].x = 0.0;
  493.       if (fabs(Points[i].y) < EPSILON) Points[i].y = 0.0;
  494.     }
  495.  
  496.     x = (int)(MAX_LB_ENTRY * Points[i].x);
  497.     y = (int)(MAX_LB_ENTRY * Points[i].y);
  498.  
  499.     if (x < Project->x1) Project->x1 = x;
  500.     if (x > Project->x2) Project->x2 = x;
  501.     if (y < Project->y1) Project->y1 = y;
  502.     if (y > Project->y2) Project->y2 = y;
  503.   }
  504.  
  505.   *visible = TRUE;
  506. }
  507.  
  508.  
  509.  
  510.  
  511. /*****************************************************************************
  512. *
  513. * FUNCTION      : Project_BBox
  514. *
  515. * ARGUMENTS     : Project - Box's projection
  516. *                 Points  - Box's edges
  517. *                 visible - Flag if box is visible
  518. *
  519. * MODIFIED ARGS : Project, visible
  520. *
  521. * RETURN VALUE  : none
  522. *
  523. * AUTHOR        : Dieter Bayer, May 1994
  524. *
  525. * DESCRIPTION
  526. *
  527. *   Project a box onto a light source.
  528. *
  529. * CHANGES
  530. *
  531. *   -
  532. *
  533. ******************************************************************************/
  534.  
  535. static void Project_Bbox(Project, Points, visible)
  536. PROJECT *Project;
  537. VECTOR *Points;
  538. int *visible;
  539. {
  540.   Project_rectangle(Project, Points[0], Points[1], Points[3], Points[2], visible);
  541.   Project_rectangle(Project, Points[4], Points[5], Points[7], Points[6], visible);
  542.   Project_rectangle(Project, Points[0], Points[1], Points[5], Points[4], visible);
  543.   Project_rectangle(Project, Points[2], Points[3], Points[7], Points[6], visible);
  544.   Project_rectangle(Project, Points[1], Points[3], Points[7], Points[5], visible);
  545.   Project_rectangle(Project, Points[0], Points[2], Points[6], Points[4], visible);
  546. }
  547.  
  548.  
  549.  
  550. /*****************************************************************************
  551. *
  552. * FUNCTION      : Project_Object
  553. *
  554. * ARGUMENTS     : Object   - Object to project
  555. *                 Project  - Projection
  556. *
  557. * MODIFIED ARGS : Project
  558. *
  559. * RETURN VALUE  : none
  560. *
  561. * AUTHOR        : Dieter Bayer, May 1994
  562. *
  563. * DESCRIPTION
  564. *
  565. *   Get the projection of a single object onto a light source.
  566. *
  567. * CHANGES
  568. *
  569. *   -
  570. *
  571. ******************************************************************************/
  572.  
  573. static void Project_Object(Project, Object, Axis, Origin)
  574. PROJECT *Project;
  575. OBJECT *Object;
  576. int Axis;
  577. VECTOR *Origin;
  578. {
  579.   int visible, Number;
  580.   DBL Volume;
  581.   VECTOR Points[8];
  582.  
  583.   /* Do not project infinite objects (always visible!) */
  584.  
  585.   BOUNDS_VOLUME(Volume, Object->Bounds);
  586.  
  587.   if (Volume > INFINITE_VOLUME)
  588.   {
  589.     Project->x1 = Project->y1 = MIN_LB_ENTRY;
  590.     Project->x2 = Project->y2 = MAX_LB_ENTRY;
  591.     return;
  592.   }
  593.  
  594.   /* Get points to project */
  595.  
  596.   Calc_Points(Axis, Object, &Number, &Points[0], Origin);
  597.  
  598.   visible = FALSE;
  599.  
  600.   Project->x1 = Project->y1 = MAX_LB_ENTRY;
  601.   Project->x2 = Project->y2 = MIN_LB_ENTRY;
  602.  
  603.   if (Number == 3)
  604.   {
  605.     Project_triangle(Project, Points[0], Points[1], Points[2], &visible);
  606.   }
  607.   else
  608.   {
  609.     Project_Bbox(Project, &Points[0], &visible);
  610.   }
  611.  
  612.   if (!visible)
  613.   {
  614.     /* Object is invisible */
  615.  
  616.     Project->x1 = Project->y1 = MAX_LB_ENTRY;
  617.     Project->x2 = Project->y2 = MIN_LB_ENTRY;
  618.   }
  619.   else
  620.   {
  621.     /* We don't want to miss something */
  622.  
  623.     Project->x1--;
  624.     Project->x2++;
  625.     Project->y1--;
  626.     Project->y2++;
  627.   }
  628.  
  629.   Print_Point(6 * POINT_MOD);
  630. }
  631.  
  632.  
  633.  
  634. /*****************************************************************************
  635. *
  636. * FUNCTION      : Project_Bounding_Slab
  637. *
  638. * ARGUMENTS     : Axis     - Axis along the objects will be projected
  639. *                 Origin   - Origin of current light source
  640. *                 Project  - Projection
  641. *                 Tree     - Current node/leaf
  642. *                 Object   - Node/leaf in bounding slab hierarchy
  643. *
  644. * MODIFIED ARGS : Project, Tree
  645. *
  646. * RETURN VALUE  : none
  647. *
  648. * AUTHOR        : Dieter Bayer, May 1994
  649. *
  650. * DESCRIPTION
  651. *
  652. *   Project the bounding slab hierarchy onto a light source and thus create
  653. *   the light buffer hierarchy for this light source.
  654. *
  655. * CHANGES
  656. *
  657. *   -
  658. *
  659. ******************************************************************************/
  660.  
  661. static void Project_Bounding_Slab(Axis, Origin, Project, Tree, Object)
  662. int Axis;
  663. VECTOR *Origin;
  664. PROJECT *Project;
  665. PROJECT_TREE_NODE **Tree;
  666. OBJECT *Object;
  667. {
  668.   unsigned short int i;
  669.   COMPOSITE *Comp;
  670.   PROJECT Temp;
  671.   PROJECT_TREE_LEAF *Leaf;
  672.   PROJECT_TREE_NODE New;
  673.  
  674.   /* If the node is totally invisible we are ready */
  675.  
  676.   if (BBox_Invisible(Axis, &Object->Bounds, Origin))
  677.     return;
  678.  
  679.   if (Object->Type & BOUNDING_OBJECT)
  680.   {
  681.     /* Current object is a bounding object, i.e. a node in the slab tree */
  682.  
  683.     Comp = (COMPOSITE *)Object;
  684.  
  685.     /* First, init new entry */
  686.  
  687.     New.Entries = 0;
  688.  
  689.     New.Object = Object;
  690.  
  691.     New.Project.x1 = New.Project.y1 = MAX_VB_ENTRY;
  692.     New.Project.x2 = New.Project.y2 = MIN_VB_ENTRY;
  693.  
  694.     for (i = 0; i < BUNCHING_FACTOR; i++)
  695.     {
  696.       New.Entry[i] = NULL;
  697.     }
  698.  
  699.     /* This is no leaf */
  700.  
  701.     New.is_leaf = FALSE;
  702.  
  703.     /* Second, get new entry, i.e. project bounding slab's entries */
  704.  
  705.     for (i = 0; i < Comp->Entries; i++)
  706.     {
  707.       Project_Bounding_Slab(Axis, Origin, &Temp, &New.Entry[New.Entries],
  708.     Comp->Objects[i]);
  709.  
  710.       /* Use only visible entries */
  711.  
  712.       if (New.Entry[New.Entries] != NULL)
  713.       {
  714.     New.Project.x1 = min(New.Project.x1, Temp.x1);
  715.     New.Project.x2 = max(New.Project.x2, Temp.x2);
  716.     New.Project.y1 = min(New.Project.y1, Temp.y1);
  717.     New.Project.y2 = max(New.Project.y2, Temp.y2);
  718.  
  719.     New.Entries++;
  720.       }
  721.     }
  722.  
  723.     /* If the new entry is visible we'll use it */
  724.  
  725.     if (New.Entries > 0)
  726.     {
  727.       /* If there's only one entry, we won't need a new node. */
  728.  
  729.       if (New.Entries == 1)
  730.       {
  731.     *Tree    = New.Entry[0];
  732.     *Project = New.Project;
  733.       }
  734.       else
  735.       {
  736.     /* Allocate memory for new node in the light tree (never freed!)  */
  737.  
  738.     *Tree = (PROJECT_TREE_NODE *)LB_malloc(sizeof(PROJECT_TREE_NODE));
  739.  
  740.     if (*Tree == NULL)
  741.     {
  742.       Fatal_MAError("light tree node");
  743.     }
  744.  
  745.     **Tree = New;
  746.  
  747.     *Project = New.Project;
  748.       }
  749.     }
  750.   }
  751.   else
  752.   {
  753.     /* Current object is a normal object, i.e. a leaf in the slab tree */
  754.  
  755.     /* Project object onto light source */
  756.  
  757.     Project_Object(Project, Object, Axis, Origin);
  758.  
  759.     /* Is the object visible? */
  760.  
  761.     if ((Project->x1 <= Project->x2) && (Project->y1 <= Project->y2))
  762.     {
  763.       /* Allocate memory for new leaf in the light tree (never freed!)  */
  764.  
  765.       *Tree = (PROJECT_TREE_NODE *)LB_malloc(sizeof(PROJECT_TREE_LEAF));
  766.  
  767.       if (*Tree == NULL)
  768.       {
  769.     Fatal_MAError("light tree leaf");
  770.       }
  771.  
  772.       /* Init new leaf */
  773.  
  774.       Leaf = (PROJECT_TREE_LEAF *)(*Tree);
  775.  
  776.       Leaf->Object = Object;
  777.  
  778.       Leaf->Project = *Project;
  779.  
  780.       /* Yes, this is a leaf */
  781.  
  782.       Leaf->is_leaf = TRUE;
  783.     }
  784.   }
  785. }
  786.  
  787.  
  788.  
  789. /*****************************************************************************
  790. *
  791. * FUNCTION      : Build_Light_Buffers
  792. *
  793. * ARGUMENTS     : none
  794. *
  795. * MODIFIED ARGS : none
  796. *
  797. * RETURN VALUE  : none
  798. *
  799. * AUTHOR        : Dieter Bayer, May 1994
  800. *
  801. * DESCRIPTION
  802. *
  803. *   Build the light buffers, i.e. the 2d representations of the bounding slab
  804. *   hierarchy seen from the light sources.
  805. *
  806. * CHANGES
  807. *
  808. *   -
  809. *
  810. ******************************************************************************/
  811.  
  812. void Build_Light_Buffers()
  813. {
  814.   int i = 0, Axis;
  815.   PROJECT Project;
  816.   LIGHT_SOURCE *Light;
  817.  
  818.   /* Shadows aren't calculated --> return */
  819.  
  820.   if (!(Quality_Flags & Q_SHADOW))
  821.     return;
  822.  
  823.   /* We don't want a light buffer --> return */
  824.  
  825.   if (!(Extended_Options & USE_LIGHT_BUFFER))
  826.     return;
  827.  
  828.   /* Build the light buffer for all point(!) light sources */
  829.  
  830.   for (Light = Frame.Light_Sources; Light != NULL; Light = Light->Next_Light_Source)
  831.   {
  832.     if (!Light->Area_Light)
  833.     {
  834.       fprintf(stderr, "Building light buffer %d", ++i);
  835.  
  836.       Begin_Point();
  837.  
  838.       /* Project bounding slabs on all six sides */
  839.  
  840.       for (Axis = 0; Axis < 6; Axis++)
  841.       {
  842.     Light->Light_Buffer[Axis] = NULL;
  843.  
  844.     Project_Bounding_Slab(Axis, &Light->Center, &Project,
  845.       &Light->Light_Buffer[Axis], Root_Object);
  846.       }
  847.  
  848.       End_Point();
  849.     }
  850.   }
  851. }
  852.  
  853. #endif
  854.  
  855.