PRISM.C 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929
  1. /****************************************************************************
  2. * prism.c
  3. *
  4. * This module implements functions that manipulate prisms.
  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. * The prism primitive is defined by a set of points in 2d space which
  30. * are interpolated by linear, quadratic, or cubic splines. The resulting
  31. * 2d curve is swept along a straight line to form the final prism object.
  32. *
  33. * All calculations are done in the object's (u,v,w)-coordinate system
  34. * with the (w)-axis being the sweep axis.
  35. *
  36. * One spline segment in the (u,v)-plane is given by the equations
  37. *
  38. * fu(t) = Au * t * t * t + Bu * t * t + Cu * t + Du and
  39. * fv(t) = Av * t * t * t + Bv * t * t + Cv * t + Dv,
  40. *
  41. * with the parameter t ranging from 0 to 1.
  42. *
  43. * To intersect a ray R = P + k * D transformed into the object's
  44. * coordinate system with the linear swept prism object, the equation
  45. *
  46. * Dv * fu(t) - Du * fv(t) - (Pu * Dv - Pv * Du) = 0
  47. *
  48. * has to be solved for t. For valid intersections (0 <= t <= 1)
  49. * the corresponding k can be calculated from equation
  50. *
  51. * Pu + k * Du = fu(t) or Pv + k * Dv = fv(t).
  52. *
  53. * In the case of conic sweeping the equation
  54. *
  55. * (Pv * Dw - Pw * Dv) * fu(t) - (Pu * Dw - Pw * Du) * fv(t)
  56. * + (Pu * Dv - Pv * Du) = 0
  57. *
  58. * has to be solved for t. For valid intersections (0 <= t <= 1)
  59. * the corresponding k can be calculated from equation
  60. *
  61. * Pu + k * Du = (Pw + k * Dw) * fu(t) or
  62. * Pv + k * Dv = (Pw + k * Dw) * fv(t).
  63. *
  64. * Note that the polynomal to solve has the same degree as the
  65. * spline segments used.
  66. *
  67. * Note that Pu, Pv, Pw and Du, Dv, Dw denote the coordinates
  68. * of the vectors P and D.
  69. *
  70. * Syntax:
  71. *
  72. * prism {
  73. * [ linear_sweep | cubic_sweep ]
  74. * [ linear_spline | quadratic_spline | cubic_spline ]
  75. *
  76. * height1, height2,
  77. * number_of_points
  78. *
  79. * <P(0)>, <P(1)>, ..., <P(n-1)>
  80. *
  81. * [ open ]
  82. * [ sturm ]
  83. * }
  84. *
  85. * Note that the P(i) are 2d vectors.
  86. *
  87. * ---
  88. *
  89. * Ideas for the prism was taken from:
  90. *
  91. * James T. Kajiya, "New techniques for ray tracing procedurally
  92. * defined objects", Computer Graphics, 17(3), July 1983, pp. 91-102
  93. *
  94. * Kirk ...
  95. *
  96. * ---
  97. *
  98. * May 1994 : Creation. [DB]
  99. *
  100. *****************************************************************************/
  101. #include "frame.h"
  102. #include "povray.h"
  103. #include "vector.h"
  104. #include "povproto.h"
  105. #include "bbox.h"
  106. #include "matrices.h"
  107. #include "objects.h"
  108. #include "polysolv.h"
  109. #include "prism.h"
  110. /*****************************************************************************
  111. * Local preprocessor defines
  112. ******************************************************************************/
  113. /* Minimal intersection depth for a valid intersection. */
  114. #define DEPTH_TOLERANCE 1.0e-4
  115. /* |Coefficients| < COEFF_LIMIT are regarded to be 0. */
  116. /*#define COEFF_LIMIT 1.0e-20 */
  117. #define COEFF_LIMIT 1.0e-16 /*changed by CEY 11/18/95 */
  118. /* Part of the prism hit. */
  119. #define BASE_HIT 1
  120. #define CAP_HIT 2
  121. #define SPLINE_HIT 3
  122. /*****************************************************************************
  123. * Local typedefs
  124. ******************************************************************************/
  125. /*****************************************************************************
  126. * Static functions
  127. ******************************************************************************/
  128. static int intersect_prism (RAY *Ray, PRISM *Prism, PRISM_INT *Intersection);
  129. static int in_curve (PRISM *Prism, DBL u, DBL v);
  130. static int test_rectangle (VECTOR P, VECTOR D, DBL x1, DBL y1, DBL x2, DBL y2);
  131. static int All_Prism_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
  132. static int Inside_Prism (VECTOR point, OBJECT *Object);
  133. static void Prism_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);
  134. static PRISM *Copy_Prism (OBJECT *Object);
  135. static void Translate_Prism (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  136. static void Rotate_Prism (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  137. static void Scale_Prism (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  138. static void Transform_Prism (OBJECT *Object, TRANSFORM *Trans);
  139. static void Invert_Prism (OBJECT *Object);
  140. static void Destroy_Prism (OBJECT *Object);
  141. /*****************************************************************************
  142. * Local variables
  143. ******************************************************************************/
  144. static METHODS Prism_Methods =
  145. {
  146. All_Prism_Intersections,
  147. Inside_Prism, Prism_Normal,
  148. (COPY_METHOD)Copy_Prism,
  149. Translate_Prism, Rotate_Prism,
  150. Scale_Prism, Transform_Prism, Invert_Prism, Destroy_Prism
  151. };
  152. /*****************************************************************************
  153. *
  154. * FUNCTION
  155. *
  156. * All_Prism_Intersections
  157. *
  158. * INPUT
  159. *
  160. * Object - Object
  161. * Ray - Ray
  162. * Depth_Stack - Intersection stack
  163. *
  164. * OUTPUT
  165. *
  166. * Depth_Stack
  167. *
  168. * RETURNS
  169. *
  170. * int - TRUE, if a intersection was found
  171. *
  172. * AUTHOR
  173. *
  174. * Dieter Bayer
  175. *
  176. * DESCRIPTION
  177. *
  178. * Determine ray/prism intersection and clip intersection found.
  179. *
  180. * CHANGES
  181. *
  182. * May 1994 : Creation.
  183. *
  184. ******************************************************************************/
  185. static int All_Prism_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
  186. {
  187. int i, max_i, Found;
  188. PRISM_INT *Inter;
  189. VECTOR IPoint;
  190. Found = FALSE;
  191. Inter = ((PRISM *)Object)->Intersections;
  192. max_i = intersect_prism(Ray, (PRISM *)Object, Inter);
  193. if (max_i)
  194. {
  195. for (i = 0; i < max_i; i++)
  196. {
  197. if ((Inter[i].d > DEPTH_TOLERANCE) && (Inter[i].d < Max_Distance))
  198. {
  199. VEvaluateRay(IPoint, Ray->Initial, Inter[i].d, Ray->Direction);
  200. if (Point_In_Clip(IPoint, Object->Clip))
  201. {
  202. push_entry_i1_i2_d1(Inter[i].d,IPoint,Object,Inter[i].t,Inter[i].n,Inter[i].w,Depth_Stack);
  203. Found = TRUE;
  204. }
  205. }
  206. }
  207. }
  208. return(Found);
  209. }
  210. /*****************************************************************************
  211. *
  212. * FUNCTION
  213. *
  214. * intersect_prism
  215. *
  216. * INPUT
  217. *
  218. * Ray - Ray
  219. * Prism - Prism
  220. * Int - Prism intersection structure
  221. *
  222. * OUTPUT
  223. *
  224. * Int
  225. *
  226. * RETURNS
  227. *
  228. * int - Number of intersections found
  229. *
  230. * AUTHOR
  231. *
  232. * Dieter Bayer
  233. *
  234. * DESCRIPTION
  235. *
  236. * Determine ray/prism intersection.
  237. *
  238. * NOTE: Order reduction cannot be used.
  239. *
  240. * CHANGES
  241. *
  242. * May 1994 : Creation.
  243. *
  244. ******************************************************************************/
  245. static int intersect_prism(RAY *Ray, PRISM *Prism, PRISM_INT *Intersection)
  246. {
  247. int i, j, n;
  248. DBL k, u, v, w, h, len;
  249. DBL x[4], y[3];
  250. DBL k1, k2, k3;
  251. VECTOR P, D;
  252. PRISM_SPLINE_ENTRY Entry;
  253. /* Don't test degenerate prisms. */
  254. if (Test_Flag(Prism, DEGENERATE_FLAG))
  255. {
  256. return(FALSE);
  257. }
  258. Increase_Counter(stats[Ray_Prism_Tests]);
  259. /* Init intersection structure. */
  260. Intersection->d =
  261. Intersection->w = 0.0;
  262. Intersection->n =
  263. Intersection->t = 0;
  264. /* Transform the ray into the prism space */
  265. MInvTransPoint(P, Ray->Initial, Prism->Trans);
  266. MInvTransDirection(D, Ray->Direction, Prism->Trans);
  267. VLength(len, D);
  268. VInverseScaleEq(D, len);
  269. /* Test overall bounding rectangle. */
  270. #ifdef PRISM_EXTRA_STATS
  271. Increase_Counter(stats[Prism_Bound_Tests]);
  272. #endif
  273. if (((D[X] >= 0.0) && (P[X] > Prism->x2)) ||
  274. ((D[X] <= 0.0) && (P[X] < Prism->x1)) ||
  275. ((D[Z] >= 0.0) && (P[Z] > Prism->y2)) ||
  276. ((D[Z] <= 0.0) && (P[Z] < Prism->y1)))
  277. {
  278. return(FALSE);
  279. }
  280. #ifdef PRISM_EXTRA_STATS
  281. Increase_Counter(stats[Prism_Bound_Tests_Succeeded]);
  282. #endif
  283. /* Number of intersections found. */
  284. i = 0;
  285. /* What kind of sweep is used? */
  286. switch (Prism->Sweep_Type)
  287. {
  288. /*************************************************************************
  289. * Linear sweep.
  290. **************************************************************************/
  291. case LINEAR_SWEEP :
  292. if (fabs(D[Y]) < EPSILON)
  293. {
  294. if ((P[Y] < Prism->Height1) || (P[Y] > Prism->Height2))
  295. {
  296. return(FALSE);
  297. }
  298. }
  299. else
  300. {
  301. if (Test_Flag(Prism, CLOSED_FLAG))
  302. {
  303. /* Intersect ray with the cap-plane. */
  304. k = (Prism->Height2 - P[Y]) / D[Y];
  305. if ((k > DEPTH_TOLERANCE) && (k < Max_Distance))
  306. {
  307. u = P[X] + k * D[X];
  308. v = P[Z] + k * D[Z];
  309. if (in_curve(Prism, u, v))
  310. {
  311. Intersection[i].t = CAP_HIT;
  312. Intersection[i++].d = k / len;
  313. }
  314. }
  315. /* Intersect ray with the base-plane. */
  316. k = (Prism->Height1 - P[Y]) / D[Y];
  317. if ((k > DEPTH_TOLERANCE) && (k < Max_Distance))
  318. {
  319. u = P[X] + k * D[X];
  320. v = P[Z] + k * D[Z];
  321. if (in_curve(Prism, u, v))
  322. {
  323. Intersection[i].t = BASE_HIT;
  324. Intersection[i++].d = k / len;
  325. }
  326. }
  327. }
  328. }
  329. /* Intersect ray with all spline segments. */
  330. if ((fabs(D[X]) > EPSILON) || (fabs(D[Z]) > EPSILON))
  331. {
  332. for (j = 0; j < Prism->Number; j++)
  333. {
  334. Entry = Prism->Spline->Entry[j];
  335. /* Test spline's bounding rectangle (modified Cohen-Sutherland). */
  336. #ifdef PRISM_EXTRA_STATS
  337. Increase_Counter(stats[Prism_Bound_Tests]);
  338. #endif
  339. if (((D[X] >= 0.0) && (P[X] > Entry.x2)) ||
  340. ((D[X] <= 0.0) && (P[X] < Entry.x1)) ||
  341. ((D[Z] >= 0.0) && (P[Z] > Entry.y2)) ||
  342. ((D[Z] <= 0.0) && (P[Z] < Entry.y1)))
  343. {
  344. continue;
  345. }
  346. /* Number of roots found. */
  347. n = 0;
  348. switch (Prism->Spline_Type)
  349. {
  350. case LINEAR_SPLINE :
  351. #ifdef PRISM_EXTRA_STATS
  352. Increase_Counter(stats[Prism_Bound_Tests_Succeeded]);
  353. #endif
  354. /* Solve linear equation. */
  355. x[0] = Entry.C[X] * D[Z] - Entry.C[Y] * D[X];
  356. x[1] = D[Z] * (Entry.D[X] - P[X]) - D[X] * (Entry.D[Y] - P[Z]);
  357. if (fabs(x[0]) > EPSILON)
  358. {
  359. y[n++] = -x[1] / x[0];
  360. }
  361. break;
  362. case QUADRATIC_SPLINE :
  363. #ifdef PRISM_EXTRA_STATS
  364. Increase_Counter(stats[Prism_Bound_Tests_Succeeded]);
  365. #endif
  366. /* Solve quadratic equation. */
  367. x[0] = Entry.B[X] * D[Z] - Entry.B[Y] * D[X];
  368. x[1] = Entry.C[X] * D[Z] - Entry.C[Y] * D[X];
  369. x[2] = D[Z] * (Entry.D[X] - P[X]) - D[X] * (Entry.D[Y] - P[Z]);
  370. n = Solve_Polynomial(2, x, y, FALSE, 0.0);
  371. break;
  372. case CUBIC_SPLINE :
  373. case BEZIER_SPLINE :
  374. if (test_rectangle(P, D, Entry.x1, Entry.y1, Entry.x2, Entry.y2))
  375. {
  376. #ifdef PRISM_EXTRA_STATS
  377. Increase_Counter(stats[Prism_Bound_Tests_Succeeded]);
  378. #endif
  379. /* Solve cubic equation. */
  380. x[0] = Entry.A[X] * D[Z] - Entry.A[Y] * D[X];
  381. x[1] = Entry.B[X] * D[Z] - Entry.B[Y] * D[X];
  382. x[2] = Entry.C[X] * D[Z] - Entry.C[Y] * D[X];
  383. x[3] = D[Z] * (Entry.D[X] - P[X]) - D[X] * (Entry.D[Y] - P[Z]);
  384. n = Solve_Polynomial(3, x, y, Test_Flag(Prism, STURM_FLAG), 0.0);
  385. }
  386. break;
  387. }
  388. /* Test roots for valid intersections. */
  389. while (n--)
  390. {
  391. w = y[n];
  392. if ((w >= 0.0) && (w <= 1.0))
  393. {
  394. if (fabs(D[X]) > EPSILON)
  395. {
  396. k = (w * (w * (w * Entry.A[X] + Entry.B[X]) + Entry.C[X]) + Entry.D[X] - P[X]) / D[X];
  397. }
  398. else
  399. {
  400. k = (w * (w * (w * Entry.A[Y] + Entry.B[Y]) + Entry.C[Y]) + Entry.D[Y] - P[Z]) / D[Z];
  401. }
  402. /* Verify that intersection height is valid. */
  403. h = P[Y] + k * D[Y];
  404. if ((h >= Prism->Height1) && (h <= Prism->Height2))
  405. {
  406. Intersection[i].t = SPLINE_HIT;
  407. Intersection[i].n = j;
  408. Intersection[i].w = w;
  409. Intersection[i++].d = k / len;
  410. }
  411. }
  412. }
  413. }
  414. }
  415. break;
  416. /*************************************************************************
  417. * Conic sweep.
  418. **************************************************************************/
  419. case CONIC_SWEEP :
  420. if (fabs(D[Y]) < EPSILON)
  421. {
  422. if ((P[Y] < Prism->Height1) || (P[Y] > Prism->Height2))
  423. {
  424. return(FALSE);
  425. }
  426. }
  427. else
  428. {
  429. if (Test_Flag(Prism, CLOSED_FLAG))
  430. {
  431. /* Intersect ray with the cap-plane. */
  432. if (fabs(Prism->Height2) > EPSILON)
  433. {
  434. k = (Prism->Height2 - P[Y]) / D[Y];
  435. if ((k > DEPTH_TOLERANCE) && (k < Max_Distance))
  436. {
  437. u = (P[X] + k * D[X]) / Prism->Height2;
  438. v = (P[Z] + k * D[Z]) / Prism->Height2;
  439. if (in_curve(Prism, u, v))
  440. {
  441. Intersection[i].t = CAP_HIT;
  442. Intersection[i++].d = k / len;
  443. }
  444. }
  445. }
  446. /* Intersect ray with the base-plane. */
  447. if (fabs(Prism->Height1) > EPSILON)
  448. {
  449. k = (Prism->Height1 - P[Y]) / D[Y];
  450. if ((k > DEPTH_TOLERANCE) && (k < Max_Distance))
  451. {
  452. u = (P[X] + k * D[X]) / Prism->Height1;
  453. v = (P[Z] + k * D[Z]) / Prism->Height1;
  454. if (in_curve(Prism, u, v))
  455. {
  456. Intersection[i].t = BASE_HIT;
  457. Intersection[i++].d = k / len;
  458. }
  459. }
  460. }
  461. }
  462. }
  463. /* Precompute ray-only dependant constants. */
  464. k1 = P[Z] * D[Y] - P[Y] * D[Z];
  465. k2 = P[Y] * D[X] - P[X] * D[Y];
  466. k3 = P[X] * D[Z] - P[Z] * D[X];
  467. /* Intersect ray with the spline segments. */
  468. if ((fabs(D[X]) > EPSILON) || (fabs(D[Z]) > EPSILON))
  469. {
  470. for (j = 0; j < Prism->Number; j++)
  471. {
  472. Entry = Prism->Spline->Entry[j];
  473. /* Test spline's bounding rectangle (modified Cohen-Sutherland). */
  474. if (((D[X] >= 0.0) && (P[X] > Entry.x2)) ||
  475. ((D[X] <= 0.0) && (P[X] < Entry.x1)) ||
  476. ((D[Z] >= 0.0) && (P[Z] > Entry.y2)) ||
  477. ((D[Z] <= 0.0) && (P[Z] < Entry.y1)))
  478. {
  479. continue;
  480. }
  481. /* Number of roots found. */
  482. n = 0;
  483. switch (Prism->Spline_Type)
  484. {
  485. case LINEAR_SPLINE :
  486. /* Solve linear equation. */
  487. x[0] = Entry.C[X] * k1 + Entry.C[Y] * k2;
  488. x[1] = Entry.D[X] * k1 + Entry.D[Y] * k2 + k3;
  489. if (fabs(x[0]) > EPSILON)
  490. {
  491. y[n++] = -x[1] / x[0];
  492. }
  493. break;
  494. case QUADRATIC_SPLINE :
  495. /* Solve quadratic equation. */
  496. x[0] = Entry.B[X] * k1 + Entry.B[Y] * k2;
  497. x[1] = Entry.C[X] * k1 + Entry.C[Y] * k2;
  498. x[2] = Entry.D[X] * k1 + Entry.D[Y] * k2 + k3;
  499. n = Solve_Polynomial(2, x, y, FALSE, 0.0);
  500. break;
  501. case CUBIC_SPLINE :
  502. case BEZIER_SPLINE :
  503. /* Solve cubic equation. */
  504. x[0] = Entry.A[X] * k1 + Entry.A[Y] * k2;
  505. x[1] = Entry.B[X] * k1 + Entry.B[Y] * k2;
  506. x[2] = Entry.C[X] * k1 + Entry.C[Y] * k2;
  507. x[3] = Entry.D[X] * k1 + Entry.D[Y] * k2 + k3;
  508. n = Solve_Polynomial(3, x, y, Test_Flag(Prism, STURM_FLAG), 0.0);
  509. break;
  510. }
  511. /* Test roots for valid intersections. */
  512. while (n--)
  513. {
  514. w = y[n];
  515. if ((w >= 0.0) && (w <= 1.0))
  516. {
  517. k = w * (w * (w * Entry.A[X] + Entry.B[X]) + Entry.C[X]) + Entry.D[X];
  518. h = D[X] - k * D[Y];
  519. if (fabs(h) > EPSILON)
  520. {
  521. k = (k * P[Y] - P[X]) / h;
  522. }
  523. else
  524. {
  525. k = w * (w * (w * Entry.A[Y] + Entry.B[Y]) + Entry.C[Y]) + Entry.D[Y];
  526. h = D[Z] - k * D[Y];
  527. if (fabs(h) > EPSILON)
  528. {
  529. k = (k * P[Y] - P[Z]) / h;
  530. }
  531. else
  532. {
  533. /* This should never happen! */
  534. continue;
  535. }
  536. }
  537. /* Verify that intersection height is valid. */
  538. h = P[Y] + k * D[Y];
  539. if ((h >= Prism->Height1) && (h <= Prism->Height2))
  540. {
  541. Intersection[i].t = SPLINE_HIT;
  542. Intersection[i].n = j;
  543. Intersection[i].w = w;
  544. Intersection[i++].d = k / len;
  545. }
  546. }
  547. }
  548. }
  549. }
  550. break;
  551. default:
  552. Error("Unknown sweep type in intersect_prism().\n");
  553. }
  554. if (i)
  555. {
  556. Increase_Counter(stats[Ray_Prism_Tests_Succeeded]);
  557. }
  558. return(i);
  559. }
  560. /*****************************************************************************
  561. *
  562. * FUNCTION
  563. *
  564. * Inside_Prism
  565. *
  566. * INPUT
  567. *
  568. * IPoint - Intersection point
  569. * Object - Object
  570. *
  571. * OUTPUT
  572. *
  573. * RETURNS
  574. *
  575. * int - TRUE if inside
  576. *
  577. * AUTHOR
  578. *
  579. * Dieter Bayer
  580. *
  581. * DESCRIPTION
  582. *
  583. * Test if point lies inside a prism.
  584. *
  585. * CHANGES
  586. *
  587. * May 1994 : Creation.
  588. *
  589. ******************************************************************************/
  590. static int Inside_Prism(VECTOR IPoint, OBJECT *Object)
  591. {
  592. VECTOR P;
  593. PRISM *Prism = (PRISM *)Object;
  594. /* Transform the point into the prism space. */
  595. MInvTransPoint(P, IPoint, Prism->Trans);
  596. if ((P[Y] >= Prism->Height1) && (P[Y] < Prism->Height2))
  597. {
  598. if (Prism->Sweep_Type == CONIC_SWEEP)
  599. {
  600. /* Scale x and z coordinate. */
  601. if (fabs(P[Y]) > EPSILON)
  602. {
  603. P[X] /= P[Y];
  604. P[Z] /= P[Y];
  605. }
  606. else
  607. {
  608. P[X] = P[Z] = HUGE_VAL;
  609. }
  610. }
  611. if (in_curve(Prism, P[X], P[Z]))
  612. {
  613. return(!Test_Flag(Prism, INVERTED_FLAG));
  614. }
  615. }
  616. return(Test_Flag(Prism, INVERTED_FLAG));
  617. }
  618. /*****************************************************************************
  619. *
  620. * FUNCTION
  621. *
  622. * Prism_Normal
  623. *
  624. * INPUT
  625. *
  626. * Result - Normal vector
  627. * Object - Object
  628. * Inter - Intersection found
  629. *
  630. * OUTPUT
  631. *
  632. * Result
  633. *
  634. * RETURNS
  635. *
  636. * AUTHOR
  637. *
  638. * Dieter Bayer
  639. *
  640. * DESCRIPTION
  641. *
  642. * Calculate the normal of the prism in a given point.
  643. *
  644. * CHANGES
  645. *
  646. * May 1994 : Creation.
  647. *
  648. * Jul 1997 : Fixed bug as reported by Darko Rozic. [DB]
  649. *
  650. ******************************************************************************/
  651. static void Prism_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
  652. {
  653. VECTOR P;
  654. PRISM_SPLINE_ENTRY Entry;
  655. PRISM *Prism = (PRISM *)Object;
  656. VECTOR N;
  657. Make_Vector(N, 0.0, 1.0, 0.0);
  658. if (Inter->i1 == SPLINE_HIT)
  659. {
  660. Entry = Prism->Spline->Entry[Inter->i2];
  661. switch (Prism->Sweep_Type)
  662. {
  663. case LINEAR_SWEEP:
  664. N[X] = Inter->d1 * (3.0 * Entry.A[Y] * Inter->d1 + 2.0 * Entry.B[Y]) + Entry.C[Y];
  665. N[Y] = 0.0;
  666. N[Z] = -(Inter->d1 * (3.0 * Entry.A[X] * Inter->d1 + 2.0 * Entry.B[X]) + Entry.C[X]);
  667. break;
  668. case CONIC_SWEEP:
  669. /* Transform the point into the prism space. */
  670. MInvTransPoint(P, Inter->IPoint, Prism->Trans);
  671. if (fabs(P[Y]) > EPSILON)
  672. {
  673. N[X] = Inter->d1 * (3.0 * Entry.A[Y] * Inter->d1 + 2.0 * Entry.B[Y]) + Entry.C[Y];
  674. N[Z] = -(Inter->d1 * (3.0 * Entry.A[X] * Inter->d1 + 2.0 * Entry.B[X]) + Entry.C[X]);
  675. N[Y] = -(P[X] * N[X] + P[Z] * N[Z]) / P[Y];
  676. }
  677. break;
  678. default:
  679. Error("Unknown sweep type in Prism_Normal().\n");
  680. }
  681. }
  682. /* Transform the normalt out of the prism space. */
  683. MTransNormal(Result, N, Prism->Trans);
  684. VNormalize(Result, Result);
  685. }
  686. /*****************************************************************************
  687. *
  688. * FUNCTION
  689. *
  690. * Translate_Prism
  691. *
  692. * INPUT
  693. *
  694. * Object - Object
  695. * Vector - Translation vector
  696. *
  697. * OUTPUT
  698. *
  699. * Object
  700. *
  701. * RETURNS
  702. *
  703. * AUTHOR
  704. *
  705. * Dieter Bayer
  706. *
  707. * DESCRIPTION
  708. *
  709. * Translate a prism.
  710. *
  711. * CHANGES
  712. *
  713. * May 1994 : Creation.
  714. *
  715. ******************************************************************************/
  716. static void Translate_Prism(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  717. {
  718. Transform_Prism(Object, Trans);
  719. }
  720. /*****************************************************************************
  721. *
  722. * FUNCTION
  723. *
  724. * Rotate_Prism
  725. *
  726. * INPUT
  727. *
  728. * Object - Object
  729. * Vector - Rotation vector
  730. *
  731. * OUTPUT
  732. *
  733. * Object
  734. *
  735. * RETURNS
  736. *
  737. * AUTHOR
  738. *
  739. * Dieter Bayer
  740. *
  741. * DESCRIPTION
  742. *
  743. * Rotate a prism.
  744. *
  745. * CHANGES
  746. *
  747. * May 1994 : Creation.
  748. *
  749. ******************************************************************************/
  750. static void Rotate_Prism(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  751. {
  752. Transform_Prism(Object, Trans);
  753. }
  754. /*****************************************************************************
  755. *
  756. * FUNCTION
  757. *
  758. * Scale_Prism
  759. *
  760. * INPUT
  761. *
  762. * Object - Object
  763. * Vector - Scaling vector
  764. *
  765. * OUTPUT
  766. *
  767. * Object
  768. *
  769. * RETURNS
  770. *
  771. * AUTHOR
  772. *
  773. * Dieter Bayer
  774. *
  775. * DESCRIPTION
  776. *
  777. * Scale a prism.
  778. *
  779. * CHANGES
  780. *
  781. * May 1994 : Creation.
  782. *
  783. ******************************************************************************/
  784. static void Scale_Prism(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  785. {
  786. Transform_Prism(Object, Trans);
  787. }
  788. /*****************************************************************************
  789. *
  790. * FUNCTION
  791. *
  792. * Transform_Prism
  793. *
  794. * INPUT
  795. *
  796. * Object - Object
  797. * Trans - Transformation to apply
  798. *
  799. * OUTPUT
  800. *
  801. * Object
  802. *
  803. * RETURNS
  804. *
  805. * AUTHOR
  806. *
  807. * Dieter Bayer
  808. *
  809. * DESCRIPTION
  810. *
  811. * Transform a prism and recalculate its bounding box.
  812. *
  813. * CHANGES
  814. *
  815. * May 1994 : Creation.
  816. *
  817. ******************************************************************************/
  818. static void Transform_Prism(OBJECT *Object, TRANSFORM *Trans)
  819. {
  820. Compose_Transforms(((PRISM *)Object)->Trans, Trans);
  821. Compute_Prism_BBox((PRISM *)Object);
  822. }
  823. /*****************************************************************************
  824. *
  825. * FUNCTION
  826. *
  827. * Invert_Prism
  828. *
  829. * INPUT
  830. *
  831. * Object - Object
  832. *
  833. * OUTPUT
  834. *
  835. * Object
  836. *
  837. * RETURNS
  838. *
  839. * AUTHOR
  840. *
  841. * Dieter Bayer
  842. *
  843. * DESCRIPTION
  844. *
  845. * Invert a prism.
  846. *
  847. * CHANGES
  848. *
  849. * May 1994 : Creation.
  850. *
  851. ******************************************************************************/
  852. static void Invert_Prism(OBJECT *Object)
  853. {
  854. Invert_Flag(Object, INVERTED_FLAG);
  855. }
  856. /*****************************************************************************
  857. *
  858. * FUNCTION
  859. *
  860. * Create_Prism
  861. *
  862. * INPUT
  863. *
  864. * OUTPUT
  865. *
  866. * RETURNS
  867. *
  868. * PRISM * - new prism
  869. *
  870. * AUTHOR
  871. *
  872. * Dieter Bayer
  873. *
  874. * DESCRIPTION
  875. *
  876. * Create a new prism.
  877. *
  878. * CHANGES
  879. *
  880. * May 1994 : Creation.
  881. *
  882. ******************************************************************************/
  883. PRISM *Create_Prism()
  884. {
  885. PRISM *New;
  886. New = (PRISM *)POV_MALLOC(sizeof(PRISM), "prism");
  887. INIT_OBJECT_FIELDS(New,PRISM_OBJECT,&Prism_Methods)
  888. New->Trans = Create_Transform();
  889. New->x1 =
  890. New->x2 =
  891. New->y1 =
  892. New->y2 =
  893. New->u1 =
  894. New->u2 =
  895. New->v1 =
  896. New->v2 =
  897. New->Height1 =
  898. New->Height2 = 0.0;
  899. New->Number = 0;
  900. New->Spline_Type = LINEAR_SPLINE;
  901. New->Sweep_Type = LINEAR_SWEEP;
  902. New->Spline = NULL;
  903. New->Intersections = NULL;
  904. Set_Flag(New, CLOSED_FLAG);
  905. return(New);
  906. }
  907. /*****************************************************************************
  908. *
  909. * FUNCTION
  910. *
  911. * Copy_Prism
  912. *
  913. * INPUT
  914. *
  915. * Object - Object
  916. *
  917. * OUTPUT
  918. *
  919. * RETURNS
  920. *
  921. * void * - New prism
  922. *
  923. * AUTHOR
  924. *
  925. * Dieter Bayer
  926. *
  927. * DESCRIPTION
  928. *
  929. * Copy a prism structure.
  930. *
  931. * NOTE: The splines are not copied, only the number of references is
  932. * counted, so that Destray_Prism() knows if they can be destroyed.
  933. *
  934. * CHANGES
  935. *
  936. * May 1994 : Creation.
  937. *
  938. * Sep 1994 : fixed memory leakage [DB]
  939. *
  940. ******************************************************************************/
  941. static PRISM *Copy_Prism(OBJECT *Object)
  942. {
  943. PRISM *New, *Prism = (PRISM *)Object;
  944. New = Create_Prism();
  945. /* Get rid of the transformation created in Create_Prism(). */
  946. Destroy_Transform(New->Trans);
  947. /* Copy prism. */
  948. *New = *Prism;
  949. New->Trans = Copy_Transform(((PRISM *)Object)->Trans);
  950. New->Spline->References++;
  951. Prism->Intersections = (PRISM_INT *)POV_MALLOC((Prism->Number+2)*sizeof(PRISM_INT), "prism intersection list");
  952. return(New);
  953. }
  954. /*****************************************************************************
  955. *
  956. * FUNCTION
  957. *
  958. * Destroy_Prism
  959. *
  960. * INPUT
  961. *
  962. * Object - Object
  963. *
  964. * OUTPUT
  965. *
  966. * Object
  967. *
  968. * RETURNS
  969. *
  970. * AUTHOR
  971. *
  972. * Dieter Bayer
  973. *
  974. * DESCRIPTION
  975. *
  976. * Destroy a prism.
  977. *
  978. * NOTE: The splines are destroyed if they are no longer used by any copy.
  979. *
  980. * CHANGES
  981. *
  982. * May 1994 : Creation.
  983. *
  984. ******************************************************************************/
  985. static void Destroy_Prism (OBJECT *Object)
  986. {
  987. PRISM *Prism = (PRISM *)Object;
  988. Destroy_Transform(Prism->Trans);
  989. POV_FREE(Prism->Intersections);
  990. if (--(Prism->Spline->References) == 0)
  991. {
  992. POV_FREE(Prism->Spline->Entry);
  993. POV_FREE(Prism->Spline);
  994. }
  995. POV_FREE(Object);
  996. }
  997. /*****************************************************************************
  998. *
  999. * FUNCTION
  1000. *
  1001. * Compute_Prism_BBox
  1002. *
  1003. * INPUT
  1004. *
  1005. * Prism - Prism
  1006. *
  1007. * OUTPUT
  1008. *
  1009. * Prism
  1010. *
  1011. * RETURNS
  1012. *
  1013. * AUTHOR
  1014. *
  1015. * Dieter Bayer
  1016. *
  1017. * DESCRIPTION
  1018. *
  1019. * Calculate the bounding box of a prism.
  1020. *
  1021. * CHANGES
  1022. *
  1023. * May 1994 : Creation.
  1024. *
  1025. ******************************************************************************/
  1026. void Compute_Prism_BBox(PRISM *Prism)
  1027. {
  1028. Make_BBox(Prism->BBox, Prism->x1, Prism->Height1, Prism->y1,
  1029. Prism->x2 - Prism->x1, Prism->Height2 - Prism->Height1, Prism->y2 - Prism->y1);
  1030. Recompute_BBox(&Prism->BBox, Prism->Trans);
  1031. }
  1032. /*****************************************************************************
  1033. *
  1034. * FUNCTION
  1035. *
  1036. * in_curve
  1037. *
  1038. * INPUT
  1039. *
  1040. * Prism - Prism to test
  1041. * u, v - Coordinates
  1042. *
  1043. * OUTPUT
  1044. *
  1045. * RETURNS
  1046. *
  1047. * int - TRUE if inside
  1048. *
  1049. * AUTHOR
  1050. *
  1051. * Dieter Bayer, June 1994
  1052. *
  1053. * DESCRIPTION
  1054. *
  1055. * Test if a 2d point lies inside a prism's spline curve.
  1056. *
  1057. * We travel from the current point in positive u direction
  1058. * and count the number of crossings with the curve.
  1059. *
  1060. * CHANGES
  1061. *
  1062. * May 1994 : Creation.
  1063. *
  1064. ******************************************************************************/
  1065. static int in_curve(PRISM *Prism, DBL u, DBL v)
  1066. {
  1067. int i, n, NC;
  1068. DBL k, w;
  1069. DBL x[4], y[3];
  1070. PRISM_SPLINE_ENTRY Entry;
  1071. NC = 0;
  1072. /* First test overall bounding rectangle. */
  1073. if ((u >= Prism->u1) && (u <= Prism->u2) &&
  1074. (v >= Prism->v1) && (v <= Prism->v2))
  1075. {
  1076. for (i = 0; i < Prism->Number; i++)
  1077. {
  1078. Entry = Prism->Spline->Entry[i];
  1079. /* Test if current segment can be hit. */
  1080. if ((v >= Entry.v1) && (v <= Entry.v2) && (u <= Entry.u2))
  1081. {
  1082. x[0] = Entry.A[Y];
  1083. x[1] = Entry.B[Y];
  1084. x[2] = Entry.C[Y];
  1085. x[3] = Entry.D[Y] - v;
  1086. n = Solve_Polynomial(3, x, y, Test_Flag(Prism, STURM_FLAG), 0.0);
  1087. while (n--)
  1088. {
  1089. w = y[n];
  1090. if ((w >= 0.0) && (w <= 1.0))
  1091. {
  1092. k = w * (w * (w * Entry.A[X] + Entry.B[X]) + Entry.C[X]) + Entry.D[X] - u;
  1093. if (k >= 0.0)
  1094. {
  1095. NC++;
  1096. }
  1097. }
  1098. }
  1099. }
  1100. }
  1101. }
  1102. return(NC & 1);
  1103. }
  1104. /*****************************************************************************
  1105. *
  1106. * FUNCTION
  1107. *
  1108. * test_rectangle
  1109. *
  1110. * INPUT
  1111. *
  1112. * OUTPUT
  1113. *
  1114. * RETURNS
  1115. *
  1116. * AUTHOR
  1117. *
  1118. * Dieter Bayer, July 1994
  1119. *
  1120. * DESCRIPTION
  1121. *
  1122. * Test if the 2d ray (= P + t * D) intersects a rectangle.
  1123. *
  1124. * CHANGES
  1125. *
  1126. * May 1994 : Creation.
  1127. *
  1128. ******************************************************************************/
  1129. static int test_rectangle(VECTOR P, VECTOR D, DBL x1, DBL z1, DBL x2, DBL z2)
  1130. {
  1131. DBL dmin, dmax, tmin, tmax;
  1132. if (fabs(D[X]) > EPSILON)
  1133. {
  1134. if (D[X] > 0.0)
  1135. {
  1136. dmin = (x1 - P[X]) / D[X];
  1137. dmax = (x2 - P[X]) / D[X];
  1138. if (dmax < EPSILON)
  1139. {
  1140. return(FALSE);
  1141. }
  1142. }
  1143. else
  1144. {
  1145. dmax = (x1 - P[X]) / D[X];
  1146. if (dmax < EPSILON)
  1147. {
  1148. return(FALSE);
  1149. }
  1150. dmin = (x2 - P[X]) / D[X];
  1151. }
  1152. if (dmin > dmax)
  1153. {
  1154. return(FALSE);
  1155. }
  1156. }
  1157. else
  1158. {
  1159. if ((P[X] < x1) || (P[X] > x2))
  1160. {
  1161. return(FALSE);
  1162. }
  1163. else
  1164. {
  1165. dmin = -BOUND_HUGE;
  1166. dmax = BOUND_HUGE;
  1167. }
  1168. }
  1169. if (fabs(D[Z]) > EPSILON)
  1170. {
  1171. if (D[Z] > 0.0)
  1172. {
  1173. tmin = (z1 - P[Z]) / D[Z];
  1174. tmax = (z2 - P[Z]) / D[Z];
  1175. }
  1176. else
  1177. {
  1178. tmax = (z1 - P[Z]) / D[Z];
  1179. tmin = (z2 - P[Z]) / D[Z];
  1180. }
  1181. if (tmax < dmax)
  1182. {
  1183. if (tmax < EPSILON)
  1184. {
  1185. return(FALSE);
  1186. }
  1187. if (tmin > dmin)
  1188. {
  1189. if (tmin > tmax)
  1190. {
  1191. return(FALSE);
  1192. }
  1193. dmin = tmin;
  1194. }
  1195. else
  1196. {
  1197. if (dmin > tmax)
  1198. {
  1199. return(FALSE);
  1200. }
  1201. }
  1202. /*dmax = tmax; */ /*not needed CEY[1/95]*/
  1203. }
  1204. else
  1205. {
  1206. if (tmin > dmin)
  1207. {
  1208. if (tmin > dmax)
  1209. {
  1210. return(FALSE);
  1211. }
  1212. /* dmin = tmin; */ /*not needed CEY[1/95]*/
  1213. }
  1214. }
  1215. }
  1216. else
  1217. {
  1218. if ((P[Z] < z1) || (P[Z] > z2))
  1219. {
  1220. return(FALSE);
  1221. }
  1222. }
  1223. return(TRUE);
  1224. }
  1225. /*****************************************************************************
  1226. *
  1227. * FUNCTION
  1228. *
  1229. * Compute_Prism
  1230. *
  1231. * INPUT
  1232. *
  1233. * Prism - Prism
  1234. * P - Points defining prism
  1235. *
  1236. * OUTPUT
  1237. *
  1238. * Prism
  1239. *
  1240. * RETURNS
  1241. *
  1242. * AUTHOR
  1243. *
  1244. * Dieter Bayer, June 1994
  1245. *
  1246. * DESCRIPTION
  1247. *
  1248. * Calculate the spline segments of a prism from a set of points.
  1249. *
  1250. * CHANGES
  1251. *
  1252. * May 1994 : Creation.
  1253. *
  1254. ******************************************************************************/
  1255. void Compute_Prism(PRISM *Prism, UV_VECT *P)
  1256. {
  1257. int i, n, number_of_splines;
  1258. int i1, i2, i3;
  1259. DBL x[4], xmin, xmax;
  1260. DBL y[4], ymin, ymax;
  1261. DBL c[3], r[2];
  1262. UV_VECT A, B, C, D, First;
  1263. /* Allocate Object->Number segments. */
  1264. if (Prism->Spline == NULL)
  1265. {
  1266. Prism->Spline = (PRISM_SPLINE *)POV_MALLOC(sizeof(PRISM_SPLINE), "spline segments of prism");
  1267. Prism->Spline->References = 1;
  1268. Prism->Spline->Entry = (PRISM_SPLINE_ENTRY *)POV_MALLOC(Prism->Number*sizeof(PRISM_SPLINE_ENTRY), "spline segments of prism");
  1269. }
  1270. else
  1271. {
  1272. /* This should never happen! */
  1273. Error("Prism segments are already defined.\n");
  1274. }
  1275. /* Allocate prism intersections list. */
  1276. Prism->Intersections = (PRISM_INT *)POV_MALLOC((Prism->Number+2)*sizeof(PRISM_INT), "prism intersection list");
  1277. /***************************************************************************
  1278. * Calculate segments.
  1279. ****************************************************************************/
  1280. /* We want to know the size of the overall bounding rectangle. */
  1281. xmax = ymax = -BOUND_HUGE;
  1282. xmin = ymin = BOUND_HUGE;
  1283. /* Get first segment point. */
  1284. switch (Prism->Spline_Type)
  1285. {
  1286. case LINEAR_SPLINE:
  1287. Assign_UV_Vect(First, P[0]);
  1288. break;
  1289. case QUADRATIC_SPLINE:
  1290. case CUBIC_SPLINE:
  1291. Assign_UV_Vect(First, P[1]);
  1292. break;
  1293. }
  1294. for (i = number_of_splines = 0; i < Prism->Number-1; i++)
  1295. {
  1296. /* Get indices of previous and next two points. */
  1297. i1 = i + 1;
  1298. i2 = i + 2;
  1299. i3 = i + 3;
  1300. switch (Prism->Spline_Type)
  1301. {
  1302. /*************************************************************************
  1303. * Linear spline (nothing more than a simple polygon).
  1304. **************************************************************************/
  1305. case LINEAR_SPLINE :
  1306. if (i1 >= Prism->Number)
  1307. {
  1308. Error("Too few points in prism. Prism not closed? Control points missing?\n");
  1309. }
  1310. /* Use linear interpolation. */
  1311. A[X] = 0.0;
  1312. B[X] = 0.0;
  1313. C[X] = -1.0 * P[i][X] + 1.0 * P[i1][X];
  1314. D[X] = 1.0 * P[i][X];
  1315. A[Y] = 0.0;
  1316. B[Y] = 0.0;
  1317. C[Y] = -1.0 * P[i][Y] + 1.0 * P[i1][Y];
  1318. D[Y] = 1.0 * P[i][Y];
  1319. x[0] = x[2] = P[i][X];
  1320. x[1] = x[3] = P[i1][X];
  1321. y[0] = y[2] = P[i][Y];
  1322. y[1] = y[3] = P[i1][Y];
  1323. break;
  1324. /*************************************************************************
  1325. * Quadratic spline.
  1326. **************************************************************************/
  1327. case QUADRATIC_SPLINE :
  1328. if (i2 >= Prism->Number)
  1329. {
  1330. Error("Too few points in prism.\n");
  1331. }
  1332. /* Use quadratic interpolation. */
  1333. A[X] = 0.0;
  1334. B[X] = 0.5 * P[i][X] - 1.0 * P[i1][X] + 0.5 * P[i2][X];
  1335. C[X] = -0.5 * P[i][X] + 0.5 * P[i2][X];
  1336. D[X] = 1.0 * P[i1][X];
  1337. A[Y] = 0.0;
  1338. B[Y] = 0.5 * P[i][Y] - 1.0 * P[i1][Y] + 0.5 * P[i2][Y];
  1339. C[Y] = -0.5 * P[i][Y] + 0.5 * P[i2][Y];
  1340. D[Y] = 1.0 * P[i1][Y];
  1341. x[0] = x[2] = P[i1][X];
  1342. x[1] = x[3] = P[i2][X];
  1343. y[0] = y[2] = P[i1][Y];
  1344. y[1] = y[3] = P[i2][Y];
  1345. break;
  1346. /*************************************************************************
  1347. * Cubic spline.
  1348. **************************************************************************/
  1349. case CUBIC_SPLINE :
  1350. if (i3 >= Prism->Number)
  1351. {
  1352. Error("Too few points in prism.\n");
  1353. }
  1354. /* Use cubic interpolation. */
  1355. A[X] = -0.5 * P[i][X] + 1.5 * P[i1][X] - 1.5 * P[i2][X] + 0.5 * P[i3][X];
  1356. B[X] = P[i][X] - 2.5 * P[i1][X] + 2.0 * P[i2][X] - 0.5 * P[i3][X];
  1357. C[X] = -0.5 * P[i][X] + 0.5 * P[i2][X];
  1358. D[X] = P[i1][X];
  1359. A[Y] = -0.5 * P[i][Y] + 1.5 * P[i1][Y] - 1.5 * P[i2][Y] + 0.5 * P[i3][Y];
  1360. B[Y] = P[i][Y] - 2.5 * P[i1][Y] + 2.0 * P[i2][Y] - 0.5 * P[i3][Y];
  1361. C[Y] = -0.5 * P[i][Y] + 0.5 * P[i2][Y];
  1362. D[Y] = P[i1][Y];
  1363. x[0] = x[2] = P[i1][X];
  1364. x[1] = x[3] = P[i2][X];
  1365. y[0] = y[2] = P[i1][Y];
  1366. y[1] = y[3] = P[i2][Y];
  1367. break;
  1368. /*************************************************************************
  1369. * Bezier spline.
  1370. **************************************************************************/
  1371. case BEZIER_SPLINE :
  1372. if (i3 >= Prism->Number)
  1373. {
  1374. Error("Too few points in prism. Prism not closed? Control points missing?\n");
  1375. }
  1376. /* Use Bernstein blending function interpolation. */
  1377. A[X] = P[i][X] - 3.0 * P[i1][X] + 3.0 * P[i2][X] - P[i3][X];
  1378. B[X] = 3.0 * P[i1][X] - 6.0 * P[i2][X] + 3.0 * P[i3][X];
  1379. C[X] = 3.0 * P[i2][X] - 3.0 * P[i3][X];
  1380. D[X] = P[i3][X];
  1381. A[Y] = P[i][Y] - 3.0 * P[i1][Y] + 3.0 * P[i2][Y] - P[i3][Y];
  1382. B[Y] = 3.0 * P[i1][Y] - 6.0 * P[i2][Y] + 3.0 * P[i3][Y];
  1383. C[Y] = 3.0 * P[i2][Y] - 3.0 * P[i3][Y];
  1384. D[Y] = P[i3][Y];
  1385. x[0] = P[i][X];
  1386. x[1] = P[i1][X];
  1387. x[2] = P[i2][X];
  1388. x[3] = P[i3][X];
  1389. y[0] = P[i][Y];
  1390. y[1] = P[i1][Y];
  1391. y[2] = P[i2][Y];
  1392. y[3] = P[i3][Y];
  1393. break;
  1394. default:
  1395. Error("Unknown spline type in Compute_Prism().\n");
  1396. }
  1397. Assign_UV_Vect(Prism->Spline->Entry[number_of_splines].A, A);
  1398. Assign_UV_Vect(Prism->Spline->Entry[number_of_splines].B, B);
  1399. Assign_UV_Vect(Prism->Spline->Entry[number_of_splines].C, C);
  1400. Assign_UV_Vect(Prism->Spline->Entry[number_of_splines].D, D);
  1401. if ((Prism->Spline_Type == QUADRATIC_SPLINE) ||
  1402. (Prism->Spline_Type == CUBIC_SPLINE))
  1403. {
  1404. /* Get maximum coordinates in current segment. */
  1405. c[0] = 3.0 * A[X];
  1406. c[1] = 2.0 * B[X];
  1407. c[2] = C[X];
  1408. n = Solve_Polynomial(2, c, r, FALSE, 0.0);
  1409. while (n--)
  1410. {
  1411. if ((r[n] >= 0.0) && (r[n] <= 1.0))
  1412. {
  1413. x[n] = r[n] * (r[n] * (r[n] * A[X] + B[X]) + C[X]) + D[X];
  1414. }
  1415. }
  1416. c[0] = 3.0 * A[Y];
  1417. c[1] = 2.0 * B[Y];
  1418. c[2] = C[Y];
  1419. n = Solve_Polynomial(2, c, r, FALSE, 0.0);
  1420. while (n--)
  1421. {
  1422. if ((r[n] >= 0.0) && (r[n] <= 1.0))
  1423. {
  1424. y[n] = r[n] * (r[n] * (r[n] * A[Y] + B[Y]) + C[Y]) + D[Y];
  1425. }
  1426. }
  1427. }
  1428. /* Set current segment's bounding rectangle. */
  1429. Prism->Spline->Entry[number_of_splines].x1 = min(min(x[0], x[1]), min(x[2], x[3]));
  1430. Prism->Spline->Entry[number_of_splines].x2 =
  1431. Prism->Spline->Entry[number_of_splines].u2 = max(max(x[0], x[1]), max(x[2], x[3]));
  1432. Prism->Spline->Entry[number_of_splines].y1 =
  1433. Prism->Spline->Entry[number_of_splines].v1 = min(min(y[0], y[1]), min(y[2], y[3]));
  1434. Prism->Spline->Entry[number_of_splines].y2 =
  1435. Prism->Spline->Entry[number_of_splines].v2 = max(max(y[0], y[1]), max(y[2], y[3]));
  1436. /* Keep track of overall bounding rectangle. */
  1437. xmin = min(xmin, Prism->Spline->Entry[number_of_splines].x1);
  1438. xmax = max(xmax, Prism->Spline->Entry[number_of_splines].x2);
  1439. ymin = min(ymin, Prism->Spline->Entry[number_of_splines].y1);
  1440. ymax = max(ymax, Prism->Spline->Entry[number_of_splines].y2);
  1441. number_of_splines++;
  1442. /* Advance to next segment. */
  1443. switch (Prism->Spline_Type)
  1444. {
  1445. case LINEAR_SPLINE:
  1446. if ((fabs(P[i1][X] - First[X]) < EPSILON) &&
  1447. (fabs(P[i1][Y] - First[Y]) < EPSILON))
  1448. {
  1449. i++;
  1450. if (i+1 < Prism->Number)
  1451. {
  1452. Assign_UV_Vect(First, P[i+1]);
  1453. }
  1454. }
  1455. break;
  1456. case QUADRATIC_SPLINE:
  1457. if ((fabs(P[i2][X] - First[X]) < EPSILON) &&
  1458. (fabs(P[i2][Y] - First[Y]) < EPSILON))
  1459. {
  1460. i += 2;
  1461. if (i+2 < Prism->Number)
  1462. {
  1463. Assign_UV_Vect(First, P[i+2]);
  1464. }
  1465. }
  1466. break;
  1467. case CUBIC_SPLINE:
  1468. if ((fabs(P[i2][X] - First[X]) < EPSILON) &&
  1469. (fabs(P[i2][Y] - First[Y]) < EPSILON))
  1470. {
  1471. i += 3;
  1472. if (i+2 < Prism->Number)
  1473. {
  1474. Assign_UV_Vect(First, P[i+2]);
  1475. }
  1476. }
  1477. break;
  1478. case BEZIER_SPLINE:
  1479. i += 3;
  1480. break;
  1481. }
  1482. }
  1483. Prism->Number = number_of_splines;
  1484. /* Set overall bounding rectangle. */
  1485. Prism->x1 =
  1486. Prism->u1 = xmin;
  1487. Prism->x2 =
  1488. Prism->u2 = xmax;
  1489. Prism->y1 =
  1490. Prism->v1 = ymin;
  1491. Prism->y2 =
  1492. Prism->v2 = ymax;
  1493. if (Prism->Sweep_Type == CONIC_SWEEP)
  1494. {
  1495. /* Recalculate bounding rectangles. */
  1496. for (i = 0; i < Prism->Number; i++)
  1497. {
  1498. x[0] = Prism->Spline->Entry[i].x1 * Prism->Height1;
  1499. x[1] = Prism->Spline->Entry[i].x1 * Prism->Height2;
  1500. x[2] = Prism->Spline->Entry[i].x2 * Prism->Height1;
  1501. x[3] = Prism->Spline->Entry[i].x2 * Prism->Height2;
  1502. xmin = min(min(x[0], x[1]), min(x[2], x[3]));
  1503. xmax = max(max(x[0], x[1]), max(x[2], x[3]));
  1504. Prism->Spline->Entry[i].x1 = xmin;
  1505. Prism->Spline->Entry[i].x2 = xmax;
  1506. y[0] = Prism->Spline->Entry[i].y1 * Prism->Height1;
  1507. y[1] = Prism->Spline->Entry[i].y1 * Prism->Height2;
  1508. y[2] = Prism->Spline->Entry[i].y2 * Prism->Height1;
  1509. y[3] = Prism->Spline->Entry[i].y2 * Prism->Height2;
  1510. ymin = min(min(y[0], y[1]), min(y[2], y[3]));
  1511. ymax = max(max(y[0], y[1]), max(y[2], y[3]));
  1512. Prism->Spline->Entry[i].y1 = ymin;
  1513. Prism->Spline->Entry[i].y2 = ymax;
  1514. }
  1515. /* Recalculate overall bounding rectangle. */
  1516. x[0] = Prism->x1 * Prism->Height1;
  1517. x[1] = Prism->x1 * Prism->Height2;
  1518. x[2] = Prism->x2 * Prism->Height1;
  1519. x[3] = Prism->x2 * Prism->Height2;
  1520. xmin = min(min(x[0], x[1]), min(x[2], x[3]));
  1521. xmax = max(max(x[0], x[1]), max(x[2], x[3]));
  1522. Prism->x1 = xmin;
  1523. Prism->x2 = xmax;
  1524. y[0] = Prism->y1 * Prism->Height1;
  1525. y[1] = Prism->y1 * Prism->Height2;
  1526. y[2] = Prism->y2 * Prism->Height1;
  1527. y[3] = Prism->y2 * Prism->Height2;
  1528. ymin = min(min(y[0], y[1]), min(y[2], y[3]));
  1529. ymax = max(max(y[0], y[1]), max(y[2], y[3]));
  1530. Prism->y1 = ymin;
  1531. Prism->y2 = ymax;
  1532. }
  1533. }