~ubuntu-branches/ubuntu/utopic/gimp/utopic

« back to all changes in this revision

Viewing changes to .pc/05_CVE-2010-454x.patch/plug-ins/common/sphere-designer.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2011-04-07 10:40:22 UTC
  • Revision ID: package-import@ubuntu.com-20110407104022-ka90cx60lwrf9ro7
Tags: 2.6.11-1ubuntu6
* SECURITY UPDATE: denial of service and possible code execution via
  malformed plugin configuration files
  - debian/patches/05_CVE-2010-454x.patch: fix format strings in
    plug-ins/{common/sphere-designer,gfig/gfig-style,
    lighting/lighting-ui}.c.
  - CVE-2010-4540
  - CVE-2010-4541
  - CVE-2010-4542
* SECURITY UPDATE: denial of service and possible code execution via
  malformed PSP image file
  - debian/patches/06_CVE-2010-4543.patch: fix buffer overflow in
    plug-ins/common/file-psp.c.
  - CVE-2010-4543

Show diffs side-by-side

added added

removed removed

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