LBUFFER.C 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337
  1. /****************************************************************************
  2. * lbuffer.c
  3. *
  4. * This module implements functions that implement the light buffer.
  5. *
  6. * This module was written by Dieter Bayer [DB].
  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. * Explanation:
  28. *
  29. * -
  30. *
  31. * ---
  32. *
  33. * Mar 1994 : Creation.
  34. *
  35. *****************************************************************************/
  36. #include "frame.h"
  37. #include "vector.h"
  38. #include "povproto.h"
  39. #include "point.h"
  40. #include "povray.h"
  41. #include "bbox.h"
  42. #include "lbuffer.h"
  43. #include "objects.h"
  44. #include "triangle.h"
  45. #include "vlbuffer.h"
  46. /*****************************************************************************
  47. * Local preprocessor defines
  48. ******************************************************************************/
  49. /*****************************************************************************
  50. * Local typedefs
  51. ******************************************************************************/
  52. /*****************************************************************************
  53. * Local variabls
  54. ******************************************************************************/
  55. /* Planes for 3d-clipping. */
  56. static VECTOR VIEW_VX1 = {-0.7071067812, 0.0, -0.7071067812};
  57. static VECTOR VIEW_VX2 = { 0.7071067812, 0.0, -0.7071067812};
  58. static VECTOR VIEW_VY1 = {0.0, -0.7071067812, -0.7071067812};
  59. static VECTOR VIEW_VY2 = {0.0, 0.7071067812, -0.7071067812};
  60. static DBL VIEW_DX1 = 0.0;
  61. static DBL VIEW_DX2 = 0.0;
  62. static DBL VIEW_DY1 = 0.0;
  63. static DBL VIEW_DY2 = 0.0;
  64. /*****************************************************************************
  65. * Static functions
  66. ******************************************************************************/
  67. static void calc_points (int Axis, OBJECT *Object, int *Number, VECTOR *Points, VECTOR Origin);
  68. static int bbox_invisible (int Axis, BBOX *BBox, VECTOR Origin);
  69. static void project_rectangle (PROJECT *Project, VECTOR P1, VECTOR P2, VECTOR P3, VECTOR P4, int *visible);
  70. static void project_triangle (PROJECT *Project, VECTOR P1, VECTOR P2, VECTOR P3, int *visible);
  71. static void project_bbox (PROJECT *Project, VECTOR *P, int *visible);
  72. static void project_object (PROJECT *Project, OBJECT *Object, int Axis, VECTOR Origin);
  73. static void project_bounding_slab (int Axis, VECTOR Origin,
  74. PROJECT *Project, PROJECT_TREE_NODE **Entry, BBOX_TREE *Node);
  75. /*****************************************************************************
  76. *
  77. * FUNCTION
  78. *
  79. * calc_points
  80. *
  81. * INPUT
  82. *
  83. * Axis - Axis along the objects will be projected
  84. * Object - Object
  85. * Number - Number of points to project
  86. * Points - Points to project
  87. * Origin - Origin of current light source
  88. *
  89. * OUTPUT
  90. *
  91. * Number, Points
  92. *
  93. * RETURNS
  94. *
  95. * AUTHOR
  96. *
  97. * Dieter Bayer
  98. *
  99. * DESCRIPTION
  100. *
  101. * Calculate the points to project depending on the object type,
  102. * the light source position and the axis. Note that only three
  103. * points are used for triangles and eight for all other objects.
  104. *
  105. * CHANGES
  106. *
  107. * May 1994 : Creation.
  108. *
  109. ******************************************************************************/
  110. static void calc_points(int Axis, OBJECT *Object, int *Number, VECTOR *Points, VECTOR Origin)
  111. {
  112. register int i;
  113. DBL Direction;
  114. VECTOR H[8];
  115. /* Get points depending on object's type */
  116. if ((Object->Methods != &Triangle_Methods) &&
  117. (Object->Methods != &Smooth_Triangle_Methods))
  118. {
  119. *Number = 8;
  120. for (i = 0; i < 8; i++)
  121. {
  122. H[i][X] = ((i & 1) ? Object->BBox.Lengths[X] : 0.0) + Object->BBox.Lower_Left[X];
  123. H[i][Y] = ((i & 2) ? Object->BBox.Lengths[Y] : 0.0) + Object->BBox.Lower_Left[Y];
  124. H[i][Z] = ((i & 4) ? Object->BBox.Lengths[Z] : 0.0) + Object->BBox.Lower_Left[Z];
  125. }
  126. }
  127. else
  128. {
  129. if (Object->Methods == &Triangle_Methods)
  130. {
  131. *Number = 3;
  132. Assign_Vector(H[0], ((TRIANGLE *)Object)->P1);
  133. Assign_Vector(H[1], ((TRIANGLE *)Object)->P2);
  134. Assign_Vector(H[2], ((TRIANGLE *)Object)->P3);
  135. }
  136. if (Object->Methods == &Smooth_Triangle_Methods)
  137. {
  138. *Number = 3;
  139. Assign_Vector(H[0], ((SMOOTH_TRIANGLE *)Object)->P1);
  140. Assign_Vector(H[1], ((SMOOTH_TRIANGLE *)Object)->P2);
  141. Assign_Vector(H[2], ((SMOOTH_TRIANGLE *)Object)->P3);
  142. }
  143. }
  144. /* Modify points so that the new z direction is the projection axis. */
  145. if ((Axis == XaxisP) || (Axis == YaxisP) || (Axis == ZaxisP))
  146. {
  147. Direction = 1.0;
  148. }
  149. else
  150. {
  151. Direction = -1.0;
  152. }
  153. switch (Axis)
  154. {
  155. case XaxisP :
  156. case XaxisM :
  157. for (i = 0; i < *Number; i++)
  158. {
  159. Points[i][X] = (H[i][Y] - Origin[Y]);
  160. Points[i][Y] = (H[i][Z] - Origin[Z]);
  161. Points[i][Z] = (H[i][X] - Origin[X]) * Direction;
  162. }
  163. break;
  164. case YaxisP :
  165. case YaxisM :
  166. for (i = 0; i < *Number; i++)
  167. {
  168. Points[i][X] = (H[i][X] - Origin[X]);
  169. Points[i][Y] = (H[i][Z] - Origin[Z]);
  170. Points[i][Z] = (H[i][Y] - Origin[Y]) * Direction;
  171. }
  172. break;
  173. case ZaxisP :
  174. case ZaxisM :
  175. for (i = 0; i < *Number; i++)
  176. {
  177. Points[i][X] = (H[i][X] - Origin[X]);
  178. Points[i][Y] = (H[i][Y] - Origin[Y]);
  179. Points[i][Z] = (H[i][Z] - Origin[Z]) * Direction;
  180. }
  181. break;
  182. default : Error("Illegal axis in module calc_points() in lbuffer.c.\n");
  183. }
  184. }
  185. /*****************************************************************************
  186. *
  187. * FUNCTION
  188. *
  189. * bbox_invisible
  190. *
  191. * INPUT
  192. *
  193. * Axis - Axis along the objects will be projected
  194. * BBox - Bounding box to test
  195. * Origin - Origin of current light source
  196. *
  197. * OUTPUT
  198. *
  199. * RETURNS
  200. *
  201. * int - Flag if bounding box is totally invisble
  202. *
  203. * AUTHOR
  204. *
  205. * Dieter Bayer
  206. *
  207. * DESCRIPTION
  208. *
  209. * Do a quick test if a bounding box is totally invisble from the
  210. * current light source in the specified axis direction.
  211. *
  212. * CHANGES
  213. *
  214. * May 1994 : Creation.
  215. *
  216. ******************************************************************************/
  217. static int bbox_invisible(int Axis, BBOX *BBox, VECTOR Origin)
  218. {
  219. DBL x1, y1, z1, x2, y2, z2, x, y, z;
  220. switch (Axis)
  221. {
  222. case XaxisP :
  223. /* Bounding box behind light source? */
  224. if ((x = BBox->Lower_Left[X] + BBox->Lengths[X] - Origin[X]) <= 0.0)
  225. {
  226. return(TRUE);
  227. }
  228. /* Bounding box on the right/left side? */
  229. y1 = BBox->Lower_Left[Y] - Origin[Y];
  230. y2 = y1 + BBox->Lengths[Y];
  231. if (((y1 > 0.0) && (y1 > x)) || ((y2 < 0.0) && (-y2 > x)))
  232. {
  233. return(TRUE);
  234. }
  235. /* Bounding box on the bottom/top side? */
  236. z1 = BBox->Lower_Left[Z] - Origin[Z];
  237. z2 = z1 + BBox->Lengths[Z];
  238. if (((z1 > 0.0) && (z1 > x)) || ((z2 < 0.0) && (-z2 > x)))
  239. {
  240. return(TRUE);
  241. }
  242. break;
  243. case XaxisM :
  244. /* Bounding box behind light source? */
  245. if ((x = BBox->Lower_Left[X] - Origin[X]) >= 0.0)
  246. {
  247. return(TRUE);
  248. }
  249. /* Bounding box on the right/left side? */
  250. y1 = BBox->Lower_Left[Y] - Origin[Y];
  251. y2 = y1 + BBox->Lengths[Y];
  252. if (((y1 > 0.0) && (y1 > -x)) || ((y2 < 0.0) && (y2 < x)))
  253. {
  254. return(TRUE);
  255. }
  256. /* Bounding box on the bottom/top side? */
  257. z1 = BBox->Lower_Left[Z] - Origin[Z];
  258. z2 = z1 + BBox->Lengths[Z];
  259. if (((z1 > 0.0) && (z1 > -x)) || ((z2 < 0.0) && (z2 < x)))
  260. {
  261. return(TRUE);
  262. }
  263. break;
  264. case YaxisP :
  265. /* Bounding box behind light source? */
  266. if ((y = BBox->Lower_Left[Y] + BBox->Lengths[Y] - Origin[Y]) <= 0.0)
  267. {
  268. return(TRUE);
  269. }
  270. /* Bounding box on the right/left side? */
  271. x1 = BBox->Lower_Left[X] - Origin[X];
  272. x2 = x1 + BBox->Lengths[X];
  273. if (((x1 > 0.0) && (x1 > y)) || ((x2 < 0.0) && (-x2 > y)))
  274. {
  275. return(TRUE);
  276. }
  277. /* Bounding box on the bottom/top side? */
  278. z1 = BBox->Lower_Left[Z] - Origin[Z];
  279. z2 = z1 + BBox->Lengths[Z];
  280. if (((z1 > 0.0) && (z1 > y)) || ((z2 < 0.0) && (-z2 > y)))
  281. {
  282. return(TRUE);
  283. }
  284. break;
  285. case YaxisM :
  286. /* Bounding box behind light source? */
  287. if ((y = BBox->Lower_Left[Y] - Origin[Y]) >= 0.0)
  288. {
  289. return(TRUE);
  290. }
  291. /* Bounding box on the right/left side? */
  292. x1 = BBox->Lower_Left[X] - Origin[X];
  293. x2 = x1 + BBox->Lengths[X];
  294. if (((x1 > 0.0) && (x1 > -y)) || ((x2 < 0.0) && (x2 < y)))
  295. {
  296. return(TRUE);
  297. }
  298. /* Bounding box on the bottom/top side? */
  299. z1 = BBox->Lower_Left[Z] - Origin[Z];
  300. z2 = z1 + BBox->Lengths[Z];
  301. if (((z1 > 0.0) && (z1 > -y)) || ((z2 < 0.0) && (z2 < y)))
  302. {
  303. return(TRUE);
  304. }
  305. break;
  306. case ZaxisP :
  307. /* Bounding box behind light source? */
  308. if ((z = BBox->Lower_Left[Z] + BBox->Lengths[Z] - Origin[Z]) <= 0.0)
  309. {
  310. return(TRUE);
  311. }
  312. /* Bounding box on the right/left side? */
  313. x1 = BBox->Lower_Left[X] - Origin[X];
  314. x2 = x1 + BBox->Lengths[X];
  315. if (((x1 > 0.0) && (x1 > z)) || ((x2 < 0.0) && (-x2 > z)))
  316. {
  317. return(TRUE);
  318. }
  319. /* Bounding box on the bottom/top side? */
  320. y1 = BBox->Lower_Left[Y] - Origin[Y];
  321. y2 = y1 + BBox->Lengths[Y];
  322. if (((y1 > 0.0) && (y1 > z)) || ((y2 < 0.0) && (-y2 > z)))
  323. {
  324. return(TRUE);
  325. }
  326. break;
  327. case ZaxisM :
  328. /* Bounding box behind light source? */
  329. if ((z = BBox->Lower_Left[Z] - Origin[Z]) >= 0.0)
  330. {
  331. return(TRUE);
  332. }
  333. /* Bounding box on the right/left side? */
  334. x1 = BBox->Lower_Left[X] - Origin[X];
  335. x2 = x1 + BBox->Lengths[X];
  336. if (((x1 > 0.0) && (x1 > -z)) || ((x2 < 0.0) && (x2 < z)))
  337. {
  338. return(TRUE);
  339. }
  340. /* Bounding box on the bottom/top side? */
  341. y1 = BBox->Lower_Left[Y] - Origin[Y];
  342. y2 = y1 + BBox->Lengths[Y];
  343. if (((y1 > 0.0) && (y1 > -z)) || ((y2 < 0.0) && (y2 < z)))
  344. {
  345. return(TRUE);
  346. }
  347. break;
  348. default :
  349. Error("Illegal axis in bbox_invisible() in lbuffer.c.\n");
  350. }
  351. return(FALSE);
  352. }
  353. /*****************************************************************************
  354. *
  355. * FUNCTION
  356. *
  357. * project_rectangle
  358. *
  359. * INPUT
  360. *
  361. * Project - Rectangle's projection
  362. * P1, P2, P3, P4 - Rectangle's edges
  363. * visible - Flag if rectangle is visible
  364. *
  365. * OUTPUT
  366. *
  367. * Project, visible
  368. *
  369. * RETURNS
  370. *
  371. * AUTHOR
  372. *
  373. * Dieter Bayer
  374. *
  375. * DESCRIPTION
  376. *
  377. * Project a rectangle onto a light source.
  378. *
  379. * CHANGES
  380. *
  381. * May 1994 : Creation.
  382. *
  383. ******************************************************************************/
  384. static void project_rectangle(PROJECT *Project, VECTOR P1, VECTOR P2, VECTOR P3, VECTOR P4, int *visible)
  385. {
  386. VECTOR Points[MAX_CLIP_POINTS];
  387. int i, number;
  388. int x, y;
  389. Assign_Vector(Points[0], P1);
  390. Assign_Vector(Points[1], P2);
  391. Assign_Vector(Points[2], P3);
  392. Assign_Vector(Points[3], P4);
  393. number = 4;
  394. Clip_Polygon(Points, &number, VIEW_VX1, VIEW_VX2, VIEW_VY1, VIEW_VY2,
  395. VIEW_DX1, VIEW_DX2, VIEW_DY1, VIEW_DY2);
  396. if (number)
  397. {
  398. for (i = 0; i < number; i++)
  399. {
  400. if (Points[i][Z] < EPSILON)
  401. {
  402. Points[i][X] = Points[i][Y] = 0.0;
  403. }
  404. else
  405. {
  406. Points[i][X] /= Points[i][Z];
  407. Points[i][Y] /= Points[i][Z];
  408. if (fabs(Points[i][X]) < EPSILON) Points[i][X] = 0.0;
  409. if (fabs(Points[i][Y]) < EPSILON) Points[i][Y] = 0.0;
  410. }
  411. x = (int)(MAX_BUFFER_ENTRY * Points[i][X]);
  412. y = (int)(MAX_BUFFER_ENTRY * Points[i][Y]);
  413. if (x < Project->x1) Project->x1 = x;
  414. if (x > Project->x2) Project->x2 = x;
  415. if (y < Project->y1) Project->y1 = y;
  416. if (y > Project->y2) Project->y2 = y;
  417. }
  418. *visible = TRUE;
  419. }
  420. }
  421. /*****************************************************************************
  422. *
  423. * FUNCTION
  424. *
  425. * project_triangle
  426. *
  427. * INPUT
  428. *
  429. * Project - Triangle's projection
  430. * P1, P2, P3 - Triangles's edges
  431. * visible - Flag if triangle is visible
  432. *
  433. * OUTPUT
  434. *
  435. * Project, visible
  436. *
  437. * RETURNS
  438. *
  439. * AUTHOR
  440. *
  441. * Dieter Bayer
  442. *
  443. * DESCRIPTION
  444. *
  445. * Project a triangle onto a light source.
  446. *
  447. * CHANGES
  448. *
  449. * May 1994 : Creation.
  450. *
  451. ******************************************************************************/
  452. static void project_triangle(PROJECT *Project, VECTOR P1, VECTOR P2, VECTOR P3, int *visible)
  453. {
  454. VECTOR Points[MAX_CLIP_POINTS];
  455. int i, number;
  456. int x, y, clip;
  457. clip = TRUE;
  458. /* Check if all points lie "in front" of the light source. */
  459. if ((P1[Z] > 0.0) && (P2[Z] > 0.0) && (P3[Z] > 0.0))
  460. {
  461. /* Check if all points lie inside the "viewing pyramid". */
  462. if ((fabs(P1[X]) <= P1[Z]) && (fabs(P2[X]) <= P2[Z]) && (fabs(P3[X]) <= P3[Z]) &&
  463. (fabs(P1[Y]) <= P1[Z]) && (fabs(P2[Y]) <= P2[Z]) && (fabs(P3[Y]) <= P3[Z]))
  464. {
  465. /* No clipping is needed. Just project the points. */
  466. clip = FALSE;
  467. }
  468. else
  469. {
  470. /* Check if all points lie on the "right side". */
  471. if ((P1[X] > 0.0) && (P1[X] > P1[Z]) &&
  472. (P2[X] > 0.0) && (P2[X] > P2[Z]) &&
  473. (P3[X] > 0.0) && (P3[X] > P3[Z]))
  474. {
  475. return;
  476. }
  477. /* Check if all points lie on the "left side". */
  478. if ((P1[X] < 0.0) && (-P1[X] > P1[Z]) &&
  479. (P2[X] < 0.0) && (-P2[X] > P2[Z]) &&
  480. (P3[X] < 0.0) && (-P3[X] > P3[Z]))
  481. {
  482. return;
  483. }
  484. /* Check if all points lie above the "top side". */
  485. if ((P1[Y] > 0.0) && (P1[Y] > P1[Z]) &&
  486. (P2[Y] > 0.0) && (P2[Y] > P2[Z]) &&
  487. (P3[Y] > 0.0) && (P3[Y] > P3[Z]))
  488. {
  489. return;
  490. }
  491. /* Check if all points lie below the "bottom side". */
  492. if ((P1[Y] < 0.0) && (-P1[Y] > P1[Z]) &&
  493. (P2[Y] < 0.0) && (-P2[Y] > P2[Z]) &&
  494. (P3[Y] < 0.0) && (-P3[Y] > P3[Z]))
  495. {
  496. return;
  497. }
  498. }
  499. }
  500. Assign_Vector(Points[0], P1);
  501. Assign_Vector(Points[1], P2);
  502. Assign_Vector(Points[2], P3);
  503. number = 3;
  504. if (clip)
  505. {
  506. Clip_Polygon(Points, &number, VIEW_VX1, VIEW_VX2, VIEW_VY1, VIEW_VY2,
  507. VIEW_DX1, VIEW_DX2, VIEW_DY1, VIEW_DY2);
  508. }
  509. if (number)
  510. {
  511. for (i = 0; i < number; i++)
  512. {
  513. if (fabs(Points[i][Z]) < EPSILON)
  514. {
  515. Points[i][X] = Points[i][Y] = 0.0;
  516. }
  517. else
  518. {
  519. Points[i][X] /= Points[i][Z];
  520. Points[i][Y] /= Points[i][Z];
  521. if (fabs(Points[i][X]) < EPSILON) Points[i][X] = 0.0;
  522. if (fabs(Points[i][Y]) < EPSILON) Points[i][Y] = 0.0;
  523. }
  524. x = (int)(MAX_BUFFER_ENTRY * Points[i][X]);
  525. y = (int)(MAX_BUFFER_ENTRY * Points[i][Y]);
  526. if (x < Project->x1) Project->x1 = x;
  527. if (x > Project->x2) Project->x2 = x;
  528. if (y < Project->y1) Project->y1 = y;
  529. if (y > Project->y2) Project->y2 = y;
  530. }
  531. *visible = TRUE;
  532. }
  533. }
  534. /*****************************************************************************
  535. *
  536. * FUNCTION
  537. *
  538. * Project_BBox
  539. *
  540. * INPUT
  541. *
  542. * Project - Box's projection
  543. * P - Box's edges
  544. * visible - Flag if box is visible
  545. *
  546. * OUTPUT
  547. *
  548. * Project, visible
  549. *
  550. * RETURNS
  551. *
  552. * AUTHOR
  553. *
  554. * Dieter Bayer
  555. *
  556. * DESCRIPTION
  557. *
  558. * Project an axis-aligned box onto a light source.
  559. *
  560. * CHANGES
  561. *
  562. * May 1994 : Creation.
  563. *
  564. ******************************************************************************/
  565. static void project_bbox(PROJECT *Project, VECTOR *P, int *visible)
  566. {
  567. int i, x, y;
  568. /* Check if all points lie "in front" of the light source. */
  569. if ((P[0][Z] > 0.0) && (P[1][Z] > 0.0) && (P[2][Z] > 0.0) && (P[3][Z] > 0.0) &&
  570. (P[4][Z] > 0.0) && (P[5][Z] > 0.0) && (P[6][Z] > 0.0) && (P[7][Z] > 0.0))
  571. {
  572. /* Check if all points lie inside the "viewing pyramid". */
  573. if ((fabs(P[0][X]) <= P[0][Z]) && (fabs(P[1][X]) <= P[1][Z]) &&
  574. (fabs(P[2][X]) <= P[2][Z]) && (fabs(P[3][X]) <= P[3][Z]) &&
  575. (fabs(P[4][X]) <= P[4][Z]) && (fabs(P[5][X]) <= P[5][Z]) &&
  576. (fabs(P[6][X]) <= P[6][Z]) && (fabs(P[7][X]) <= P[7][Z]) &&
  577. (fabs(P[0][Y]) <= P[0][Z]) && (fabs(P[1][Y]) <= P[1][Z]) &&
  578. (fabs(P[2][Y]) <= P[2][Z]) && (fabs(P[3][Y]) <= P[3][Z]) &&
  579. (fabs(P[4][Y]) <= P[4][Z]) && (fabs(P[5][Y]) <= P[5][Z]) &&
  580. (fabs(P[6][Y]) <= P[6][Z]) && (fabs(P[7][Y]) <= P[7][Z]))
  581. {
  582. /* No clipping is needed. Just project the points. */
  583. for (i = 0; i < 8; i++)
  584. {
  585. if (P[i][Z] < EPSILON)
  586. {
  587. P[i][X] = P[i][Y] = 0.0;
  588. }
  589. else
  590. {
  591. P[i][X] /= P[i][Z];
  592. P[i][Y] /= P[i][Z];
  593. if (fabs(P[i][X]) < EPSILON) P[i][X] = 0.0;
  594. if (fabs(P[i][Y]) < EPSILON) P[i][Y] = 0.0;
  595. }
  596. x = (int)(MAX_BUFFER_ENTRY * P[i][X]);
  597. y = (int)(MAX_BUFFER_ENTRY * P[i][Y]);
  598. if (x < Project->x1) Project->x1 = x;
  599. if (x > Project->x2) Project->x2 = x;
  600. if (y < Project->y1) Project->y1 = y;
  601. if (y > Project->y2) Project->y2 = y;
  602. }
  603. *visible = TRUE;
  604. return;
  605. }
  606. else
  607. {
  608. /* Check if all points lie on the "right side". */
  609. for (i = 0; i < 8; i++)
  610. {
  611. if ((P[i][X] < 0.0) || (P[i][X] <= P[i][Z])) break;
  612. }
  613. if (i == 8) return;
  614. /* Check if all points lie on the "left side". */
  615. for (i = 0; i < 8; i++)
  616. {
  617. if ((P[i][X] > 0.0) || (-P[i][X] <= P[i][Z])) break;
  618. }
  619. if (i == 8) return;
  620. /* Check if all points lie above the "top side". */
  621. for (i = 0; i < 8; i++)
  622. {
  623. if ((P[i][Y] < 0.0) || (P[i][Y] <= P[i][Z])) break;
  624. }
  625. if (i == 8) return;
  626. /* Check if all points lie below the "bottom side". */
  627. for (i = 0; i < 8; i++)
  628. {
  629. if ((P[i][Y] > 0.0) || (-P[i][Y] <= P[i][Z])) break;
  630. }
  631. if (i == 8) return;
  632. }
  633. }
  634. project_rectangle(Project, P[0], P[1], P[3], P[2], visible);
  635. project_rectangle(Project, P[4], P[5], P[7], P[6], visible);
  636. project_rectangle(Project, P[0], P[1], P[5], P[4], visible);
  637. project_rectangle(Project, P[2], P[3], P[7], P[6], visible);
  638. project_rectangle(Project, P[1], P[3], P[7], P[5], visible);
  639. project_rectangle(Project, P[0], P[2], P[6], P[4], visible);
  640. }
  641. /*****************************************************************************
  642. *
  643. * FUNCTION
  644. *
  645. * project_object
  646. *
  647. * INPUT
  648. *
  649. * Object - Object to project
  650. * Project - Projection
  651. *
  652. * OUTPUT
  653. *
  654. * Project
  655. *
  656. * RETURNS
  657. *
  658. * AUTHOR
  659. *
  660. * Dieter Bayer
  661. *
  662. * DESCRIPTION
  663. *
  664. * Get the projection of a single object onto a light source.
  665. *
  666. * CHANGES
  667. *
  668. * May 1994 : Creation.
  669. *
  670. ******************************************************************************/
  671. static void project_object(PROJECT *Project, OBJECT *Object, int Axis, VECTOR Origin)
  672. {
  673. int visible, Number;
  674. VECTOR Points[8];
  675. /* Do not project infinite objects (always visible!) */
  676. if (Test_Flag(Object, INFINITE_FLAG))
  677. {
  678. Project->x1 = Project->y1 = MIN_BUFFER_ENTRY;
  679. Project->x2 = Project->y2 = MAX_BUFFER_ENTRY;
  680. return;
  681. }
  682. /* Get points to project */
  683. calc_points(Axis, Object, &Number, Points, Origin);
  684. visible = FALSE;
  685. Project->x1 = Project->y1 = MAX_BUFFER_ENTRY;
  686. Project->x2 = Project->y2 = MIN_BUFFER_ENTRY;
  687. if (Number == 3)
  688. {
  689. project_triangle(Project, Points[0], Points[1], Points[2], &visible);
  690. }
  691. else
  692. {
  693. project_bbox(Project, Points, &visible);
  694. }
  695. if (!visible)
  696. {
  697. /* Object is invisible */
  698. Project->x1 = Project->y1 = MAX_BUFFER_ENTRY;
  699. Project->x2 = Project->y2 = MIN_BUFFER_ENTRY;
  700. }
  701. else
  702. {
  703. /* We don't want to miss something */
  704. Project->x1 -= 2;
  705. Project->x2 += 2;
  706. Project->y1 -= 2;
  707. Project->y2 += 2;
  708. }
  709. }
  710. /*****************************************************************************
  711. *
  712. * FUNCTION
  713. *
  714. * project_bounding_slab
  715. *
  716. * INPUT
  717. *
  718. * Axis - Axis along the objects will be projected
  719. * Origin - Origin of current light source
  720. * Project - Projection
  721. * Tree - Current node/leaf
  722. * Object - Node/leaf in bounding slab hierarchy
  723. *
  724. * OUTPUT
  725. *
  726. * Project, Tree
  727. *
  728. * RETURNS
  729. *
  730. * AUTHOR
  731. *
  732. * Dieter Bayer
  733. *
  734. * DESCRIPTION
  735. *
  736. * Project the bounding slab hierarchy onto a light source and thus create
  737. * the light buffer hierarchy for this light source.
  738. *
  739. * CHANGES
  740. *
  741. * May 1994 : Creation.
  742. *
  743. ******************************************************************************/
  744. static void project_bounding_slab(int Axis, VECTOR Origin, PROJECT *Project, PROJECT_TREE_NODE **Tree, BBOX_TREE *Node)
  745. {
  746. short int i;
  747. PROJECT Temp;
  748. PROJECT_TREE_LEAF *Leaf;
  749. PROJECT_TREE_NODE New;
  750. COOPERATE_1
  751. /* If the node is totally invisible we are ready. */
  752. if (bbox_invisible(Axis, &Node->BBox, Origin))
  753. {
  754. return;
  755. }
  756. if (Node->Entries)
  757. {
  758. /* Current object is a bounding object, i.e. a node in the slab tree. */
  759. /* First, Init new entry. */
  760. New.Entries = 0;
  761. New.Node = Node;
  762. New.Project.x1 = New.Project.y1 = MAX_BUFFER_ENTRY;
  763. New.Project.x2 = New.Project.y2 = MIN_BUFFER_ENTRY;
  764. /* Allocate temporary memory for node/leaf entries. */
  765. New.Entry = (PROJECT_TREE_NODE **)POV_MALLOC(Node->Entries*sizeof(PROJECT_TREE_NODE *), "temporary tree entry");
  766. /* This is no leaf, it's a node. */
  767. New.is_leaf = FALSE;
  768. /* Second, Get new entry, i.e. project bounding slab's entries. */
  769. for (i = 0; i < Node->Entries; i++)
  770. {
  771. New.Entry[i] = NULL;
  772. project_bounding_slab(Axis, Origin, &Temp, &New.Entry[New.Entries], Node->Node[i]);
  773. /* Use only visible entries. */
  774. if (New.Entry[New.Entries] != NULL)
  775. {
  776. New.Project.x1 = min(New.Project.x1, Temp.x1);
  777. New.Project.x2 = max(New.Project.x2, Temp.x2);
  778. New.Project.y1 = min(New.Project.y1, Temp.y1);
  779. New.Project.y2 = max(New.Project.y2, Temp.y2);
  780. New.Entries++;
  781. }
  782. }
  783. /* If there are any visible entries, we'll use them. */
  784. if (New.Entries > 0)
  785. {
  786. /* If there's only one entry, we won't need a new node. */
  787. if (New.Entries == 1)
  788. {
  789. *Tree = New.Entry[0];
  790. *Project = New.Project;
  791. }
  792. else
  793. {
  794. /* Allocate memory for new node in the light tree. */
  795. *Tree = (PROJECT_TREE_NODE *)POV_MALLOC(sizeof(PROJECT_TREE_NODE), "light tree node");
  796. **Tree = New;
  797. /* Allocate memory for node/leaf entries. */
  798. (*Tree)->Entry = (PROJECT_TREE_NODE **)POV_MALLOC(New.Entries*sizeof(PROJECT_TREE_NODE *), "light tree node");
  799. memcpy((*Tree)->Entry, New.Entry, New.Entries*sizeof(PROJECT_TREE_NODE *));
  800. *Project = New.Project;
  801. }
  802. }
  803. /* Get rid of temporary node/leaf entries. */
  804. POV_FREE(New.Entry);
  805. }
  806. else
  807. {
  808. /* Current object is a normal object, i.e. a leaf in the slab tree. */
  809. /* If object doesn't cast shadows we can skip. */
  810. if (!Test_Flag((OBJECT *)Node->Node, NO_SHADOW_FLAG))
  811. {
  812. /* Project object onto light source. */
  813. project_object(Project, (OBJECT *)Node->Node, Axis, Origin);
  814. /* Is the object visible? */
  815. if ((Project->x1 <= Project->x2) && (Project->y1 <= Project->y2))
  816. {
  817. /* Allocate memory for new leaf in the light tree. */
  818. *Tree = (PROJECT_TREE_NODE *)POV_MALLOC(sizeof(PROJECT_TREE_LEAF), "light tree leaf");
  819. /* Init new leaf. */
  820. Leaf = (PROJECT_TREE_LEAF *)(*Tree);
  821. Leaf->Node = Node;
  822. Leaf->Project = *Project;
  823. /* Yes, this is a leaf. */
  824. Leaf->is_leaf = TRUE;
  825. }
  826. }
  827. }
  828. }
  829. /*****************************************************************************
  830. *
  831. * FUNCTION
  832. *
  833. * Build_Light_Buffers
  834. *
  835. * INPUT
  836. *
  837. * OUTPUT
  838. *
  839. * RETURNS
  840. *
  841. * AUTHOR
  842. *
  843. * Dieter Bayer
  844. *
  845. * DESCRIPTION
  846. *
  847. * Build the light buffers, i.e. the 2d representations of the bounding slab
  848. * hierarchy seen from the light sources.
  849. *
  850. * CHANGES
  851. *
  852. * May 1994 : Creation.
  853. *
  854. ******************************************************************************/
  855. void Build_Light_Buffers()
  856. {
  857. int Axis;
  858. PROJECT Project;
  859. LIGHT_SOURCE *Light;
  860. if (!(opts.Quality_Flags & Q_SHADOW) || (!opts.Use_Slabs))
  861. {
  862. opts.Options &= ~USE_LIGHT_BUFFER;
  863. }
  864. if (opts.Options & USE_LIGHT_BUFFER)
  865. {
  866. Status_Info("\nCreating light buffers");
  867. /* Build the light buffer for all point(!) light sources */
  868. for (Light = Frame.Light_Sources; Light != NULL; Light = Light->Next_Light_Source)
  869. {
  870. if ((!Light->Area_Light) && (Light->Light_Type!=FILL_LIGHT_SOURCE))
  871. {
  872. Status_Info(".");
  873. /* Project bounding slabs on all six sides */
  874. for (Axis = 0; Axis < 6; Axis++)
  875. {
  876. Light->Light_Buffer[Axis] = NULL;
  877. project_bounding_slab(Axis, Light->Center, &Project,
  878. &Light->Light_Buffer[Axis], Root_Object);
  879. }
  880. }
  881. }
  882. }
  883. }
  884. /*****************************************************************************
  885. *
  886. * FUNCTION
  887. *
  888. * Destroy_Light_Buffers
  889. *
  890. * INPUT
  891. *
  892. * OUTPUT
  893. *
  894. * RETURNS
  895. *
  896. * AUTHOR
  897. *
  898. * Dieter Bayer
  899. *
  900. * DESCRIPTION
  901. *
  902. * Destroy the light buffers.
  903. *
  904. * CHANGES
  905. *
  906. * Sep 1994 : Creation.
  907. *
  908. ******************************************************************************/
  909. void Destroy_Light_Buffers()
  910. {
  911. int Axis;
  912. LIGHT_SOURCE *Light;
  913. if (opts.Options & USE_LIGHT_BUFFER)
  914. {
  915. for (Light = Frame.Light_Sources; Light != NULL; Light = Light->Next_Light_Source)
  916. {
  917. if ((!Light->Area_Light) && (Light->Light_Type!=FILL_LIGHT_SOURCE))
  918. {
  919. for (Axis = 0; Axis < 6; Axis++)
  920. {
  921. if (Light->Light_Buffer[Axis] != NULL)
  922. {
  923. Destroy_Project_Tree(Light->Light_Buffer[Axis]);
  924. }
  925. Light->Light_Buffer[Axis] = NULL;
  926. }
  927. }
  928. }
  929. }
  930. }
  931. /*****************************************************************************
  932. *
  933. * FUNCTION
  934. *
  935. * Intersect_Light_Tree
  936. *
  937. * INPUT
  938. *
  939. * Ray - Shadow ray
  940. * Tree - Light tree's top-node
  941. * x - X-coordinate of the shadow ray
  942. * y - Y-coordinate of the shadow ray
  943. * Best_Intersection - Intersection found
  944. * Best_Object - Object found
  945. *
  946. * OUTPUT
  947. *
  948. * Best_Intersection, Best_Object
  949. *
  950. * RETURNS
  951. *
  952. * AUTHOR
  953. *
  954. * Dieter Bayer
  955. *
  956. * DESCRIPTION
  957. *
  958. * Intersect a shadow ray with the light tree
  959. * (same as for the vista tree but without pruning).
  960. *
  961. * CHANGES
  962. *
  963. * May 1994 : Creation.
  964. *
  965. ******************************************************************************/
  966. int Intersect_Light_Tree(RAY *Ray, PROJECT_TREE_NODE *Tree, int x, int y, INTERSECTION *Best_Intersection, OBJECT **Best_Object)
  967. {
  968. INTERSECTION New_Intersection;
  969. unsigned short i;
  970. int Found;
  971. RAYINFO rayinfo;
  972. DBL key;
  973. BBOX_TREE *BBox_Node;
  974. PROJECT_TREE_NODE *Node;
  975. /* If there's no vista tree then return. */
  976. if (Tree == NULL)
  977. {
  978. return(FALSE);
  979. }
  980. /* Start with an empty priority queue */
  981. VLBuffer_Queue->QSize = 0;
  982. Found = FALSE;
  983. #ifdef BBOX_EXTRA_STATS
  984. Increase_Counter(stats[totalQueueResets]);
  985. #endif
  986. /* Traverse the tree. */
  987. Node_Queue->QSize = 0;
  988. /* Create the direction vectors for this ray */
  989. Create_Rayinfo(Ray, &rayinfo);
  990. /* Fill the priority queue with all possible candidates */
  991. /* Check root */
  992. Increase_Counter(stats[LBuffer_Tests]);
  993. if ((x >= Tree->Project.x1) && (x <= Tree->Project.x2) &&
  994. (y >= Tree->Project.y1) && (y <= Tree->Project.y2))
  995. {
  996. Increase_Counter(stats[LBuffer_Tests_Succeeded]);
  997. Node_Queue->Queue[(Node_Queue->QSize)++] = Tree;
  998. }
  999. /* Loop until queue is empty. */
  1000. while (Node_Queue->QSize > 0)
  1001. {
  1002. Tree = Node_Queue->Queue[--(Node_Queue->QSize)];
  1003. if (Tree->is_leaf)
  1004. {
  1005. /* Leaf --> test object's bounding box in 3d */
  1006. Check_And_Enqueue(VLBuffer_Queue,
  1007. ((PROJECT_TREE_LEAF *)Tree)->Node,
  1008. &((PROJECT_TREE_LEAF *)Tree)->Node->BBox, &rayinfo);
  1009. }
  1010. else
  1011. {
  1012. /* Check siblings of the node in 2d */
  1013. for (i = 0; i < Tree->Entries; i++)
  1014. {
  1015. Node = Tree->Entry[i];
  1016. Increase_Counter(stats[LBuffer_Tests]);
  1017. if ((x >= Node->Project.x1) && (x <= Node->Project.x2) &&
  1018. (y >= Node->Project.y1) && (y <= Node->Project.y2))
  1019. {
  1020. Increase_Counter(stats[LBuffer_Tests_Succeeded]);
  1021. /* Reallocate queues if they're too small. */
  1022. Reinitialize_VLBuffer_Code();
  1023. /* Add node to node queue */
  1024. Node_Queue->Queue[(Node_Queue->QSize)++] = Node;
  1025. }
  1026. }
  1027. }
  1028. }
  1029. /* Now test the candidates in the priority queue */
  1030. while (VLBuffer_Queue->QSize > 0)
  1031. {
  1032. Priority_Queue_Delete(VLBuffer_Queue, &key, &BBox_Node);
  1033. if (key > Best_Intersection->Depth)
  1034. {
  1035. break;
  1036. }
  1037. if (Intersection(&New_Intersection, (OBJECT *)BBox_Node->Node, Ray))
  1038. {
  1039. if (New_Intersection.Depth < Best_Intersection->Depth)
  1040. {
  1041. *Best_Intersection = New_Intersection;
  1042. *Best_Object = (OBJECT *)BBox_Node->Node;
  1043. Found = TRUE;
  1044. }
  1045. }
  1046. }
  1047. return(Found);
  1048. }