2
* GIMP - The GNU Image Manipulation Program
3
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
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.
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.
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.
21
* SphereDesigner v0.4 - creates textured spheres
22
* by Vidar Madsen <vidar@prosalg.no>
24
* Status: Last updated 1999-09-11
27
* - Might crash if you click OK or Cancel before first preview is rendered
28
* - Phong might look weird with transparent textures
31
* - Saving / Loading of presets needs an overhaul
33
* - Global controls: Gamma, ++
34
* - Beautification of GUI
35
* - Clean up messy source (lots of Glade remnants)
36
* - (Probably more. ;-)
44
#include <glib/gstdio.h>
46
#include <libgimp/gimp.h>
47
#include <libgimp/gimpui.h>
49
#include "libgimp/stdplugins-intl.h"
52
#define PLUG_IN_PROC "plug-in-spheredesigner"
53
#define PLUG_IN_BINARY "sphere-designer"
55
#define RESPONSE_RESET 1
57
#define PREVIEWSIZE 150
59
/* These must be adjusted as more functionality is added */
63
#define MAXTEXTUREPEROBJ 20
65
#define MAXNORMALPEROBJ 20
67
#define MAXCOLPERGRADIENT 5
69
static void query (void);
70
static void run (const gchar *name,
72
const GimpParam *param,
74
GimpParam **return_vals);
76
const GimpPlugInInfo PLUG_IN_INFO =
80
query, /* query_proc */
133
#define SMARTAMBIENT 0x00000001
136
#define NOSHADOW 0x00000001
139
#define GRADIENT 0x00000001
150
gdouble pos[MAXCOLPERGRADIENT];
151
GimpVector4 color[MAXCOLPERGRADIENT];
159
GimpVector4 color1, color2;
161
GimpVector4 ambient, diffuse;
163
GimpVector4 scale, translate, rotate;
165
GimpVector4 reflection;
166
GimpVector4 refraction;
167
GimpVector4 transparent;
169
GimpVector4 phongcolor;
173
GimpVector4 turbulence;
189
texture texture[MAXTEXTUREPEROBJ];
191
texture normal[MAXNORMALPEROBJ];
255
object obj[MAXOBJECT];
257
light light[MAXLIGHT];
259
texture texture[MAXTEXTURE];
262
gdouble smartambient;
264
atmos atmos[MAXATMOS];
269
GimpVector4 location, lookat, up, right;
274
static GtkWidget *drawarea = NULL;
276
static guchar img[PREVIEWSIZE * PREVIEWSIZE * 3];
278
static guint idle_id = 0;
289
static struct textures_t textures[] =
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 },
303
static inline void vset (GimpVector4 *v,
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,
314
static gint traceray (ray *r,
318
static gdouble turbulence (gdouble *point,
323
#define COLORBUTTONWIDTH 30
324
#define COLORBUTTONHEIGHT 20
326
static GtkTreeView *texturelist = NULL;
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;
338
#define DOT(a,b) (a[0] * b[0] + a[1] * b[1] + a[2] * b[2])
342
static gint p[B + B + 2];
343
static gdouble g[B + B + 2][3];
344
static gboolean start = TRUE;
354
/* Create an array of random gradient vectors uniformly on the unit sphere */
357
g_rand_set_seed (gr, 1); /* Use static seed, to get reproducable results */
359
for (i = 0; i < B; i++)
362
{ /* Choose uniformly in a cube */
363
for (j = 0; j < 3; j++)
364
v[j] = g_rand_double_range (gr, -1, 1);
367
while (s > 1.0); /* If not in sphere try again */
369
for (j = 0; j < 3; j++) /* Else normalize */
373
/* Create a pseudorandom permutation of [1..B] */
375
for (i = 0; i < B; i++)
377
for (i = B; i > 0; i -= 2)
380
p[i] = p[j = g_rand_int_range (gr, 0, B)];
384
/* Extend g and p arrays to allow for faster indexing */
386
for (i = 0; i < B + 2; i++)
389
for (j = 0; j < 3; j++)
390
g[B + i][j] = g[i][j];
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); \
404
noise3 (gdouble * vec)
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;
416
setup (0, bx0, bx1, rx0, rx1);
417
setup (1, by0, by1, ry0, ry1);
418
setup (2, bz0, bz1, rz0, rz1);
428
#define at(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
430
#define surve(t) ( t * t * (3. - 2. * t) )
432
#define lerp(t, a, b) ( a + t * (b - a) )
440
u = at (rx0, ry0, rz0);
442
v = at (rx1, ry0, rz0);
446
u = at (rx0, ry1, rz0);
448
v = at (rx1, ry1, rz0);
451
c = lerp (sy, a, b); /* interpolate in y at lo x */
454
u = at (rx0, ry0, rz1);
456
v = at (rx1, ry0, rz1);
460
u = at (rx0, ry1, rz1);
462
v = at (rx1, ry1, rz1);
465
d = lerp (sy, a, b); /* interpolate in y at hi x */
467
return 1.5 * lerp (sz, c, d); /* interpolate in z */
471
turbulence (gdouble * point, gdouble lofreq, gdouble hifreq)
473
gdouble freq, t, p[3];
475
p[0] = point[0] + 123.456;
476
p[1] = point[1] + 234.567;
477
p[2] = point[2] + 345.678;
480
for (freq = lofreq; freq < hifreq; freq *= 2.)
482
t += noise3 (p) / freq;
487
return t - 0.3; /* readjust to make mean value = 0.0 */
490
static struct world_t world;
493
vcopy (GimpVector4 *a, GimpVector4 *b)
499
vcross (GimpVector4 *r, GimpVector4 *a, GimpVector4 *b)
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;
506
static inline gdouble
507
vdot (GimpVector4 *a, GimpVector4 *b)
509
return a->x * b->x + a->y * b->y + a->z * b->z;
512
static inline gdouble
513
vdist (GimpVector4 *a, GimpVector4 *b)
521
return sqrt (x * x + y * y + z * z);
524
static inline gdouble
525
vlen (GimpVector4 *a)
527
return sqrt (a->x * a->x + a->y * a->y + a->z * a->z);
531
vnorm (GimpVector4 *a, gdouble v)
542
vrotate (GimpVector4 *axis, gdouble ang, GimpVector4 *vector)
544
gdouble rad = ang / 180.0 * G_PI;
545
gdouble ax = vector->x;
546
gdouble ay = vector->y;
547
gdouble az = vector->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;
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;
570
vset (GimpVector4 *v, gdouble a, gdouble b, gdouble c)
579
vcset (GimpVector4 *v, gdouble a, gdouble b, gdouble c, gdouble d)
588
vvrotate (GimpVector4 *p, GimpVector4 *rot)
594
vset (&axis, 1, 0, 0);
595
vrotate (&axis, rot->x, p);
599
vset (&axis, 0, 1, 0);
600
vrotate (&axis, rot->y, p);
604
vset (&axis, 0, 0, 1);
605
vrotate (&axis, rot->z, p);
610
vsub (GimpVector4 *a, GimpVector4 *b)
619
vadd (GimpVector4 *a, GimpVector4 *b)
628
vneg (GimpVector4 *a)
637
vmul (GimpVector4 *v, gdouble a)
646
vvmul (GimpVector4 *a, GimpVector4 *b)
655
vvdiv (GimpVector4 *a, GimpVector4 *b)
663
vmix (GimpVector4 *r, GimpVector4 *a, GimpVector4 *b, gdouble v)
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;
674
vmax (GimpVector4 *a)
676
gdouble max = fabs (a->x);
678
if (fabs (a->y) > max)
680
if (fabs (a->z) > max)
682
if (fabs (a->w) > max)
690
vavg (GimpVector4 * a)
694
s = (a->x + a->y + a->z) / 3.0;
695
a->x = a->y = a->z = s;
700
trianglenormal (GimpVector4 * n, gdouble *t, triangle * tri)
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);
710
*t = vdot (&tmp.b, &tmp.c);
714
checkdisc (ray * r, disc * disc)
716
GimpVector4 p, *v = &disc->a;
720
i = r->v2.x - r->v1.x;
721
j = r->v2.y - r->v1.y;
722
k = r->v2.z - r->v1.z;
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);
727
p.x = r->v1.x + i * t;
728
p.y = r->v1.y + j * t;
729
p.z = r->v1.z + k * t;
740
checksphere (ray * r, sphere * sphere)
742
GimpVector4 cendir, rdir;
743
gdouble dirproj, cdlensq;
744
gdouble linear, constant, rsq, quadratic, discriminant;
745
gdouble smallzero, solmin, solmax, tolerance = 0.001;
747
vcopy (&rdir, &r->v2);
748
vsub (&rdir, &r->v1);
750
rsq = sphere->r * sphere->r;
752
vcopy (&cendir, &r->v1);
753
vsub (&cendir, &sphere->a);
754
dirproj = vdot (&rdir, &cendir);
755
cdlensq = vdot (&cendir, &cendir);
757
if ((cdlensq >= rsq) && (dirproj > 0.0))
760
linear = 2.0 * dirproj;
761
constant = cdlensq - rsq;
762
quadratic = vdot (&rdir, &rdir);
764
smallzero = (constant / linear);
765
if ((smallzero < tolerance) && (smallzero > -tolerance))
767
solmin = -linear / quadratic;
769
if (solmin > tolerance)
780
discriminant = linear * linear - 4.0 * quadratic * constant;
781
if (discriminant < 0.0)
784
discriminant = sqrt (discriminant);
785
solmax = (-linear + discriminant) / (quadratic);
786
solmin = (-linear - discriminant) / (quadratic);
788
if (solmax < tolerance)
791
if (solmin < tolerance)
811
checkcylinder (ray * r, cylinder * cylinder)
819
checkplane (ray * r, plane * plane)
821
GimpVector4 *v = &plane->a;
825
i = r->v2.x - r->v1.x;
826
j = r->v2.y - r->v1.y;
827
k = r->v2.z - r->v1.z;
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);
836
checktri (ray * r, triangle * tri)
838
GimpVector4 ed1, ed2;
839
GimpVector4 tvec, pvec, qvec;
840
gdouble det, idet, t, u, v;
841
GimpVector4 *orig, dir;
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);
861
vsub (&tvec, &tri->a);
862
u = vdot (&tvec, &pvec) * idet;
869
vcross (&qvec, &tvec, &ed1);
870
v = vdot (&dir, &qvec) * idet;
872
if ((v < 0.0) || (u + v > 1.0))
875
t = vdot (&ed2, &qvec) * idet;
881
transformpoint (GimpVector4 * p, texture * t)
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);
889
vsub (p, &t->translate);
891
if ((t->turbulence.x != 0.0) || (t->turbulence.y != 0.0) ||
892
(t->turbulence.z != 0.0))
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;
905
checker (GimpVector4 *q, GimpVector4 *col, texture *t)
911
transformpoint (&p, t);
926
if ((p.x - (gint) p.x) < 0.5)
928
if ((p.y - (gint) p.y) < 0.5)
930
if ((p.z - (gint) p.z) < 0.5)
933
*col = (c) ? t->color1 : t->color2;
937
gradcolor (GimpVector4 *col, gradient *t, gdouble val)
943
val = CLAMP (val, 0.0, 1.0);
945
for (i = 0; i < t->numcol; i++)
947
if (t->pos[i] == val)
954
d = (val - t->pos[i - 1]) / (t->pos[i] - t->pos[i - 1]);
955
vcopy (&tmpcol, &t->color[i]);
957
vcopy (col, &tmpcol);
958
vcopy (&tmpcol, &t->color[i - 1]);
959
vmul (&tmpcol, 1.0 - d);
964
g_printerr ("Error in gradient!\n");
969
marble (GimpVector4 *q, GimpVector4 *col, texture *t)
975
transformpoint (&p, t);
977
f = sin (p.x * 4) / 2 + 0.5;
980
if (t->flags & GRADIENT)
981
gradcolor (col, &t->gradient, f);
983
vmix (col, &t->color1, &t->color2, f);
987
lizard (GimpVector4 *q, GimpVector4 *col, texture *t)
993
transformpoint (&p, t);
995
f = fabs (sin (p.x * 4));
996
f += fabs (sin (p.y * 4));
997
f += fabs (sin (p.z * 4));
1001
if (t->flags & GRADIENT)
1002
gradcolor (col, &t->gradient, f);
1004
vmix (col, &t->color1, &t->color2, f);
1008
wood (GimpVector4 *q, GimpVector4 *col, texture *t)
1014
transformpoint (&p, t);
1019
f = pow (f, t->exp);
1021
if (t->flags & GRADIENT)
1022
gradcolor (col, &t->gradient, f);
1024
vmix (col, &t->color1, &t->color2, f);
1028
spiral (GimpVector4 *q, GimpVector4 *col, texture *t)
1034
transformpoint (&p, t);
1036
f = fabs (atan2 (p.x, p.z) / G_PI / 2 + p.y + 99999);
1039
f = pow (f, t->exp);
1041
if (t->flags & GRADIENT)
1042
gradcolor (col, &t->gradient, f);
1044
vmix (col, &t->color1, &t->color2, f);
1048
spots (GimpVector4 *q, GimpVector4 *col, texture *t)
1054
transformpoint (&p, t);
1060
vset (&r, (gint) (p.x + 0.5), (gint) (p.y + 0.5), (gint) (p.z + 0.5));
1063
f = CLAMP (f, 0.0, 1.0);
1064
f = pow (f, t->exp);
1066
if (t->flags & GRADIENT)
1067
gradcolor (col, &t->gradient, f);
1069
vmix (col, &t->color1, &t->color2, f);
1073
perlin (GimpVector4 * q, GimpVector4 * col, texture * t)
1075
gdouble f, point[3];
1079
transformpoint (&p, t);
1085
f = turbulence (point, 1, 256) * 0.3 + 0.5;
1087
f = pow (f, t->exp);
1089
if (t->flags & GRADIENT)
1090
gradcolor (col, &t->gradient, f);
1092
vmix (col, &t->color1, &t->color2, f);
1096
imagepixel (GimpVector4 * q, GimpVector4 * col, texture * t)
1103
transformpoint (&p, t);
1105
x = (p.x * t->image.xsize);
1106
y = (p.y * t->image.ysize);
1108
x = (x % t->image.xsize + t->image.xsize) % t->image.xsize;
1109
y = (y % t->image.ysize + t->image.ysize) % t->image.ysize;
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);
1116
objcolor (GimpVector4 *col, GimpVector4 *p, common *obj)
1122
vcset (col, 0, 0, 0, 0);
1124
for (i = 0; i < obj->numtexture; i++)
1126
t = &obj->texture[i];
1128
if (world.quality < 1)
1130
vadd (col, &t->color1);
1134
vset (&tmpcol, 0, 0, 0);
1138
vcopy (&tmpcol, &t->color1);
1141
checker (p, &tmpcol, t);
1144
marble (p, &tmpcol, t);
1147
lizard (p, &tmpcol, t);
1150
perlin (p, &tmpcol, t);
1153
wood (p, &tmpcol, t);
1156
spiral (p, &tmpcol, t);
1159
spots (p, &tmpcol, t);
1162
imagepixel (p, &tmpcol, t);
1169
/* Silently ignore non-color textures */
1173
g_printerr ("Warning: unknown texture %d\n", t->type);
1176
vmul (&tmpcol, t->amount);
1177
vadd (col, &tmpcol);
1181
g_printerr ("Warning: object %p has no textures\n", obj);
1186
objnormal (GimpVector4 *res, common *obj, GimpVector4 *p)
1193
trianglenormal (res, NULL, (triangle *) obj);
1196
vcopy (res, &((disc *) obj)->a);
1199
vcopy (res, &((plane *) obj)->a);
1202
vcopy (res, &((sphere *) obj)->a);
1206
vset (res, 1, 1, 1); /* fixme */
1209
g_error ("objnormal(): Unsupported object type!?\n");
1213
for (i = 0; i < obj->numnormal; i++)
1216
GimpVector4 tmpcol[6];
1217
GimpVector4 q[6], nres;
1218
texture *t = &obj->normal[i];
1219
gdouble nstep = 0.1;
1221
vset (&nres, 0, 0, 0);
1222
for (k = 0; k < 6; k++)
1236
for (k = 0; k < 6; k++)
1237
marble (&q[k], &tmpcol[k], t);
1240
for (k = 0; k < 6; k++)
1241
lizard (&q[k], &tmpcol[k], t);
1244
for (k = 0; k < 6; k++)
1245
perlin (&q[k], &tmpcol[k], t);
1248
for (k = 0; k < 6; k++)
1249
wood (&q[k], &tmpcol[k], t);
1252
for (k = 0; k < 6; k++)
1253
spiral (&q[k], &tmpcol[k], t);
1256
for (k = 0; k < 6; k++)
1257
spots (&q[k], &tmpcol[k], t);
1260
for (k = 0; k < 6; k++)
1261
imagepixel (&q[k], &tmpcol[k], t);
1273
g_printerr ("Warning: unknown texture %d\n", t->type);
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;
1282
vmul (&nres, t->amount);
1295
5 = Reflection + Refraction
1299
calclight (GimpVector4 * col, GimpVector4 * point, common * obj)
1308
vcset (col, 0, 0, 0, 0);
1310
objcolor (&pcol, point, obj);
1313
if (world.quality < 2)
1319
for (i = 0; i < obj->numtexture; i++)
1321
if (obj->texture[i].type == PHONG)
1323
if (obj->texture[i].type == REFLECTION)
1325
if (obj->texture[i].type == REFRACTION)
1327
if (obj->texture[i].type == TRANSPARENT)
1329
if (obj->texture[i].type == SMOKE)
1331
vcopy (&lcol, &pcol);
1332
vvmul (&lcol, &obj->texture[i].ambient);
1336
objnormal (&norm, obj, point);
1342
for (i = 0; i < world.numlight; i++)
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);
1349
vsub (&r.v1, &r.v2);
1351
b = vdot (&r.v1, &norm);
1356
for (j = 0; j < obj->numtexture; j++)
1358
if (obj->texture[j].type == PHONG)
1360
if (obj->texture[j].type == REFLECTION)
1362
if (obj->texture[j].type == REFRACTION)
1364
if (obj->texture[j].type == TRANSPARENT)
1366
if (obj->texture[j].type == SMOKE)
1368
vcopy (&lcol, &pcol);
1369
vvmul (&lcol, &world.light[i].color);
1370
vvmul (&lcol, &obj->texture[j].diffuse);
1379
calcphong (common * obj, ray * r2, GimpVector4 * col)
1391
vcopy (&norm, &r2->v2);
1392
vsub (&norm, &r2->v1);
1398
for (i = 0; i < world.numlight; i++)
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);
1405
o = traceray (&r, NULL, -1, 1.0);
1411
/* OK, light is visible */
1413
vsub (&r.v1, &r.v2);
1415
b = -vdot (&r.v1, &norm);
1417
for (j = 0; j < obj->numtexture; j++)
1419
if (obj->texture[j].type != PHONG)
1422
ps = obj->texture[j].phongsize;
1426
ps = (b - (1 - ps)) / ps;
1428
vcopy (&lcol, &obj->texture[j].phongcolor);
1429
vvmul (&lcol, &world.light[i].color);
1437
traceray (ray * r, GimpVector4 * col, gint level, gdouble imp)
1440
gdouble t = -1.0, min = 0.0;
1442
common *obj, *bobj = NULL;
1446
if ((level == 0) || (imp < 0.005))
1448
vset (col, 0, 1, 0);
1452
for (i = 0; i < world.numobj; i++)
1454
obj = (common *) & world.obj[i];
1458
t = checktri (r, (triangle *) & world.obj[i]);
1461
t = checkdisc (r, (disc *) & world.obj[i]);
1464
t = checkplane (r, (plane *) & world.obj[i]);
1467
t = checksphere (r, (sphere *) & world.obj[i]);
1470
t = checkcylinder (r, (cylinder *) & world.obj[i]);
1473
g_error ("Illegal object!!\n");
1478
if (!(obj->flags & NOSHADOW) && (level == -1))
1484
if ((!bobj) || (t < min))
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;
1502
calclight (col, &p, bobj);
1504
if (world.flags & SMARTAMBIENT)
1506
gdouble ambient = 0.3 * exp (-min / world.smartambient);
1508
objcolor (&lcol, &p, bobj);
1509
vmul (&lcol, ambient);
1513
for (i = 0; i < bobj->numtexture; i++)
1516
if ((world.quality >= 4)
1517
&& ((bobj->texture[i].type == REFLECTION)
1518
|| (bobj->texture[i].type == PHONG)))
1521
GimpVector4 refcol, norm, ocol;
1524
objcolor (&ocol, &p, bobj);
1526
vcopy (&ref.v1, &p);
1527
vcopy (&ref.v2, &r->v1);
1528
ref.inside = r->inside;
1531
vmix (&ref.v1, &ref.v1, &ref.v2, 0.9999); /* push it a tad */
1534
objnormal (&norm, bobj, &p);
1536
vrotate (&norm, 180.0, &ref.v2);
1538
vmul (&norm, -0.0001); /* push it a tad */
1539
vadd (&ref.v1, &norm);
1541
vnorm (&ref.v2, 1.0);
1544
if ((world.quality >= 5)
1545
&& (bobj->texture[i].type == REFLECTION))
1547
traceray (&ref, &refcol, level - 1,
1548
imp * vmax (&bobj->texture[i].reflection));
1549
vvmul (&refcol, &bobj->texture[i].reflection);
1551
vadd (col, &refcol);
1553
if (bobj->texture[i].type == PHONG)
1555
vcset (&refcol, 0, 0, 0, 0);
1556
calcphong (bobj, &ref, &refcol);
1558
vadd (col, &refcol);
1563
if ((world.quality >= 5) && (col->w < 1.0))
1568
vcopy (&ref.v1, &p);
1569
vcopy (&ref.v2, &p);
1570
vsub (&ref.v2, &r->v1);
1571
vnorm (&ref.v2, 1.0);
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);
1580
if ((world.quality >= 5) && (bobj->texture[i].type == TRANSPARENT))
1585
vcopy (&ref.v1, &p);
1586
vcopy (&ref.v2, &p);
1587
vsub (&ref.v2, &r->v1);
1588
vnorm (&ref.v2, 1.0);
1591
vmix (&ref.v1, &ref.v1, &ref.v2, 0.999); /* push it a tad */
1593
traceray (&ref, &refcol, level - 1,
1594
imp * vmax (&bobj->texture[i].transparent));
1595
vvmul (&refcol, &bobj->texture[i].transparent);
1597
vadd (col, &refcol);
1600
if ((world.quality >= 5) && (bobj->texture[i].type == SMOKE))
1602
GimpVector4 smcol, raydir, norm;
1606
vcopy (&ref.v1, &p);
1607
vcopy (&ref.v2, &p);
1608
vsub (&ref.v2, &r->v1);
1609
vnorm (&ref.v2, 1.0);
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);
1620
vcopy (&smcol, &bobj->texture[i].color1);
1621
vmul (&smcol, tran);
1625
if ((world.quality >= 5) && (bobj->texture[i].type == REFRACTION))
1627
GimpVector4 refcol, norm, tmpv;
1629
double c1, c2, n1, n2, n;
1631
vcopy (&ref.v1, &p);
1632
vcopy (&ref.v2, &p);
1633
vsub (&ref.v2, &r->v1);
1634
vadd (&ref.v2, &r->v2);
1636
vmix (&ref.v1, &ref.v1, &ref.v2, 0.999); /* push it a tad */
1639
objnormal (&norm, bobj, &p);
1649
ref.ior = bobj->texture[i].ior;
1652
c1 = vdot (&norm, &ref.v2);
1657
n1 = r->ior; /* IOR of current media */
1658
n2 = ref.ior; /* IOR of new media */
1660
c2 = 1.0 - n * n * (1.0 - c1 * c1);
1664
/* FIXME: Internal reflection should occur */
1674
vcopy (&tmpv, &norm);
1675
vmul (&tmpv, n * c1 - c2);
1676
vadd (&ref.v2, &tmpv);
1678
vnorm (&ref.v2, 1.0);
1681
traceray (&ref, &refcol, level - 1,
1682
imp * vmax (&bobj->texture[i].refraction));
1684
vvmul (&refcol, &bobj->texture[i].refraction);
1685
vadd (col, &refcol);
1691
vcset (col, 0, 0, 0, 0);
1693
vcset (&p, 0, 0, 0, 0);
1696
for (i = 0; i < world.numatmos; i++)
1699
if (world.atmos[i].type == FOG)
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);
1709
vcopy (&tmpcol, &world.atmos[i].color);
1710
vmul (&tmpcol, 1.0 - v);
1711
vadd (col, &tmpcol);
1719
setdefaults (texture * t)
1721
memset (t, 0, sizeof (texture));
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);
1736
mklabel (texture * t)
1738
struct textures_t *l;
1739
static gchar tmps[100];
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"));
1748
strcpy (tmps, "<unknown>");
1749
if ((t->majtype == 0) || (t->majtype == 1))
1751
strcat (tmps, " / ");
1755
if (t->type == l->n)
1757
strcat (tmps, gettext (l->s));
1767
currenttexture (void)
1769
GtkTreeSelection *sel;
1773
sel = gtk_tree_view_get_selection (texturelist);
1775
if (gtk_tree_selection_get_selected (sel, NULL, &iter))
1777
gtk_tree_model_get (gtk_tree_view_get_model (texturelist), &iter,
1788
GtkTreeModel *model;
1789
GtkTreeSelection *sel;
1793
sel = gtk_tree_view_get_selection (texturelist);
1795
if (gtk_tree_selection_get_selected (sel, NULL, &iter))
1797
model = gtk_tree_view_get_model (texturelist);
1799
gtk_tree_model_get (model, &iter,
1802
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
1808
static gboolean noupdate = FALSE;
1811
setvals (texture *t)
1813
struct textures_t *l;
1819
gtk_adjustment_set_value (GTK_ADJUSTMENT (amountscale), t->amount);
1821
gtk_adjustment_set_value (GTK_ADJUSTMENT (scalescale), t->oscale);
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);
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);
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);
1835
gtk_adjustment_set_value (GTK_ADJUSTMENT (turbulencescale),
1837
gtk_adjustment_set_value (GTK_ADJUSTMENT (expscale), t->exp);
1845
if (l->n == t->type)
1847
gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (texturemenu),
1854
gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (typemenu), t->majtype);
1860
selectitem (GtkTreeSelection *treeselection,
1863
setvals (currenttexture ());
1869
GtkListStore *list_store;
1871
gint n = s.com.numtexture;
1873
if (n == MAXTEXTUREPEROBJ - 1)
1876
setdefaults (&s.com.texture[n]);
1878
list_store = GTK_LIST_STORE (gtk_tree_view_get_model (texturelist));
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],
1885
gtk_tree_selection_select_iter (gtk_tree_view_get_selection (texturelist),
1896
GtkListStore *list_store;
1898
texture *t = currenttexture ();
1899
gint n = s.com.numtexture;
1901
if (n == MAXTEXTUREPEROBJ - 1)
1906
s.com.texture[n] = *t;
1908
list_store = GTK_LIST_STORE (gtk_tree_view_get_model (texturelist));
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],
1915
gtk_tree_selection_select_iter (gtk_tree_view_get_selection (texturelist),
1926
GtkListStore *list_store;
1927
GtkTreeSelection *sel;
1931
sel = gtk_tree_view_get_selection (texturelist);
1933
for (n = 0; n < s.com.numtexture; n++)
1935
if (s.com.numtexture && (s.com.texture[n].majtype < 0))
1939
for (i = n; i < s.com.numtexture - 1; i++)
1940
s.com.texture[i] = s.com.texture[i + 1];
1947
list_store = GTK_LIST_STORE (gtk_tree_view_get_model (texturelist));
1949
for (n = 0; n < s.com.numtexture; n++)
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],
1958
if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list_store), &iter))
1959
gtk_tree_selection_select_iter (sel, &iter);
1967
GtkTreeSelection *sel;
1968
GtkTreeModel *model;
1972
sel = gtk_tree_view_get_selection (texturelist);
1974
if (gtk_tree_selection_get_selected (sel, NULL, &iter))
1976
model = gtk_tree_view_get_model (texturelist);
1978
gtk_tree_model_get (model, &iter,
1982
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
1989
loadit (const gchar * fn)
1992
gchar endbuf[21 * (G_ASCII_DTOSTR_BUF_SIZE + 1)];
1993
gchar *end = endbuf;
1999
f = g_fopen (fn, "rt");
2002
g_message (_("Could not open '%s' for reading: %s"),
2003
gimp_filename_to_utf8 (fn), g_strerror (errno));
2007
if (2 != fscanf (f, "%d %d", &majtype, &type) || majtype < 0 || majtype > 2)
2009
g_message (_("File '%s' is not a valid save file."),
2010
gimp_filename_to_utf8 (fn));
2017
s.com.numtexture = 0;
2022
if (!fgets (line, 1023, f))
2025
i = s.com.numtexture;
2026
t = &s.com.texture[i];
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);
2079
loadpreset_response (GtkWidget *dialog,
2083
if (response_id == GTK_RESPONSE_OK)
2085
GtkTreeModel *model = gtk_tree_view_get_model (texturelist);
2088
name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
2090
gtk_list_store_clear (GTK_LIST_STORE (model));
2098
gtk_widget_hide (dialog);
2102
saveit (const gchar *fn)
2106
gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
2108
f = g_fopen (fn, "wt");
2111
g_message (_("Could not open '%s' for writing: %s"),
2112
gimp_filename_to_utf8 (fn), g_strerror (errno));
2116
for (i = 0; i < s.com.numtexture; i++)
2118
texture *t = &s.com.texture[i];
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));
2152
savepreset_response (GtkWidget *dialog,
2156
if (response_id == GTK_RESPONSE_OK)
2158
gchar *name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
2164
gtk_widget_hide (dialog);
2168
loadpreset (GtkWidget *widget,
2171
fileselect (GTK_FILE_CHOOSER_ACTION_OPEN, parent);
2175
savepreset (GtkWidget *widget,
2178
fileselect (GTK_FILE_CHOOSER_ACTION_SAVE, parent);
2182
fileselect (GtkFileChooserAction action,
2185
static GtkWidget *windows[2] = { NULL, NULL };
2187
gchar *titles[] = { N_("Open File"), N_("Save File") };
2188
void *handlers[] = { loadpreset_response, savepreset_response };
2190
if (! windows[action])
2192
GtkWidget *dialog = windows[action] =
2193
gtk_file_chooser_dialog_new (gettext (titles[action]),
2194
GTK_WINDOW (parent),
2197
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2199
action == GTK_FILE_CHOOSER_ACTION_OPEN ?
2200
GTK_STOCK_OPEN : GTK_STOCK_SAVE,
2205
gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
2207
GTK_RESPONSE_CANCEL,
2210
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
2212
if (action == GTK_FILE_CHOOSER_ACTION_SAVE)
2213
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog),
2216
g_signal_connect (dialog, "destroy",
2217
G_CALLBACK (gtk_widget_destroyed),
2219
g_signal_connect (dialog, "response",
2220
G_CALLBACK (handlers[action]),
2224
gtk_window_present (GTK_WINDOW (windows[action]));
2232
memset (&world, 0, sizeof (world));
2234
s.com.type = SPHERE;
2235
s.a.x = s.a.y = s.a.z = 0.0;
2238
/* not: world.obj[0] = s;
2239
* s is a sphere so error C2115: '=' : incompatible types
2241
memcpy (&world.obj[0], &s, sizeof (s));
2244
world.obj[0].com.numtexture = 0;
2245
world.obj[0].com.numnormal = 0;
2247
for (i = 0; i < s.com.numtexture; i++)
2250
common *d = &world.obj[0].com;
2251
texture *t = &c->texture[i];
2252
if ((t->amount <= 0.0) || (t->majtype < 0))
2254
if (t->majtype == 0)
2255
{ /* Normal texture */
2256
if (t->type == PHONG)
2258
t->phongcolor = t->color1;
2259
t->phongsize = t->oscale / 25.0;
2261
d->texture[d->numtexture] = *t;
2262
vmul (&d->texture[d->numtexture].scale,
2263
d->texture[d->numtexture].oscale);
2266
else if (t->majtype == 1)
2268
d->normal[d->numnormal] = *t;
2269
vmul (&d->normal[d->numnormal].scale,
2270
d->texture[d->numnormal].oscale);
2273
else if (t->majtype == 2)
2276
vcopy (&l.a, &t->translate);
2277
vcopy (&l.color, &t->color1);
2278
vmul (&l.color, t->amount);
2279
world.light[world.numlight] = l;
2286
world.flags |= SMARTAMBIENT;
2287
world.smartambient = 40.0;
2291
expose_event (GtkWidget *widget,
2292
GdkEventExpose *event)
2294
GtkStyle *style = gtk_widget_get_style (widget);
2295
guchar *data = img + event->area.y * 3 * PREVIEWSIZE + event->area.x * 3;
2297
gdk_draw_rgb_image_dithalign (widget->window,
2299
event->area.x, event->area.y,
2300
event->area.width, event->area.height,
2302
data, PREVIEWSIZE * 3,
2303
- event->area.x, - event->area.y);
2309
restartrender (void)
2312
g_source_remove (idle_id);
2314
idle_id = g_idle_add ((GSourceFunc) render, NULL);
2318
selecttexture (GtkWidget *widget,
2326
t = currenttexture ();
2330
gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &t->type);
2337
selecttype (GtkWidget *widget,
2345
t = currenttexture ();
2349
gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &t->majtype);
2356
getscales (GtkWidget *widget,
2365
t = currenttexture ();
2369
t->amount = GTK_ADJUSTMENT (amountscale)->value;
2370
t->exp = GTK_ADJUSTMENT (expscale)->value;
2372
f = GTK_ADJUSTMENT (turbulencescale)->value;
2373
vset (&t->turbulence, f, f, f);
2375
t->oscale = GTK_ADJUSTMENT (scalescale)->value;
2377
t->scale.x = GTK_ADJUSTMENT (scalexscale)->value;
2378
t->scale.y = GTK_ADJUSTMENT (scaleyscale)->value;
2379
t->scale.z = GTK_ADJUSTMENT (scalezscale)->value;
2381
t->rotate.x = GTK_ADJUSTMENT (rotxscale)->value;
2382
t->rotate.y = GTK_ADJUSTMENT (rotyscale)->value;
2383
t->rotate.z = GTK_ADJUSTMENT (rotzscale)->value;
2385
t->translate.x = GTK_ADJUSTMENT (posxscale)->value;
2386
t->translate.y = GTK_ADJUSTMENT (posyscale)->value;
2387
t->translate.z = GTK_ADJUSTMENT (poszscale)->value;
2394
color1_changed (GimpColorButton *button)
2396
texture *t = currenttexture ();
2402
gimp_color_button_get_color (button, &color);
2404
t->color1.x = color.r;
2405
t->color1.y = color.g;
2406
t->color1.z = color.b;
2407
t->color1.w = color.a;
2414
color2_changed (GimpColorButton *button)
2416
texture *t = currenttexture ();
2422
gimp_color_button_get_color (button, &color);
2424
t->color2.x = color.r;
2425
t->color2.y = color.g;
2426
t->color2.z = color.b;
2427
t->color2.w = color.a;
2434
drawcolor1 (GtkWidget *w)
2436
static GtkWidget *lastw = NULL;
2439
texture *t = currenttexture ();
2451
gimp_rgba_set (&color,
2452
t->color1.x, t->color1.y, t->color1.z, t->color1.w);
2454
gimp_color_button_set_color (GIMP_COLOR_BUTTON (w), &color);
2458
drawcolor2 (GtkWidget *w)
2460
static GtkWidget *lastw = NULL;
2463
texture *t = currenttexture ();
2475
gimp_rgba_set (&color,
2476
t->color2.x, t->color2.y, t->color2.z, t->color2.w);
2478
gimp_color_button_set_color (GIMP_COLOR_BUTTON (w), &color);
2481
static gboolean do_run = FALSE;
2484
sphere_response (GtkWidget *widget,
2488
switch (response_id)
2490
case RESPONSE_RESET:
2491
s.com.numtexture = 3;
2493
setdefaults (&s.com.texture[0]);
2494
setdefaults (&s.com.texture[1]);
2495
setdefaults (&s.com.texture[2]);
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);
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);
2505
gtk_list_store_clear (GTK_LIST_STORE (gtk_tree_view_get_model (texturelist)));
2510
case GTK_RESPONSE_OK:
2513
g_source_remove (idle_id);
2520
gtk_widget_hide (widget);
2529
GtkListStore *store;
2530
GtkTreeViewColumn *col;
2531
GtkTreeSelection *selection;
2533
GtkWidget *main_hbox;
2534
GtkWidget *main_vbox;
2537
GtkWidget *scrolled;
2542
GimpRGB rgb = { 0, 0, 0, 0 };
2544
window = gimp_dialog_new (_("Sphere Designer"), PLUG_IN_BINARY,
2546
gimp_standard_help_func, PLUG_IN_PROC,
2548
GIMP_STOCK_RESET, RESPONSE_RESET,
2549
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2550
GTK_STOCK_OK, GTK_RESPONSE_OK,
2554
gtk_dialog_set_alternative_button_order (GTK_DIALOG (window),
2557
GTK_RESPONSE_CANCEL,
2560
gimp_window_set_transient (GTK_WINDOW (window));
2562
g_signal_connect (window, "response",
2563
G_CALLBACK (sphere_response),
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);
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);
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);
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);
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);
2589
g_signal_connect (drawarea, "expose-event",
2590
G_CALLBACK (expose_event), NULL);
2592
hbox = gtk_hbox_new (TRUE, 0);
2593
gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
2594
gtk_widget_show (hbox);
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);
2600
g_signal_connect (button, "clicked",
2601
G_CALLBACK (loadpreset),
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);
2608
g_signal_connect (button, "clicked",
2609
G_CALLBACK (savepreset),
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);
2616
scrolled = gtk_scrolled_window_new (NULL, NULL);
2617
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled),
2619
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
2621
GTK_POLICY_AUTOMATIC);
2622
gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 0);
2623
gtk_widget_show (scrolled);
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);
2629
texturelist = GTK_TREE_VIEW (list);
2631
selection = gtk_tree_view_get_selection (texturelist);
2633
gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
2635
g_signal_connect (selection, "changed",
2636
G_CALLBACK (selectitem),
2639
gtk_widget_set_size_request (list, -1, 150);
2640
gtk_container_add (GTK_CONTAINER (scrolled), list);
2641
gtk_widget_show (list);
2643
col = gtk_tree_view_column_new_with_attributes (_("Layers"),
2644
gtk_cell_renderer_text_new (),
2647
gtk_tree_view_append_column (texturelist, col);
2649
hbox = gtk_hbox_new (TRUE, 0);
2650
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
2651
gtk_widget_show (hbox);
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);
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);
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);
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);
2675
frame = gimp_frame_new (_("Properties"));
2676
gtk_box_pack_start (GTK_BOX (main_hbox), frame, TRUE, TRUE, 0);
2677
gtk_widget_show (frame);
2679
vbox = gtk_vbox_new (FALSE, 0);
2680
gtk_container_add (GTK_CONTAINER (frame), vbox);
2681
gtk_widget_show (vbox);
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);
2690
typemenu = gimp_int_combo_box_new (_("Texture"), 0,
2694
gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (typemenu), 0,
2695
G_CALLBACK (selecttype),
2698
gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
2699
_("Type:"), 0.0, 0.5,
2700
typemenu, 2, FALSE);
2702
texturemenu = g_object_new (GIMP_TYPE_INT_COMBO_BOX, NULL);
2704
struct textures_t *t;
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),
2713
gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (texturemenu), 0,
2714
G_CALLBACK (selecttexture),
2717
gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
2718
_("Texture:"), 0.0, 0.5,
2719
texturemenu, 2, FALSE);
2721
hbox = gtk_hbox_new (FALSE, 12);
2722
gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
2723
_("Colors:"), 0.0, 0.5,
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);
2733
g_signal_connect (button, "color-changed",
2734
G_CALLBACK (color1_changed),
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);
2744
g_signal_connect (button, "color-changed",
2745
G_CALLBACK (color2_changed),
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),
2755
turbulencescale = gimp_scale_entry_new (GTK_TABLE (table), 0, 4,
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),
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),
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),
2777
frame = gimp_frame_new (_("Transformations"));
2778
gtk_box_pack_start (GTK_BOX (main_hbox), frame, TRUE, TRUE, 0);
2779
gtk_widget_show (frame);
2781
vbox = gtk_vbox_new (FALSE, 0);
2782
gtk_container_add (GTK_CONTAINER (frame), vbox);
2783
gtk_widget_show (vbox);
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);
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),
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),
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),
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),
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),
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),
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),
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),
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),
2855
gtk_widget_show (window);
2861
pixelval (gdouble v)
2879
gint tx = PREVIEWSIZE;
2880
gint ty = PREVIEWSIZE;
2890
if (world.obj[0].com.numtexture > 0)
2892
for (y = 0; y < ty; y++)
2894
dest_row = img + y * PREVIEWSIZE * 3;
2896
for (x = 0; x < tx; x++)
2898
gint g, gridsize = 16;
2900
g = ((x / gridsize + y / gridsize) % 2) * 60 + 100;
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);
2907
hit = traceray (&r, &col, 10, 1.0);
2911
else if (col.w > 1.0)
2915
pixelval (255 * col.x) * col.w + g * (1.0 - col.w);
2917
pixelval (255 * col.y) * col.w + g * (1.0 - col.w);
2919
pixelval (255 * col.z) * col.w + g * (1.0 - col.w);
2924
gtk_widget_queue_draw (drawarea);
2930
realrender (GimpDrawable *drawable)
2936
gint x1, y1, x2, y2;
2939
GimpPixelRgn pr, dpr;
2940
guchar *buffer, *ibuffer;
2947
gimp_pixel_rgn_init (&pr, drawable, 0, 0,
2948
gimp_drawable_width (drawable->drawable_id),
2949
gimp_drawable_height (drawable->drawable_id), 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,
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);
2963
gimp_progress_init (_("Rendering sphere"));
2965
for (y = 0; y < ty; y++)
2968
for (x = 0; x < tx; x++)
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);
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);
2980
gimp_pixel_rgn_get_row (&pr, ibuffer, x1, y1 + y, x2 - x1);
2981
for (x = 0; x < (x2 - x1); x++)
2983
gint k, dx = x * 4, sx = x * bpp;
2984
gfloat a = buffer[dx + 3] / 255.0;
2986
for (k = 0; k < bpp; k++)
2989
buffer[dx + k] * a + ibuffer[sx + k] * (1.0 - a);
2992
gimp_pixel_rgn_set_row (&dpr, ibuffer, x1, y1 + y, x2 - x1);
2993
gimp_progress_update ((gdouble) y / (gdouble) ty);
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);
3005
static const GimpParamDef args[] =
3007
{ GIMP_PDB_INT32, "run-mode", "Interactive, non-interactive" },
3008
{ GIMP_PDB_IMAGE, "image", "Input image (unused)" },
3009
{ GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }
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",
3020
N_("Sphere _Designer..."),
3023
G_N_ELEMENTS (args), 0,
3026
gimp_plugin_menu_register (PLUG_IN_PROC, "<Image>/Filters/Render");
3030
sphere_main (GimpDrawable *drawable)
3032
gimp_ui_init (PLUG_IN_BINARY, TRUE);
3034
memset (img, 0, PREVIEWSIZE * PREVIEWSIZE * 3);
3037
if (s.com.numtexture == 0)
3039
/* Setup and use default list */
3040
sphere_response (NULL, RESPONSE_RESET, NULL);
3044
/* Reuse the list from a previous invocation */
3054
run (const gchar *name,
3056
const GimpParam *param,
3058
GimpParam **return_vals)
3060
static GimpParam values[1];
3061
GimpDrawable *drawable;
3062
GimpRunMode run_mode;
3063
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
3066
run_mode = param[0].data.d_int32;
3071
*return_vals = values;
3073
values[0].type = GIMP_PDB_STATUS;
3074
values[0].data.d_status = status;
3076
drawable = gimp_drawable_get (param[2].data.d_drawable);
3078
if (! gimp_drawable_mask_intersect (drawable->drawable_id, &x, &y, &w, &h))
3080
g_message (_("Region selected for plug-in is empty"));
3086
case GIMP_RUN_INTERACTIVE:
3087
s.com.numtexture = 0;
3088
gimp_get_data (PLUG_IN_PROC, &s);
3089
if (!sphere_main (drawable))
3091
gimp_drawable_detach (drawable);
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)
3100
gimp_drawable_detach (drawable);
3104
case GIMP_RUN_NONINTERACTIVE:
3106
/* Not implementet yet... */
3107
gimp_drawable_detach (drawable);
3111
gimp_set_data (PLUG_IN_PROC, &s, sizeof (s));
3113
realrender (drawable);
3114
gimp_displays_flush ();
3117
*return_vals = values;
3119
values[0].type = GIMP_PDB_STATUS;
3120
values[0].data.d_status = status;
3122
gimp_drawable_detach (drawable);