home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / common / spheredesigner.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-16  |  76.3 KB  |  2,905 lines

  1. /*
  2.  * The GIMP -- an image manipulation program
  3.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  4.  *
  5.  * SphereDesigner v0.4 - creates textured spheres
  6.  * by Vidar Madsen <vidar@prosalg.no>
  7.  *
  8.  * Status: Last updated 1999-09-11
  9.  *
  10.  * Known issues:
  11.  * - Might crash if you click OK or Cancel before first preview is rendered
  12.  * - Phong might look weird with transparent textures
  13.  *
  14.  * Todo:
  15.  * - Saving / Loading of presets needs an overhaul
  16.  * - Antialiasing
  17.  * - Global controls: Gamma, ++
  18.  * - Beautification of GUI
  19.  * - Clean up messy source (lots of Glade remnants)
  20.  * - (Probably more. ;-)
  21.  */
  22.  
  23. #define PLUG_IN_NAME "SphereDesigner"
  24.  
  25. #ifdef HAVE_CONFIG_H
  26. #include "config.h"
  27. #endif
  28.  
  29. #include <stdio.h>
  30. #include <string.h>
  31. #ifdef HAVE_SYS_TIME_H
  32. #include <sys/time.h>
  33. #endif
  34. #ifdef HAVE_UNISTD_H
  35. #include <unistd.h>
  36. #endif
  37. #include <stdlib.h>
  38. #include <string.h>
  39.  
  40. #include <gtk/gtk.h>
  41.  
  42. #include <libgimp/gimp.h>
  43. #include <libgimp/gimpui.h>
  44.  
  45. #include "libgimp/stdplugins-intl.h"
  46.  
  47.  
  48. #ifndef SRAND_FUNC
  49. #define SRAND_FUNC srand
  50. #endif
  51. #ifndef RAND_FUNC
  52. #define RAND_FUNC rand
  53. #endif
  54.  
  55. #define PREVIEWSIZE 150
  56.  
  57. /* These must be adjusted as more functionality is added */
  58. #define MAXOBJECT 5
  59. #define MAXLIGHT 5
  60. #define MAXTEXTURE 20
  61. #define MAXTEXTUREPEROBJ 20
  62. #define MAXNORMAL 20
  63. #define MAXNORMALPEROBJ 20
  64. #define MAXATMOS 1
  65. #define MAXCOLPERGRADIENT 5
  66.  
  67. static void      query  (void);
  68. static void      run    (gchar   *name,
  69.                          gint     nparams,
  70.                          GimpParam  *param,
  71.                          gint    *nreturn_vals,
  72.                          GimpParam **return_vals);
  73.  
  74. GimpPlugInInfo PLUG_IN_INFO =
  75. {
  76.   NULL,  /* init_proc  */
  77.   NULL,  /* quit_proc  */
  78.   query, /* query_proc */
  79.   run,   /* run_proc   */
  80. };
  81.  
  82. enum {
  83.   TRIANGLE, DISC, PLANE, SPHERE, CYLINDER, LIGHT
  84. };
  85.  
  86. enum {
  87.   SOLID, CHECKER, MARBLE, LIZARD, IMAGE, PHONG, REFLECTION, REFRACTION, PERLIN,
  88.   WOOD, TRANSPARENT, SPIRAL, SPOTS, SMOKE
  89. };
  90.  
  91. enum {
  92.   PERSPECTIVE, ORTHOGONAL, FISHEYE
  93. };
  94.  
  95. enum {
  96.   FOG
  97. };
  98.  
  99. /* World-flags */
  100. #define SMARTAMBIENT 0x00000001
  101.  
  102. /* Object-flags */
  103. #define NOSHADOW   0x00000001
  104.  
  105. /* Texture-flags */
  106. #define GRADIENT   0x00000001
  107.  
  108. typedef struct {
  109.   double x,y,z,w;
  110. } vector;
  111.  
  112. typedef struct {
  113.   short xsize, ysize;
  114.   unsigned char *rgb;
  115. } image;
  116.  
  117. typedef struct {
  118.   short numcol;
  119.   double pos[MAXCOLPERGRADIENT];
  120.   vector color[MAXCOLPERGRADIENT];
  121. } gradient;
  122.  
  123. typedef struct {
  124.   int majtype;
  125.   int type;
  126.   unsigned long flags;
  127.   vector color1, color2;
  128.   gradient gradient;
  129.   vector ambient, diffuse;
  130.   double oscale;
  131.   vector scale, translate, rotate;
  132.   image image;
  133.   vector reflection;
  134.   vector refraction;
  135.   vector transparent;
  136.   double ior;
  137.   vector phongcolor;
  138.   double phongsize;
  139.   double amount;
  140.   double exp;
  141.   vector turbulence;
  142. } texture;
  143.  
  144. typedef struct {
  145.   short type;
  146.   double density;
  147.   vector color;
  148.   double turbulence;
  149. } atmos;
  150.  
  151. typedef struct {
  152.   short type;
  153.   unsigned long flags;
  154.   short numtexture;
  155.   texture texture[MAXTEXTUREPEROBJ];
  156.   short numnormal;
  157.   texture normal[MAXNORMALPEROBJ];
  158. } common;
  159.  
  160. typedef struct {
  161.   common com;
  162.   vector a,b,c;
  163. } triangle;
  164.  
  165. typedef struct {
  166.   common com;
  167.   vector a;
  168.   double b, r;
  169. } disc;
  170.  
  171. typedef struct {
  172.   common com;
  173.   vector a;
  174.   double r;
  175. } sphere;
  176.  
  177. typedef struct {
  178.   common com;
  179.   vector a, b, c;
  180. } cylinder;
  181.  
  182. typedef struct {
  183.   common com;
  184.   vector a;
  185.   double b;
  186. } plane;
  187.  
  188. typedef struct {
  189.   common com;
  190.   vector color;
  191.   vector a;
  192. } light;
  193.  
  194. typedef struct {
  195.   vector v1, v2;
  196.   short inside;
  197.   double ior;
  198. } ray;
  199.  
  200. typedef union {
  201.   common com;
  202.   triangle tri;
  203.   disc disc;
  204.   plane plane;
  205.   sphere sphere;
  206.   cylinder cylinder;
  207. } object;
  208.  
  209.  
  210. struct world_t {
  211.   int numobj;
  212.   object obj[MAXOBJECT];
  213.   int numlight;
  214.   light light[MAXLIGHT];
  215.   int numtexture;
  216.   texture texture[MAXTEXTURE];
  217.   unsigned long flags;
  218.   short quality;
  219.   double smartambient;
  220.   short numatmos;
  221.   atmos atmos[MAXATMOS];
  222. };
  223.  
  224. struct camera_t {
  225.   vector location, lookat, up, right;
  226.   short type;
  227.   double fov, tilt;
  228. };
  229.  
  230. int traceray(ray *r, vector *col, int level, double imp);
  231.  
  232. GtkWidget *drawarea = NULL;
  233.  
  234. unsigned char img[PREVIEWSIZE*PREVIEWSIZE*3];
  235.  
  236. int running = 0;
  237.  
  238. sphere s;
  239.  
  240. struct textures_t {
  241.   int index;
  242.   char *s;
  243.   long n;
  244. };
  245.  
  246. struct textures_t textures[] = {
  247.   {0,N_("Solid"), SOLID},
  248.   {1,N_("Checker"),CHECKER},
  249.   {2,N_("Marble"),MARBLE},
  250.   {3,N_("Lizard"),LIZARD},
  251.   {4,N_("Phong"),PHONG},
  252.   {5,N_("Noise"),PERLIN},
  253.   {6,N_("Wood"),WOOD},
  254.   {7,N_("Spiral"),SPIRAL},
  255.   {8,N_("Spots"),SPOTS},
  256.   {0,NULL,0}
  257. };
  258.  
  259. struct {
  260.   int solid, phong, light;
  261. } settings = {1,1,1};
  262.  
  263. inline void vset(vector *v, double a, double b, double c);
  264. gint restartrender(void);
  265. void drawcolor1(GtkWidget *w);
  266. void drawcolor2(GtkWidget *w);
  267. void render(void);
  268. void realrender(GimpDrawable *drawable);
  269. void fileselect(int);
  270.  
  271. #define COLORBUTTONWIDTH 30
  272. #define COLORBUTTONHEIGHT 20
  273.  
  274. GtkWidget *texturelist = NULL;
  275. GtkObject *scalexscale,*scaleyscale,*scalezscale;
  276. GtkObject *rotxscale,*rotyscale,*rotzscale;
  277. GtkObject *posxscale,*posyscale,*poszscale;
  278. GtkObject *scalescale;
  279. GtkObject *turbulencescale;
  280. GtkObject *amountscale;
  281. GtkObject *expscale;
  282. GtkWidget *typemenu_menu;
  283. GtkWidget *texturemenu_menu;
  284. GtkWidget *typemenu;
  285. GtkWidget *texturemenu;
  286.  
  287. #define DOT(a,b) (a[0] * b[0] + a[1] * b[1] + a[2] * b[2])
  288.  
  289. #define B 256
  290.  
  291. static int p[B + B + 2];
  292. static double g[B + B + 2][3];
  293. static int start = 1;
  294.  
  295. void init(void)
  296. {
  297.   int i, j, k;
  298.   double v[3], s;
  299.  
  300. /* Create an array of random gradient vectors uniformly on the unit sphere */
  301.  
  302.   SRAND_FUNC(1); /* Use static seed, to get reproducable results */
  303.   for (i = 0 ; i < B ; i++) {
  304.     do {                            /* Choose uniformly in a cube */
  305.       for (j=0 ; j<3 ; j++)
  306.     v[j] = (double)((RAND_FUNC() % (B + B)) - B) / B;
  307.       s = DOT(v,v);
  308.     } while (s > 1.0);              /* If not in sphere try again */
  309.     s = sqrt(s);
  310.     for (j = 0 ; j < 3 ; j++)       /* Else normalize */
  311.       g[i][j] = v[j] / s;
  312.   }
  313.  
  314. /* Create a pseudorandom permutation of [1..B] */
  315.  
  316.   for (i = 0 ; i < B ; i++)
  317.     p[i] = i;
  318.   for (i = B ; i > 0 ; i -= 2) {
  319.     k = p[i];
  320.     p[i] = p[j = RAND_FUNC() % B];
  321.     p[j] = k;
  322.   }
  323.  
  324. /* Extend g and p arrays to allow for faster indexing */
  325.  
  326.   for (i = 0 ; i < B + 2 ; i++) {
  327.     p[B + i] = p[i];
  328.     for (j = 0 ; j < 3 ; j++)
  329.       g[B + i][j] = g[i][j];
  330.   }
  331. }
  332.  
  333. #define setup(i,b0,b1,r0,r1) \
  334.         t = vec[i] + 10000.; \
  335.         b0 = ((int)t) & (B-1); \
  336.         b1 = (b0+1) & (B-1); \
  337.         r0 = t - (int)t; \
  338.         r1 = r0 - 1.;
  339.  
  340. double noise3(double *vec)
  341. {
  342.   int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
  343.   double rx0, rx1, ry0, ry1, rz0, rz1, *q, sx, sy, sz, a, b, c, d, t, u, v;
  344.   int i, j;
  345.  
  346.   if(start) {
  347.     start = 0;
  348.     init();
  349.   }
  350.  
  351.   setup(0, bx0,bx1, rx0,rx1);
  352.   setup(1, by0,by1, ry0,ry1);
  353.   setup(2, bz0,bz1, rz0,rz1);
  354.  
  355.   i = p[ bx0 ];
  356.   j = p[ bx1 ];
  357.   
  358.   b00 = p[ i + by0 ];
  359.   b10 = p[ j + by0 ];
  360.   b01 = p[ i + by1 ];
  361.   b11 = p[ j + by1 ];
  362.   
  363. #define at(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
  364.  
  365. #define surve(t) ( t * t * (3. - 2. * t) )
  366.  
  367. #define lerp(t, a, b) ( a + t * (b - a) )
  368.  
  369.   sx = surve(rx0);
  370.   sy = surve(ry0);
  371.   sz = surve(rz0);
  372.  
  373.  
  374.   q = g[ b00 + bz0 ] ; u = at(rx0,ry0,rz0);
  375.   q = g[ b10 + bz0 ] ; v = at(rx1,ry0,rz0);
  376.   a = lerp(sx, u, v);
  377.  
  378.   q = g[ b01 + bz0 ] ; u = at(rx0,ry1,rz0);
  379.   q = g[ b11 + bz0 ] ; v = at(rx1,ry1,rz0);
  380.   b = lerp(sx, u, v);
  381.  
  382.   c = lerp(sy, a, b);          /* interpolate in y at lo x */
  383.  
  384.   q = g[ b00 + bz1 ] ; u = at(rx0,ry0,rz1);
  385.   q = g[ b10 + bz1 ] ; v = at(rx1,ry0,rz1);
  386.   a = lerp(sx, u, v);
  387.  
  388.   q = g[ b01 + bz1 ] ; u = at(rx0,ry1,rz1);
  389.   q = g[ b11 + bz1 ] ; v = at(rx1,ry1,rz1);
  390.   b = lerp(sx, u, v);
  391.  
  392.   d = lerp(sy, a, b);          /* interpolate in y at hi x */
  393.  
  394.   return 1.5 * lerp(sz, c, d); /* interpolate in z */
  395. }
  396.  
  397.  
  398. double turbulence(double *point, double lofreq, double hifreq)
  399. {
  400.   double noise3(), freq, t, p[3];
  401.  
  402.   p[0] = point[0] + 123.456;
  403.   p[1] = point[1] + 234.567;
  404.   p[2] = point[2] + 345.678;
  405.  
  406.   t = 0;
  407.   for (freq = lofreq ; freq < hifreq ; freq *= 2.) {
  408.     t += noise3(p) / freq;
  409.     p[0] *= 2.;
  410.     p[1] *= 2.;
  411.     p[2] *= 2.;
  412.   }
  413.   return t - 0.3; /* readjust to make mean value = 0.0 */
  414. }
  415.  
  416. struct camera_t camera;
  417. struct world_t world;
  418.  
  419. inline void vcopy(vector *a, vector *b)
  420. {
  421.   a->x = b->x;
  422.   a->y = b->y;
  423.   a->z = b->z;
  424.   a->w = b->w;
  425. }
  426.  
  427. inline void vcross(vector *r, vector *a, vector *b)
  428. {
  429.   vector t;
  430.   t.x = a->y * b->z - a->z * b->y;
  431.   t.y = -(a->x * b->z - a->z * b->x);
  432.   t.z = a->x * b->y - a->y * b->x;
  433.   vcopy(r, &t);
  434. }
  435.  
  436. inline double vdot(vector *a, vector *b)
  437. {
  438.   double s;
  439.   s = a->x * b->x;
  440.   s += a->y * b->y;
  441.   s += a->z * b->z;
  442.   return s;
  443. }
  444.  
  445. inline double vdist(vector *a, vector *b)
  446. {
  447.   double x,y,z;
  448.   x = a->x - b->x;
  449.   y = a->y - b->y;
  450.   z = a->z - b->z;
  451.   return sqrt(x*x+y*y+z*z);
  452. }
  453.  
  454. inline double vlen(vector *a)
  455. {
  456.   double l;
  457.   l = sqrt(a->x*a->x + a->y*a->y + a->z*a->z);
  458.   return l;
  459. }
  460.  
  461. inline void vnorm(vector *a, double v)
  462. {
  463.   double d;
  464.   d  = sqrt(a->x*a->x + a->y*a->y + a->z*a->z);
  465.   a->x *= v/d;
  466.   a->y *= v/d;
  467.   a->z *= v/d;
  468. }
  469.  
  470. inline void vrotate(vector *axis, double ang, vector *vector)
  471. {
  472.   double rad = ang / 180.0 * G_PI;
  473.   double ax = vector->x;
  474.   double ay = vector->y;
  475.   double az = vector->z;
  476.   double x = axis->x;
  477.   double y = axis->y;
  478.   double z = axis->z;
  479.   double c = cos(rad);
  480.   double s = sin(rad);
  481.   double c1 = 1.0 - c;
  482.   double xx = c1 * x * x;
  483.   double yy = c1 * y * y;
  484.   double zz = c1 * z * z;
  485.   double xy = c1 * x * y;
  486.   double xz = c1 * x * z;
  487.   double yz = c1 * y * z;
  488.   double sx = s * x;
  489.   double sy = s * y;
  490.   double sz = s * z;
  491.   vector->x = (xx + c)*ax + (xy + sz)*ay + (xz - sy)*az;
  492.   vector->y = (xy - sz)*ax + (yy + c)*ay + (yz + sx)*az;
  493.   vector->z = (xz + sy)*ax + (yz - sx)*ay + (zz + c )*az;
  494. }
  495.  
  496. inline void vset(vector *v, double a, double b, double c)
  497. {
  498.   v->x = a;
  499.   v->y = b;
  500.   v->z = c;
  501.   v->w = 1.0;
  502. }
  503.  
  504. inline void vcset(vector *v, double a, double b, double c, double d)
  505. {
  506.   v->x = a;
  507.   v->y = b;
  508.   v->z = c;
  509.   v->w = d;
  510. }
  511.  
  512. inline void vvrotate(vector *p, vector *rot)
  513. {
  514.   vector axis;
  515.   if(rot->x != 0.0) {
  516.     vset(&axis, 1,0,0);
  517.     vrotate(&axis, rot->x, p);
  518.   }
  519.   if(rot->y != 0.0) {
  520.     vset(&axis, 0,1,0);
  521.     vrotate(&axis, rot->y, p);
  522.   }
  523.   if(rot->z != 0.0) {
  524.     vset(&axis, 0,0,1);
  525.     vrotate(&axis, rot->z, p);
  526.   }
  527. }
  528.  
  529. inline void vsub(vector *a, vector *b)
  530. {
  531.   a->x -= b->x;
  532.   a->y -= b->y;
  533.   a->z -= b->z;
  534.   a->w -= b->w;
  535. }
  536.  
  537. inline void vadd(vector *a, vector *b)
  538. {
  539.   a->x += b->x;
  540.   a->y += b->y;
  541.   a->z += b->z;
  542.   a->w += b->w;
  543. }
  544.  
  545. inline void vneg(vector *a)
  546. {
  547.   a->x = -a->x;
  548.   a->y = -a->y;
  549.   a->z = -a->z;
  550.   a->w = -a->w;
  551. }
  552.  
  553. inline void vmul(vector *v, double a)
  554. {
  555.   v->x *= a;
  556.   v->y *= a;
  557.   v->z *= a;
  558.   v->w *= a;
  559. }
  560.  
  561. inline void vvmul(vector *a, vector *b)
  562. {
  563.   a->x *= b->x;
  564.   a->y *= b->y;
  565.   a->z *= b->z;
  566.   a->w *= b->w;
  567. }
  568.  
  569. inline void vvdiv(vector *a, vector *b)
  570. {
  571.   a->x /= b->x;
  572.   a->y /= b->y;
  573.   a->z /= b->z;
  574. }
  575.  
  576. void vmix(vector *r, vector *a, vector *b, double v)
  577. {
  578.   double i = 1.0 - v;
  579.   r->x = a->x * v + b->x * i;
  580.   r->y = a->y * v + b->y * i;
  581.   r->z = a->z * v + b->z * i;
  582.   r->w = a->w * v + b->w * i;
  583. }
  584.  
  585. double vmax(vector *a)
  586. {
  587.   double max = fabs(a->x);
  588.   if(fabs(a->y) > max) max = fabs(a->y);
  589.   if(fabs(a->z) > max) max = fabs(a->z);
  590.   if(fabs(a->w) > max) max = fabs(a->w);
  591.   return max;
  592. }
  593.  
  594. void vavg(vector *a)
  595. {
  596.   double s = (a->x + a->y + a->z) / 3.0;
  597.   a->x = a->y = a->z = s;
  598. }
  599.  
  600.  
  601. void trianglenormal(vector *n, double *t, triangle *tri)
  602. {
  603.   triangle tmp;
  604.   vcopy(&tmp.b, &tri->b);
  605.   vcopy(&tmp.c, &tri->c);
  606.   vsub(&tmp.b, &tri->a);
  607.   vsub(&tmp.c, &tri->a);
  608.   vset(&tmp.a, 0,0,0);
  609.   vcross(n, &tmp.b, &tmp.c);
  610.   if(t)
  611.     *t = vdot(&tmp.b, &tmp.c);
  612. }
  613.  
  614. double checkdisc(ray *r, disc *disc)
  615. {
  616.   vector p, *v = &disc->a;
  617.   double t, d;
  618.   double i,j,k;
  619.  
  620.   i = r->v2.x - r->v1.x;
  621.   j = r->v2.y - r->v1.y;
  622.   k = r->v2.z - r->v1.z;
  623.  
  624.   t = -(v->x * r->v1.x + v->y * r->v1.y + v->z * r->v1.z - disc->b) /
  625.     (v->x * i + v->y * j + v->z * k);
  626.  
  627.   p.x = r->v1.x + i * t;
  628.   p.y = r->v1.y + j * t;
  629.   p.z = r->v1.z + k * t;
  630.  
  631.   d = vdist(&p, v);
  632.  
  633.   if(d > disc->r) t = 0.0;
  634.  
  635.   return t;
  636. }
  637.  
  638. double checksphere(ray *r, sphere *sphere)
  639. {
  640.   vector cendir, rdir;
  641.   double dirproj, cdlensq;
  642.   double linear, constant, rsq, quadratic, discriminant;
  643.   double smallzero, solmin, solmax, tolerance = 0.001;
  644.  
  645.   vcopy(&rdir, &r->v2);
  646.   vsub(&rdir, &r->v1);
  647.  
  648.   rsq = sphere->r * sphere->r;
  649.  
  650.   vcopy(&cendir, &r->v1);
  651.   vsub(&cendir, &sphere->a);
  652.   dirproj = vdot(&rdir, &cendir);
  653.   cdlensq = vdot(&cendir, &cendir);
  654.  
  655.   if((cdlensq >= rsq) && (dirproj > 0.0))
  656.     return 0.0;
  657.  
  658.   linear = 2.0 * dirproj;
  659.   constant = cdlensq - rsq;
  660.   quadratic = vdot(&rdir, &rdir);
  661.  
  662.   smallzero = (constant / linear);
  663.   if((smallzero < tolerance) && (smallzero > -tolerance)) {
  664.     solmin = -linear / quadratic;
  665.  
  666.     if (solmin > tolerance) {
  667.       return solmin;
  668.       /*
  669.       *hits = solmin;
  670.       return 1;
  671.       */
  672.     } else
  673.       return 0.0;
  674.   }
  675.   discriminant = linear * linear - 4.0 * quadratic * constant;
  676.   if(discriminant < 0.0)
  677.     return 0.0;
  678.   quadratic *= 2.0;
  679.   discriminant = sqrt(discriminant);
  680.   solmax = (-linear + discriminant) / (quadratic);
  681.   solmin = (-linear - discriminant) / (quadratic);
  682.  
  683.   if (solmax < tolerance)
  684.     return 0.0;
  685.   
  686.   if(solmin < tolerance) {
  687.     return solmax;
  688.     /*
  689.     *hits = solmax;
  690.     return 1;
  691.     */
  692.   } else {
  693.     return solmin;
  694.     /*
  695.     *hits++ = solmin;
  696.     *hits = solmax;
  697.     return 2;
  698.     */
  699.   }
  700.  
  701.  
  702. }
  703.  
  704. double checkcylinder(ray *r, cylinder *cylinder)
  705. {
  706.   /* fixme */
  707.   return 0;
  708. }
  709.  
  710.  
  711. double checkplane(ray *r, plane *plane)
  712. {
  713.   vector *v = &plane->a;
  714.   double t;
  715.   double i,j,k;
  716.  
  717.   i = r->v2.x - r->v1.x;
  718.   j = r->v2.y - r->v1.y;
  719.   k = r->v2.z - r->v1.z;
  720.  
  721.   t = -(v->x * r->v1.x + v->y * r->v1.y + v->z * r->v1.z - plane->b) /
  722.     (v->x * i + v->y * j + v->z * k);
  723.  
  724.   return t;
  725. }
  726.  
  727. double checktri(ray *r, triangle *tri)
  728. {
  729.   vector ed1, ed2;
  730.   vector tvec, pvec, qvec;
  731.   double det, idet, t, u, v;
  732.   vector *orig, dir;
  733.  
  734.   orig = &r->v1;
  735.   memcpy(&dir, &r->v2, sizeof(vector));
  736.   vsub(&dir, orig);
  737.  
  738.   ed1.x = tri->c.x - tri->a.x;
  739.   ed1.y = tri->c.y - tri->a.y;
  740.   ed1.z = tri->c.z - tri->a.z;
  741.   ed2.x = tri->b.x - tri->a.x;
  742.   ed2.y = tri->b.y - tri->a.y;
  743.   ed2.z = tri->b.z - tri->a.z;
  744.   vcross(&pvec, &dir, &ed2);
  745.   det = vdot(&ed1, &pvec);
  746.  
  747.   idet = 1.0 / det;
  748.  
  749.   tvec.x = orig->x;
  750.   tvec.y = orig->y;
  751.   tvec.z = orig->z;
  752.   vsub(&tvec, &tri->a);
  753.   u = vdot(&tvec, &pvec) * idet;
  754.  
  755.   if(u < 0.0) return 0;
  756.   if(u > 1.0) return 0;
  757.  
  758.   vcross(&qvec, &tvec, &ed1);
  759.   v = vdot(&dir, &qvec) * idet;
  760.  
  761.   if((v < 0.0) || (u+v > 1.0)) return 0;
  762.   
  763.   t = vdot(&ed2, &qvec) * idet;
  764.  
  765.   return t;
  766. }
  767.  
  768. double turbulence(double *point, double lofreq, double hifreq);
  769.  
  770. void transformpoint(vector *p, texture *t)
  771. {
  772.   double point[3], f;
  773.  
  774.   if((t->rotate.x != 0.0) || (t->rotate.y != 0.0) || (t->rotate.z != 0.0))
  775.     vvrotate(p, &t->rotate);
  776.   vvdiv(p, &t->scale);
  777.  
  778.   vsub(p, &t->translate);
  779.  
  780.   if((t->turbulence.x != 0.0) || (t->turbulence.y != 0.0) ||
  781.      (t->turbulence.z != 0.0)) {
  782.     point[0] = p->x;
  783.     point[1] = p->y;
  784.     point[2] = p->z;
  785.     f = turbulence(point,1,256);
  786.     p->x += t->turbulence.x * f;
  787.     p->y += t->turbulence.y * f;
  788.     p->z += t->turbulence.z * f;
  789.   }
  790.  
  791. }
  792.  
  793. void checker(vector *q, vector *col, texture *t)
  794. {
  795.   int c = 0;
  796.   vector p;
  797.  
  798.   vcopy(&p, q);
  799.   transformpoint(&p, t);
  800.  
  801.   vmul(&p, 0.25);
  802.  
  803.   p.x += 0.00001;
  804.   p.y += 0.00001;
  805.   p.z += 0.00001;
  806.  
  807.   if(p.x < 0.0) p.x = 0.5 - p.x;
  808.   if(p.y < 0.0) p.y = 0.5 - p.y;
  809.   if(p.z < 0.0) p.z = 0.5 - p.z;
  810.   
  811.   if((p.x - (int)p.x) < 0.5) c ^= 1;
  812.   if((p.y - (int)p.y) < 0.5) c ^= 1;
  813.   if((p.z - (int)p.z) < 0.5) c ^= 1;
  814.  
  815.   if(c) { vcopy(col, &t->color1); }
  816.   else  { vcopy(col, &t->color2); }
  817. }
  818.  
  819. void gradcolor(vector *col, gradient *t, double val)
  820. {
  821.   int i;
  822.   double d;
  823.   vector tmpcol;
  824.  
  825.   if(val < 0.0) val = 0.0;
  826.   if(val > 1.0) val = 1.0;
  827.   for(i = 0; i < t->numcol; i++) {
  828.     if(t->pos[i] == val) { vcopy(col, &t->color[i]); return; }
  829.     if(t->pos[i] > val) {
  830.       d = (val - t->pos[i-1]) / (t->pos[i] - t->pos[i-1]);
  831.       vcopy(&tmpcol, &t->color[i]);
  832.       vmul(&tmpcol, d);
  833.       vcopy(col, &tmpcol);
  834.       vcopy(&tmpcol, &t->color[i-1]);
  835.       vmul(&tmpcol, 1.0 - d);
  836.       vadd(col, &tmpcol);
  837.       return;
  838.     }
  839.   }
  840.   fprintf(stderr, "Error in gradient!\n");
  841.   vset(col, 0,1,0);
  842. }
  843.  
  844. void marble(vector *q, vector *col, texture *t)
  845. {
  846.   double f;
  847.   vector p;
  848.  
  849.   vcopy(&p, q);
  850.   transformpoint(&p, t);
  851.  
  852.   f = sin(p.x*4)/2 + 0.5;
  853.   f = pow(f, t->exp);
  854.  
  855.   if(t->flags & GRADIENT)
  856.     gradcolor(col, &t->gradient, f);
  857.   else
  858.     vmix(col, &t->color1, &t->color2, f);
  859. }
  860.  
  861. void lizard(vector *q, vector *col, texture *t)
  862. {
  863.   double f;
  864.   vector p;
  865.  
  866.   vcopy(&p, q);
  867.   transformpoint(&p, t);
  868.  
  869.   f = fabs(sin(p.x*4));
  870.   f += fabs(sin(p.y*4));
  871.   f += fabs(sin(p.z*4));
  872.   f /= 3.0;
  873.   f = pow(f, t->exp);
  874.  
  875.   if(t->flags & GRADIENT)
  876.     gradcolor(col, &t->gradient, f);
  877.   else
  878.     vmix(col, &t->color1, &t->color2, f);
  879.  
  880. }
  881.  
  882. void wood(vector *q, vector *col, texture *t)
  883. {
  884.   double f;
  885.   vector p;
  886.  
  887.   vcopy(&p, q);
  888.   transformpoint(&p, t);
  889.  
  890.   f = fabs(p.x);
  891.   f = f - (int)f;
  892.  
  893.   f = pow(f, t->exp);
  894.  
  895.   if(t->flags & GRADIENT)
  896.     gradcolor(col, &t->gradient, f);
  897.   else
  898.     vmix(col, &t->color1, &t->color2, f);
  899. }
  900.  
  901. void spiral(vector *q, vector *col, texture *t)
  902. {
  903.   double f;
  904.   vector p;
  905.  
  906.   vcopy(&p, q);
  907.   transformpoint(&p, t);
  908.  
  909.   f = fabs(atan2(p.x, p.z)/G_PI/2 + p.y + 99999);
  910.   f = f - (int)f;
  911.  
  912.   f = pow(f, t->exp);
  913.  
  914.   if(t->flags & GRADIENT)
  915.     gradcolor(col, &t->gradient, f);
  916.   else
  917.     vmix(col, &t->color1, &t->color2, f);
  918. }
  919.  
  920. void spots(vector *q, vector *col, texture *t)
  921. {
  922.   double f;
  923.   vector p, r;
  924.  
  925.   vcopy(&p, q);
  926.   transformpoint(&p, t);
  927.  
  928.   p.x += 10000.0;
  929.   p.y += 10000.0;
  930.   p.z += 10000.0;
  931.  
  932.   vset(&r, (int)(p.x+0.5), (int)(p.y+0.5), (int)(p.z+0.5));
  933.   f = vdist(&p,&r);
  934.   f = cos(f*G_PI);
  935.   if(f < 0.0) f = 0.0;
  936.   else if(f > 1.0) f = 1.0;
  937.   f = pow(f, t->exp);
  938.  
  939.   if(t->flags & GRADIENT)
  940.     gradcolor(col, &t->gradient, f);
  941.   else
  942.     vmix(col, &t->color1, &t->color2, f);
  943. }
  944.  
  945. void perlin(vector *q, vector *col, texture *t)
  946. {
  947.   double f, point[3];
  948.   vector p;
  949.  
  950.   vcopy(&p, q);
  951.   transformpoint(&p, t);
  952.  
  953.   point[0] = p.x;
  954.   point[1] = p.y;
  955.   point[2] = p.z;
  956.  
  957.   f = turbulence(point,1,256)*0.3 + 0.5;
  958.  
  959.   f = pow(f, t->exp);
  960.  
  961.   if(t->flags & GRADIENT)
  962.     gradcolor(col, &t->gradient, f);
  963.   else
  964.     vmix(col, &t->color1, &t->color2, f);
  965. }
  966.  
  967. void imagepixel(vector *q, vector *col, texture *t)
  968. {
  969.   vector p;
  970.   int x,y;
  971.   unsigned char *rgb;
  972.  
  973.   vcopy(&p, q);
  974.   transformpoint(&p, t);
  975.  
  976.   x = (p.x * t->image.xsize);
  977.   y = (p.y * t->image.ysize);
  978.  
  979.   x = (x % t->image.xsize + t->image.xsize) % t->image.xsize;
  980.   y = (y % t->image.ysize + t->image.ysize) % t->image.ysize;
  981.  
  982.   rgb = &t->image.rgb[x*3 + (t->image.ysize-1-y)*t->image.xsize*3];
  983.   vset(col, rgb[0] / 255.0, rgb[1] / 255.0, rgb[2] / 255.0);
  984. }
  985.  
  986. double frand(double v)
  987. {
  988.   return (RAND_FUNC() / (double) G_MAXRAND - 0.5) * v;
  989. }
  990.  
  991. int traceray(ray *r, vector *col, int level, double imp);
  992.  
  993. void objcolor(vector *col, vector *p, common *obj)
  994. {
  995.   int i;
  996.   texture *t;
  997.   vector tmpcol;
  998.  
  999.   vcset(col, 0,0,0,0);
  1000.  
  1001.   for(i = 0; i < obj->numtexture; i++) {
  1002.     t = &obj->texture[i];
  1003.  
  1004.     if(world.quality < 1) {
  1005.       vadd(col, &t->color1);
  1006.       continue;
  1007.     }
  1008.  
  1009.     vset(&tmpcol, 0,0,0);
  1010.     switch(t->type) {
  1011.     case SOLID:
  1012.       vcopy(&tmpcol, &t->color1);
  1013.       break;
  1014.     case CHECKER:
  1015.       checker(p, &tmpcol, t);
  1016.       break;
  1017.     case MARBLE:
  1018.       marble(p, &tmpcol, t);
  1019.       break;
  1020.     case LIZARD:
  1021.       lizard(p, &tmpcol, t);
  1022.       break;
  1023.     case PERLIN:
  1024.       perlin(p, &tmpcol, t);
  1025.       break;
  1026.     case WOOD:
  1027.       wood(p, &tmpcol, t);
  1028.       break;
  1029.     case SPIRAL:
  1030.       spiral(p, &tmpcol, t);
  1031.       break;
  1032.     case SPOTS:
  1033.       spots(p, &tmpcol, t);
  1034.       break;
  1035.     case IMAGE:
  1036.       imagepixel(p, &tmpcol, t);
  1037.       break;
  1038.     case PHONG:
  1039.     case REFRACTION:
  1040.     case REFLECTION:
  1041.     case TRANSPARENT:
  1042.     case SMOKE:
  1043.       /* Silently ignore non-color textures */
  1044.       continue;
  1045.       break;
  1046.     default:
  1047.       fprintf(stderr, "Warning: unknown texture %d\n", t->type);
  1048.       break;
  1049.     }
  1050.     vmul(&tmpcol, t->amount);
  1051.     vadd(col, &tmpcol);
  1052.   }
  1053.   if(!i) {
  1054.     fprintf(stderr, "Warning: object %p has no textures\n", obj);
  1055.   }
  1056.  
  1057. }
  1058.  
  1059. void objnormal(vector *res, common *obj, vector *p)
  1060. {
  1061.   int i;
  1062.  
  1063.   switch(obj->type) {
  1064.   case TRIANGLE:
  1065.     trianglenormal(res, NULL, (triangle *)obj);
  1066.     break;
  1067.   case DISC:
  1068.     vcopy(res, &((disc *)obj)->a);
  1069.     break;
  1070.   case PLANE:
  1071.     vcopy(res, &((plane *)obj)->a);
  1072.     break;
  1073.   case SPHERE:
  1074.     vcopy(res, &((sphere *)obj)->a);
  1075.     vsub(res, p);
  1076.     break;
  1077.   case CYLINDER:
  1078.     vset(res, 1,1,1); /* fixme */
  1079.     break;
  1080.   default:
  1081.     fprintf(stderr, "objnormal(): Unsupported object type!?\n");
  1082.     exit(0);
  1083.   }
  1084.   vnorm(res, 1.0);
  1085.  
  1086.   for(i = 0; i < obj->numnormal; i++) {
  1087.     int k;
  1088.     vector tmpcol[6];
  1089.     vector q[6], nres;
  1090.     texture *t = &obj->normal[i];
  1091.     double nstep = 0.1;
  1092.  
  1093.     vset(&nres, 0,0,0);
  1094.     for(k = 0; k < 6; k++) {
  1095.       vcopy(&q[k], p);
  1096.     }
  1097.     q[0].x += nstep;
  1098.     q[1].x -= nstep;
  1099.     q[2].y += nstep;
  1100.     q[3].y -= nstep;
  1101.     q[4].z += nstep;
  1102.     q[5].z -= nstep;
  1103.  
  1104.     switch(t->type) {
  1105.     case MARBLE:
  1106.       for(k = 0; k < 6; k++)
  1107.     marble(&q[k], &tmpcol[k], t);
  1108.       break;
  1109.     case LIZARD:
  1110.       for(k = 0; k < 6; k++)
  1111.     lizard(&q[k], &tmpcol[k], t);
  1112.       break;
  1113.     case PERLIN:
  1114.       for(k = 0; k < 6; k++)
  1115.     perlin(&q[k], &tmpcol[k], t);
  1116.       break;
  1117.     case WOOD:
  1118.       for(k = 0; k < 6; k++)
  1119.     wood(&q[k], &tmpcol[k], t);
  1120.       break;
  1121.     case SPIRAL:
  1122.       for(k = 0; k < 6; k++)
  1123.     spiral(&q[k], &tmpcol[k], t);
  1124.       break;
  1125.     case SPOTS:
  1126.       for(k = 0; k < 6; k++)
  1127.     spots(&q[k], &tmpcol[k], t);
  1128.       break;
  1129.     case IMAGE:
  1130.       for(k = 0; k < 6; k++)
  1131.     imagepixel(&q[k], &tmpcol[k], t);
  1132.       break;
  1133.     case CHECKER:
  1134.     case SOLID:
  1135.     case PHONG:
  1136.     case REFRACTION:
  1137.     case REFLECTION:
  1138.     case TRANSPARENT:
  1139.     case SMOKE:
  1140.       continue;
  1141.       break;
  1142.     default:
  1143.       fprintf(stderr, "Warning: unknown texture %d\n", t->type);
  1144.       break;
  1145.     }
  1146.  
  1147.     nres.x = tmpcol[0].x - tmpcol[1].x;
  1148.     nres.y = tmpcol[2].x - tmpcol[3].x;
  1149.     nres.z = tmpcol[4].x - tmpcol[5].x;
  1150.     vadd(&nres, res);
  1151.     vnorm(&nres, 1.0);
  1152.     vmul(&nres, t->amount);
  1153.     vadd(res, &nres);
  1154.     vnorm(res, 1.0);
  1155.   }
  1156. }
  1157.  
  1158. /* 
  1159.    Quality:
  1160.    0 = Color only
  1161.    1 = Textures
  1162.    2 = Light + Normals
  1163.    3 = Shadows
  1164.    4 = Phong
  1165.    5 = Reflection + Refraction
  1166.  */
  1167.  
  1168. void calclight(vector *col, vector *point, common *obj)
  1169. {
  1170.   int i, j, o;
  1171.   ray r;
  1172.   double d, b, a;
  1173.   vector lcol;
  1174.   vector norm;
  1175.   vector pcol;
  1176.  
  1177.   vcset(col, 0,0,0,0);
  1178.  
  1179.   objcolor(&pcol, point, obj);
  1180.   a = pcol.w;
  1181.  
  1182.   if(world.quality < 2) {
  1183.     vcopy(col, &pcol);
  1184.     return;
  1185.   }
  1186.  
  1187.   for(i = 0; i < obj->numtexture; i++) {
  1188.     if(obj->texture[i].type == PHONG) continue;
  1189.     if(obj->texture[i].type == REFLECTION) continue;
  1190.     if(obj->texture[i].type == REFRACTION) continue;
  1191.     if(obj->texture[i].type == TRANSPARENT) continue;
  1192.     if(obj->texture[i].type == SMOKE) continue;
  1193.     vcopy(&lcol, &pcol);
  1194.     vvmul(&lcol, &obj->texture[i].ambient);
  1195.     vadd(col, &lcol);
  1196.   }
  1197.  
  1198.   objnormal(&norm, obj, point);
  1199.   vnorm(&norm, 1.0);
  1200.  
  1201.   r.inside = -1;
  1202.   r.ior = 1.0;
  1203.  
  1204.   for(i = 0; i < world.numlight; i++) {
  1205.     vcopy(&r.v1, point);
  1206.     vcopy(&r.v2, &world.light[i].a);
  1207.     vmix(&r.v1, &r.v1, &r.v2, 0.9999);
  1208.     d = vdist(&r.v1, &r.v2);
  1209.  
  1210.     vsub(&r.v1, &r.v2);
  1211.     vnorm(&r.v1, 1.0);
  1212.     b = vdot(&r.v1, &norm);
  1213.  
  1214.     if(b < 0.0) continue;
  1215.  
  1216.     for(j = 0; j < obj->numtexture; j++) {
  1217.       if(obj->texture[j].type == PHONG) continue;
  1218.       if(obj->texture[j].type == REFLECTION) continue;
  1219.       if(obj->texture[j].type == REFRACTION) continue;
  1220.       if(obj->texture[j].type == TRANSPARENT) continue;
  1221.       if(obj->texture[j].type == SMOKE) continue;
  1222.       vcopy(&lcol, &pcol);
  1223.       vvmul(&lcol, &world.light[i].color);
  1224.       vvmul(&lcol, &obj->texture[j].diffuse);
  1225.       vmul(&lcol, b);
  1226.       vadd(col, &lcol);
  1227.     }
  1228.   }
  1229.   col->w = a;
  1230. }
  1231.  
  1232. void calcphong(common *obj, ray *r2, vector *col)
  1233. {
  1234.   int i, j, o;
  1235.   ray r;
  1236.   double d, b;
  1237.   vector lcol;
  1238.   vector norm;
  1239.   vector pcol;
  1240.   double ps;
  1241.  
  1242.   vcopy(&pcol, col);
  1243.  
  1244.   vcopy(&norm, &r2->v2);
  1245.   vsub(&norm, &r2->v1);
  1246.   vnorm(&norm, 1.0);
  1247.  
  1248.   r.inside = -1;
  1249.   r.ior = 1.0;
  1250.  
  1251.   for(i = 0; i < world.numlight; i++) {
  1252.     vcopy(&r.v1, &r2->v1);
  1253.     vcopy(&r.v2, &world.light[i].a);
  1254.     vmix(&r.v1, &r.v1, &r.v2, 0.9999);
  1255.     d = vdist(&r.v1, &r.v2);
  1256.  
  1257.     o = traceray(&r, NULL, -1, 1.0);
  1258.     if(o) {
  1259.       continue;
  1260.     }
  1261.  
  1262.     /* OK, light is visible */
  1263.  
  1264.     vsub(&r.v1, &r.v2);
  1265.     vnorm(&r.v1, 1.0);
  1266.     b = -vdot(&r.v1, &norm);
  1267.     
  1268.     for(j = 0; j < obj->numtexture; j++) {
  1269.       if(obj->texture[j].type != PHONG) continue;
  1270.  
  1271.       ps = obj->texture[j].phongsize;
  1272.  
  1273.       if(b < (1-ps)) continue;
  1274.       ps = (b-(1-ps))/ps;
  1275.  
  1276.       vcopy(&lcol, &obj->texture[j].phongcolor);
  1277.       vvmul(&lcol, &world.light[i].color);
  1278.       vmul(&lcol, ps);
  1279.       vadd(col, &lcol);
  1280.     }
  1281.   }
  1282. }
  1283.  
  1284. int traceray(ray *r, vector *col, int level, double imp)
  1285. {
  1286.   int i, b = -1;
  1287.   double t = -1.0, min = 0.0;
  1288.   int type = -1;
  1289.   common *obj, *bobj = NULL;
  1290.   int hits = 0;
  1291.   vector p;
  1292.  
  1293.   if((level == 0) || (imp < 0.005)) {
  1294.     vset(col, 0,1,0);
  1295.     return 0;
  1296.   }
  1297.  
  1298.   for(i = 0; i < world.numobj; i++) {
  1299.     obj = (common *)&world.obj[i];
  1300.     switch(obj->type) {
  1301.     case TRIANGLE:
  1302.       t = checktri(r, (triangle *)&world.obj[i]);
  1303.       break;
  1304.     case DISC:
  1305.       t = checkdisc(r, (disc *)&world.obj[i]);
  1306.       break;
  1307.     case PLANE:
  1308.       t = checkplane(r, (plane *)&world.obj[i]);
  1309.       break;
  1310.     case SPHERE:
  1311.       t = checksphere(r, (sphere *)&world.obj[i]);
  1312.       break;
  1313.     case CYLINDER:
  1314.       t = checkcylinder(r, (cylinder *)&world.obj[i]);
  1315.       break;
  1316.     default:
  1317.       fprintf(stderr, "Illegal object!!\n");
  1318.       exit(0);
  1319.     }
  1320.     if(t <= 0.0) continue;
  1321.  
  1322.     if(!(obj->flags & NOSHADOW) && (level == -1)) {
  1323.       return i+1;
  1324.     }
  1325.  
  1326.     hits++;
  1327.     if((!bobj) || (t < min)) {
  1328.  
  1329.       min = t;
  1330.       b = i;
  1331.       type = obj->type;
  1332.       bobj = obj;
  1333.     }
  1334.   }
  1335.   if(level == -1) return 0;
  1336.  
  1337.   if(bobj) {
  1338.     p.x = r->v1.x + (r->v2.x - r->v1.x) * min;
  1339.     p.y = r->v1.y + (r->v2.y - r->v1.y) * min;
  1340.     p.z = r->v1.z + (r->v2.z - r->v1.z) * min;
  1341.  
  1342.     calclight(col, &p, bobj);
  1343.  
  1344.     if(world.flags & SMARTAMBIENT) {
  1345.       double ambient = 0.3 * exp(-min/world.smartambient);
  1346.       vector lcol;
  1347.       objcolor(&lcol, &p, bobj);
  1348.       vmul(&lcol, ambient);
  1349.       vadd(col, &lcol);
  1350.     }
  1351.  
  1352.     for(i = 0; i < bobj->numtexture; i++) {
  1353.       
  1354.       if((world.quality >= 4) && ((bobj->texture[i].type == REFLECTION) || (bobj->texture[i].type == PHONG))) {
  1355.  
  1356.     vector refcol, norm, ocol;
  1357.     ray ref;
  1358.  
  1359.     objcolor(&ocol, &p, bobj);
  1360.  
  1361.     vcopy(&ref.v1, &p);
  1362.     vcopy(&ref.v2, &r->v1);
  1363.     ref.inside = r->inside;
  1364.     ref.ior = r->ior;
  1365.  
  1366.     vmix(&ref.v1, &ref.v1, &ref.v2, 0.9999); /* push it a tad */
  1367.  
  1368.     vsub(&ref.v2, &p);
  1369.     objnormal(&norm, bobj, &p);
  1370.     vnorm(&norm, 1.0);
  1371.     vrotate(&norm, 180.0, &ref.v2);
  1372.  
  1373.     vmul(&norm, -0.0001); /* push it a tad */
  1374.     vadd(&ref.v1, &norm);
  1375.  
  1376.     vnorm(&ref.v2, 1.0);
  1377.     vadd(&ref.v2, &p);
  1378.  
  1379.     if((world.quality >= 5) && (bobj->texture[i].type == REFLECTION)) {
  1380.       traceray(&ref, &refcol, level - 1, imp * vmax(&bobj->texture[i].reflection));
  1381.       vvmul(&refcol, &bobj->texture[i].reflection);
  1382.       refcol.w = ocol.w;
  1383.       vadd(col, &refcol);
  1384.     }
  1385.     if(bobj->texture[i].type == PHONG) {
  1386.       vcset(&refcol,0,0,0,0);
  1387.       calcphong(bobj, &ref, &refcol);
  1388.       refcol.w = ocol.w;
  1389.       vadd(col, &refcol);
  1390.     }
  1391.  
  1392.       }
  1393.  
  1394.       if((world.quality >= 5) && (col->w < 1.0)) {
  1395.     vector refcol;
  1396.     ray ref;
  1397.  
  1398.     vcopy(&ref.v1, &p);
  1399.     vcopy(&ref.v2, &p);
  1400.     vsub(&ref.v2, &r->v1);
  1401.     vnorm(&ref.v2, 1.0);
  1402.     vadd(&ref.v2, &p);
  1403.  
  1404.     vmix(&ref.v1, &ref.v1, &ref.v2, 0.999); /* push it a tad */
  1405.     traceray(&ref, &refcol, level - 1, imp * (1.0 - col->w));
  1406.     vmul(&refcol, (1.0 - col->w));
  1407.     vadd(col, &refcol);
  1408.       }
  1409.  
  1410.       if((world.quality >= 5) && (bobj->texture[i].type == TRANSPARENT)) {
  1411.     vector refcol;
  1412.     ray ref;
  1413.  
  1414.     vcopy(&ref.v1, &p);
  1415.     vcopy(&ref.v2, &p);
  1416.     vsub(&ref.v2, &r->v1);
  1417.     vnorm(&ref.v2, 1.0);
  1418.     vadd(&ref.v2, &p);
  1419.  
  1420.     vmix(&ref.v1, &ref.v1, &ref.v2, 0.999); /* push it a tad */
  1421.  
  1422.     traceray(&ref, &refcol, level - 1, imp * vmax(&bobj->texture[i].transparent));
  1423.     vvmul(&refcol, &bobj->texture[i].transparent);
  1424.  
  1425.     vadd(col, &refcol);
  1426.       }
  1427.  
  1428.       if((world.quality >= 5) && (bobj->texture[i].type == SMOKE)) {
  1429.     vector smcol, raydir, norm;
  1430.     double tran;
  1431.     ray ref;
  1432.  
  1433.     vcopy(&ref.v1, &p);
  1434.     vcopy(&ref.v2, &p);
  1435.     vsub(&ref.v2, &r->v1);
  1436.     vnorm(&ref.v2, 1.0);
  1437.     vadd(&ref.v2, &p);
  1438.  
  1439.     objnormal(&norm, bobj, &p);
  1440.     vcopy(&raydir, &r->v2);
  1441.     vsub(&raydir, &r->v1);
  1442.     vnorm(&raydir, 1.0);
  1443.     tran = vdot(&norm, &raydir);
  1444.     if(tran < 0.0) continue;
  1445.     tran *= tran;
  1446.     vcopy(&smcol, &bobj->texture[i].color1);
  1447.     vmul(&smcol, tran);
  1448.     vadd(col, &smcol);
  1449.       }
  1450.  
  1451.       if((world.quality >= 5) && (bobj->texture[i].type == REFRACTION)) {
  1452.     vector refcol, norm, tmpv;
  1453.     ray ref;
  1454.     double c1, c2, n1, n2, n;
  1455.  
  1456.     vcopy(&ref.v1, &p);
  1457.     vcopy(&ref.v2, &p);
  1458.     vsub(&ref.v2, &r->v1);
  1459.     vadd(&ref.v2, &r->v2);
  1460.  
  1461.     vmix(&ref.v1, &ref.v1, &ref.v2, 0.999); /* push it a tad */
  1462.  
  1463.     vsub(&ref.v2, &p);
  1464.     objnormal(&norm, bobj, &p);
  1465.  
  1466.     if(r->inside == b) {
  1467.       ref.inside = -1;
  1468.       ref.ior = 1.0;
  1469.     } else {
  1470.       ref.inside = b;
  1471.       ref.ior = bobj->texture[i].ior;
  1472.     }
  1473.  
  1474.     c1 = vdot(&norm, &ref.v2);
  1475.  
  1476.     if(ref.inside < 0) c1 = -c1;
  1477.     
  1478.     n1 = r->ior;   /* IOR of current media  */
  1479.     n2 = ref.ior;  /* IOR of new media  */
  1480.     n = n1 / n2;
  1481.     c2 = 1.0 - n*n * (1.0 - c1*c1);
  1482.  
  1483.     if(c2 < 0.0) {
  1484.       /* FIXME: Internal reflection should occur */
  1485.       c2 = sqrt(-c2);
  1486.  
  1487.     } else {
  1488.       c2 = sqrt(c2);
  1489.     }
  1490.  
  1491.     vmul(&ref.v2, n);
  1492.     vcopy(&tmpv, &norm);
  1493.     vmul(&tmpv, n * c1 - c2);
  1494.     vadd(&ref.v2, &tmpv);
  1495.  
  1496.     vnorm(&ref.v2, 1.0);
  1497.     vadd(&ref.v2, &p);
  1498.  
  1499.     traceray(&ref, &refcol, level - 1, imp * vmax(&bobj->texture[i].refraction));
  1500.  
  1501.     vvmul(&refcol, &bobj->texture[i].refraction);
  1502.     vadd(col, &refcol);
  1503.       }
  1504.     }
  1505.   } else {
  1506.     vcset(col, 0,0,0,0);
  1507.     min = 10000.0;
  1508.     vcset(&p,0,0,0,0);
  1509.   }
  1510.  
  1511.   for(i = 0; i < world.numatmos; i++) {
  1512.     vector tmpcol;
  1513.     if(world.atmos[i].type == FOG) {
  1514.       double v, pt[3];
  1515.       pt[0] = p.x; pt[1] = p.y; pt[2] = p.z;
  1516.       if((v = world.atmos[i].turbulence) > 0.0)
  1517.     v = turbulence(pt,1,256) * world.atmos[i].turbulence;
  1518.       v = exp(-(min+v) / world.atmos[i].density);
  1519.       vmul(col, v);
  1520.       vcopy(&tmpcol, &world.atmos[i].color);
  1521.       vmul(&tmpcol, 1.0 - v);
  1522.       vadd(col, &tmpcol);
  1523.     }
  1524.   }
  1525.  
  1526.   return hits;
  1527. }
  1528.  
  1529. void setdefaults(texture *t)
  1530. {
  1531.   memset(t, 0, sizeof(texture));
  1532.   t->type = SOLID;
  1533.   vcset(&t->color1, 1,1,1,1);
  1534.   vcset(&t->color2, 0,0,0,1);
  1535.   vcset(&t->diffuse, 1,1,1,1);
  1536.   vcset(&t->ambient, 0,0,0,1);
  1537.   vset(&t->scale,1,1,1);
  1538.   vset(&t->rotate,0,0,0);
  1539.   vset(&t->translate,0,0,0);
  1540.   t->oscale = 1.0;
  1541.   t->amount = 1.0;
  1542.   t->exp = 1.0;
  1543. }
  1544.  
  1545. char *mklabel(texture *t)
  1546. {
  1547.   struct textures_t *l;
  1548.   static char tmps[100];
  1549.   if(t->majtype == 0) strcpy(tmps, _("Texture"));
  1550.   else if(t->majtype == 1) strcpy(tmps, _("Bumpmap"));
  1551.   else if(t->majtype == 2) strcpy(tmps, _("Light"));
  1552.   else strcpy(tmps, _("(unknown!?)"));
  1553.   if((t->majtype == 0) || (t->majtype == 1)) {
  1554.     strcat(tmps, " / ");
  1555.     l = textures;
  1556.     while(l->s) {
  1557.       if(t->type == l->n) {
  1558.     strcat(tmps, gettext(l->s));
  1559.     break;
  1560.     }
  1561.       l++;
  1562.     }
  1563.   }
  1564.   return tmps;
  1565. }
  1566.  
  1567. GtkWidget *currentitem(GtkWidget *list)
  1568. {
  1569.   GList *h;
  1570.   GtkWidget *tmpw;
  1571.   h = GTK_LIST(list)->selection;
  1572.   if(!h) return NULL;
  1573.   tmpw = h->data;
  1574.   return tmpw;
  1575. }
  1576.  
  1577. texture *currenttexture(void)
  1578. {
  1579.   GtkWidget *tmpw;
  1580.   texture *t;
  1581.   tmpw = currentitem(texturelist);
  1582.   if(!tmpw) return NULL;
  1583.   t = gtk_object_get_data(GTK_OBJECT(tmpw), "texture");
  1584.   return t;
  1585. }
  1586.  
  1587. void relabel(void)
  1588. {
  1589.   GtkWidget *tmpw = currentitem(texturelist);
  1590.   texture *t = currenttexture();
  1591.   if(!tmpw || !t) return;
  1592.   tmpw = GTK_BIN(tmpw)->child;
  1593.   gtk_label_set_text(GTK_LABEL(tmpw), mklabel(t));
  1594. }
  1595.  
  1596. int noupdate = 0;
  1597.  
  1598. void setvals(texture *t)
  1599. {
  1600.   struct textures_t *l;
  1601.  
  1602.   if(!t) return;
  1603.  
  1604.   noupdate = 1;
  1605.   gtk_adjustment_set_value(GTK_ADJUSTMENT(amountscale), t->amount);
  1606.  
  1607.   gtk_adjustment_set_value(GTK_ADJUSTMENT(scalescale), t->oscale);
  1608.  
  1609.   gtk_adjustment_set_value(GTK_ADJUSTMENT(scalexscale), t->scale.x);
  1610.   gtk_adjustment_set_value(GTK_ADJUSTMENT(scaleyscale), t->scale.y);
  1611.   gtk_adjustment_set_value(GTK_ADJUSTMENT(scalezscale), t->scale.z);
  1612.  
  1613.   gtk_adjustment_set_value(GTK_ADJUSTMENT(rotxscale), t->rotate.x);
  1614.   gtk_adjustment_set_value(GTK_ADJUSTMENT(rotyscale), t->rotate.y);
  1615.   gtk_adjustment_set_value(GTK_ADJUSTMENT(rotzscale), t->rotate.z);
  1616.  
  1617.   gtk_adjustment_set_value(GTK_ADJUSTMENT(posxscale), t->translate.x);
  1618.   gtk_adjustment_set_value(GTK_ADJUSTMENT(posyscale), t->translate.y);
  1619.   gtk_adjustment_set_value(GTK_ADJUSTMENT(poszscale), t->translate.z);
  1620.  
  1621.   gtk_adjustment_set_value(GTK_ADJUSTMENT(turbulencescale), t->turbulence.x);
  1622.   gtk_adjustment_set_value(GTK_ADJUSTMENT(expscale), t->exp);
  1623.  
  1624.   drawcolor1(NULL);
  1625.   drawcolor2(NULL);
  1626.  
  1627.   l = textures;
  1628.   while(l->s) {
  1629.     if(l->n == t->type) {
  1630.       gtk_option_menu_set_history(GTK_OPTION_MENU(texturemenu), l->index);
  1631.       break;
  1632.     }
  1633.     l++;
  1634.   }
  1635.   gtk_option_menu_set_history(GTK_OPTION_MENU(typemenu), t->majtype);
  1636.  
  1637.   noupdate = 0;
  1638. }
  1639.  
  1640.  
  1641. void selectitem(GtkWidget *wg, GtkWidget *p)
  1642. {
  1643.   setvals(currenttexture());
  1644. }
  1645.  
  1646. void addtexture(void)
  1647. {
  1648.   GtkWidget *item;
  1649.   int n = s.com.numtexture;
  1650.  
  1651.   if(n == MAXTEXTUREPEROBJ-1) return;
  1652.  
  1653.   setdefaults(&s.com.texture[n]);
  1654.  
  1655.   item = gtk_list_item_new_with_label(mklabel(&s.com.texture[n]));
  1656.   gtk_object_set_data (GTK_OBJECT(item), "texture", &s.com.texture[n]);
  1657.   gtk_container_add(GTK_CONTAINER(texturelist), item);
  1658.   gtk_widget_show(item);
  1659.  
  1660.   gtk_list_select_child(GTK_LIST(texturelist), item);
  1661.  
  1662.   s.com.numtexture++;
  1663.   restartrender();
  1664. }
  1665.  
  1666. void duptexture(void)
  1667. {
  1668.   GtkWidget *item;
  1669.   texture *t = currenttexture();
  1670.   int n = s.com.numtexture;
  1671.  
  1672.   if(n == MAXTEXTUREPEROBJ-1) return;
  1673.   if(!t) return;
  1674.  
  1675.   memcpy(&s.com.texture[n], t, sizeof(texture));
  1676.  
  1677.   item = gtk_list_item_new_with_label(mklabel(&s.com.texture[n]));
  1678.   gtk_object_set_data (GTK_OBJECT(item), "texture", &s.com.texture[n]);
  1679.   gtk_container_add(GTK_CONTAINER(texturelist), item);
  1680.   gtk_widget_show(item);
  1681.  
  1682.   gtk_list_select_child(GTK_LIST(texturelist), item);
  1683.  
  1684.   s.com.numtexture++;
  1685.   restartrender();
  1686. }
  1687.  
  1688. void rebuildlist(void)
  1689. {
  1690.   GtkWidget *item;
  1691.   int n;
  1692.  
  1693.   for(n = 0; n < s.com.numtexture; n++) {
  1694.     if(s.com.numtexture && (s.com.texture[n].majtype < 0)) {
  1695.       int i;
  1696.       for(i = n; i < s.com.numtexture-1; i++)
  1697.     memcpy(&s.com.texture[i],&s.com.texture[i+1],sizeof(texture));
  1698.       s.com.numtexture--;
  1699.       n--;
  1700.     }
  1701.   }
  1702.  
  1703.   for(n = 0; n < s.com.numtexture; n++) {
  1704.     item = gtk_list_item_new_with_label(mklabel(&s.com.texture[n]));
  1705.     gtk_object_set_data (GTK_OBJECT(item), "texture", &s.com.texture[n]);
  1706.     gtk_container_add(GTK_CONTAINER(texturelist), item);
  1707.     gtk_widget_show(item);
  1708.   }
  1709.   restartrender();
  1710. }
  1711.  
  1712. void sphere_reset(void)
  1713. {
  1714.   s.com.numtexture = 3;
  1715.  
  1716.   setdefaults(&s.com.texture[0]);
  1717.   setdefaults(&s.com.texture[1]);
  1718.   setdefaults(&s.com.texture[2]);
  1719.  
  1720.   s.com.texture[1].majtype = 2;
  1721.   vset(&s.com.texture[1].color1, 1,1,1);
  1722.   vset(&s.com.texture[1].translate, -15,-15,-15);
  1723.  
  1724.   s.com.texture[2].majtype = 2;
  1725.   vset(&s.com.texture[2].color1, 0,0.4,0.4);
  1726.   vset(&s.com.texture[2].translate, 15,15,-15);
  1727.  
  1728.   gtk_list_clear_items(GTK_LIST(texturelist), 0, -1);
  1729.   rebuildlist();
  1730.   restartrender();
  1731. }
  1732.  
  1733. void deltexture(void)
  1734. {
  1735.   texture *t;
  1736.   GtkWidget *tmpw;
  1737.   tmpw = currentitem(texturelist);
  1738.   if(!tmpw) return;
  1739.   t = currenttexture();
  1740.   if(!t) return;
  1741.   t->majtype = -1;
  1742.   gtk_widget_destroy(tmpw);
  1743. }
  1744.  
  1745. void loadit(char *fn)
  1746. {
  1747.   FILE *f;
  1748.   char line[1024];
  1749.   int i;
  1750.   texture *t;
  1751.  
  1752.   s.com.numtexture = 0;
  1753.  
  1754.   f = fopen(fn, "rt");
  1755.   while(!feof(f)) {
  1756.     if(!fgets(line, 1023, f)) break;
  1757.     i = s.com.numtexture;
  1758.     t = &s.com.texture[i];
  1759.     setdefaults(t);
  1760.     sscanf(line, "%d %d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n",
  1761.        &t->majtype, &t->type,
  1762.        &t->color1.x,&t->color1.y,&t->color1.z,&t->color1.w,
  1763.        &t->color2.x,&t->color2.y,&t->color2.z,&t->color2.w,
  1764.        &t->oscale, &t->turbulence.x, &t->amount, &t->exp,
  1765.        &t->scale.x,&t->scale.y,&t->scale.z,
  1766.        &t->rotate.x,&t->rotate.y,&t->rotate.z,
  1767.        &t->translate.x,&t->translate.y,&t->translate.z);
  1768.     s.com.numtexture++;
  1769.   }
  1770.   fclose(f);
  1771. }
  1772.  
  1773. void loadpreset_ok(GtkWidget *w, GtkFileSelection *fs)
  1774. {
  1775.   char *fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs));
  1776.   gtk_widget_hide(GTK_WIDGET(fs));
  1777.   gtk_list_clear_items(GTK_LIST(texturelist), 0, -1);
  1778.   loadit(fn);
  1779.   rebuildlist();
  1780.   restartrender();
  1781. }
  1782.  
  1783. void saveit(char *fn)
  1784. {
  1785.   int i;
  1786.   FILE *f;
  1787.  
  1788.   f = fopen(fn, "wt");
  1789.   for(i = 0; i < s.com.numtexture; i++) {
  1790.     texture *t = &s.com.texture[i];
  1791.     if(t->majtype < 0) continue;
  1792.     fprintf(f, "%d %d %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n",
  1793.         t->majtype, t->type,
  1794.         t->color1.x,t->color1.y,t->color1.z,t->color1.w,
  1795.         t->color2.x,t->color2.y,t->color2.z,t->color2.w,
  1796.         t->oscale, t->turbulence.x, t->amount, t->exp,
  1797.         t->scale.x,t->scale.y,t->scale.z,
  1798.         t->rotate.x,t->rotate.y,t->rotate.z,
  1799.         t->translate.x,t->translate.y,t->translate.z);
  1800.   }
  1801.   fclose(f);
  1802.  
  1803. }
  1804.  
  1805. void savepreset_ok(GtkWidget *w, GtkFileSelection *fs)
  1806. {
  1807.   char *fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs));
  1808.   gtk_widget_hide(GTK_WIDGET(fs));
  1809.   saveit(fn);
  1810. }
  1811.  
  1812. void loadpreset(void)
  1813. {
  1814.   fileselect(0);
  1815. }
  1816.  
  1817. void savepreset(void)
  1818. {
  1819.   fileselect(1);
  1820. }
  1821.  
  1822. void fileselect(int action)
  1823. {
  1824.   static GtkWidget *windows[2] = {NULL,NULL};
  1825.  
  1826.   char *titles[] = { N_("Open file"), N_("Save file") };
  1827.   void *handlers[] = { loadpreset_ok, savepreset_ok };
  1828.  
  1829.   if(!windows[action]) {
  1830.     windows[action] = gtk_file_selection_new( gettext(titles[action]));
  1831.     gtk_window_set_position (GTK_WINDOW (windows[action]), GTK_WIN_POS_MOUSE);
  1832.     
  1833.     gtk_signal_connect (GTK_OBJECT (windows[action]), "destroy",
  1834.             GTK_SIGNAL_FUNC(gtk_widget_destroy),
  1835.                         &windows[action]);
  1836.     gtk_signal_connect (GTK_OBJECT (windows[action]), "delete_event",
  1837.             GTK_SIGNAL_FUNC(gtk_widget_hide),
  1838.                         &windows[action]);
  1839.  
  1840.     gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (windows[action])->ok_button),
  1841.                         "clicked", GTK_SIGNAL_FUNC(handlers[action]),
  1842.                         windows[action]);
  1843.     gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION (windows[action])->cancel_button),
  1844.                               "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy),
  1845.                               GTK_OBJECT (windows[action]));
  1846.  
  1847.     gimp_help_connect_help_accel (windows[action], gimp_standard_help_func,
  1848.                   "filters/spheredesigner.html");
  1849.   }
  1850.   gtk_widget_show (windows[action]);
  1851. }
  1852.  
  1853. void initworld(void)
  1854. {
  1855.   int i;
  1856.  
  1857.   memset(&world, 0, sizeof(world));
  1858.  
  1859.   s.com.type = SPHERE;
  1860.   s.a.x = s.a.y = s.a.z = 0.0;
  1861.   s.r = 4.0;
  1862.  
  1863.   memcpy(&world.obj[0], &s, sizeof(s));
  1864.   world.numobj = 1;
  1865.  
  1866.   world.obj[0].com.numtexture = 0;
  1867.   world.obj[0].com.numnormal = 0;
  1868.   
  1869.   for(i = 0; i < s.com.numtexture; i++) {
  1870.     common *c = &s.com;
  1871.     common *d = &world.obj[0].com;
  1872.     texture *t = &c->texture[i];
  1873.     if((t->amount <= 0.0) || (t->majtype < 0)) continue;
  1874.     if(t->majtype == 0) { /* Normal texture */
  1875.       if(t->type == PHONG) {
  1876.     memcpy(&t->phongcolor, &t->color1, sizeof(t->color1));
  1877.     t->phongsize = t->oscale / 25.0;
  1878.       }
  1879.       memcpy(&d->texture[d->numtexture],t,sizeof(texture));
  1880.       vmul(&d->texture[d->numtexture].scale, d->texture[d->numtexture].oscale);
  1881.       d->numtexture++;
  1882.     } else if(t->majtype == 1) { /* Bumpmap */
  1883.       memcpy(&d->normal[d->numnormal],t,sizeof(texture));
  1884.       vmul(&d->normal[d->numnormal].scale, d->texture[d->numnormal].oscale);
  1885.       d->numnormal++;
  1886.     } else if(t->majtype == 2) { /* Lightsource */
  1887.       light l;
  1888.       vcopy(&l.a, &t->translate);
  1889.       vcopy(&l.color, &t->color1);
  1890.       vmul(&l.color, t->amount);
  1891.       memcpy(&world.light[world.numlight], &l, sizeof(l));
  1892.       world.numlight++;
  1893.     }
  1894.   }
  1895.  
  1896.   world.quality = 5;
  1897.  
  1898.   world.flags |= SMARTAMBIENT;
  1899.   world.smartambient = 40.0;
  1900. }
  1901.  
  1902. void drawit(gpointer data)
  1903. {
  1904.   if(!drawarea) return;
  1905.   gdk_draw_rgb_image(drawarea->window,
  1906.                      drawarea->style->white_gc,
  1907.                      0, 0, PREVIEWSIZE, PREVIEWSIZE, GDK_RGB_DITHER_MAX,
  1908.                      data, PREVIEWSIZE*3);
  1909. }
  1910.  
  1911. static gint
  1912. expose_event (GtkWidget *widget, GdkEventExpose *event)
  1913. {
  1914.   drawit(img);
  1915.   return FALSE;
  1916. }
  1917.  
  1918. gint restartrender(void)
  1919. {
  1920.   if(running) {
  1921.     running = 2;
  1922.     return 0;
  1923.   }
  1924.   render();
  1925.   return 0;
  1926. }
  1927.  
  1928. void destroy_window(GtkWidget  *widget, GtkWidget **window)
  1929. {
  1930.   *window = NULL;
  1931. }
  1932.  
  1933. void selecttexture(GtkWidget *wg, gpointer data)
  1934. {
  1935.   texture *t;
  1936.   int n = (long)data;
  1937.   if(noupdate) return;
  1938.   t = currenttexture();
  1939.   if(!t) return;
  1940.   t->type = n;
  1941.   relabel();
  1942.   restartrender();
  1943. }
  1944.  
  1945. void selecttype(GtkWidget *wg, gpointer data)
  1946. {
  1947.   texture *t;
  1948.   long n = (long)data;
  1949.   if(noupdate) return;
  1950.   t = currenttexture();
  1951.   if(!t) return;
  1952.   t->majtype = n;
  1953.   relabel();
  1954.   restartrender();
  1955. }
  1956.  
  1957. void getscales(GtkWidget *wg, gpointer data)
  1958. {
  1959.   double f;
  1960.   texture *t;
  1961.   if(noupdate) return;
  1962.   t = currenttexture();
  1963.   if(!t) return;
  1964.   t->amount = GTK_ADJUSTMENT(amountscale)->value;
  1965.   t->exp = GTK_ADJUSTMENT(expscale)->value;
  1966.   f = GTK_ADJUSTMENT(turbulencescale)->value;
  1967.   vset(&t->turbulence, f,f,f);
  1968.  
  1969.   t->oscale = GTK_ADJUSTMENT(scalescale)->value;
  1970.   t->scale.x = GTK_ADJUSTMENT(scalexscale)->value;
  1971.   t->scale.y = GTK_ADJUSTMENT(scaleyscale)->value;
  1972.   t->scale.z = GTK_ADJUSTMENT(scalezscale)->value;
  1973.  
  1974.   t->rotate.x = GTK_ADJUSTMENT(rotxscale)->value;
  1975.   t->rotate.y = GTK_ADJUSTMENT(rotyscale)->value;
  1976.   t->rotate.z = GTK_ADJUSTMENT(rotzscale)->value;
  1977.  
  1978.   t->translate.x = GTK_ADJUSTMENT(posxscale)->value;
  1979.   t->translate.y = GTK_ADJUSTMENT(posyscale)->value;
  1980.   t->translate.z = GTK_ADJUSTMENT(poszscale)->value;
  1981. }
  1982.  
  1983. void mktexturemenu(GtkWidget *texturemenu_menu)
  1984. {
  1985.   GtkWidget *item;
  1986.   struct textures_t *t;
  1987.  
  1988.   t = textures;
  1989.   while(t->s) {
  1990.     item = gtk_menu_item_new_with_label ( gettext(t->s));
  1991.     gtk_widget_show(item);
  1992.     gtk_menu_append (GTK_MENU (texturemenu_menu), item);
  1993.     gtk_signal_connect (GTK_OBJECT(item), "activate",
  1994.             GTK_SIGNAL_FUNC(selecttexture), (void *)t->n);
  1995.     t++;
  1996.   }
  1997. }
  1998.  
  1999. void drawcolor1(GtkWidget *w)
  2000. {
  2001.   static GtkWidget *lastw = NULL;
  2002.   int x, y;
  2003.   guchar buf[COLORBUTTONWIDTH*3];
  2004.   texture *t = currenttexture();
  2005.  
  2006.   if(w) lastw = w;
  2007.   else w = lastw;
  2008.   if(!w) return;
  2009.   if(!t) return;
  2010.  
  2011.   for(x = 0; x < COLORBUTTONWIDTH; x++) {
  2012.     buf[x*3+0] = t->color1.x * 255.0;
  2013.     buf[x*3+1] = t->color1.y * 255.0;
  2014.     buf[x*3+2] = t->color1.z * 255.0;
  2015.   }
  2016.   for(y = 0; y < COLORBUTTONHEIGHT; y++)
  2017.     gtk_preview_draw_row (GTK_PREVIEW(w), buf, 0, y, COLORBUTTONWIDTH);
  2018.   gtk_widget_draw(w, NULL);
  2019. }
  2020.  
  2021. void drawcolor2(GtkWidget *w)
  2022. {
  2023.   static GtkWidget *lastw = NULL;
  2024.   int x, y;
  2025.   guchar buf[COLORBUTTONWIDTH*3];
  2026.   texture *t = currenttexture();
  2027.  
  2028.   if(w) lastw = w;
  2029.   else w = lastw;
  2030.   if(!w) return;
  2031.   if(!t) return;
  2032.  
  2033.   for(x = 0; x < COLORBUTTONWIDTH; x++) {
  2034.     buf[x*3+0] = t->color2.x * 255.0;
  2035.     buf[x*3+1] = t->color2.y * 255.0;
  2036.     buf[x*3+2] = t->color2.z * 255.0;
  2037.   }
  2038.   for(y = 0; y < COLORBUTTONHEIGHT; y++)
  2039.     gtk_preview_draw_row (GTK_PREVIEW(w), buf, 0, y, COLORBUTTONWIDTH);
  2040.   gtk_widget_draw(w, NULL);
  2041. }
  2042.  
  2043. void selectcolor1_ok(GtkWidget *w, gpointer d)
  2044. {
  2045.   texture *t = currenttexture();
  2046.   GtkWidget *win = (GtkWidget *)d;
  2047.   gdouble tmpcol[4];
  2048.   if(!t) return;
  2049.   gtk_color_selection_get_color (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (win)->colorsel), tmpcol);
  2050.   t->color1.x = tmpcol[0];
  2051.   t->color1.y = tmpcol[1];
  2052.   t->color1.z = tmpcol[2];
  2053.   t->color1.w = tmpcol[3];
  2054.   drawcolor1(NULL);
  2055.   gtk_widget_destroy(win);
  2056. }
  2057.  
  2058. void selectcolor2_ok(GtkWidget *w, gpointer d)
  2059. {
  2060.   texture *t = currenttexture();
  2061.   GtkWidget *win = (GtkWidget *)d;
  2062.   gdouble tmpcol[4];
  2063.   if(!t) return;
  2064.   gtk_color_selection_get_color (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (win)->colorsel), tmpcol);
  2065.   t->color2.x = tmpcol[0];
  2066.   t->color2.y = tmpcol[1];
  2067.   t->color2.z = tmpcol[2];
  2068.   t->color2.w = tmpcol[3];
  2069.   drawcolor2(NULL);
  2070.   gtk_widget_destroy(win);
  2071. }
  2072.  
  2073. void selectcolor1(vector *col)
  2074. {
  2075.   static GtkWidget *window = NULL;
  2076.   gdouble tmpcol[4];
  2077.   texture *t = currenttexture();
  2078.  
  2079.   if(!t) return;
  2080.  
  2081.   if(window) {
  2082.     gtk_widget_show(window);
  2083.     gdk_window_raise(window->window);
  2084.     return;
  2085.   }
  2086.  
  2087.   window = gtk_color_selection_dialog_new( _("Color Selection Dialog"));
  2088.   
  2089.   gtk_color_selection_set_opacity (GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG (window)->colorsel), TRUE);
  2090.  
  2091.   gtk_signal_connect (GTK_OBJECT (window), "destroy",
  2092.                       GTK_SIGNAL_FUNC(gtk_widget_destroyed),
  2093.                       &window);
  2094.   tmpcol[0] = t->color1.x;
  2095.   tmpcol[1] = t->color1.y;
  2096.   tmpcol[2] = t->color1.z;
  2097.   tmpcol[3] = t->color1.w;
  2098.  
  2099.   gtk_color_selection_set_color(GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(window)->colorsel), tmpcol);
  2100.  
  2101.   gtk_signal_connect(GTK_OBJECT(GTK_COLOR_SELECTION_DIALOG(window)->ok_button),
  2102.              "clicked",
  2103.                      GTK_SIGNAL_FUNC(selectcolor1_ok), window);
  2104.   gtk_signal_connect_object(GTK_OBJECT(GTK_COLOR_SELECTION_DIALOG(window)->cancel_button),
  2105.                 "clicked",
  2106.                 GTK_SIGNAL_FUNC(gtk_widget_destroy),
  2107.                             GTK_OBJECT (window));
  2108.   gtk_widget_show (window);
  2109. }
  2110.  
  2111. void selectcolor2(vector *col)
  2112. {
  2113.   static GtkWidget *window = NULL;
  2114.   gdouble tmpcol[4];
  2115.   texture *t = currenttexture();
  2116.  
  2117.   if(!t) return;
  2118.  
  2119.   if(window) {
  2120.     gtk_widget_show(window);
  2121.     gdk_window_raise(window->window);
  2122.     return;
  2123.   }
  2124.  
  2125.   window = gtk_color_selection_dialog_new( _("Color Selection Dialog"));
  2126.  
  2127.   gtk_color_selection_set_opacity (GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG (window)->colorsel), TRUE);
  2128.  
  2129.   gtk_signal_connect (GTK_OBJECT (window), "destroy",
  2130.                       GTK_SIGNAL_FUNC(gtk_widget_destroyed),
  2131.                       &window);
  2132.   tmpcol[0] = t->color2.x;
  2133.   tmpcol[1] = t->color2.y;
  2134.   tmpcol[2] = t->color2.z;
  2135.   tmpcol[3] = t->color2.w;
  2136.  
  2137.   gtk_color_selection_set_color(GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(window)->colorsel), tmpcol);
  2138.  
  2139.   gtk_signal_connect(GTK_OBJECT(GTK_COLOR_SELECTION_DIALOG(window)->ok_button),
  2140.              "clicked",
  2141.                      GTK_SIGNAL_FUNC(selectcolor2_ok), window);
  2142.   gtk_signal_connect_object(GTK_OBJECT(GTK_COLOR_SELECTION_DIALOG(window)->cancel_button),
  2143.                 "clicked",
  2144.                 GTK_SIGNAL_FUNC(gtk_widget_destroy),
  2145.                             GTK_OBJECT (window));
  2146.   gtk_widget_show (window);
  2147. }
  2148.  
  2149. int do_run = 0;
  2150.  
  2151. void sphere_ok(GtkWidget *widget, gpointer data)
  2152. {
  2153.   running = -1;
  2154.   do_run = 1;
  2155.   gtk_widget_hide (GTK_WIDGET (data));
  2156.   gtk_main_quit();
  2157. }
  2158.  
  2159. void sphere_cancel(GtkWidget *widget, gpointer data)
  2160. {
  2161.   gtk_widget_hide (GTK_WIDGET (data));
  2162.   gtk_main_quit();
  2163. }
  2164.  
  2165. GtkWidget* makewindow (void)
  2166. {
  2167.   GtkWidget *window;
  2168.   GtkWidget *table1;
  2169.   GtkWidget *frame2;
  2170.   GtkWidget *frame3;
  2171.   GtkWidget *viewport2;
  2172.   GtkWidget *hbox1;
  2173.   GtkWidget *addbutton;
  2174.   GtkWidget *dupbutton;
  2175.   GtkWidget *delbutton;
  2176.   GtkWidget *loadbutton;
  2177.   GtkWidget *savebutton;
  2178.   GtkWidget *okbutton;
  2179.   GtkWidget *cancelbutton;
  2180.   GtkWidget *resetbutton;
  2181.   GtkWidget *frame4;
  2182.   GtkWidget *table2;
  2183.   GtkWidget *label2;
  2184.   GtkWidget *label3;
  2185.   GtkWidget *label4;
  2186.   GtkWidget *hbox3;
  2187.   GtkWidget *colorbutton1;
  2188.   GtkWidget *colorbutton2;
  2189.   GtkWidget *label5;
  2190.   GtkWidget *label6;
  2191.   GtkWidget *item;
  2192.   GtkWidget *label7;
  2193.   GtkWidget *label8;
  2194.   GtkWidget *updatebutton;
  2195.   GtkWidget *label1;
  2196.   GtkWidget *_scalescale;
  2197.   GtkWidget *_rotscale;
  2198.   GtkWidget *_turbulencescale;
  2199.   GtkWidget *_amountscale;
  2200.   GtkWidget *_expscale;
  2201.   GtkWidget *tmpw;
  2202.  
  2203.   window = gimp_dialog_new (_("Sphere Designer"), "spheredesigner",
  2204.                 gimp_standard_help_func, "filters/spheredesigner.html",
  2205.                 GTK_WIN_POS_MOUSE,
  2206.                 FALSE, TRUE, FALSE,
  2207.  
  2208.                 _("OK"), sphere_ok,
  2209.                 NULL, NULL, &okbutton, TRUE, FALSE,
  2210.                 _("Reset"), sphere_reset,
  2211.                 NULL, NULL, &resetbutton, FALSE, FALSE,
  2212.                 _("Cancel"), sphere_cancel,
  2213.                 NULL, NULL, &cancelbutton, FALSE, TRUE,
  2214.  
  2215.                 NULL);
  2216.  
  2217.   gtk_object_set_data (GTK_OBJECT (window), "window", window);
  2218.   gtk_object_set_data (GTK_OBJECT (window), "okbutton", okbutton);
  2219.   gtk_object_set_data (GTK_OBJECT (window), "cancelbutton", cancelbutton);
  2220.   gtk_object_set_data (GTK_OBJECT (window), "resetbutton", cancelbutton);
  2221.  
  2222.   table1 = gtk_table_new (3, 3, FALSE);
  2223.   gtk_object_set_data (GTK_OBJECT (window), "table1", table1);
  2224.   gtk_widget_show (table1);
  2225.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (window)->vbox), table1);
  2226.   gtk_table_set_row_spacings (GTK_TABLE (table1), 4);
  2227.   gtk_table_set_col_spacings (GTK_TABLE (table1), 4);
  2228.   gtk_container_set_border_width (GTK_CONTAINER (table1), 6);
  2229.  
  2230.   frame2 = gtk_frame_new (_("Preview"));
  2231.   gtk_object_set_data (GTK_OBJECT (window), "frame2", frame2);
  2232.   gtk_widget_show (frame2);
  2233.   gtk_table_attach (GTK_TABLE (table1), frame2, 0, 1, 0, 1,
  2234.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  2235.  
  2236.   drawarea = gtk_drawing_area_new ();
  2237.   gtk_object_set_data (GTK_OBJECT (window), "drawarea", drawarea);
  2238.   gtk_widget_show (drawarea);
  2239.   gtk_container_add (GTK_CONTAINER (frame2), drawarea);
  2240.   gtk_widget_set_usize (drawarea, PREVIEWSIZE, PREVIEWSIZE);
  2241.   gtk_signal_connect (GTK_OBJECT (drawarea), "expose_event",
  2242.                       (GtkSignalFunc) expose_event, NULL);
  2243.  
  2244.   updatebutton = gtk_button_new_with_label ( _("Update"));
  2245.   gtk_object_set_data (GTK_OBJECT (window), "updatebutton", updatebutton);
  2246.   gtk_widget_show (updatebutton);
  2247.   gtk_table_attach (GTK_TABLE (table1), updatebutton, 0, 1, 1, 2,
  2248.                     (GtkAttachOptions) GTK_EXPAND | GTK_FILL, (GtkAttachOptions) GTK_EXPAND | GTK_FILL, 0, 0);
  2249.  
  2250.   gtk_signal_connect (GTK_OBJECT(updatebutton), "clicked", GTK_SIGNAL_FUNC(restartrender), NULL);
  2251.  
  2252.  
  2253.   frame3 = gtk_frame_new ( _("Textures"));
  2254.   gtk_object_set_data (GTK_OBJECT (window), "frame3", frame3);
  2255.   gtk_widget_show (frame3);
  2256.   gtk_table_attach (GTK_TABLE (table1), frame3, 1, 2, 0, 2,
  2257.                     (GtkAttachOptions) GTK_EXPAND | GTK_FILL, (GtkAttachOptions) GTK_EXPAND | GTK_FILL, 0, 0);
  2258.  
  2259.   viewport2 = gtk_viewport_new (NULL, NULL);
  2260.   gtk_object_set_data (GTK_OBJECT (window), "viewport2", viewport2);
  2261.   gtk_widget_set_usize (viewport2, 150, -1);
  2262.   gtk_widget_show (viewport2);
  2263.   gtk_container_add (GTK_CONTAINER (frame3), viewport2);
  2264.  
  2265.   texturelist = gtk_list_new ();
  2266.   gtk_object_set_data (GTK_OBJECT (window), "texturelist", texturelist);
  2267.   gtk_widget_show (texturelist);
  2268.   gtk_container_add (GTK_CONTAINER (viewport2), texturelist);
  2269.   gtk_signal_connect (GTK_OBJECT(texturelist), "selection_changed",
  2270.                       GTK_SIGNAL_FUNC(selectitem), texturelist);
  2271.  
  2272.   hbox1 = gtk_hbox_new (TRUE, 0);
  2273.   gtk_object_set_data (GTK_OBJECT (window), "hbox1", hbox1);
  2274.   gtk_widget_show (hbox1);
  2275.   gtk_table_attach (GTK_TABLE (table1), hbox1, 1, 2, 2, 3,
  2276.                     (GtkAttachOptions) GTK_EXPAND | GTK_FILL, (GtkAttachOptions) GTK_EXPAND | GTK_FILL, 0, 0);
  2277.  
  2278.   addbutton = gtk_button_new_with_label ( _("Add"));
  2279.   gtk_object_set_data (GTK_OBJECT (window), "addbutton", addbutton);
  2280.   gtk_widget_show (addbutton);
  2281.   gtk_box_pack_start (GTK_BOX (hbox1), addbutton, TRUE, TRUE, 0);
  2282.   gtk_signal_connect_object (GTK_OBJECT (addbutton), "clicked",
  2283.                              GTK_SIGNAL_FUNC (addtexture), NULL);
  2284.  
  2285.   dupbutton = gtk_button_new_with_label ( _("Dup"));
  2286.   gtk_object_set_data (GTK_OBJECT (window), "dupbutton", dupbutton);
  2287.   gtk_widget_show (dupbutton);
  2288.   gtk_box_pack_start (GTK_BOX (hbox1), dupbutton, TRUE, TRUE, 0);
  2289.   gtk_signal_connect_object (GTK_OBJECT (dupbutton), "clicked",
  2290.                              GTK_SIGNAL_FUNC (duptexture), NULL);
  2291.  
  2292.   delbutton = gtk_button_new_with_label ( _("Del"));
  2293.   gtk_object_set_data (GTK_OBJECT (window), "delbutton", delbutton);
  2294.   gtk_widget_show (delbutton);
  2295.   gtk_box_pack_start (GTK_BOX (hbox1), delbutton, TRUE, TRUE, 0);
  2296.   gtk_signal_connect_object (GTK_OBJECT (delbutton), "clicked",
  2297.                              GTK_SIGNAL_FUNC (deltexture), NULL);
  2298.  
  2299.   hbox1 = gtk_hbox_new (TRUE, 0);
  2300.   gtk_object_set_data (GTK_OBJECT (window), "hbox1", hbox1);
  2301.   gtk_widget_show (hbox1);
  2302.   gtk_table_attach (GTK_TABLE (table1), hbox1, 0, 1, 2, 3,
  2303.                     (GtkAttachOptions) GTK_EXPAND | GTK_FILL, (GtkAttachOptions) GTK_EXPAND | GTK_FILL, 0, 0);
  2304.  
  2305.   loadbutton = gtk_button_new_with_label ( _("Load"));
  2306.   gtk_object_set_data (GTK_OBJECT (window), "loadbutton", loadbutton);
  2307.   gtk_widget_show (loadbutton);
  2308.   gtk_box_pack_start (GTK_BOX (hbox1), loadbutton, TRUE, TRUE, 0);
  2309.   gtk_signal_connect_object (GTK_OBJECT (loadbutton), "clicked",
  2310.                              GTK_SIGNAL_FUNC (loadpreset), NULL);
  2311.  
  2312.   savebutton = gtk_button_new_with_label ( _("Save"));
  2313.   gtk_object_set_data (GTK_OBJECT (window), "savebutton", savebutton);
  2314.   gtk_widget_show (savebutton);
  2315.   gtk_box_pack_start (GTK_BOX (hbox1), savebutton, TRUE, TRUE, 0);
  2316.   gtk_signal_connect_object (GTK_OBJECT (savebutton), "clicked",
  2317.                              GTK_SIGNAL_FUNC (savepreset), NULL);
  2318.  
  2319.   frame4 = gtk_frame_new ( _("Texture Properties"));
  2320.   gtk_object_set_data (GTK_OBJECT (window), "frame4", frame4);
  2321.   gtk_widget_show (frame4);
  2322.   gtk_table_attach (GTK_TABLE (table1), frame4, 2, 3, 0, 3,
  2323.                     (GtkAttachOptions) GTK_EXPAND | GTK_FILL, (GtkAttachOptions) GTK_EXPAND | GTK_FILL, 0, 0);
  2324.  
  2325.   table2 = gtk_table_new (6, 4, FALSE);
  2326.   gtk_object_set_data (GTK_OBJECT (window), "table2", table2);
  2327.   gtk_widget_show (table2);
  2328.   gtk_container_add (GTK_CONTAINER (frame4), table2);
  2329.   gtk_container_set_border_width (GTK_CONTAINER (table2), 5);
  2330.   gtk_table_set_col_spacings (GTK_TABLE (table2), 4);
  2331.   gtk_table_set_row_spacings (GTK_TABLE (table2), 2);
  2332.  
  2333.   label2 = gtk_label_new ( _("Type:"));
  2334.   gtk_object_set_data (GTK_OBJECT (window), "label2", label2);
  2335.   gtk_widget_show (label2);
  2336.   gtk_table_attach (GTK_TABLE (table2), label2, 0, 1, 0, 1,
  2337.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
  2338.   gtk_misc_set_alignment (GTK_MISC (label2), 1.0, 0.5);
  2339.  
  2340.   label3 = gtk_label_new ( _("Texture:"));
  2341.   gtk_object_set_data (GTK_OBJECT (window), "label3", label3);
  2342.   gtk_widget_show (label3);
  2343.   gtk_table_attach (GTK_TABLE (table2), label3, 0, 1, 1, 2,
  2344.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
  2345.   gtk_misc_set_alignment (GTK_MISC (label3), 1.0, 0.5);
  2346.  
  2347.   label4 = gtk_label_new ( _("Colors:"));
  2348.   gtk_object_set_data (GTK_OBJECT (window), "label4", label4);
  2349.   gtk_widget_show (label4);
  2350.   gtk_table_attach (GTK_TABLE (table2), label4, 0, 1, 2, 3,
  2351.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  2352.   gtk_misc_set_alignment (GTK_MISC (label4), 1.0, 0.5);
  2353.  
  2354.   hbox3 = gtk_hbox_new (FALSE, 0);
  2355.   gtk_object_set_data (GTK_OBJECT (window), "hbox3", hbox3);
  2356.   gtk_widget_show (hbox3);
  2357.   gtk_table_attach (GTK_TABLE (table2), hbox3, 1, 2, 2, 3,
  2358.                     (GtkAttachOptions) GTK_EXPAND | GTK_FILL, (GtkAttachOptions) GTK_EXPAND | GTK_FILL, 0, 0);
  2359.  
  2360.   colorbutton1 = gtk_button_new();
  2361.   gtk_object_set_data (GTK_OBJECT (window), "colorbutton1", colorbutton1);
  2362.   gtk_widget_show (colorbutton1);
  2363.   gtk_box_pack_start (GTK_BOX (hbox3), colorbutton1, TRUE, FALSE, 0);
  2364.   gtk_signal_connect (GTK_OBJECT (colorbutton1), "clicked",
  2365.                       (GtkSignalFunc)selectcolor1, NULL);
  2366.   tmpw = gtk_preview_new(GTK_PREVIEW_COLOR);
  2367.   gtk_preview_size (GTK_PREVIEW (tmpw), COLORBUTTONWIDTH, COLORBUTTONHEIGHT);
  2368.   gtk_container_add (GTK_CONTAINER (colorbutton1), tmpw);
  2369.   gtk_widget_show(tmpw);
  2370.   drawcolor1(tmpw);
  2371.  
  2372.   colorbutton2 = gtk_button_new();
  2373.   gtk_object_set_data (GTK_OBJECT (window), "colorbutton2", colorbutton2);
  2374.   gtk_widget_show (colorbutton2);
  2375.   gtk_box_pack_start (GTK_BOX (hbox3), colorbutton2, TRUE, FALSE, 0);
  2376.   gtk_signal_connect (GTK_OBJECT (colorbutton2), "clicked",
  2377.                       (GtkSignalFunc)selectcolor2, NULL);
  2378.   tmpw = gtk_preview_new(GTK_PREVIEW_COLOR);
  2379.   gtk_preview_size (GTK_PREVIEW (tmpw), COLORBUTTONWIDTH, COLORBUTTONHEIGHT);
  2380.   gtk_container_add (GTK_CONTAINER (colorbutton2), tmpw);
  2381.   gtk_widget_show(tmpw);
  2382.   drawcolor2(tmpw);
  2383.  
  2384.   label5 = gtk_label_new ( _("Scale:"));
  2385.   gtk_object_set_data (GTK_OBJECT (window), "label5", label5);
  2386.   gtk_widget_show (label5);
  2387.   gtk_table_attach (GTK_TABLE (table2), label5, 0, 1, 3, 4,
  2388.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  2389.   gtk_misc_set_alignment (GTK_MISC (label5), 1.0, 1.0);
  2390.  
  2391.   _scalescale = gtk_hscale_new (GTK_ADJUSTMENT (scalescale = gtk_adjustment_new (1.0, 0.0, 5.1, 0.1, 0.1, 0.1)));
  2392.   gtk_widget_set_usize(_scalescale, 100, -1);
  2393.   gtk_object_set_data (GTK_OBJECT (window), "_scalescale", _scalescale);
  2394.   gtk_widget_show (_scalescale);
  2395.   gtk_table_attach (GTK_TABLE (table2), _scalescale, 1, 2, 3, 4,
  2396.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
  2397.   gtk_scale_set_digits (GTK_SCALE (_scalescale), 2);
  2398.   gtk_signal_connect(GTK_OBJECT(scalescale), "value_changed",
  2399.                      (GtkSignalFunc)getscales, NULL);
  2400.  
  2401.   label5 = gtk_label_new ( _("Turbulence:"));
  2402.   gtk_object_set_data (GTK_OBJECT (window), "label5", label5);
  2403.   gtk_widget_show (label5);
  2404.   gtk_table_attach (GTK_TABLE (table2), label5, 0, 1, 4, 5,
  2405.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  2406.   gtk_misc_set_alignment (GTK_MISC (label5), 1.0, 1.0);
  2407.  
  2408.   _turbulencescale = gtk_hscale_new (GTK_ADJUSTMENT (turbulencescale = gtk_adjustment_new (0.0, 0.0, 5.1, 0.1, 0.1, 0.1)));
  2409.   gtk_widget_set_usize(_turbulencescale, 100, -1);
  2410.   gtk_object_set_data (GTK_OBJECT (window), "_turbulencescale", _turbulencescale);
  2411.   gtk_widget_show (_turbulencescale);
  2412.   gtk_table_attach (GTK_TABLE (table2), _turbulencescale, 1, 2, 4, 5,
  2413.                     (GtkAttachOptions) GTK_EXPAND | GTK_FILL, (GtkAttachOptions) GTK_EXPAND, 0, 0);
  2414.   gtk_scale_set_digits (GTK_SCALE (_turbulencescale), 2);
  2415.   gtk_signal_connect(GTK_OBJECT(turbulencescale), "value_changed",
  2416.                      (GtkSignalFunc)getscales, NULL);
  2417.  
  2418.   label6 = gtk_label_new ( _("Scale X:"));
  2419.   gtk_object_set_data (GTK_OBJECT (window), "label6", label6);
  2420.   gtk_widget_show (label6);
  2421.   gtk_table_attach (GTK_TABLE (table2), label6, 2, 3, 0, 1,
  2422.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  2423.   gtk_misc_set_alignment (GTK_MISC (label6), 1.0, 1.0);
  2424.  
  2425.   _scalescale = gtk_hscale_new (GTK_ADJUSTMENT (scalexscale = gtk_adjustment_new (1.0, 0.0, 5.1, 0.1, 0.1, 0.1)));
  2426.   gtk_widget_set_usize(_scalescale, 100, -1);
  2427.   gtk_object_set_data (GTK_OBJECT (window), "_scalescale", _scalescale);
  2428.   gtk_scale_set_digits (GTK_SCALE (_scalescale), 2);
  2429.   gtk_widget_show (_scalescale);
  2430.   gtk_table_attach (GTK_TABLE (table2), _scalescale, 3, 4, 0, 1,
  2431.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
  2432.   gtk_signal_connect(GTK_OBJECT(scalexscale), "value_changed",
  2433.                      (GtkSignalFunc)getscales, NULL);
  2434.  
  2435.   label6 = gtk_label_new ( _("Scale Y:"));
  2436.   gtk_object_set_data (GTK_OBJECT (window), "label6", label6);
  2437.   gtk_widget_show (label6);
  2438.   gtk_table_attach (GTK_TABLE (table2), label6, 2, 3, 1, 2,
  2439.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  2440.   gtk_misc_set_alignment (GTK_MISC (label6), 1.0, 1.0);
  2441.  
  2442.   _scalescale = gtk_hscale_new (GTK_ADJUSTMENT (scaleyscale = gtk_adjustment_new (1.0, 0.0, 5.1, 0.1, 0.1, 0.1)));
  2443.   gtk_widget_set_usize(_scalescale, 100, -1);
  2444.   gtk_object_set_data (GTK_OBJECT (window), "_scalescale", _scalescale);
  2445.   gtk_scale_set_digits (GTK_SCALE (_scalescale), 2);
  2446.   gtk_widget_show (_scalescale);
  2447.   gtk_table_attach (GTK_TABLE (table2), _scalescale, 3, 4, 1, 2,
  2448.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
  2449.   gtk_signal_connect(GTK_OBJECT(scaleyscale), "value_changed",
  2450.                      (GtkSignalFunc)getscales, NULL);
  2451.  
  2452.   label6 = gtk_label_new ( _("Scale Z:"));
  2453.   gtk_object_set_data (GTK_OBJECT (window), "label6", label6);
  2454.   gtk_widget_show (label6);
  2455.   gtk_table_attach (GTK_TABLE (table2), label6, 2, 3, 2, 3,
  2456.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  2457.   gtk_misc_set_alignment (GTK_MISC (label6), 1.0, 1.0);
  2458.  
  2459.   _scalescale = gtk_hscale_new (GTK_ADJUSTMENT (scalezscale = gtk_adjustment_new (1.0, 0.0, 5.1, 0.1, 0.1, 0.1)));
  2460.   gtk_widget_set_usize(_scalescale, 100, -1);
  2461.   gtk_object_set_data (GTK_OBJECT (window), "_scalescale", _scalescale);
  2462.   gtk_scale_set_digits (GTK_SCALE (_scalescale), 2);
  2463.   gtk_widget_show (_scalescale);
  2464.   gtk_table_attach (GTK_TABLE (table2), _scalescale, 3, 4, 2, 3,
  2465.                     (GtkAttachOptions) GTK_EXPAND | GTK_FILL, (GtkAttachOptions) GTK_EXPAND, 0, 0);
  2466.   gtk_signal_connect(GTK_OBJECT(scalezscale), "value_changed",
  2467.                      (GtkSignalFunc)getscales, NULL);
  2468.  
  2469.  
  2470.   label6 = gtk_label_new ( _("Rotate X:"));
  2471.   gtk_object_set_data (GTK_OBJECT (window), "label6", label6);
  2472.   gtk_widget_show (label6);
  2473.   gtk_table_attach (GTK_TABLE (table2), label6, 2, 3, 3, 4,
  2474.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  2475.   gtk_misc_set_alignment (GTK_MISC (label6), 1.0, 1.0);
  2476.  
  2477.   _rotscale = gtk_hscale_new (GTK_ADJUSTMENT (rotxscale = gtk_adjustment_new (1.0, 0.0, 360.1, 0.1, 0.1, 0.1)));
  2478.   gtk_widget_set_usize(_rotscale, 100, -1);
  2479.   gtk_object_set_data (GTK_OBJECT (window), "_rotscale", _rotscale);
  2480.   gtk_scale_set_digits (GTK_SCALE (_rotscale), 2);
  2481.   gtk_widget_show (_rotscale);
  2482.   gtk_table_attach (GTK_TABLE (table2), _rotscale, 3, 4, 3, 4,
  2483.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
  2484.   gtk_signal_connect(GTK_OBJECT(rotxscale), "value_changed",
  2485.                      (GtkSignalFunc)getscales, NULL);
  2486.  
  2487.   label6 = gtk_label_new ( _("Rotate Y:"));
  2488.   gtk_object_set_data (GTK_OBJECT (window), "label6", label6);
  2489.   gtk_widget_show (label6);
  2490.   gtk_table_attach (GTK_TABLE (table2), label6, 2, 3, 4, 5,
  2491.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  2492.   gtk_misc_set_alignment (GTK_MISC (label6), 1.0, 1.0);
  2493.  
  2494.   _rotscale = gtk_hscale_new (GTK_ADJUSTMENT (rotyscale = gtk_adjustment_new (1.0, 0.0, 360.1, 0.1, 0.1, 0.1)));
  2495.   gtk_widget_set_usize(_rotscale, 100, -1);
  2496.   gtk_object_set_data (GTK_OBJECT (window), "_rotscale", _rotscale);
  2497.   gtk_scale_set_digits (GTK_SCALE (_rotscale), 2);
  2498.   gtk_widget_show (_rotscale);
  2499.   gtk_table_attach (GTK_TABLE (table2), _rotscale, 3, 4, 4, 5,
  2500.                     (GtkAttachOptions) GTK_EXPAND | GTK_FILL, (GtkAttachOptions) GTK_EXPAND, 0, 0);
  2501.   gtk_signal_connect(GTK_OBJECT(rotyscale), "value_changed",
  2502.                      (GtkSignalFunc)getscales, NULL);
  2503.  
  2504.   label6 = gtk_label_new ( _("Rotate Z:"));
  2505.   gtk_object_set_data (GTK_OBJECT (window), "label6", label6);
  2506.   gtk_widget_show (label6);
  2507.   gtk_table_attach (GTK_TABLE (table2), label6, 2, 3, 5, 6,
  2508.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  2509.   gtk_misc_set_alignment (GTK_MISC (label6), 1.0, 1.0);
  2510.  
  2511.   _rotscale = gtk_hscale_new (GTK_ADJUSTMENT (rotzscale = gtk_adjustment_new (1.0, 0.0, 360.1, 0.1, 0.1, 0.1)));
  2512.   gtk_widget_set_usize(_rotscale, 100, -1);
  2513.   gtk_object_set_data (GTK_OBJECT (window), "_rotscale", _rotscale);
  2514.   gtk_scale_set_digits (GTK_SCALE (_rotscale), 2);
  2515.   gtk_widget_show (_rotscale);
  2516.   gtk_table_attach (GTK_TABLE (table2), _rotscale, 3, 4, 5, 6,
  2517.                     (GtkAttachOptions) GTK_EXPAND | GTK_FILL, (GtkAttachOptions) GTK_EXPAND, 0, 0);
  2518.   gtk_signal_connect(GTK_OBJECT(rotzscale), "value_changed",
  2519.                      (GtkSignalFunc)getscales, NULL);
  2520.  
  2521.   label6 = gtk_label_new ( _("Pos X:"));
  2522.   gtk_object_set_data (GTK_OBJECT (window), "label6", label6);
  2523.   gtk_widget_show (label6);
  2524.   gtk_table_attach (GTK_TABLE (table2), label6, 5, 6, 0, 1,
  2525.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  2526.   gtk_misc_set_alignment (GTK_MISC (label6), 1.0, 1.0);
  2527.  
  2528.   _scalescale = gtk_hscale_new (GTK_ADJUSTMENT (posxscale = gtk_adjustment_new (0.0, -20.0, 20.1, 0.1, 0.1, 0.1)));
  2529.   gtk_widget_set_usize(_scalescale, 100, -1);
  2530.   gtk_object_set_data (GTK_OBJECT (window), "_scalescale", _scalescale);
  2531.   gtk_scale_set_digits (GTK_SCALE (_scalescale), 2);
  2532.   gtk_widget_show (_scalescale);
  2533.   gtk_table_attach (GTK_TABLE (table2), _scalescale, 6, 7, 0, 1,
  2534.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
  2535.   gtk_signal_connect(GTK_OBJECT(posxscale), "value_changed",
  2536.                      (GtkSignalFunc)getscales, NULL);
  2537.  
  2538.   label6 = gtk_label_new ( _("Pos Y:"));
  2539.   gtk_object_set_data (GTK_OBJECT (window), "label6", label6);
  2540.   gtk_widget_show (label6);
  2541.   gtk_table_attach (GTK_TABLE (table2), label6, 5, 6, 1, 2,
  2542.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  2543.   gtk_misc_set_alignment (GTK_MISC (label6), 1.0, 1.0);
  2544.  
  2545.   _scalescale = gtk_hscale_new (GTK_ADJUSTMENT (posyscale = gtk_adjustment_new (1.0, -20.0, 20.1, 0.1, 0.1, 0.1)));
  2546.   gtk_widget_set_usize(_scalescale, 100, -1);
  2547.   gtk_object_set_data (GTK_OBJECT (window), "_scalescale", _scalescale);
  2548.   gtk_scale_set_digits (GTK_SCALE (_scalescale), 2);
  2549.   gtk_widget_show (_scalescale);
  2550.   gtk_table_attach (GTK_TABLE (table2), _scalescale, 6, 7, 1, 2,
  2551.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
  2552.   gtk_signal_connect(GTK_OBJECT(posyscale), "value_changed",
  2553.                      (GtkSignalFunc)getscales, NULL);
  2554.  
  2555.   label6 = gtk_label_new ( _("Pos Z:"));
  2556.   gtk_object_set_data (GTK_OBJECT (window), "label6", label6);
  2557.   gtk_widget_show (label6);
  2558.   gtk_table_attach (GTK_TABLE (table2), label6, 5, 6, 2, 3,
  2559.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  2560.   gtk_misc_set_alignment (GTK_MISC (label6), 1.0, 1.0);
  2561.  
  2562.   _scalescale = gtk_hscale_new (GTK_ADJUSTMENT (poszscale = gtk_adjustment_new (1.0, -20.0, 20.1, 0.1, 0.1, 0.1)));
  2563.   gtk_widget_set_usize(_scalescale, 100, -1);
  2564.   gtk_object_set_data (GTK_OBJECT (window), "_scalescale", _scalescale);
  2565.   gtk_scale_set_digits (GTK_SCALE (_scalescale), 2);
  2566.   gtk_widget_show (_scalescale);
  2567.   gtk_table_attach (GTK_TABLE (table2), _scalescale, 6, 7, 2, 3,
  2568.                     (GtkAttachOptions) GTK_EXPAND | GTK_FILL, (GtkAttachOptions) GTK_EXPAND, 0, 0);
  2569.   gtk_signal_connect(GTK_OBJECT(poszscale), "value_changed",
  2570.                      (GtkSignalFunc)getscales, NULL);
  2571.  
  2572.   typemenu = gtk_option_menu_new ();
  2573.   gtk_object_set_data (GTK_OBJECT (window), "typemenu", typemenu);
  2574.   gtk_widget_show (typemenu);
  2575.   gtk_table_attach (GTK_TABLE (table2), typemenu, 1, 2, 0, 1,
  2576.                     GTK_FILL | GTK_EXPAND, GTK_EXPAND, 0, 0);
  2577.   typemenu_menu = gtk_menu_new ();
  2578.   item = gtk_menu_item_new_with_label ( _("Texture"));
  2579.   gtk_widget_show (item);
  2580.   gtk_signal_connect (GTK_OBJECT(item), "activate",
  2581.               GTK_SIGNAL_FUNC(selecttype), NULL);
  2582.   gtk_menu_append (GTK_MENU (typemenu_menu), item);
  2583.  
  2584.   item = gtk_menu_item_new_with_label ( _("Bump"));
  2585.   gtk_widget_show (item);
  2586.   gtk_signal_connect (GTK_OBJECT(item), "activate",
  2587.               GTK_SIGNAL_FUNC(selecttype), (long *)1);
  2588.   gtk_menu_append (GTK_MENU (typemenu_menu), item);
  2589.  
  2590.   item = gtk_menu_item_new_with_label ( _("Light"));
  2591.   gtk_widget_show (item);
  2592.   gtk_signal_connect (GTK_OBJECT(item), "activate",
  2593.               GTK_SIGNAL_FUNC(selecttype), (long *)2);
  2594.   gtk_menu_append (GTK_MENU (typemenu_menu), item);
  2595.  
  2596.   gtk_option_menu_set_menu (GTK_OPTION_MENU (typemenu), typemenu_menu);
  2597.  
  2598.   texturemenu = gtk_option_menu_new ();
  2599.   gtk_object_set_data (GTK_OBJECT (window), "texturemenu", texturemenu);
  2600.   gtk_widget_show (texturemenu);
  2601.   gtk_table_attach (GTK_TABLE (table2), texturemenu, 1, 2, 1, 2,
  2602.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
  2603.  
  2604.   texturemenu_menu = gtk_menu_new ();
  2605.   mktexturemenu (texturemenu_menu);
  2606.  
  2607.   gtk_option_menu_set_menu (GTK_OPTION_MENU (texturemenu), texturemenu_menu);
  2608.  
  2609.   label7 = gtk_label_new ( _("Amount:"));
  2610.   gtk_object_set_data (GTK_OBJECT (window), "label7", label7);
  2611.   gtk_widget_show (label7);
  2612.   gtk_table_attach (GTK_TABLE (table2), label7, 0, 1, 5, 6,
  2613.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  2614.   gtk_misc_set_alignment (GTK_MISC (label7), 1.0, 1.0);
  2615.  
  2616.   _amountscale = gtk_hscale_new (GTK_ADJUSTMENT (amountscale = gtk_adjustment_new (1.0, 0, 1.01, .01, .01, .01)));
  2617.   gtk_widget_set_usize(_amountscale, 100, -1);
  2618.   gtk_object_set_data (GTK_OBJECT (window), "_amountscale", _amountscale);
  2619.   gtk_widget_show (_amountscale);
  2620.   gtk_table_attach (GTK_TABLE (table2), _amountscale, 1, 2, 5, 6,
  2621.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  2622.   gtk_scale_set_digits (GTK_SCALE (_amountscale), 2);
  2623.   gtk_signal_connect(GTK_OBJECT(amountscale), "value_changed",
  2624.                      (GtkSignalFunc)getscales, NULL);
  2625.  
  2626.   label8 = gtk_label_new ( _("Exp:"));
  2627.   gtk_object_set_data (GTK_OBJECT (window), "label8", label8);
  2628.   gtk_widget_show (label8);
  2629.   gtk_table_attach (GTK_TABLE (table2), label8, 0, 1, 6, 7,
  2630.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  2631.   gtk_misc_set_alignment (GTK_MISC (label8), 1.0, 1.0);
  2632.  
  2633.   _expscale = gtk_hscale_new (GTK_ADJUSTMENT (expscale = gtk_adjustment_new (1.0, 0, 1.01, .01, .01, .01)));
  2634.   gtk_widget_set_usize(_expscale, 100, -1);
  2635.   gtk_object_set_data (GTK_OBJECT (window), "_expscale", _expscale);
  2636.   gtk_widget_show (_expscale);
  2637.   gtk_table_attach (GTK_TABLE (table2), _expscale, 1, 2, 6, 7,
  2638.                     (GtkAttachOptions) GTK_EXPAND | GTK_FILL, (GtkAttachOptions) GTK_EXPAND | GTK_FILL, 0, 0);
  2639.   gtk_scale_set_digits (GTK_SCALE (_expscale), 2);
  2640.   gtk_signal_connect(GTK_OBJECT(expscale), "value_changed",
  2641.                      (GtkSignalFunc)getscales, NULL);
  2642.  
  2643.   label1 = gtk_label_new ( _("by Vidar Madsen\nSeptember 1999"));
  2644.   gtk_object_set_data (GTK_OBJECT (window), "label1", label1);
  2645.   gtk_widget_show (label1);
  2646.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), label1,
  2647.               TRUE, TRUE, 0);
  2648.  
  2649.   gtk_widget_show (window);
  2650.  
  2651.   return window;
  2652. }
  2653.  
  2654. unsigned char pixelval(double v)
  2655. {
  2656.   v += 0.5;
  2657.   if(v < 0.0) return 0;
  2658.   if(v > 255.0) return 255;
  2659.   return v;
  2660. }
  2661.  
  2662. void render(void)
  2663. {
  2664.   int x, y, p;
  2665.   ray r;
  2666.   vector col;
  2667.   int hit;
  2668.   int tx, ty;
  2669.   guchar *dest_row;
  2670.   int bpp;
  2671.  
  2672.   r.v1.z = -10.0;
  2673.   r.v2.z = 0.0;
  2674.  
  2675.   running = 2;
  2676.  
  2677.   tx = PREVIEWSIZE;
  2678.   ty = PREVIEWSIZE;
  2679.   bpp = 3;
  2680.  
  2681.   while(running > 0) {
  2682.  
  2683.     if(running == 2) {
  2684.       running = 1;
  2685.       initworld();
  2686.     }
  2687.     if(world.obj[0].com.numtexture == 0) break;
  2688.  
  2689.     for(y = 0; y < ty; y++) {
  2690.       dest_row = img + y*PREVIEWSIZE*3;
  2691.  
  2692.       for(x = 0; x < tx; x++) {
  2693.     int g, gridsize = 16;
  2694.     g = ((x/gridsize+y/gridsize)%2)*60+100;
  2695.  
  2696.     r.v1.x = r.v2.x = 8.5 * (x / (float)(tx-1) - 0.5);
  2697.     r.v1.y = r.v2.y = 8.5 * (y / (float)(ty-1) - 0.5);
  2698.  
  2699.     p = x*bpp;
  2700.  
  2701.     hit = traceray(&r, &col, 10, 1.0);
  2702.  
  2703.     if(col.w < 0.0) col.w = 0.0;
  2704.     else if(col.w > 1.0) col.w = 1.0;
  2705.  
  2706.     dest_row[p+0] = pixelval(255 * col.x) * col.w + g * (1.0 - col.w);
  2707.     dest_row[p+1] = pixelval(255 * col.y) * col.w + g * (1.0 - col.w);
  2708.     dest_row[p+2] = pixelval(255 * col.z) * col.w + g * (1.0 - col.w);
  2709.  
  2710.     if(running != 1) {
  2711.       break;
  2712.     }
  2713.       }
  2714.       drawit(img);
  2715.       while(gtk_events_pending())
  2716.     gtk_main_iteration();
  2717.       if(running != 1) {
  2718.     break;
  2719.       }
  2720.     }
  2721.     if(running == 1) break;
  2722.     if(running == -1) break;
  2723.   }
  2724.   running = 0;
  2725.   drawit(img);
  2726. }
  2727.  
  2728. void realrender(GimpDrawable *drawable)
  2729. {
  2730.   int x, y, alpha;
  2731.   ray r;
  2732.   vector rcol;
  2733.   int tx, ty;
  2734.   gint x1, y1, x2, y2;
  2735.   guchar *dest;
  2736.   int bpp;
  2737.   GimpPixelRgn pr, dpr;
  2738.   guchar *buffer, *ibuffer;
  2739.  
  2740.   if(running > 0) return; /* Fixme: abort preview-render instead! */
  2741.  
  2742.   initworld();
  2743.  
  2744.   r.v1.z = -10.0;
  2745.   r.v2.z = 0.0;
  2746.  
  2747.   alpha = gimp_drawable_has_alpha(drawable->id);
  2748.  
  2749.   gimp_pixel_rgn_init(&pr, drawable, 0, 0,
  2750.               gimp_drawable_width(drawable->id),
  2751.               gimp_drawable_height(drawable->id), FALSE, FALSE);
  2752.   gimp_pixel_rgn_init(&dpr, drawable, 0, 0,
  2753.               gimp_drawable_width(drawable->id),
  2754.               gimp_drawable_height(drawable->id), TRUE, TRUE);
  2755.   gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2);
  2756.   bpp = gimp_drawable_bpp(drawable->id);
  2757.   buffer = g_malloc((x2 - x1) * 4);
  2758.   ibuffer = g_malloc((x2 - x1) * 4);
  2759.  
  2760.   tx = x2 - x1;
  2761.   ty = y2 - y1;
  2762.  
  2763.   gimp_progress_init ( _("Rendering..."));
  2764.  
  2765.   for(y = 0; y < ty; y++) {
  2766.     dest = buffer;
  2767.     for(x = 0; x < tx; x++) {
  2768.       r.v1.x = r.v2.x = 8.1 * (x / (float)(tx-1) - 0.5);
  2769.       r.v1.y = r.v2.y = 8.1 * (y / (float)(ty-1) - 0.5);
  2770.  
  2771.       traceray(&r, &rcol, 10, 1.0);
  2772.       dest[0] = pixelval(255 * rcol.x);
  2773.       dest[1] = pixelval(255 * rcol.y);
  2774.       dest[2] = pixelval(255 * rcol.z);
  2775.       dest[3] = pixelval(255 * rcol.w);
  2776.       dest += 4;
  2777.     }
  2778.     gimp_pixel_rgn_get_row(&pr, ibuffer, x1, y1 + y, x2 - x1);
  2779.     for(x = 0; x < (x2-x1); x++) {
  2780.       int k, dx = x * 4, sx = x * bpp;
  2781.       float a = buffer[dx+3] / 255.0;
  2782.       for(k = 0; k < bpp; k++) {
  2783.     ibuffer[sx+k] = buffer[dx+k] * a + ibuffer[sx+k] * (1.0 - a);
  2784.       }
  2785.     }
  2786.     gimp_pixel_rgn_set_row(&dpr, ibuffer, x1, y1 + y, x2 - x1);
  2787.     gimp_progress_update((double)y / (double)ty);
  2788.   }
  2789.   g_free(buffer);
  2790.   g_free(ibuffer);
  2791.   gimp_drawable_flush (drawable);
  2792.   gimp_drawable_merge_shadow (drawable->id, TRUE);
  2793.   gimp_drawable_update (drawable->id, x1, y1, (x2 - x1), (y2 - y1));
  2794. }
  2795.  
  2796. static void
  2797. query (void)
  2798. {
  2799.   static GimpParamDef args[] =
  2800.   {
  2801.     { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
  2802.     { GIMP_PDB_IMAGE, "image", "Input image (unused)" },
  2803.     { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }
  2804.   };
  2805.   static gint nargs = sizeof (args) / sizeof (args[0]);
  2806.  
  2807.   gimp_install_procedure ("plug_in_spheredesigner",
  2808.                           "Renders textures spheres",
  2809.                           "This plugin can be used to create textured and/or bumpmapped spheres, and uses a small lightweight raytracer to perform the task with good quality",
  2810.               "Vidar Madsen",
  2811.                           "Vidar Madsen",
  2812.                           "1999",
  2813.                           N_("<Image>/Filters/Render/Sphere Designer..."),
  2814.                           "RGB*, GRAY*",
  2815.                           GIMP_PLUGIN,
  2816.               nargs, 0,
  2817.                           args, NULL);
  2818. }
  2819.  
  2820.  
  2821. int sphere_main(GimpDrawable *drawable)
  2822. {
  2823.   initworld ();
  2824.  
  2825.   gimp_ui_init ("spheredesigner", TRUE);
  2826.  
  2827.   memset (img, 0, PREVIEWSIZE*PREVIEWSIZE*3);
  2828.   makewindow ();
  2829.  
  2830.   if (!s.com.numtexture)
  2831.     sphere_reset ();
  2832.   else
  2833.     rebuildlist ();
  2834.  
  2835.   drawit (img);
  2836.   gtk_main ();
  2837.   gdk_flush ();
  2838.  
  2839.   return do_run;
  2840. }
  2841.  
  2842. static void
  2843. run (gchar   *name,
  2844.      gint     nparams,
  2845.      GimpParam  *param,
  2846.      gint    *nreturn_vals,
  2847.      GimpParam **return_vals)
  2848. {
  2849.   static GimpParam values[1];
  2850.   GimpDrawable *drawable;
  2851.   GimpRunModeType run_mode;
  2852.   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  2853.  
  2854.   run_mode = param[0].data.d_int32;
  2855.  
  2856.   *nreturn_vals = 1;
  2857.   *return_vals = values;
  2858.  
  2859.   values[0].type = GIMP_PDB_STATUS;
  2860.   values[0].data.d_status = status;
  2861.  
  2862.   drawable = gimp_drawable_get (param[2].data.d_drawable);
  2863.  
  2864.   switch(run_mode) {
  2865.   case GIMP_RUN_INTERACTIVE:
  2866.     INIT_I18N_UI();
  2867.     s.com.numtexture = 0;
  2868.     gimp_get_data(PLUG_IN_NAME, &s);
  2869.     if(!sphere_main(drawable)) {
  2870.       gimp_drawable_detach(drawable);
  2871.       return;
  2872.     }
  2873.     break;
  2874.   case GIMP_RUN_WITH_LAST_VALS:
  2875.     INIT_I18N();
  2876.     s.com.numtexture = 0;
  2877.     gimp_get_data(PLUG_IN_NAME, &s);
  2878.     if(s.com.numtexture == 0) {
  2879.       gimp_drawable_detach(drawable);
  2880.       return;
  2881.     }
  2882.     break;
  2883.   case GIMP_RUN_NONINTERACTIVE:
  2884.   default:
  2885.     /* Not implementet yet... */
  2886.     gimp_drawable_detach(drawable);
  2887.     return;
  2888.   }
  2889.  
  2890.   gimp_set_data(PLUG_IN_NAME, &s, sizeof(s));
  2891.  
  2892.   realrender(drawable);
  2893.   gimp_displays_flush ();
  2894.  
  2895.   *nreturn_vals = 1;
  2896.   *return_vals = values;
  2897.  
  2898.   values[0].type = GIMP_PDB_STATUS;
  2899.   values[0].data.d_status = status;
  2900.   
  2901.   gimp_drawable_detach (drawable);
  2902. }
  2903.  
  2904. MAIN ()
  2905.