home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Graphics / Graphics.zip / povsrc31.zip / octree.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-26  |  29.9 KB  |  1,172 lines

  1. /****************************************************************************
  2. *                   octree.c
  3. *
  4. *  This module contains all oct-tree functions for radiosity.
  5. *
  6. *  This file was written by Jim McElhiney.
  7. *
  8. *  from Persistence of Vision(tm) Ray Tracer
  9. *  Copyright 1996,1999 Persistence of Vision Team
  10. *---------------------------------------------------------------------------
  11. *  NOTICE: This source code file is provided so that users may experiment
  12. *  with enhancements to POV-Ray and to port the software to platforms other
  13. *  than those supported by the POV-Ray Team.  There are strict rules under
  14. *  which you are permitted to use this file.  The rules are in the file
  15. *  named POVLEGAL.DOC which should be distributed with this file.
  16. *  If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  17. *  Team Coordinator by email to team-coord@povray.org or visit us on the web at
  18. *  http://www.povray.org. The latest version of POV-Ray may be found at this site.
  19. *
  20. * This program is based on the popular DKB raytracer version 2.12.
  21. * DKBTrace was originally written by David K. Buck.
  22. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  23. *
  24. *****************************************************************************/
  25.  
  26. /************************************************************************
  27. *  Oct-tree routines.  Used by Radiosity calculation routies.
  28. *
  29. *  To understand the relationship between an ot_id (x,y,z,size) and
  30. *  a place in model space, you have to scale the integer values:
  31. *  The nominal space occupied is given as follows:
  32. *      fsize = pow(2,size-127);
  33. *      lox = (float)x *fsize; loy = (float)y * fsize; loz = (float)z * fsize;
  34. *      hix = lox + fsize;  hiy = loy + fsize;  hiz = loz + fsize;
  35. *  All elements within this node are guaranteed to stick outside of the
  36. *  nominal box by a distance of less than fsize/2 in x, y, and/or z.
  37. *  Therefore, the following box is guaranteed to contain all of the
  38. *  elements:
  39. *      minx = lox - fsize/2.;  miny = loy - fsize/2.;  minz = loz - fsize/2.;
  40. *      maxx = lox + fsize/2.;  maxy = loy + fsize/2.;  maxz = loz + fsize/2.;
  41. *  Implemented by and (c) 1994-6 Jim McElhiney, mcelhiney@acm.org  or 71201,1326
  42. *  All standard POV distribution rights granted.  All other rights reserved.
  43. *************************************************************************/
  44.  
  45. #include "frame.h"
  46. #include "vector.h"
  47. #include "povproto.h"
  48. #include "povray.h"
  49. #include "octree.h"
  50. #include "radiosit.h"
  51.  
  52.  
  53.  
  54. /*****************************************************************************
  55. * Local preprocessor defines
  56. ******************************************************************************/
  57.  
  58. #define SAFE_METHOD 1
  59. /* #define OT_DEBUG 1 */
  60.  
  61.  
  62.  
  63. /*****************************************************************************
  64. * Local typedefs
  65. ******************************************************************************/
  66.  
  67.  
  68.  
  69. /*****************************************************************************
  70. * Local variables
  71. ******************************************************************************/
  72.  
  73. #ifdef RADSTATS
  74. long ot_inscount = 0;
  75. long ot_nodecount = 0;
  76. long ot_blockcount = 0;
  77. long ot_minsize = 1000;
  78. long ot_maxsize = 0;
  79. #endif
  80.  
  81. #ifdef RADSTATS
  82. long overflows = 0;
  83. long thisloops = 0;
  84. long totloops = 0;
  85. long minloops = 1000;
  86. long maxloops = 0;
  87. #endif
  88.  
  89.  
  90.  
  91. /*****************************************************************************
  92. * Static functions
  93. ******************************************************************************/
  94.  
  95. long ot_save_node (VECTOR point, OT_ID *node);
  96. long ot_traverse (OT_NODE *subtree, long (*function)(OT_BLOCK *block, void * handle1), void * handle2);
  97. long ot_free_subtree (OT_NODE *node);
  98.  
  99.  
  100.  
  101.  
  102.  
  103. /*****************************************************************************
  104. *
  105. * FUNCTION
  106. *
  107. *   ot_ins
  108. *
  109. * INPUT
  110. *   
  111. * OUTPUT
  112. *   
  113. * RETURNS
  114. *   
  115. * AUTHOUR
  116. *
  117. *   Jim McElhiney
  118. *   
  119. * DESCRIPTION
  120. *
  121. *   Called with a pointer to the root pointer, because this routine can
  122. *   create a new root block higher up.
  123. *
  124. * CHANGES
  125. *
  126. *   --- 1994 : Creation.
  127. *
  128. ******************************************************************************/
  129. /* The data to store */
  130. /* The oct-tree node id at which to store */
  131. void ot_ins(OT_NODE **root_ptr, OT_BLOCK *new_block, OT_ID *new_id)
  132. {
  133.   long target_size, dx, dy, dz, index;
  134.   OT_NODE *temp_node, *this_node;
  135.   OT_ID temp_id;
  136.  
  137. #ifdef RADSTATS
  138.   ot_inscount++;
  139. #endif
  140.  
  141.   /* If there is no root yet, create one.  This is a first-time-through */
  142.  
  143.   if (*root_ptr == NULL)
  144.   {
  145.     *root_ptr = (OT_NODE *)POV_CALLOC(1, sizeof(OT_NODE), "octree node");
  146.  
  147. #ifdef RADSTATS
  148.     ot_nodecount = 1;
  149. #endif
  150.  
  151.     /* Might as well make it the right size for our first data block */
  152.  
  153.     (*root_ptr)->Id = *new_id;
  154.   }
  155.  
  156.   /*
  157.    * What if the thing we're inserting is bigger than the biggest node in the
  158.    * existing tree?  Add a new top to the tree till it's big enough.
  159.    */
  160.   while ((*root_ptr)->Id.Size < new_id->Size)
  161.   {
  162.     /* root too small */
  163.     ot_newroot(root_ptr);
  164.   }
  165.  
  166.   /*
  167.    * What if the new block is the right size, but for an area of space which
  168.    * does not overlap with the current tree?  New bigger root, until the
  169.    * areas overlap.
  170.    */
  171.  
  172.   /* Build a temp id, like a cursor to move around with */
  173.  
  174.   temp_id = *new_id;
  175.  
  176.   /* First, find the parent of our new node which is as big as root */
  177.  
  178.   while (temp_id.Size < (*root_ptr)->Id.Size)
  179.   {
  180.     ot_parent(&temp_id, &temp_id);
  181.   }
  182.  
  183.   while((temp_id.x != (*root_ptr)->Id.x) ||
  184.         (temp_id.y != (*root_ptr)->Id.y) ||
  185.         (temp_id.z != (*root_ptr)->Id.z))
  186.   {
  187.     /* while separate subtrees... */
  188.  
  189.     ot_newroot(root_ptr);       /* create bigger root */
  190.  
  191.     ot_parent(&temp_id, &temp_id);      /* and move cursor up one, too */
  192.   }
  193.  
  194.   /*
  195.    * At this point, the new node is known to fit under the current tree
  196.    * somewhere.  Go back down the tree to the right level, making new nodes
  197.    * as you go.
  198.    */
  199.  
  200.   this_node = *root_ptr;        /* start at the root */
  201.  
  202.   while (this_node->Id.Size > new_id->Size)
  203.   {
  204.     /* First, pick the node id of the child we are talking about */
  205.  
  206.     target_size = this_node->Id.Size - 1;       /* this is the size we want */
  207.  
  208.     temp_id = *new_id;  /* start with the new one */
  209.  
  210.     while (temp_id.Size < target_size)
  211.     {
  212.       ot_parent(&temp_id, &temp_id);    /* climb up till one below here */
  213.     }
  214.  
  215.     /* Now we have to pick which child number we are talking about */
  216.  
  217.     dx = (temp_id.x & 1) * 4;
  218.     dy = (temp_id.y & 1) * 2;
  219.     dz = (temp_id.z & 1);
  220.  
  221.     index = dx + dy + dz;
  222.  
  223.     if (this_node->Kids[index] == NULL)
  224.     {
  225.       /* Next level down doesn't exist yet, so create it */
  226.       temp_node = (OT_NODE *)POV_CALLOC(1, sizeof(OT_NODE), "octree node");
  227.  
  228. #ifdef RADSTATS
  229.       ot_nodecount++;
  230. #endif
  231.  
  232.       /* Fill in the data */
  233.       temp_node->Id = temp_id;
  234.  
  235.       /* Add it onto the tree */
  236.       this_node->Kids[index] = temp_node;
  237.     }
  238.  
  239.     /* Now follow it down and repeat */
  240.     this_node = this_node->Kids[index];
  241.   }
  242.  
  243.   /* Finally, we're in the right place, so insert the new value */
  244.   ot_list_insert(&(this_node->Values), new_block);
  245. }
  246.  
  247.  
  248.  
  249. /*****************************************************************************
  250. *
  251. * FUNCTION
  252. *
  253. *   ot_list_insert
  254. *
  255. * INPUT
  256. *   
  257. * OUTPUT
  258. *   
  259. * RETURNS
  260. *   
  261. * AUTHOUR
  262. *
  263. *   Jim McElhiney
  264. *   
  265. * DESCRIPTION
  266. *
  267. *   -
  268. *
  269. * CHANGES
  270. *
  271. *   --- 1994 : Creation.
  272. *
  273. ******************************************************************************/
  274.  
  275. void ot_list_insert(OT_BLOCK **list_head, OT_BLOCK *new_block)
  276. {
  277.   new_block->next = *list_head; /* copy addr of old first block */
  278.  
  279.   *list_head = new_block;
  280. }
  281.  
  282.  
  283.  
  284. /*****************************************************************************
  285. *
  286. * FUNCTION
  287. *
  288. *   ot_newroot
  289. *
  290. * INPUT
  291. *   
  292. * OUTPUT
  293. *   
  294. * RETURNS
  295. *   
  296. * AUTHOUR
  297. *
  298. *   Jim McElhiney
  299. *   
  300. * DESCRIPTION
  301. *
  302. *   Modify a tree so that it has a bigger root, owning the old root passed in.
  303. *   Note that this function is called with a POINTER TO the root pointer,
  304. *   since the root pointer will be changed.
  305. *
  306. * CHANGES
  307. *
  308. *   --- 1994 : Creation.
  309. *
  310. ******************************************************************************/
  311.  
  312. void ot_newroot(OT_NODE **root_ptr)
  313. {
  314.   OT_NODE *newroot;
  315.   long dx, dy, dz, index;
  316.  
  317.   newroot = (OT_NODE *)POV_CALLOC(1, sizeof(OT_NODE), "octree node");
  318.  
  319. #ifdef RADSTATS
  320.   ot_nodecount++;
  321. #endif
  322.   ot_parent(&newroot->Id, &((*root_ptr)->Id));  /* sets the x/y/z/size id */
  323.  
  324.   /*
  325.    * Function:  decide which child of the new root the old root is. Theory:
  326.    * x,y,z values are measured in block sizes, and are a factor of 2 smaller
  327.    * at each level higher.  The parent of both (3,4,5,k) and (2,5,4,k) is
  328.    * (1,2,2,k+1), so the oddness of the child's ordinates determines which
  329.    * child it is, and hence the value of the index into the parent's array of
  330.    * children.  First half of array (4 entries) is kids with low/even x;
  331.    * First half of those is kids with low/even y (2 entries), and the very
  332.    * first entry is the one with low/even everything.
  333.    */
  334.   dx = ((*root_ptr)->Id.x & 1) * 4;
  335.   dy = ((*root_ptr)->Id.y & 1) * 2;
  336.   dz = ((*root_ptr)->Id.z & 1);
  337.   index = dx + dy + dz;
  338.   newroot->Kids[index] = *root_ptr;
  339.   *root_ptr = newroot;
  340. }
  341.  
  342.  
  343.  
  344. /*****************************************************************************
  345. *
  346. * FUNCTION
  347. *
  348. *   ot_dist_traverse
  349. *
  350. * INPUT
  351. *   
  352. * OUTPUT
  353. *   
  354. * RETURNS
  355. *   
  356. * AUTHOUR
  357. *
  358. *   Jim McElhiney
  359. *   
  360. * DESCRIPTION
  361. *
  362. *   Call "function(&node, handle)" for every node which is less than a node
  363. *   width from the test point. Post traverse = small stuff first = the kids
  364. *   before this node. "function(*node, handle)" must return true/false on
  365. *   whether or not to continue with further processing.  Returns 0 if
  366. *   execution was halted this way, 1 otherwise;
  367. *
  368. * CHANGES
  369. *
  370. *   --- 1994 : Creation.
  371. *
  372. ******************************************************************************/
  373.  
  374. long ot_dist_traverse(OT_NODE *subtree, VECTOR point, int bounce_depth, long (*function)(OT_BLOCK *block, void *handle1), void *handle)
  375. /* only those nodes with this recur depth */
  376. {
  377. #ifdef RADSTATS
  378.   extern long ot_seenodecount, ot_seeblockcount;
  379.  
  380. #endif
  381.   long i, oksofar;
  382.   OT_NODE *this_node;
  383.   OT_BLOCK *this_block;
  384.  
  385. #ifdef RADSTATS
  386.   ot_seenodecount++;
  387. #endif
  388.  
  389.   /* First, recurse to the child nodes */
  390.   oksofar = 1;
  391.   for (i = 0; i < 8 && oksofar; i++)
  392.   {     /* for each potential kid */
  393.     this_node = subtree->Kids[i];
  394.     if (this_node != NULL)
  395.     {   /* ...which exists */
  396.       if (ot_point_in_node(point, &this_node->Id))
  397.       { /* ...and in range */
  398.         /*oksofar = ot_dist_traverse(this_node, point, bounce_depth,
  399.                                    function, handle);
  400.         */
  401.         if (!ot_dist_traverse(this_node, point, bounce_depth,
  402.                                    function, handle))
  403.           oksofar = 0;
  404.       }
  405.     }
  406.   }
  407.  
  408.   /*
  409.    * Now, call the specified routine for each data block hung off this tree
  410.    * node
  411.    */
  412.  
  413.   /* if ( ot_point_in_node(point, &subtree->Id) ) { */
  414.   {
  415.     this_block = subtree->Values;
  416.     while (oksofar && (this_block != NULL))
  417.     {
  418. #ifdef RADSTATS
  419.       if (subtree->Id.Size < 100 || subtree->Id.Size > 140 )
  420.       {
  421.         Debug_Info("bounds error, unreasonable size %d\n", subtree->Id.Size);
  422.       }
  423.       ot_seeblockcount++;
  424. #endif
  425.       if ((int)this_block->Bounce_Depth == bounce_depth)
  426.       {
  427.         /*oksofar = (*function) (this_block, handle);*/
  428.         if (!( (*function) (this_block, handle)))
  429.           oksofar = 0;
  430.       }
  431.       this_block = this_block->next;
  432.     }
  433.   }
  434.  
  435.   return oksofar;
  436. }
  437.  
  438.  
  439. /*****************************************************************************
  440. *
  441. * FUNCTION
  442. *
  443. *   ot_traverse - call a function for every block in the tree.
  444. *
  445. * INPUT
  446. *   
  447. * OUTPUT
  448. *   
  449. * RETURNS
  450. *   
  451. * AUTHOUR
  452. *
  453. *   Jim McElhiney
  454. *   
  455. * DESCRIPTION
  456. *
  457. * Call "function(&block, handle)" for every block hanging off every node.
  458. *   Post traverse = small stuff first = the kids before this node.
  459. *   "function(*node, handle)" must return true/false on whether or not to
  460. *   Continue with further processing.  Returns 0 if execution
  461. *   was halted this way, 1 otherwise;
  462. *
  463. * CHANGES
  464. *
  465. *   --- Jan 1996 : Creation.
  466. *
  467. ******************************************************************************/
  468. long
  469. ot_traverse(OT_NODE *subtree, long (*function)(OT_BLOCK * bl, void * handle1), void *handle)
  470. /* Call "function(&block, handle)" for every block hanging off every node.
  471.    Post traverse = small stuff first = the kids before this node.
  472.    "function(*node, handle)" must return true/false on whether or not to
  473.    Continue with further processing.  Returns 0 if execution
  474.    was halted this way, 1 otherwise;
  475. */
  476. {
  477.   long i, oksofar;
  478.   OT_NODE *this_node;
  479.   OT_BLOCK *this_block;
  480.  
  481.  
  482.   /* First, recurse to the child nodes */
  483.   oksofar = 1;
  484.   if (subtree!=NULL)
  485.   {
  486.     
  487.     for (i=0; i<8 && oksofar; i++ )     /* for each potential kid */
  488.     {
  489.       this_node = subtree->Kids[i];
  490.       if ( this_node != NULL )          /* ...which exists */
  491.       {
  492.         oksofar = ot_traverse(this_node, function, handle);
  493.       }
  494.     }
  495.  
  496.     /* Now, call the specified routine for each data block hung off
  497.        this tree node */
  498.     this_block = subtree->Values;
  499.     while ( oksofar  &&  (this_block != NULL) )
  500.     {
  501.       oksofar = (*function)(this_block, handle);
  502.       this_block = this_block->next;
  503.     }
  504.   }
  505.  
  506.   return oksofar;
  507. }
  508.  
  509.  
  510.  
  511. /*****************************************************************************
  512. *
  513. * FUNCTION
  514. *
  515. *   ot_point_in_node
  516. *
  517. * INPUT
  518. *   
  519. * OUTPUT
  520. *   
  521. * RETURNS
  522. *   
  523. * AUTHOUR
  524. *
  525. *   Jim McElhiney
  526. *   
  527. * DESCRIPTION
  528. *
  529. *   Returns true if the specified point is inside the max extent of the node
  530. *   with the specified ID.
  531. *
  532. * CHANGES
  533. *
  534. *   --- 1994 : Creation.
  535. *
  536. ******************************************************************************/
  537.  
  538. long ot_point_in_node(VECTOR point, OT_ID *id)
  539. {
  540.   DBL sized, minx, miny, minz, lox, loy, loz, hix, hiy, hiz;
  541.  
  542.   union
  543.   {
  544.     float f;
  545.     long l;
  546.   }
  547.   size;                         /* MUST be float, NOT DBL */
  548.  
  549.   size.l = id->Size << 23;
  550.   sized = (DBL) size.f;
  551.   minx = (DBL) id->x * sized - OT_BIAS;
  552.   miny = (DBL) id->y * sized - OT_BIAS;
  553.   minz = (DBL) id->z * sized - OT_BIAS;
  554.  
  555.   lox = minx - sized * .5;
  556.   hix = minx + sized * 1.5;
  557.   loy = miny - sized * .5;
  558.   hiy = miny + sized * 1.5;
  559.   loz = minz - sized * .5;
  560.   hiz = minz + sized * 1.5;
  561.  
  562.   return(point[X] >= lox && point[X] < hix &&
  563.          point[Y] >= loy && point[Y] < hiy &&
  564.          point[Z] >= loz && point[Z] < hiz);
  565. }
  566.  
  567.  
  568.  
  569. /*****************************************************************************
  570. *
  571. * FUNCTION
  572. *
  573. *   ot_index_sphere
  574. *
  575. * INPUT
  576. *   
  577. * OUTPUT
  578. *   
  579. * RETURNS
  580. *   
  581. * AUTHOUR
  582. *
  583. *   Jim McElhiney
  584. *   
  585. * DESCRIPTION
  586. *
  587. *   Return the oct-tree index for an object with the specified bounding
  588. *   sphere. This is the smallest box in the tree that this object fits in with
  589. *   a maximum 50% hand-over in any (or all) directions. For example, an object
  590. *   at (.49, .49, 49) of radius 1 fits in the box (0,0,0) size 127 (length 1).
  591. *
  592. * CHANGES
  593. *
  594. *   --- 1994 : Creation.
  595. *
  596. ******************************************************************************/
  597.  
  598. void ot_index_sphere(VECTOR point, DBL radius, OT_ID *id)
  599. {
  600.   VECTOR min_point, max_point;
  601.  
  602.   min_point[X] = point[X] - radius;
  603.   min_point[Y] = point[Y] - radius;
  604.   min_point[Z] = point[Z] - radius;
  605.   max_point[X] = point[X] + radius;
  606.   max_point[Y] = point[Y] + radius;
  607.   max_point[Z] = point[Z] + radius;
  608.  
  609.   ot_index_box(min_point, max_point, id);
  610.  
  611. #ifdef RADSTATS
  612.   if (id->Size < ot_minsize)
  613.   {
  614.     ot_minsize = id->Size;
  615.   }
  616.   if (id->Size > ot_maxsize)
  617.   {
  618.     ot_maxsize = id->Size;
  619.   }
  620. #endif
  621. }
  622.  
  623.  
  624.  
  625.  
  626. /*****************************************************************************
  627. *
  628. * FUNCTION
  629. *
  630. *   ot_index_box
  631. *
  632. * INPUT
  633. *   
  634. * OUTPUT
  635. *   
  636. * RETURNS
  637. *   
  638. * AUTHOUR
  639. *
  640. *   Jim McElhiney
  641. *   
  642. * DESCRIPTION
  643. *
  644. *   Return the oct-tree index for an object with the specified bounding box.
  645. *   near_point is lox, loy, loz; far_point is hix, hiy, hiz. This is the
  646. *   smallest box in the tree that this object fits in with a maximum 50%
  647. *   hang-over in any (or all) directions. For example, an object with extent
  648. *   (-.49, -.49, -49) to (1.49, 1.49, 1.49) is the largest that fits in the
  649. *   box (0,0,0) with size 127 (length 1).
  650. *
  651. *   PORTABILITY WARNING:  this function REQUIRES IEEE single precision floating
  652. *   point format to work.  This is true of most common systems except VAXen,
  653. *   Crays, and Alpha AXP in VAX compatibility mode.  Local "float" variables
  654. *   can NOT be made double precision "double" or "DBL".
  655. *
  656. * CHANGES
  657. *
  658. *   --- 1994 : Creation.
  659. *
  660. ******************************************************************************/
  661.  
  662. void ot_index_box(VECTOR min_point, VECTOR max_point, OT_ID *id)
  663. {
  664.   long done, idx, idy, idz;
  665.   float dx, dy, dz, maxdel;     /* MUST BE "float" NOT "DBL" */
  666.   DBL bsized, maxord;
  667.   union
  668.   {
  669.     float f;
  670.     long l;
  671.   }
  672.   convert;
  673.   OT_ID base_id, test_id;
  674.  
  675.   dx = (float) (max_point[X] - min_point[X]);
  676.   dy = (float) (max_point[Y] - min_point[Y]);
  677.   dz = (float) (max_point[Z] - min_point[Z]);
  678.   maxdel = MAX3(dx, dy, dz);
  679.  
  680.   /*
  681.    * This hex operation does a floor to next lower power of 2, by clearing
  682.    * all of the mantissa bits.  Works only on IEEE single precision floats
  683.    */
  684.   convert.f = maxdel;
  685.   convert.l &= 0xff800000;
  686.   bsized = (DBL) convert.f;
  687.  
  688. #ifdef SAFE_METHOD
  689.  
  690.   /*
  691.    * This block checks for the case where the node id would cause integer
  692.    * overflow, since it is a small buffer far away
  693.    */
  694.   maxord = MAX3(fabs(min_point[X]), fabs(min_point[Y]), fabs(min_point[Z]));
  695.   maxord += OT_BIAS;
  696.   while (maxord / bsized > 1000000000.)
  697.   {
  698. #ifdef RADSTATS
  699.     overflows++;
  700. #endif
  701.     bsized *= 2.;
  702.   }
  703. #endif
  704.  
  705.   /* calculate the smallest possible node that the item might fit into */
  706.   base_id.x = (long) floor((min_point[X] + OT_BIAS) / bsized);
  707.   base_id.y = (long) floor((min_point[Y] + OT_BIAS) / bsized);
  708.   base_id.z = (long) floor((min_point[Z] + OT_BIAS) / bsized);
  709.  
  710.   /*
  711.    * This magic hex operation extracts the exponent, which gives us an
  712.    * integer number suitable for labelling a range of a power of 2.  In IEEE
  713.    * format, value = pow(2,exponent-127). Therefore, if our index is, say,
  714.    * 129, then the item has a maximum extent of (2 to the (129-127)), or
  715.    * about 4 space units.
  716.    */
  717.   convert.f = (float) bsized;
  718.   base_id.Size = (convert.l & 0x7f800000) >> 23;
  719.  
  720.   /* Now increase the node size until it fits for sure */
  721. #ifdef RADSTATS
  722.   thisloops = 0;
  723. #endif
  724.   done = 0;
  725.   while (!done)
  726.   {
  727.     test_id.Size = base_id.Size;
  728.     for (idx = 0; idx < 2 && !done; idx++)
  729.     {
  730.       for (idy = 0; idy < 2 && !done; idy++)
  731.       {
  732.         for (idz = 0; idz < 2 && !done; idz++)
  733.         {
  734.           test_id.x = base_id.x + idx;
  735.           test_id.y = base_id.y + idy;
  736.           test_id.z = base_id.z + idz;
  737.           if (ot_point_in_node(min_point, &test_id) &&
  738.               ot_point_in_node(max_point, &test_id))
  739.           {
  740.             done = 1;
  741.           }
  742.         }
  743.       }
  744.     }
  745.  
  746.     /*
  747.      * Debug_Info("looping %d,%d,%d,%d  min=%d, max=%d\n", test_id.x, test_id.y,
  748.      * test_id.z, test_id.Size, ot_point_in_node(min_point, &test_id),
  749.      * ot_point_in_node(max_point, &test_id));
  750.      */
  751.     ot_parent(&base_id, &base_id);
  752. #ifdef RADSTATS
  753.     totloops++;
  754.     thisloops++;
  755. #endif
  756.   }
  757. #ifdef RADSTATS
  758.   if (thisloops < minloops)
  759.     minloops = thisloops;
  760.   if (thisloops > maxloops)
  761.     maxloops = thisloops;
  762. #endif
  763.   *id = test_id;
  764.  
  765. #ifdef OT_DEBUG
  766.   if (id->Size > 139)
  767.   {
  768.     Debug_Info("unusually large id, maxdel=%.4f, bsized=%.4f, isize=%d\n",
  769.            maxdel, bsized, id->Size);
  770.   }
  771. #endif
  772. }
  773.  
  774.  
  775.  
  776. /*****************************************************************************
  777. *
  778. * FUNCTION
  779. *
  780. *   ot_parent
  781. *
  782. * INPUT
  783. *   
  784. * OUTPUT
  785. *   
  786. * RETURNS
  787. *   
  788. * AUTHOUR
  789. *
  790. *   Jim McElhiney
  791. *   
  792. * DESCRIPTION
  793. *
  794. *   Set the x/y/z/size block ID info of dad = the parent ID of kid
  795. *
  796. * CHANGES
  797. *
  798. *   --- 1994 : Creation.
  799. *   Apr 2000 : changed (kid_id->? - 1) to (kid_id->? + 1)
  800. *
  801. ******************************************************************************/
  802.  
  803. void ot_parent(OT_ID *dad_id, OT_ID  *kid_id)
  804. {
  805.   dad_id->Size = kid_id->Size + 1;
  806.   dad_id->x = (kid_id->x > 0) ? (kid_id->x >> 1) : (kid_id->x + 1) / 2;
  807.   dad_id->y = (kid_id->y > 0) ? (kid_id->y >> 1) : (kid_id->y + 1) / 2;
  808.   dad_id->z = (kid_id->z > 0) ? (kid_id->z >> 1) : (kid_id->z + 1) / 2;
  809. }
  810.  
  811.  
  812.  
  813. /*****************************************************************************
  814. *
  815. * FUNCTION
  816. *
  817. *   ot_save_tree
  818. *
  819. * INPUT
  820. *   
  821. * OUTPUT
  822. *   
  823. * RETURNS 1 for success, 0 for failure.
  824. *   
  825. * AUTHOUR
  826. *
  827. *   Jim McElhiney
  828. *   
  829. * DESCRIPTION
  830. *
  831. *   Given the root pointer of the in-memory cache tree, and a file descriptor
  832. *   of a file you want to write to, write the whole tree to that file.
  833. *
  834. * CHANGES
  835. *
  836. *   Jan 1996 : Creation by JDM.
  837. *
  838. * TO DO
  839. *
  840. *  Code must be written which turns Radiosity_File_*  flags on and off.
  841. *  These flags should be in the opts structure.
  842. *
  843. ******************************************************************************/
  844. long
  845. ot_save_tree(OT_NODE *root, FILE *fd)
  846. {
  847.   long retval = 0;
  848.  
  849.   if ( fd != NULL ) {
  850.     retval = ot_traverse(root, ot_write_block, (void *)fd);
  851.   }
  852.   else
  853.   {
  854.     Warning(0, "bad radiosity cache file handle\n");
  855.   }
  856.  
  857.   return retval;
  858. }
  859.  
  860.  
  861.  
  862. /*****************************************************************************
  863. *
  864. * FUNCTION
  865. *
  866. *   ot_write_block
  867. *
  868. * INPUT
  869. *   
  870. * OUTPUT
  871. *   
  872. * RETURNS
  873. *   
  874. * AUTHOUR
  875. *
  876. *   Jim McElhiney
  877. *   
  878. * DESCRIPTION
  879. *
  880. *   Write one block (not a node) from the memory cache to the cache file.
  881. *
  882. * CHANGES
  883. *
  884. *   --- Jan 1996 : Creation.
  885. *
  886. ******************************************************************************/
  887. long
  888. ot_write_block/* must be passed as void * for compatibility */(OT_BLOCK *bl, void *fd)
  889. {
  890.  
  891.   if ( bl->Bounce_Depth == 1 )
  892.   {
  893.     fprintf((FILE *)fd, "C%ld\t%g\t%g\t%g\t%02lx%02lx%02lx\t%.4f\t%.4f\t%.4f\t%g\t%g\t%02lx%02lx%02lx\n", /* tw */
  894.               (long)bl->Bounce_Depth,
  895.  
  896.       bl->Point[X], bl->Point[Y], bl->Point[Z],
  897.       (long)((bl->S_Normal[X]+1.)*.5*254.+.499999),
  898.       (long)((bl->S_Normal[Y]+1.)*.5*254.+.499999),
  899.       (long)((bl->S_Normal[Z]+1.)*.5*254.+.499999),
  900.  
  901.       bl->Illuminance[X], bl->Illuminance[Y], bl->Illuminance[Z],
  902.       bl->Harmonic_Mean_Distance,
  903.       
  904.       bl->Nearest_Distance,
  905.       (long)((bl->To_Nearest_Surface[X]+1.)*.5*254.+.499999),
  906.       (long)((bl->To_Nearest_Surface[Y]+1.)*.5*254.+.499999),
  907.       (long)((bl->To_Nearest_Surface[Z]+1.)*.5*254.+.499999)
  908.     );
  909.   }
  910.   return 1;
  911. }
  912.  
  913.  
  914. /*****************************************************************************
  915. *
  916. * FUNCTION
  917. *
  918. *   ot_free_tree() - get rid of the entire in-memory radiosity cache tree,
  919. *   and zero the pointer to its root.
  920. *
  921. * INPUT - pointer to the tree root pointer.
  922. *   
  923. * RETURNS - success 1, failure 0
  924. *   
  925. * AUTHOUR
  926. *
  927. *   Jim McElhiney
  928. *   
  929. * DESCRIPTION
  930. *
  931. *   Free a complete radiosity cache tree, and all of its nodes and blocks.
  932. *   NOTE parameter is a pointer to the tree pointer...tree pointer will get zeroed.
  933. *   Example call:
  934. *      ot_free_tree(&ot_root);
  935. *   Returns 1 for success, 0 for failure.
  936. *
  937. * CHANGES
  938. *
  939. *   --- Jan 1996 : Creation.
  940. *
  941. ******************************************************************************/
  942. long
  943. ot_free_tree(OT_NODE **ppRoot)
  944. /* Free a complete radiosity cache tree, and all of its nodes and blocks.
  945.    Note parameter is a pointer to the tree pointer...tree pointer will get zeroed.
  946.    Example call:
  947.       ot_free_tree(&ot_root);
  948.    Returns 1 for success, 0 for failure.
  949. */
  950. {
  951.   long all_ok;
  952.  
  953.   all_ok = ot_free_subtree(*ppRoot);
  954.   *ppRoot = NULL;
  955.  
  956.   return all_ok;
  957. }
  958.  
  959.  
  960. /*****************************************************************************
  961. *
  962. * FUNCTION
  963. *
  964. *   ot_free_subtree - free every node from this node downwards, and all blocks
  965. *   hanging off those nodes, and then free the node which was passed.
  966. *
  967. * INPUT
  968. *   
  969. * OUTPUT
  970. *   
  971. * RETURNS
  972. *   
  973. * AUTHOUR
  974. *
  975. *   Jim McElhiney
  976. *   
  977. * DESCRIPTION
  978. *
  979. *   Set the x/y/z/size block ID info of dad = the parent ID of kid
  980. *
  981. * CHANGES
  982. *
  983. *   --- Jan 1996 : Creation.
  984. *
  985. ******************************************************************************/
  986. long
  987. ot_free_subtree(OT_NODE *subtree)
  988. /* Free this subtree.  That is, free all of its daughters, then 
  989.    free all of the blocks hanging off this node, then free this node itself.
  990.  
  991.    Returns 0 if problems were encountered anywhere in the tree.
  992.    Currently, this code assumes success.  If called with an invalid tree pointer,
  993.    it would probably crash with a memory protection error.
  994. */
  995. {
  996.   long i, oksofar;
  997.   OT_NODE *this_node;
  998.   OT_BLOCK *this_block, *next_block;
  999.  
  1000.   /* First, recurse to the child nodes */
  1001.   oksofar = 1;
  1002.   for (i=0; i<8 && oksofar; i++ )   /* for each potential kid */
  1003.   {
  1004.     this_node = subtree->Kids[i];
  1005.     if ( this_node != NULL ) {      /* ...which exists */
  1006.       oksofar &= ot_free_subtree(this_node);
  1007.     }
  1008.   }
  1009.  
  1010.   /* Now, free each block hanging off this node. */
  1011.   this_block = subtree->Values;
  1012.   while ( this_block != NULL )
  1013.   {
  1014.     next_block = this_block->next;
  1015.     POV_FREE(this_block);
  1016.     this_block = next_block;
  1017.   }
  1018.  
  1019.   /* Finally, free this block itself */
  1020.   POV_FREE(subtree);
  1021.  
  1022.   return oksofar;
  1023. }
  1024.  
  1025.  
  1026. /*****************************************************************************
  1027. *
  1028. * FUNCTION
  1029. *
  1030. *   ot_read_file
  1031. *
  1032. * INPUT
  1033. *   file descriptor handle of file (already opened) to read into memory.
  1034. *   
  1035. * OUTPUT
  1036. *   
  1037. * RETURNS - Success 1 / failure 0
  1038. *   
  1039. * AUTHOUR
  1040. *
  1041. *   Jim McElhiney
  1042. *   
  1043. * DESCRIPTION
  1044. *
  1045. *   Read in a radiosity cache file, building a tree from its values.
  1046. *   If there is an existing tree, these values are added to it.
  1047. *
  1048. * CHANGES
  1049. *
  1050. *   --- Jan 1996 : Creation.
  1051. *
  1052. ******************************************************************************/
  1053. long
  1054. ot_read_file(FILE *fd)
  1055. /* Read in a radiosity cache file, building a tree from its values.
  1056.    If there is an existing tree, these values are added to it.
  1057. */
  1058. {
  1059.   long retval, line_num, tempdepth, tx, ty, tz, goodreads;
  1060.   int count, goodparse, readret;
  1061.   DBL brightness;
  1062.   OT_BLOCK bl, *new_block;
  1063.   OT_ID id;
  1064.   char normal_string[30], to_nearest_string[30], line[101];
  1065.  
  1066.   memset(&bl, 0, sizeof(OT_BLOCK));
  1067.  
  1068.   if ( fd != NULL )
  1069.   {
  1070.     line_num = 0;
  1071.  
  1072.     Make_Colour(Radiosity_Gather_Total, 0., 0., 0.);
  1073.     Radiosity_Gather_Total_Count = 0;
  1074.  
  1075.     goodparse = 1;
  1076.     goodreads = 0;
  1077.  
  1078.     while ( ((readret = fscanf(fd, "%99[^\n]\n", line)) == 1) && goodparse )
  1079.     {
  1080.       switch ( line[0] )
  1081.       {
  1082.         case 'B':    /* the file contains the old radiosity_brightness value */
  1083.         {
  1084.           if ( sscanf(line, "B%lf\n", &brightness) == 1 )
  1085.           {
  1086.             opts.Radiosity_Brightness = brightness;
  1087.           }
  1088.           break;
  1089.         }
  1090.         case 'P':    /* the file made it to the point that the Preview was done */
  1091.         {
  1092.           opts.Radiosity_Preview_Done = 1;
  1093.           break;
  1094.         }    
  1095.         case 'C':
  1096.         {
  1097.           count = sscanf(line, "C%ld %lf %lf %lf %s %f %f %f %f %f %s\n", /* tw */
  1098.                      &tempdepth,      /* since you can't scan a short */
  1099.                      &bl.Point[X], &bl.Point[Y], &bl.Point[Z],
  1100.                      normal_string,
  1101.                      &bl.Illuminance[X], &bl.Illuminance[Y], &bl.Illuminance[Z],
  1102.                      &bl.Harmonic_Mean_Distance,
  1103.                      &bl.Nearest_Distance, to_nearest_string );
  1104.           if ( count == 11 )
  1105.           {
  1106.             bl.Bounce_Depth = (short)tempdepth;
  1107.  
  1108.             /* normals aren't very critical for direction precision, so they are packed */
  1109.             sscanf(normal_string, "%02lx%02lx%02lx", &tx, &ty, &tz);
  1110.             bl.S_Normal[X] = ((double)tx * (1./ 254.))*2.-1.;
  1111.             bl.S_Normal[Y] = ((double)ty * (1./ 254.))*2.-1.;
  1112.             bl.S_Normal[Z] = ((double)tz * (1./ 254.))*2.-1.;
  1113.             VNormalizeEq(bl.S_Normal);
  1114.  
  1115.             sscanf(to_nearest_string, "%02lx%02lx%02lx", &tx, &ty, &tz);
  1116.             bl.To_Nearest_Surface[X] = ((double)tx * (1./ 254.))*2.-1.;
  1117.             bl.To_Nearest_Surface[Y] = ((double)ty * (1./ 254.))*2.-1.;
  1118.             bl.To_Nearest_Surface[Z] = ((double)tz * (1./ 254.))*2.-1.;
  1119.             VNormalizeEq(bl.To_Nearest_Surface);
  1120.  
  1121.             line_num++;
  1122.  
  1123.             new_block = (OT_BLOCK *)POV_MALLOC(sizeof (OT_BLOCK), "octree node from file");
  1124.             if ( new_block != NULL )
  1125.             {
  1126.               memcpy(new_block, &bl, sizeof (OT_BLOCK));
  1127.  
  1128.               ot_index_sphere(bl.Point, bl.Harmonic_Mean_Distance * opts.Real_Radiosity_Error_Bound, &id);
  1129.               ot_ins(&ot_root, new_block, &id);
  1130.               goodreads++;
  1131.             }
  1132.             else
  1133.             {
  1134.               goodparse = 0;    /* allocation error, better stop now */
  1135.             }
  1136.           }
  1137.           break;
  1138.         }
  1139.  
  1140.         default:
  1141.         {
  1142.           /* wrong leading character on line, just try again on next line */
  1143.         }
  1144.  
  1145.       }   /* end switch */
  1146.     }     /* end while-reading loop */
  1147.  
  1148.     if ( (readret != EOF)  ||  !goodparse ) {
  1149.       Status_Info("\nError processing the radiosity cache file at line %ld", (long)line);
  1150.       retval = 0;
  1151.     }
  1152.     else
  1153.     {
  1154.       if ( goodreads > 0 )
  1155.       {
  1156.         Status_Info("\nReloaded %ld values from radiosity cache file.", goodreads);
  1157.       }
  1158.       else
  1159.       {
  1160.         Status_Info("\nUnable to read any values from the radiosity cache file.");
  1161.       }
  1162.       retval = 1;
  1163.     }
  1164.   }
  1165.   else
  1166.   {
  1167.     retval = 0;
  1168.   }
  1169.  
  1170.   return retval;
  1171. }
  1172.