QUATERN.C 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. /*****************************************************************************
  2. * quatern.c
  3. *
  4. * This module implements Quaternion algebra julia fractals.
  5. *
  6. * This file was written by Pascal Massimino.
  7. * Revised and updated for POV-Ray 3.x by Tim Wegner
  8. *
  9. * from Persistence of Vision(tm) Ray Tracer
  10. * Copyright 1996,1999 Persistence of Vision Team
  11. *---------------------------------------------------------------------------
  12. * NOTICE: This source code file is provided so that users may experiment
  13. * with enhancements to POV-Ray and to port the software to platforms other
  14. * than those supported by the POV-Ray Team. There are strict rules under
  15. * which you are permitted to use this file. The rules are in the file
  16. * named POVLEGAL.DOC which should be distributed with this file.
  17. * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  18. * Team Coordinator by email to team-coord@povray.org or visit us on the web at
  19. * http://www.povray.org. The latest version of POV-Ray may be found at this site.
  20. *
  21. * This program is based on the popular DKB raytracer version 2.12.
  22. * DKBTrace was originally written by David K. Buck.
  23. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  24. *
  25. *****************************************************************************/
  26. #include "frame.h"
  27. #include "povray.h"
  28. #include "vector.h"
  29. #include "povproto.h"
  30. #include "fractal.h"
  31. #include "quatern.h"
  32. #include "spheres.h"
  33. /*****************************************************************************
  34. * Local preprocessor defines
  35. ******************************************************************************/
  36. #ifndef Fractal_Tolerance
  37. #define Fractal_Tolerance 1e-8
  38. #endif
  39. #define Deriv_z2(n1,n2,n3,n4) \
  40. { \
  41. tmp = (n1)*x - (n2)*y - (n3)*z - (n4)*w; \
  42. (n2) = (n1)*y + x*(n2); \
  43. (n3) = (n1)*z + x*(n3); \
  44. (n4) = (n1)*w + x*(n4); \
  45. (n1) = tmp; \
  46. }
  47. #define Deriv_z3(n1,n2,n3,n4) \
  48. { \
  49. dtmp = 2.0*((n2)*y + (n3)*z + (n4)*w); \
  50. dtmp2 = 6.0*x*(n1) - dtmp; \
  51. (n1) = ( (n1)*x3 - x*dtmp )*3.0; \
  52. (n2) = (n2)*x4 + y*dtmp2; \
  53. (n3) = (n3)*x4 + z*dtmp2; \
  54. (n4) = (n4)*x4 + w*dtmp2; \
  55. }
  56. /*****************************************************************************
  57. * Local typedefs
  58. ******************************************************************************/
  59. /*****************************************************************************
  60. * Static functions
  61. ******************************************************************************/
  62. /*****************************************************************************
  63. * Local variables
  64. ******************************************************************************/
  65. /*****************************************************************************
  66. *
  67. * FUNCTION
  68. *
  69. * INPUT
  70. *
  71. * OUTPUT
  72. *
  73. * RETURNS
  74. *
  75. * AUTHOR
  76. *
  77. * Pascal Massimino
  78. *
  79. * DESCRIPTION
  80. *
  81. * -
  82. *
  83. * CHANGES
  84. *
  85. * Dec 1994 : Creation.
  86. *
  87. ******************************************************************************/
  88. int Iteration_z3(VECTOR point, FRACTAL *Julia)
  89. {
  90. int i;
  91. DBL x, y, z, w;
  92. DBL d, x2, tmp;
  93. DBL Exit_Value;
  94. Sx[0] = x = point[X];
  95. Sy[0] = y = point[Y];
  96. Sz[0] = z = point[Z];
  97. Sw[0] = w = (Julia->SliceDist
  98. - Julia->Slice[X]*x
  99. - Julia->Slice[Y]*y
  100. - Julia->Slice[Z]*z)/Julia->Slice[T];
  101. Exit_Value = Julia->Exit_Value;
  102. for (i = 1; i <= Julia->n; ++i)
  103. {
  104. d = y * y + z * z + w * w;
  105. x2 = x * x;
  106. if ((d + x2) > Exit_Value)
  107. {
  108. return (FALSE);
  109. }
  110. tmp = 3.0 * x2 - d;
  111. Sx[i] = x = x * (x2 - 3.0 * d) + Julia->Julia_Parm[X];
  112. Sy[i] = y = y * tmp + Julia->Julia_Parm[Y];
  113. Sz[i] = z = z * tmp + Julia->Julia_Parm[Z];
  114. Sw[i] = w = w * tmp + Julia->Julia_Parm[T];
  115. }
  116. return (TRUE);
  117. }
  118. /*****************************************************************************
  119. *
  120. * FUNCTION
  121. *
  122. * INPUT
  123. *
  124. * OUTPUT
  125. *
  126. * RETURNS
  127. *
  128. * AUTHOR
  129. *
  130. * Pascal Massimino
  131. *
  132. * DESCRIPTION
  133. *
  134. * -
  135. *
  136. * CHANGES
  137. *
  138. * Dec 1994 : Creation.
  139. *
  140. ******************************************************************************/
  141. int Iteration_Julia(VECTOR point, FRACTAL *Julia)
  142. {
  143. int i;
  144. DBL x, y, z, w;
  145. DBL d, x2;
  146. DBL Exit_Value;
  147. Sx[0] = x = point[X];
  148. Sy[0] = y = point[Y];
  149. Sz[0] = z = point[Z];
  150. Sw[0] = w = (Julia->SliceDist
  151. - Julia->Slice[X]*x
  152. - Julia->Slice[Y]*y
  153. - Julia->Slice[Z]*z)/Julia->Slice[T];
  154. Exit_Value = Julia->Exit_Value;
  155. for (i = 1; i <= Julia->n; ++i)
  156. {
  157. d = y * y + z * z + w * w;
  158. x2 = x * x;
  159. if ((d + x2) > Exit_Value)
  160. {
  161. return (FALSE);
  162. }
  163. x *= 2.0;
  164. Sy[i] = y = x * y + Julia->Julia_Parm[Y];
  165. Sz[i] = z = x * z + Julia->Julia_Parm[Z];
  166. Sw[i] = w = x * w + Julia->Julia_Parm[T];
  167. Sx[i] = x = x2 - d + Julia->Julia_Parm[X];;
  168. }
  169. return (TRUE);
  170. }
  171. /*****************************************************************************
  172. *
  173. * FUNCTION
  174. *
  175. * INPUT
  176. *
  177. * OUTPUT
  178. *
  179. * RETURNS
  180. *
  181. * AUTHOR
  182. *
  183. * Pascal Massimino
  184. *
  185. * DESCRIPTION
  186. *
  187. * D_Iteration puts in *Dist a lower bound for the distance from *point to the
  188. * set
  189. *
  190. * CHANGES
  191. *
  192. * Dec 1994 : Creation.
  193. *
  194. ******************************************************************************/
  195. /*----------- Distance estimator + iterations ------------*/
  196. int D_Iteration_z3(VECTOR point, FRACTAL *Julia, DBL *Dist)
  197. {
  198. int i, j;
  199. DBL Norm, d;
  200. DBL xx, yy, zz;
  201. DBL x, y, z, w;
  202. DBL tmp, x2;
  203. DBL Exit_Value;
  204. DBL Pow;
  205. x = Sx[0] = point[X];
  206. y = Sy[0] = point[Y];
  207. z = Sz[0] = point[Z];
  208. w = Sw[0] = (Julia->SliceDist
  209. - Julia->Slice[X]*x
  210. - Julia->Slice[Y]*y
  211. - Julia->Slice[Z]*z)/Julia->Slice[T];
  212. Exit_Value = Julia->Exit_Value;
  213. for (i = 1; i <= Julia->n; i++)
  214. {
  215. d = y * y + z * z + w * w;
  216. x2 = x * x;
  217. if ((Norm = d + x2) > Exit_Value)
  218. {
  219. /* Distance estimator */
  220. x = Sx[0];
  221. y = Sy[0];
  222. z = Sz[0];
  223. w = Sw[0];
  224. Pow = 1.0 / 3.0;
  225. for (j = 1; j < i; ++j)
  226. {
  227. xx = x * Sx[j] - y * Sy[j] - z * Sz[j] - w * Sw[j];
  228. yy = x * Sy[j] + y * Sx[j] - z * Sw[j] + w * Sz[j];
  229. zz = x * Sz[j] + y * Sw[j] + z * Sx[j] - w * Sy[j];
  230. w = x * Sw[j] - y * Sz[j] + z * Sy[j] + w * Sx[j];
  231. x = xx;
  232. y = yy;
  233. z = zz;
  234. Pow /= 3.0;
  235. }
  236. *Dist = Pow * sqrt(Norm / (x * x + y * y + z * z + w * w)) * log(Norm);
  237. return (FALSE);
  238. }
  239. tmp = 3.0 * x2 - d;
  240. Sx[i] = x = x * (x2 - 3.0 * d) + Julia->Julia_Parm[X];
  241. Sy[i] = y = y * tmp + Julia->Julia_Parm[Y];
  242. Sz[i] = z = z * tmp + Julia->Julia_Parm[Z];
  243. Sw[i] = w = w * tmp + Julia->Julia_Parm[T];
  244. }
  245. *Dist = Precision;
  246. return (TRUE);
  247. }
  248. /*****************************************************************************
  249. *
  250. * FUNCTION
  251. *
  252. * INPUT
  253. *
  254. * OUTPUT
  255. *
  256. * RETURNS
  257. *
  258. * AUTHOR
  259. *
  260. * Pascal Massimino
  261. *
  262. * DESCRIPTION
  263. *
  264. * -
  265. *
  266. * CHANGES
  267. *
  268. * Dec 1994 : Creation.
  269. *
  270. ******************************************************************************/
  271. int D_Iteration_Julia(VECTOR point, FRACTAL *Julia, DBL *Dist)
  272. {
  273. int i, j;
  274. DBL Norm, d;
  275. DBL Exit_Value;
  276. DBL x, y, z, w;
  277. DBL xx, yy, zz, x2;
  278. DBL Pow;
  279. x = Sx[0] = point[X];
  280. y = Sy[0] = point[Y];
  281. z = Sz[0] = point[Z];
  282. w = Sw[0] = (Julia->SliceDist
  283. - Julia->Slice[X]*x
  284. - Julia->Slice[Y]*y
  285. - Julia->Slice[Z]*z)/Julia->Slice[T];
  286. Exit_Value = Julia->Exit_Value;
  287. for (i = 1; i <= Julia->n; i++)
  288. {
  289. d = y * y + z * z + w * w;
  290. x2 = x * x;
  291. if ((Norm = d + x2) > Exit_Value)
  292. {
  293. /* Distance estimator */
  294. x = Sx[0];
  295. y = Sy[0];
  296. z = Sz[0];
  297. w = Sw[0];
  298. Pow = 1.0 / 2.0;
  299. for (j = 1; j < i; ++j)
  300. {
  301. xx = x * Sx[j] - y * Sy[j] - z * Sz[j] - w * Sw[j];
  302. yy = x * Sy[j] + y * Sx[j] + w * Sz[j] - z * Sw[j];
  303. zz = x * Sz[j] + z * Sx[j] + y * Sw[j] - w * Sy[j];
  304. w = x * Sw[j] + w * Sx[j] + z * Sy[j] - y * Sz[j];
  305. x = xx;
  306. y = yy;
  307. z = zz;
  308. Pow /= 2.0;
  309. }
  310. *Dist = Pow * sqrt(Norm / (x * x + y * y + z * z + w * w)) * log(Norm);
  311. return (FALSE);
  312. }
  313. x *= 2.0;
  314. Sy[i] = y = x * y + Julia->Julia_Parm[Y];
  315. Sz[i] = z = x * z + Julia->Julia_Parm[Z];
  316. Sw[i] = w = x * w + Julia->Julia_Parm[T];
  317. Sx[i] = x = x2 - d + Julia->Julia_Parm[X];
  318. }
  319. *Dist = Precision;
  320. return (TRUE);
  321. }
  322. /*****************************************************************************
  323. *
  324. * FUNCTION
  325. *
  326. * INPUT
  327. *
  328. * OUTPUT
  329. *
  330. * RETURNS
  331. *
  332. * AUTHOR
  333. *
  334. * Pascal Massimino
  335. *
  336. * DESCRIPTION
  337. *
  338. * Provided the iterations sequence has been built, perform the computation of
  339. * the Normal
  340. *
  341. * CHANGES
  342. *
  343. * Dec 1994 : Creation.
  344. *
  345. ******************************************************************************/
  346. void Normal_Calc_z3(VECTOR Result, int N_Max, FRACTAL *fractal)
  347. {
  348. DBL
  349. n11 = 1.0, n12 = 0.0, n13 = 0.0, n14 = 0.0,
  350. n21 = 0.0, n22 = 1.0, n23 = 0.0, n24 = 0.0,
  351. n31 = 0.0, n32 = 0.0, n33 = 1.0, n34 = 0.0;
  352. DBL x, y, z, w;
  353. int i;
  354. DBL tmp, dtmp, dtmp2, x2, x3, x4;
  355. x = Sx[0];
  356. y = Sy[0];
  357. z = Sz[0];
  358. w = Sw[0];
  359. for (i = 1; i <= N_Max; i++)
  360. {
  361. tmp = y * y + z * z + w * w;
  362. x2 = x * x;
  363. x3 = x2 - tmp;
  364. x4 = 3.0 * x2 - tmp;
  365. Deriv_z3(n11, n12, n13, n14);
  366. Deriv_z3(n21, n22, n23, n24);
  367. Deriv_z3(n31, n32, n33, n34);
  368. x = Sx[i];
  369. y = Sy[i];
  370. z = Sz[i];
  371. w = Sw[i];
  372. }
  373. Result[X] = n11 * x + n12 * y + n13 * z + n14 * w;
  374. Result[Y] = n21 * x + n22 * y + n23 * z + n24 * w;
  375. Result[Z] = n31 * x + n32 * y + n33 * z + n34 * w;
  376. }
  377. /*****************************************************************************
  378. *
  379. * FUNCTION
  380. *
  381. * INPUT
  382. *
  383. * OUTPUT
  384. *
  385. * RETURNS
  386. *
  387. * AUTHOR
  388. *
  389. * Pascal Massimino
  390. *
  391. * DESCRIPTION
  392. *
  393. * -
  394. *
  395. * CHANGES
  396. *
  397. * Dec 1994 : Creation.
  398. *
  399. ******************************************************************************/
  400. void Normal_Calc_Julia(VECTOR Result, int N_Max, FRACTAL *fractal)
  401. {
  402. DBL
  403. n11 = 1.0, n12 = 0.0, n13 = 0.0, n14 = 0.0,
  404. n21 = 0.0, n22 = 1.0, n23 = 0.0, n24 = 0.0,
  405. n31 = 0.0, n32 = 0.0, n33 = 1.0, n34 = 0.0;
  406. DBL tmp;
  407. DBL x, y, z, w;
  408. int i;
  409. x = Sx[0];
  410. y = Sy[0];
  411. z = Sz[0];
  412. w = Sw[0];
  413. for (i = 1; i <= N_Max; i++)
  414. {
  415. Deriv_z2(n11, n12, n13, n14);
  416. Deriv_z2(n21, n22, n23, n24);
  417. Deriv_z2(n31, n32, n33, n34);
  418. x = Sx[i];
  419. y = Sy[i];
  420. z = Sz[i];
  421. w = Sw[i];
  422. }
  423. Result[X] = n11 * x + n12 * y + n13 * z + n14 * w;
  424. Result[Y] = n21 * x + n22 * y + n23 * z + n24 * w;
  425. Result[Z] = n31 * x + n32 * y + n33 * z + n34 * w;
  426. }
  427. /*****************************************************************************
  428. *
  429. * FUNCTION
  430. *
  431. * INPUT
  432. *
  433. * OUTPUT
  434. *
  435. * RETURNS
  436. *
  437. * AUTHOR
  438. *
  439. * Pascal Massimino
  440. *
  441. * DESCRIPTION
  442. *
  443. * -
  444. *
  445. * CHANGES
  446. *
  447. * Dec 1994 : Creation.
  448. *
  449. ******************************************************************************/
  450. int F_Bound_Julia(RAY *Ray, FRACTAL *Fractal, DBL *Depth_Min, DBL *Depth_Max)
  451. {
  452. return (Intersect_Sphere(Ray, Fractal->Center, Fractal->Radius_Squared, Depth_Min, Depth_Max));
  453. }