IMAGE.C 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405
  1. /****************************************************************************
  2. * image.c
  3. *
  4. * This module implements the mapped textures including image map, bump map
  5. * and material map.
  6. *
  7. * from Persistence of Vision(tm) Ray Tracer
  8. * Copyright 1996,1998,1999 Persistence of Vision Team
  9. *---------------------------------------------------------------------------
  10. * NOTICE: This source code file is provided so that users may experiment
  11. * with enhancements to POV-Ray and to port the software to platforms other
  12. * than those supported by the POV-Ray Team. There are strict rules under
  13. * which you are permitted to use this file. The rules are in the file
  14. * named POVLEGAL.DOC which should be distributed with this file.
  15. * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  16. * Team Coordinator by email to team-coord@povray.org or visit us on the web at
  17. * http://www.povray.org. The latest version of POV-Ray may be found at this site.
  18. *
  19. * This program is based on the popular DKB raytracer version 2.12.
  20. * DKBTrace was originally written by David K. Buck.
  21. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  22. *
  23. *****************************************************************************/
  24. #include "frame.h"
  25. #include "vector.h"
  26. #include "povproto.h"
  27. #include "texture.h"
  28. #include "image.h"
  29. #include "matrices.h"
  30. #include "povray.h"
  31. /*****************************************************************************
  32. * Local preprocessor defines
  33. ******************************************************************************/
  34. /*****************************************************************************
  35. * Local typedefs
  36. ******************************************************************************/
  37. /*****************************************************************************
  38. * Local variables
  39. ******************************************************************************/
  40. /*****************************************************************************
  41. * Static functions
  42. ******************************************************************************/
  43. static int cylindrical_image_map (VECTOR EPoint, IMAGE * Image, DBL *u, DBL *v);
  44. static int torus_image_map (VECTOR EPoint, IMAGE * Image, DBL *u, DBL *v);
  45. static int spherical_image_map (VECTOR EPoint, IMAGE * Image, DBL *u, DBL *v);
  46. static int planar_image_map (VECTOR EPoint, IMAGE * Image, DBL *u, DBL *v);
  47. static void no_interpolation (IMAGE * Image, DBL xcoor, DBL ycoor, COLOUR colour, int *index);
  48. static DBL bilinear (DBL *corners, DBL x, DBL y);
  49. static DBL norm_dist (DBL *corners, DBL x, DBL y);
  50. static void Interp (IMAGE * Image, DBL xcoor, DBL ycoor, COLOUR colour, int *index);
  51. static void image_colour_at (IMAGE * Image, DBL xcoor, DBL ycoor, COLOUR colour, int *index);
  52. static int map (VECTOR EPoint, TPATTERN * Turb, DBL *xcoor, DBL *ycoor);
  53. /*
  54. * 2-D to 3-D Procedural Texture Mapping of a Bitmapped Image onto an Object:
  55. *
  56. * A. Simplistic (planar) method of image projection devised by DKB and AAC:
  57. *
  58. * 1. Transform texture in 3-D space if requested. 2. Determine local object 2-d
  59. * coords from 3-d coords by <X Y Z> triple. 3. Return pixel color value at
  60. * that position on the 2-d plane of "Image". 3. Map colour value in Image
  61. * [0..255] to a more normal colour range [0..1].
  62. *
  63. * B. Specialized shape projection variations by Alexander Enzmann:
  64. *
  65. * 1. Cylindrical mapping 2. Spherical mapping 3. Torus mapping
  66. */
  67. /*****************************************************************************
  68. *
  69. * FUNCTION
  70. *
  71. * image_map
  72. *
  73. * INPUT
  74. *
  75. * EPoint -- 3-D point at which function is evaluated
  76. * Pigment -- Pattern containing various parameters
  77. *
  78. * OUTPUT
  79. *
  80. * Colour -- color at EPoint
  81. *
  82. * RETURNS
  83. *
  84. * int - TRUE, if current point on the image map
  85. * FALSE, if current point is not on the image map
  86. *
  87. * AUTHOR
  88. *
  89. * POV-Ray Team
  90. *
  91. * DESCRIPTION : Determines color of a 3-D point from a 2-D bitmap
  92. *
  93. * CHANGES
  94. *
  95. ******************************************************************************/
  96. int image_map(VECTOR EPoint, PIGMENT *Pigment, COLOUR colour)
  97. {
  98. int reg_number;
  99. DBL xcoor = 0.0, ycoor = 0.0;
  100. /* If outside map coverage area, return clear */
  101. if (map(EPoint, ((TPATTERN *) Pigment), &xcoor, &ycoor))
  102. {
  103. Make_ColourA(colour, 1.0, 1.0, 1.0, 0.0, 1.0);
  104. return(FALSE);
  105. }
  106. else
  107. {
  108. image_colour_at(Pigment->Vals.Image, xcoor, ycoor, colour, &reg_number);
  109. }
  110. return(TRUE);
  111. }
  112. /*****************************************************************************
  113. *
  114. * FUNCTION
  115. *
  116. * INPUT
  117. *
  118. * OUTPUT
  119. *
  120. * RETURNS
  121. *
  122. * AUTHOR
  123. *
  124. * DESCRIPTION
  125. *
  126. * Very different stuff than the other routines here. This routine takes an
  127. * intersection point and a texture and returns a new texture based on the
  128. * index/color of that point in an image/materials map. CdW 7/91
  129. *
  130. * CHANGES
  131. *
  132. ******************************************************************************/
  133. TEXTURE *material_map(VECTOR EPoint, TEXTURE *Texture)
  134. {
  135. int reg_number = 0;
  136. int Material_Number;
  137. int numtex;
  138. DBL xcoor = 0.0, ycoor = 0.0;
  139. COLOUR colour;
  140. TEXTURE *Temp_Tex;
  141. /*
  142. * Now we have transformed x, y, z we use image mapping routine to determine
  143. * texture index.
  144. */
  145. if (map(EPoint, ((TPATTERN *) Texture), &xcoor, &ycoor))
  146. {
  147. Material_Number = 0;
  148. }
  149. else
  150. {
  151. Make_ColourA(colour, 0.0, 0.0, 0.0, 0.0, 0.0);
  152. image_colour_at(Texture->Vals.Image, xcoor, ycoor, colour, &reg_number);
  153. if (Texture->Vals.Image->Colour_Map == NULL)
  154. {
  155. Material_Number = (int)(colour[RED] * 255.0);
  156. }
  157. else
  158. {
  159. Material_Number = reg_number;
  160. }
  161. }
  162. if (Material_Number > Texture->Num_Of_Mats)
  163. {
  164. Material_Number %= Texture->Num_Of_Mats;
  165. }
  166. for (numtex = 0, Temp_Tex = Texture->Materials;
  167. (Temp_Tex->Next_Material != NULL) && (numtex < Material_Number);
  168. Temp_Tex = Temp_Tex->Next_Material, numtex++)
  169. {
  170. /* do nothing */
  171. }
  172. return (Temp_Tex);
  173. }
  174. /*****************************************************************************
  175. *
  176. * FUNCTION
  177. *
  178. * INPUT
  179. *
  180. * OUTPUT
  181. *
  182. * RETURNS
  183. *
  184. * AUTHOR
  185. *
  186. * DESCRIPTION
  187. *
  188. * CHANGES
  189. *
  190. ******************************************************************************/
  191. void bump_map(VECTOR EPoint, TNORMAL *Tnormal, VECTOR normal)
  192. {
  193. DBL xcoor = 0.0, ycoor = 0.0;
  194. int index, index2, index3;
  195. COLOUR colour1, colour2, colour3;
  196. VECTOR p1, p2, p3;
  197. VECTOR bump_normal;
  198. VECTOR xprime, yprime, zprime, Temp;
  199. DBL Length;
  200. DBL Amount = Tnormal->Amount;
  201. IMAGE *Image = Tnormal->Vals.Image;
  202. Make_ColourA(colour1, 0.0, 0.0, 0.0, 0.0, 0.0);
  203. Make_ColourA(colour2, 0.0, 0.0, 0.0, 0.0, 0.0);
  204. Make_ColourA(colour3, 0.0, 0.0, 0.0, 0.0, 0.0);
  205. /* going to have to change this */
  206. /* need to know if bump point is off of image for all 3 points */
  207. if (map(EPoint, (TPATTERN *) Tnormal, &xcoor, &ycoor))
  208. {
  209. return;
  210. }
  211. else
  212. {
  213. image_colour_at(Image, xcoor, ycoor, colour1, &index);
  214. }
  215. xcoor--;
  216. ycoor++;
  217. if (xcoor < 0.0)
  218. {
  219. xcoor += (DBL)Image->iwidth;
  220. }
  221. else
  222. {
  223. if (xcoor >= Image->iwidth)
  224. {
  225. xcoor -= (DBL)Image->iwidth;
  226. }
  227. }
  228. if (ycoor < 0.0)
  229. {
  230. ycoor += (DBL)Image->iheight;
  231. }
  232. else
  233. {
  234. if (ycoor >= (DBL)Image->iheight)
  235. {
  236. ycoor -= (DBL)Image->iheight;
  237. }
  238. }
  239. image_colour_at(Image, xcoor, ycoor, colour2, &index2);
  240. xcoor += 2.0;
  241. if (xcoor < 0.0)
  242. {
  243. xcoor += (DBL)Image->iwidth;
  244. }
  245. else
  246. {
  247. if (xcoor >= Image->iwidth)
  248. {
  249. xcoor -= (DBL)Image->iwidth;
  250. }
  251. }
  252. image_colour_at(Image, xcoor, ycoor, colour3, &index3);
  253. if (Image->Colour_Map == NULL || Image->Use_Colour_Flag)
  254. {
  255. p1[X] = 0;
  256. p1[Y] = Amount * (0.229 * colour1[RED] + 0.587 * colour1[GREEN] + 0.114 * colour1[BLUE]);
  257. p1[Z] = 0;
  258. p2[X] = -1;
  259. p2[Y] = Amount * (0.229 * colour2[RED] + 0.587 * colour2[GREEN] + 0.114 * colour2[BLUE]);
  260. p2[Z] = 1;
  261. p3[X] = 1;
  262. p3[Y] = Amount * (0.229 * colour3[RED] + 0.587 * colour3[GREEN] + 0.114 * colour3[BLUE]);
  263. p3[Z] = 1;
  264. }
  265. else
  266. {
  267. p1[X] = 0;
  268. p1[Y] = Amount * index;
  269. p1[Z] = 0;
  270. p2[X] = -1;
  271. p2[Y] = Amount * index2;
  272. p2[Z] = 1;
  273. p3[X] = 1;
  274. p3[Y] = Amount * index3;
  275. p3[Z] = 1;
  276. }
  277. /* we have points 1,2,3 for a triangle now we need the surface normal for it */
  278. VSub(xprime, p1, p2);
  279. VSub(yprime, p3, p2);
  280. VCross(bump_normal, yprime, xprime);
  281. VNormalize(bump_normal, bump_normal);
  282. Assign_Vector(yprime, normal);
  283. Make_Vector(Temp, 0.0, 1.0, 0.0);
  284. VCross(xprime, yprime, Temp);
  285. VLength(Length, xprime);
  286. if (Length < EPSILON)
  287. {
  288. if (fabs(normal[Y] - 1.0) < Small_Tolerance)
  289. {
  290. Make_Vector(yprime, 0.0, 1.0, 0.0);
  291. Make_Vector(xprime, 1.0, 0.0, 0.0);
  292. Length = 1.0;
  293. }
  294. else
  295. {
  296. Make_Vector(yprime, 0.0, -1.0, 0.0);
  297. Make_Vector(xprime, 1.0, 0.0, 0.0);
  298. Length = 1.0;
  299. }
  300. }
  301. VScaleEq(xprime, 1.0 / Length);
  302. VCross(zprime, xprime, yprime);
  303. VNormalizeEq(zprime);
  304. VScaleEq(xprime, bump_normal[X]);
  305. VScaleEq(yprime, bump_normal[Y]);
  306. VScaleEq(zprime, bump_normal[Z]);
  307. VAdd(Temp, xprime, yprime);
  308. VScaleEq(zprime, -1);
  309. VAdd(normal, Temp, zprime);
  310. }
  311. /*****************************************************************************
  312. *
  313. * FUNCTION
  314. *
  315. * INPUT
  316. *
  317. * OUTPUT
  318. *
  319. * RETURNS
  320. *
  321. * AUTHOR
  322. *
  323. * DESCRIPTION
  324. *
  325. * CHANGES
  326. *
  327. ******************************************************************************/
  328. static void image_colour_at(IMAGE *Image, DBL xcoor, DBL ycoor, COLOUR colour, int *index)
  329. {
  330. switch (Image->Interpolation_Type)
  331. {
  332. case NO_INTERPOLATION:
  333. no_interpolation(Image, xcoor, ycoor, colour, index);
  334. break;
  335. default:
  336. Interp(Image, xcoor, ycoor, colour, index);
  337. break;
  338. }
  339. }
  340. /*****************************************************************************
  341. *
  342. * FUNCTION
  343. *
  344. * INPUT
  345. *
  346. * OUTPUT
  347. *
  348. * RETURNS
  349. *
  350. * AUTHOR
  351. *
  352. * DESCRIPTION
  353. *
  354. * Map a point (x, y, z) on a cylinder of radius 1, height 1, that has its axis
  355. * of symmetry along the y-axis to the square [0,1]x[0,1].
  356. *
  357. * CHANGES
  358. *
  359. ******************************************************************************/
  360. static int cylindrical_image_map(VECTOR EPoint, IMAGE *Image, DBL *u, DBL *v)
  361. {
  362. DBL len, theta;
  363. DBL x = EPoint[X];
  364. DBL y = EPoint[Y];
  365. DBL z = EPoint[Z];
  366. if ((Image->Once_Flag) && ((y < 0.0) || (y > 1.0)))
  367. {
  368. return 0;
  369. }
  370. *v = fmod(y * Image->height, Image->height);
  371. /* Make sure this vector is on the unit sphere. */
  372. len = sqrt(x * x + y * y + z * z);
  373. if (len == 0.0)
  374. {
  375. return 0;
  376. }
  377. else
  378. {
  379. x /= len;
  380. z /= len;
  381. }
  382. /* Determine its angle from the point (1, 0, 0) in the x-z plane. */
  383. len = sqrt(x * x + z * z);
  384. if (len == 0.0)
  385. {
  386. return 0;
  387. }
  388. else
  389. {
  390. if (z == 0.0)
  391. {
  392. if (x > 0)
  393. {
  394. theta = 0.0;
  395. }
  396. else
  397. {
  398. theta = M_PI;
  399. }
  400. }
  401. else
  402. {
  403. theta = acos(x / len);
  404. if (z < 0.0)
  405. {
  406. theta = TWO_M_PI - theta;
  407. }
  408. }
  409. theta /= TWO_M_PI; /* This will be from 0 to 1 */
  410. }
  411. *u = (theta * Image->width);
  412. return 1;
  413. }
  414. /*****************************************************************************
  415. *
  416. * FUNCTION
  417. *
  418. * INPUT
  419. *
  420. * OUTPUT
  421. *
  422. * RETURNS
  423. *
  424. * AUTHOR
  425. *
  426. * DESCRIPTION
  427. *
  428. * Map a point (x, y, z) on a torus to a 2-d image.
  429. *
  430. * CHANGES
  431. *
  432. ******************************************************************************/
  433. static int torus_image_map(VECTOR EPoint, IMAGE *Image, DBL *u, DBL *v)
  434. {
  435. DBL len, phi, theta;
  436. DBL r0;
  437. DBL x = EPoint[X];
  438. DBL y = EPoint[Y];
  439. DBL z = EPoint[Z];
  440. r0 = Image->Gradient[X];
  441. /* Determine its angle from the x-axis. */
  442. len = sqrt(x * x + z * z);
  443. if (len == 0.0)
  444. {
  445. return 0;
  446. }
  447. else
  448. {
  449. if (z == 0.0)
  450. {
  451. if (x > 0)
  452. {
  453. theta = 0.0;
  454. }
  455. else
  456. {
  457. theta = M_PI;
  458. }
  459. }
  460. else
  461. {
  462. theta = acos(x / len);
  463. if (z < 0.0)
  464. {
  465. theta = TWO_M_PI - theta;
  466. }
  467. }
  468. }
  469. theta = 0.0 - theta;
  470. /* Now rotate about the y-axis to get the point (x, y, z) into the x-y plane. */
  471. x = len - r0;
  472. len = sqrt(x * x + y * y);
  473. phi = acos(-x / len);
  474. if (y > 0.0)
  475. {
  476. phi = TWO_M_PI - phi;
  477. }
  478. /* Determine the parametric coordinates. */
  479. theta /= TWO_M_PI;
  480. phi /= TWO_M_PI;
  481. *u = (-theta * Image->width);
  482. *v = (phi * Image->height);
  483. return 1;
  484. }
  485. /*****************************************************************************
  486. *
  487. * FUNCTION
  488. *
  489. * INPUT
  490. *
  491. * OUTPUT
  492. *
  493. * RETURNS
  494. *
  495. * AUTHOR
  496. *
  497. * DESCRIPTION
  498. *
  499. * Map a point (x, y, z) on a sphere of radius 1 to a 2-d image. (Or is it the
  500. * other way around?)
  501. *
  502. * CHANGES
  503. *
  504. ******************************************************************************/
  505. static int spherical_image_map(VECTOR EPoint, IMAGE *Image, DBL *u, DBL *v)
  506. {
  507. DBL len, phi, theta;
  508. DBL x = EPoint[X];
  509. DBL y = EPoint[Y];
  510. DBL z = EPoint[Z];
  511. /* Make sure this vector is on the unit sphere. */
  512. len = sqrt(x * x + y * y + z * z);
  513. if (len == 0.0)
  514. {
  515. return 0;
  516. }
  517. else
  518. {
  519. x /= len;
  520. y /= len;
  521. z /= len;
  522. }
  523. /* Determine its angle from the x-z plane. */
  524. phi = 0.5 + asin(y) / M_PI; /* This will be from 0 to 1 */
  525. /* Determine its angle from the point (1, 0, 0) in the x-z plane. */
  526. len = sqrt(x * x + z * z);
  527. if (len == 0.0)
  528. {
  529. /* This point is at one of the poles. Any value of xcoord will be ok... */
  530. theta = 0;
  531. }
  532. else
  533. {
  534. if (z == 0.0)
  535. {
  536. if (x > 0)
  537. {
  538. theta = 0.0;
  539. }
  540. else
  541. {
  542. theta = M_PI;
  543. }
  544. }
  545. else
  546. {
  547. theta = acos(x / len);
  548. if (z < 0.0)
  549. {
  550. theta = TWO_M_PI - theta;
  551. }
  552. }
  553. theta /= TWO_M_PI; /* This will be from 0 to 1 */
  554. }
  555. *u = (theta * Image->width);
  556. *v = (phi * Image->height);
  557. return 1;
  558. }
  559. /*
  560. * 2-D to 3-D Procedural Texture Mapping of a Bitmapped Image onto an Object:
  561. *
  562. * Simplistic planar method of object image projection devised by DKB and AAC.
  563. *
  564. * 1. Transform texture in 3-D space if requested. 2. Determine local object 2-d
  565. * coords from 3-d coords by <X Y Z> triple. 3. Return pixel color value at
  566. * that position on the 2-d plane of "Image". 3. Map colour value in Image
  567. * [0..255] to a more normal colour range [0..1].
  568. */
  569. /*****************************************************************************
  570. *
  571. * FUNCTION
  572. *
  573. * INPUT
  574. *
  575. * OUTPUT
  576. *
  577. * RETURNS
  578. *
  579. * AUTHOR
  580. *
  581. * DESCRIPTION
  582. *
  583. * Return 0 if there is no color at this point (i.e. invisible), return 1 if a
  584. * good mapping is found.
  585. *
  586. * CHANGES
  587. *
  588. ******************************************************************************/
  589. static int planar_image_map(VECTOR EPoint, IMAGE *Image, DBL *u, DBL *v)
  590. {
  591. DBL x = EPoint[X];
  592. DBL y = EPoint[Y];
  593. DBL z = EPoint[Z];
  594. if (Image->Gradient[X] != 0.0)
  595. {
  596. if ((Image->Once_Flag) && ((x < 0.0) || (x > 1.0)))
  597. {
  598. return 0;
  599. }
  600. if (Image->Gradient[X] > 0)
  601. {
  602. *u = fmod(x * Image->width, Image->width);
  603. }
  604. else
  605. {
  606. *v = fmod(x * Image->height, Image->height);
  607. }
  608. }
  609. if (Image->Gradient[Y] != 0.0)
  610. {
  611. if ((Image->Once_Flag) && ((y < 0.0) || (y > 1.0)))
  612. {
  613. return 0;
  614. }
  615. if (Image->Gradient[Y] > 0)
  616. {
  617. *u = fmod(y * Image->width, Image->width);
  618. }
  619. else
  620. {
  621. *v = fmod(y * Image->height, Image->height);
  622. }
  623. }
  624. if (Image->Gradient[Z] != 0.0)
  625. {
  626. if ((Image->Once_Flag) && ((z < 0.0) || (z > 1.0)))
  627. {
  628. return 0;
  629. }
  630. if (Image->Gradient[Z] > 0)
  631. {
  632. *u = fmod(z * Image->width, Image->width);
  633. }
  634. else
  635. {
  636. *v = fmod(z * Image->height, Image->height);
  637. }
  638. }
  639. return 1;
  640. }
  641. /*****************************************************************************
  642. *
  643. * FUNCTION
  644. *
  645. * map
  646. *
  647. * INPUT
  648. *
  649. * EPoint -- 3-D point at which function is evaluated
  650. * TPattern -- Pattern containing various parameters
  651. *
  652. * OUTPUT
  653. *
  654. * xcoor, ycoor -- 2-D result
  655. *
  656. * RETURNS
  657. *
  658. * Map returns 1 if point off of map 0 if on map
  659. *
  660. * AUTHOR
  661. *
  662. * POV-Ray Team
  663. *
  664. * DESCRIPTION : Maps a 3-D point to a 2-D point depending upon map type
  665. *
  666. * CHANGES
  667. *
  668. ******************************************************************************/
  669. static int map(VECTOR EPoint, TPATTERN *TPattern, DBL *xcoor, DBL *ycoor)
  670. {
  671. IMAGE *Image = TPattern->Vals.Image;
  672. /* Now determine which mapper to use. */
  673. switch (Image->Map_Type)
  674. {
  675. case PLANAR_MAP:
  676. if (!planar_image_map(EPoint, Image, xcoor, ycoor))
  677. {
  678. return (1);
  679. }
  680. break;
  681. case SPHERICAL_MAP:
  682. if (!spherical_image_map(EPoint, Image, xcoor, ycoor))
  683. {
  684. return (1);
  685. }
  686. break;
  687. case CYLINDRICAL_MAP:
  688. if (!cylindrical_image_map(EPoint, Image, xcoor, ycoor))
  689. {
  690. return (1);
  691. }
  692. break;
  693. case TORUS_MAP:
  694. if (!torus_image_map(EPoint, Image, xcoor, ycoor))
  695. {
  696. return (1);
  697. }
  698. break;
  699. default:
  700. if (!planar_image_map(EPoint, Image, xcoor, ycoor))
  701. {
  702. return (1);
  703. }
  704. break;
  705. }
  706. /* Now make sure the point is on the image */
  707. *ycoor += Small_Tolerance;
  708. *xcoor += Small_Tolerance;
  709. /* Compensate for y coordinates on the images being upsidedown */
  710. *ycoor = (DBL)Image->iheight - *ycoor;
  711. if (*xcoor < 0.0)
  712. {
  713. *xcoor += (DBL)Image->iwidth;
  714. }
  715. else
  716. {
  717. if (*xcoor >= (DBL)Image->iwidth)
  718. {
  719. *xcoor -= (DBL)Image->iwidth;
  720. }
  721. }
  722. if (*ycoor < 0.0)
  723. {
  724. *ycoor += (DBL)Image->iheight;
  725. }
  726. else
  727. {
  728. if (*ycoor >= (DBL)Image->iheight)
  729. {
  730. *ycoor -= (DBL)Image->iheight;
  731. }
  732. }
  733. if ((*xcoor >= (DBL)Image->iwidth) ||
  734. (*ycoor >= (DBL)Image->iheight) ||
  735. (*xcoor < 0.0) || (*ycoor < 0.0))
  736. {
  737. Error("Picture index out of range.");
  738. }
  739. return (0);
  740. }
  741. /*****************************************************************************
  742. *
  743. * FUNCTION
  744. *
  745. * INPUT
  746. *
  747. * OUTPUT
  748. *
  749. * RETURNS
  750. *
  751. * AUTHOR
  752. *
  753. * DESCRIPTION
  754. *
  755. * CHANGES
  756. *
  757. ******************************************************************************/
  758. static void no_interpolation(IMAGE *Image, DBL xcoor, DBL ycoor, COLOUR colour, int *index)
  759. {
  760. IMAGE_LINE *line;
  761. int iycoor, ixcoor;
  762. IMAGE_COLOUR *map_colour;
  763. if(Image->Once_Flag)
  764. {
  765. if (xcoor < 0.0)
  766. {
  767. xcoor = 0.0;
  768. }
  769. else
  770. {
  771. if (xcoor >= (DBL)Image->iwidth)
  772. {
  773. xcoor -= 1.0;
  774. }
  775. }
  776. if (ycoor < 0.0)
  777. {
  778. ycoor = 0.0;
  779. }
  780. else
  781. {
  782. if (ycoor >= (DBL)Image->iheight)
  783. {
  784. ycoor -= 1.0;
  785. }
  786. }
  787. }
  788. else
  789. {
  790. if (xcoor < 0.0)
  791. {
  792. xcoor += (DBL)Image->iwidth;
  793. }
  794. else
  795. {
  796. if (xcoor >= (DBL)Image->iwidth)
  797. {
  798. xcoor -= (DBL)Image->iwidth;
  799. }
  800. }
  801. if (ycoor < 0.0)
  802. {
  803. ycoor += (DBL)Image->iheight;
  804. }
  805. else
  806. {
  807. if (ycoor >= (DBL)Image->iheight)
  808. {
  809. ycoor -= (DBL)Image->iheight;
  810. }
  811. }
  812. }
  813. iycoor = (int)ycoor;
  814. ixcoor = (int)xcoor;
  815. if (Image->Colour_Map == NULL)
  816. {
  817. line = &Image->data.rgb_lines[iycoor];
  818. colour[RED] += (DBL)line->red[ixcoor] / 255.0;
  819. colour[GREEN] += (DBL)line->green[ixcoor] / 255.0;
  820. colour[BLUE] += (DBL)line->blue[ixcoor] / 255.0;
  821. if (line->transm != NULL)
  822. {
  823. colour[TRANSM] += (DBL)line->transm[ixcoor] / 255.0;
  824. }
  825. *index = -1;
  826. }
  827. else
  828. {
  829. *index = Image->data.map_lines[iycoor][ixcoor];
  830. map_colour = &Image->Colour_Map[*index];
  831. colour[RED] += (DBL)map_colour->Red / 255.0;
  832. colour[GREEN] += (DBL)map_colour->Green / 255.0;
  833. colour[BLUE] += (DBL)map_colour->Blue / 255.0;
  834. colour[FILTER] += (DBL)map_colour->Filter / 255.0;
  835. colour[TRANSM] += (DBL)map_colour->Transmit / 255.0;
  836. }
  837. }
  838. /*****************************************************************************
  839. *
  840. * FUNCTION
  841. *
  842. * INPUT
  843. *
  844. * OUTPUT
  845. *
  846. * RETURNS
  847. *
  848. * AUTHOR
  849. *
  850. * DESCRIPTION
  851. *
  852. * CHANGES
  853. *
  854. ******************************************************************************/
  855. /* Interpolate color and filter values when mapping */
  856. static void Interp(IMAGE *Image, DBL xcoor, DBL ycoor, COLOUR colour, int *index)
  857. {
  858. int iycoor, ixcoor, i;
  859. int Corners_Index[4];
  860. DBL Index_Crn[4];
  861. COLOUR Corner_Colour[4];
  862. DBL Red_Crn[4];
  863. DBL Green_Crn[4];
  864. DBL Blue_Crn[4];
  865. DBL Filter_Crn[4];
  866. DBL Transm_Crn[4];
  867. DBL val1, val2, val3, val4, val5;
  868. val1 = val2 = val3 = val4 = val5 = 0.0;
  869. iycoor = (int)ycoor;
  870. ixcoor = (int)xcoor;
  871. for (i = 0; i < 4; i++)
  872. {
  873. Make_ColourA(Corner_Colour[i], 0.0, 0.0, 0.0, 0.0, 0.0);
  874. }
  875. /* OK, now that you have the corners, what are you going to do with them? */
  876. if (Image->Interpolation_Type == BILINEAR)
  877. {
  878. no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor, Corner_Colour[0], &Corners_Index[0]);
  879. no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor, Corner_Colour[1], &Corners_Index[1]);
  880. no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor - 1, Corner_Colour[2], &Corners_Index[2]);
  881. no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor - 1, Corner_Colour[3], &Corners_Index[3]);
  882. for (i = 0; i < 4; i++)
  883. {
  884. Red_Crn[i] = Corner_Colour[i][RED];
  885. Green_Crn[i] = Corner_Colour[i][GREEN];
  886. Blue_Crn[i] = Corner_Colour[i][BLUE];
  887. Filter_Crn[i] = Corner_Colour[i][FILTER];
  888. Transm_Crn[i] = Corner_Colour[i][TRANSM];
  889. /*
  890. * Debug_Info("Crn %d = %lf %lf
  891. * %lf\n",i,Red_Crn[i],Blue_Crn[i],Green_Crn[i]);
  892. */
  893. }
  894. val1 = bilinear(Red_Crn, xcoor, ycoor);
  895. val2 = bilinear(Green_Crn, xcoor, ycoor);
  896. val3 = bilinear(Blue_Crn, xcoor, ycoor);
  897. val4 = bilinear(Filter_Crn, xcoor, ycoor);
  898. val5 = bilinear(Transm_Crn, xcoor, ycoor);
  899. }
  900. if (Image->Interpolation_Type == NORMALIZED_DIST)
  901. {
  902. no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor - 1, Corner_Colour[0], &Corners_Index[0]);
  903. no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor - 1, Corner_Colour[1], &Corners_Index[1]);
  904. no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor, Corner_Colour[2], &Corners_Index[2]);
  905. no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor, Corner_Colour[3], &Corners_Index[3]);
  906. for (i = 0; i < 4; i++)
  907. {
  908. Red_Crn[i] = Corner_Colour[i][RED];
  909. Green_Crn[i] = Corner_Colour[i][GREEN];
  910. Blue_Crn[i] = Corner_Colour[i][BLUE];
  911. Filter_Crn[i] = Corner_Colour[i][FILTER];
  912. Transm_Crn[i] = Corner_Colour[i][TRANSM];
  913. /*
  914. * Debug_Info("Crn %d = %lf %lf
  915. * %lf\n",i,Red_Crn[i],Blue_Crn[i],Green_Crn[i]);
  916. */
  917. }
  918. val1 = norm_dist(Red_Crn, xcoor, ycoor);
  919. val2 = norm_dist(Green_Crn, xcoor, ycoor);
  920. val3 = norm_dist(Blue_Crn, xcoor, ycoor);
  921. val4 = norm_dist(Filter_Crn, xcoor, ycoor);
  922. val5 = norm_dist(Transm_Crn, xcoor, ycoor);
  923. }
  924. colour[RED] += val1;
  925. colour[GREEN] += val2;
  926. colour[BLUE] += val3;
  927. colour[FILTER] += val4;
  928. colour[TRANSM] += val5;
  929. /* Debug_Info("Final = %lf %lf %lf\n",val1,val2,val3); */
  930. /* use bilinear for index try average later */
  931. for (i = 0; i < 4; i++)
  932. {
  933. Index_Crn[i] = (DBL)Corners_Index[i];
  934. }
  935. if (Image->Interpolation_Type == BILINEAR)
  936. {
  937. *index = (int)(bilinear(Index_Crn, xcoor, ycoor) + 0.5);
  938. }
  939. if (Image->Interpolation_Type == NORMALIZED_DIST)
  940. {
  941. *index = (int)(norm_dist(Index_Crn, xcoor, ycoor) + 0.5);
  942. }
  943. }
  944. /*****************************************************************************
  945. *
  946. * FUNCTION
  947. *
  948. * INPUT
  949. *
  950. * OUTPUT
  951. *
  952. * RETURNS
  953. *
  954. * AUTHOR
  955. *
  956. * DESCRIPTION
  957. *
  958. * CHANGES
  959. *
  960. ******************************************************************************/
  961. /* These interpolation techniques are taken from an article by */
  962. /* Girish T. Hagan in the C Programmer's Journal V 9 No. 8 */
  963. /* They were adapted for POV-Ray by CdW */
  964. static DBL bilinear(DBL *corners, DBL x, DBL y)
  965. {
  966. DBL p, q;
  967. DBL val;
  968. p = x - (int)x;
  969. q = y - (int)y;
  970. if ((p == 0.0) && (q == 0.0))
  971. {
  972. return (*corners); /* upper left */
  973. }
  974. val = (p * q * *corners) + (q * (1 - p) * *(corners + 1)) +
  975. (p * (1 - q) * *(corners + 2)) + ((1 - p) * (1 - q) * *(corners + 3));
  976. return (val);
  977. }
  978. /*****************************************************************************
  979. *
  980. * FUNCTION
  981. *
  982. * INPUT
  983. *
  984. * OUTPUT
  985. *
  986. * RETURNS
  987. *
  988. * AUTHOR
  989. *
  990. * DESCRIPTION
  991. *
  992. * CHANGES
  993. *
  994. ******************************************************************************/
  995. #define MAX_PTS 4
  996. #define PYTHAGOREAN_SQ(a,b) ( (a)*(a) + (b)*(b) )
  997. static DBL norm_dist(DBL *corners, DBL x, DBL y)
  998. {
  999. register int i;
  1000. DBL p, q;
  1001. DBL wts[MAX_PTS];
  1002. DBL sum_inv_wts = 0.0;
  1003. DBL sum_I = 0.0;
  1004. p = x - (int)x;
  1005. q = y - (int)y;
  1006. if ((p == 0.0) && (q == 0.0))
  1007. {
  1008. return (*corners); /* upper left */
  1009. }
  1010. wts[0] = PYTHAGOREAN_SQ(p, q);
  1011. wts[1] = PYTHAGOREAN_SQ(1 - p, q);
  1012. wts[2] = PYTHAGOREAN_SQ(p, 1 - q);
  1013. wts[3] = PYTHAGOREAN_SQ(1 - p, 1 - q);
  1014. for (i = 0; i < MAX_PTS; i++)
  1015. {
  1016. sum_inv_wts += 1 / wts[i];
  1017. sum_I += *(corners + i) / wts[i];
  1018. }
  1019. return (sum_I / sum_inv_wts);
  1020. }
  1021. /*****************************************************************************
  1022. *
  1023. * FUNCTION
  1024. *
  1025. * Create_Image
  1026. *
  1027. * INPUT
  1028. *
  1029. * OUTPUT
  1030. *
  1031. * RETURNS
  1032. *
  1033. * AUTHOR
  1034. *
  1035. * POV-Ray Team
  1036. *
  1037. * DESCRIPTION
  1038. *
  1039. * -
  1040. *
  1041. * CHANGES
  1042. *
  1043. * -
  1044. *
  1045. ******************************************************************************/
  1046. IMAGE *Create_Image()
  1047. {
  1048. IMAGE *Image;
  1049. Image = (IMAGE *) POV_MALLOC(sizeof(IMAGE), "image file");
  1050. Image->References = 1;
  1051. Image->File_Type = NO_FILE;
  1052. Image->Map_Type = PLANAR_MAP;
  1053. Image->Interpolation_Type = NO_INTERPOLATION;
  1054. Image->Once_Flag = FALSE;
  1055. Image->Use_Colour_Flag = FALSE;
  1056. Make_Vector(Image->Gradient, 1.0, -1.0, 0.0);
  1057. return (Image);
  1058. }
  1059. /*****************************************************************************
  1060. *
  1061. * FUNCTION
  1062. *
  1063. * Copy_Image
  1064. *
  1065. * INPUT
  1066. *
  1067. * OUTPUT
  1068. *
  1069. * RETURNS
  1070. *
  1071. * AUTHOR
  1072. *
  1073. * POV-Ray Team
  1074. *
  1075. * DESCRIPTION
  1076. *
  1077. * -
  1078. *
  1079. * CHANGES
  1080. *
  1081. * -
  1082. *
  1083. ******************************************************************************/
  1084. IMAGE *Copy_Image(IMAGE *Old)
  1085. {
  1086. if (Old != NULL)
  1087. {
  1088. Old->References++;
  1089. }
  1090. return (Old);
  1091. }
  1092. /*****************************************************************************
  1093. *
  1094. * FUNCTION
  1095. *
  1096. * Destroy_Image
  1097. *
  1098. * INPUT
  1099. *
  1100. * OUTPUT
  1101. *
  1102. * RETURNS
  1103. *
  1104. * AUTHOR
  1105. *
  1106. * POV-Ray Team
  1107. *
  1108. * DESCRIPTION
  1109. *
  1110. * -
  1111. *
  1112. * CHANGES
  1113. *
  1114. * -
  1115. *
  1116. ******************************************************************************/
  1117. void Destroy_Image(IMAGE *Image)
  1118. {
  1119. int i;
  1120. if ((Image == NULL) || (--(Image->References) > 0))
  1121. {
  1122. return;
  1123. }
  1124. if (Image->Colour_Map != NULL)
  1125. {
  1126. POV_FREE(Image->Colour_Map);
  1127. Image->Colour_Map = NULL;
  1128. if (Image->data.map_lines != NULL)
  1129. {
  1130. for (i = 0; i < Image->iheight; i++)
  1131. {
  1132. POV_FREE(Image->data.map_lines[i]);
  1133. }
  1134. POV_FREE(Image->data.map_lines);
  1135. Image->data.map_lines = NULL;
  1136. }
  1137. }
  1138. else
  1139. {
  1140. if (Image->data.rgb_lines != NULL)
  1141. {
  1142. for (i = 0; i < Image->iheight; i++)
  1143. {
  1144. POV_FREE(Image->data.rgb_lines[i].red);
  1145. POV_FREE(Image->data.rgb_lines[i].green);
  1146. POV_FREE(Image->data.rgb_lines[i].blue);
  1147. if (Image->data.rgb_lines[i].transm != NULL)
  1148. {
  1149. POV_FREE(Image->data.rgb_lines[i].transm);
  1150. }
  1151. }
  1152. POV_FREE(Image->data.rgb_lines);
  1153. Image->data.rgb_lines = NULL;
  1154. }
  1155. }
  1156. POV_FREE(Image);
  1157. }