OCTREE.C 30 KB

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