~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to plug-ins/MapObject/mapobject_shade.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2008-10-06 13:30:41 UTC
  • mto: This revision was merged to the branch mainline in revision 35.
  • Revision ID: james.westby@ubuntu.com-20081006133041-3panbkcanaymfsmp
Tags: upstream-2.6.0
ImportĀ upstreamĀ versionĀ 2.6.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************/
2
 
/* Shading stuff */
3
 
/*****************/
4
 
 
5
 
#include "config.h"
6
 
 
7
 
#include <string.h>
8
 
 
9
 
#include <libgimp/gimp.h>
10
 
#include <libgimp/gimpui.h>
11
 
 
12
 
#include "mapobject_apply.h"
13
 
#include "mapobject_main.h"
14
 
#include "mapobject_image.h"
15
 
#include "mapobject_shade.h"
16
 
 
17
 
gdouble            bx1, by1, bx2, by2;
18
 
get_ray_color_func get_ray_color;
19
 
 
20
 
typedef struct
21
 
{
22
 
  gdouble     u, v;
23
 
  gdouble     t;
24
 
  GimpVector3 s;
25
 
  GimpVector3 n;
26
 
  gint        face;
27
 
} FaceIntersectInfo;
28
 
 
29
 
/*****************/
30
 
/* Phong shading */
31
 
/*****************/
32
 
 
33
 
static GimpRGB
34
 
phong_shade (GimpVector3 *pos,
35
 
             GimpVector3 *viewpoint,
36
 
             GimpVector3 *normal,
37
 
             GimpVector3 *light,
38
 
             GimpRGB      *diff_col,
39
 
             GimpRGB      *spec_col,
40
 
             gint         type)
41
 
{
42
 
  GimpRGB       ambientcolor, diffusecolor, specularcolor;
43
 
  gdouble      NL, RV, dist;
44
 
  GimpVector3  L, NN, V, N;
45
 
 
46
 
  /* Compute ambient intensity */
47
 
  /* ========================= */
48
 
 
49
 
  N = *normal;
50
 
  ambientcolor = *diff_col;
51
 
  gimp_rgb_multiply (&ambientcolor, mapvals.material.ambient_int);
52
 
 
53
 
  /* Compute (N*L) term of Phong's equation */
54
 
  /* ====================================== */
55
 
 
56
 
  if (type == POINT_LIGHT)
57
 
    gimp_vector3_sub (&L, light, pos);
58
 
  else
59
 
    L = *light;
60
 
 
61
 
  dist = gimp_vector3_length (&L);
62
 
 
63
 
  if (dist != 0.0)
64
 
    gimp_vector3_mul (&L, 1.0 / dist);
65
 
 
66
 
  NL = 2.0 * gimp_vector3_inner_product (&N, &L);
67
 
 
68
 
  if (NL >= 0.0)
69
 
    {
70
 
      /* Compute (R*V)^alpha term of Phong's equation */
71
 
      /* ============================================ */
72
 
 
73
 
      gimp_vector3_sub (&V, viewpoint, pos);
74
 
      gimp_vector3_normalize (&V);
75
 
 
76
 
      gimp_vector3_mul (&N, NL);
77
 
      gimp_vector3_sub (&NN, &N, &L);
78
 
      RV = gimp_vector3_inner_product (&NN, &V);
79
 
      RV = pow (RV, mapvals.material.highlight);
80
 
 
81
 
      /* Compute diffuse and specular intensity contribution */
82
 
      /* =================================================== */
83
 
 
84
 
      diffusecolor = *diff_col;
85
 
      gimp_rgb_multiply (&diffusecolor, mapvals.material.diffuse_ref);
86
 
      gimp_rgb_multiply (&diffusecolor, NL);
87
 
 
88
 
      specularcolor = *spec_col;
89
 
      gimp_rgb_multiply (&specularcolor, mapvals.material.specular_ref);
90
 
      gimp_rgb_multiply (&specularcolor, RV);
91
 
 
92
 
      gimp_rgb_add (&diffusecolor, &specularcolor);
93
 
      gimp_rgb_multiply (&diffusecolor, mapvals.material.diffuse_int);
94
 
      gimp_rgb_clamp (&diffusecolor);
95
 
 
96
 
      gimp_rgb_add (&ambientcolor, &diffusecolor);
97
 
    }
98
 
 
99
 
  return ambientcolor;
100
 
}
101
 
 
102
 
static gint
103
 
plane_intersect (GimpVector3 *dir,
104
 
                 GimpVector3 *viewp,
105
 
                 GimpVector3 *ipos,
106
 
                 gdouble     *u,
107
 
                 gdouble     *v)
108
 
{
109
 
  static gdouble det, det1, det2, det3, t;
110
 
 
111
 
  imat[0][0] = dir->x;
112
 
  imat[1][0] = dir->y;
113
 
  imat[2][0] = dir->z;
114
 
 
115
 
  /* Compute determinant of the first 3x3 sub matrix (denominator) */
116
 
  /* ============================================================= */
117
 
 
118
 
  det = (imat[0][0] * imat[1][1] * imat[2][2] +
119
 
         imat[0][1] * imat[1][2] * imat[2][0] +
120
 
         imat[0][2] * imat[1][0] * imat[2][1] -
121
 
         imat[0][2] * imat[1][1] * imat[2][0] -
122
 
         imat[0][0] * imat[1][2] * imat[2][1] -
123
 
         imat[2][2] * imat[0][1] * imat[1][0]);
124
 
 
125
 
  /* If the determinant is non-zero, a intersection point exists */
126
 
  /* =========================================================== */
127
 
 
128
 
  if (det != 0.0)
129
 
    {
130
 
      /* Now, lets compute the numerator determinants (wow ;) */
131
 
      /* ==================================================== */
132
 
 
133
 
      det1 = (imat[0][3] * imat[1][1] * imat[2][2] +
134
 
              imat[0][1] * imat[1][2] * imat[2][3] +
135
 
              imat[0][2] * imat[1][3] * imat[2][1] -
136
 
              imat[0][2] * imat[1][1] * imat[2][3] -
137
 
              imat[1][2] * imat[2][1] * imat[0][3] -
138
 
              imat[2][2] * imat[0][1] * imat[1][3]);
139
 
 
140
 
      det2 = (imat[0][0] * imat[1][3] * imat[2][2] +
141
 
              imat[0][3] * imat[1][2] * imat[2][0] +
142
 
              imat[0][2] * imat[1][0] * imat[2][3] -
143
 
              imat[0][2] * imat[1][3] * imat[2][0] -
144
 
              imat[1][2] * imat[2][3] * imat[0][0] -
145
 
              imat[2][2] * imat[0][3] * imat[1][0]);
146
 
 
147
 
      det3 = (imat[0][0] * imat[1][1] * imat[2][3] +
148
 
              imat[0][1] * imat[1][3] * imat[2][0] +
149
 
              imat[0][3] * imat[1][0] * imat[2][1] -
150
 
              imat[0][3] * imat[1][1] * imat[2][0] -
151
 
              imat[1][3] * imat[2][1] * imat[0][0] -
152
 
              imat[2][3] * imat[0][1] * imat[1][0]);
153
 
 
154
 
      /* Now we have the simultanous solutions. Lets compute the unknowns */
155
 
      /* (skip u&v if t is <0, this means the intersection is behind us)  */
156
 
      /* ================================================================ */
157
 
 
158
 
      t = det1 / det;
159
 
 
160
 
      if (t > 0.0)
161
 
        {
162
 
          *u = 1.0 + ((det2 / det) - 0.5);
163
 
          *v = 1.0 + ((det3 / det) - 0.5);
164
 
 
165
 
          ipos->x = viewp->x + t * dir->x;
166
 
          ipos->y = viewp->y + t * dir->y;
167
 
          ipos->z = viewp->z + t * dir->z;
168
 
 
169
 
          return TRUE;
170
 
        }
171
 
    }
172
 
 
173
 
  return FALSE;
174
 
}
175
 
 
176
 
/*****************************************************************************
177
 
 * These routines computes the color of the surface
178
 
 * of the plane at a given point
179
 
 *****************************************************************************/
180
 
 
181
 
GimpRGB
182
 
get_ray_color_plane (GimpVector3 *pos)
183
 
{
184
 
  GimpRGB color = background;
185
 
 
186
 
  static gint         inside = FALSE;
187
 
  static GimpVector3  ray, spos;
188
 
  static gdouble      vx, vy;
189
 
 
190
 
  /* Construct a line from our VP to the point */
191
 
  /* ========================================= */
192
 
 
193
 
  gimp_vector3_sub (&ray, pos, &mapvals.viewpoint);
194
 
  gimp_vector3_normalize (&ray);
195
 
 
196
 
  /* Check for intersection. This is a quasi ray-tracer. */
197
 
  /* =================================================== */
198
 
 
199
 
  if (plane_intersect (&ray, &mapvals.viewpoint, &spos, &vx, &vy) == TRUE)
200
 
    {
201
 
      color = get_image_color (vx, vy, &inside);
202
 
 
203
 
      if (color.a != 0.0 && inside == TRUE &&
204
 
          mapvals.lightsource.type != NO_LIGHT)
205
 
        {
206
 
          /* Compute shading at this point */
207
 
          /* ============================= */
208
 
 
209
 
          color = phong_shade (&spos,
210
 
                               &mapvals.viewpoint,
211
 
                               &mapvals.normal,
212
 
                               &mapvals.lightsource.position,
213
 
                               &color,
214
 
                               &mapvals.lightsource.color,
215
 
                               mapvals.lightsource.type);
216
 
 
217
 
          gimp_rgb_clamp (&color);
218
 
        }
219
 
    }
220
 
 
221
 
  if (mapvals.transparent_background == FALSE && color.a < 1.0)
222
 
    {
223
 
      gimp_rgb_composite (&color, &background,
224
 
                          GIMP_RGB_COMPOSITE_BEHIND);
225
 
    }
226
 
 
227
 
  return color;
228
 
}
229
 
 
230
 
/***********************************************************************/
231
 
/* Given the NorthPole, Equator and a third vector (normal) compute    */
232
 
/* the conversion from spherical oordinates to image space coordinates */
233
 
/***********************************************************************/
234
 
 
235
 
static void
236
 
sphere_to_image (GimpVector3 *normal,
237
 
                 gdouble     *u,
238
 
                 gdouble     *v)
239
 
{
240
 
  static gdouble      alpha, fac;
241
 
  static GimpVector3  cross_prod;
242
 
 
243
 
  alpha = acos (-gimp_vector3_inner_product (&mapvals.secondaxis, normal));
244
 
 
245
 
  *v = alpha / G_PI;
246
 
 
247
 
  if (*v == 0.0 || *v == 1.0)
248
 
    {
249
 
      *u = 0.0;
250
 
    }
251
 
  else
252
 
    {
253
 
      fac = (gimp_vector3_inner_product (&mapvals.firstaxis, normal) /
254
 
             sin (alpha));
255
 
 
256
 
      /* Make sure that we map to -1.0..1.0 (take care of rounding errors) */
257
 
      /* ================================================================= */
258
 
 
259
 
      fac = CLAMP (fac, -1.0, 1.0);
260
 
 
261
 
      *u = acos (fac) / (2.0 * G_PI);
262
 
 
263
 
      cross_prod = gimp_vector3_cross_product (&mapvals.secondaxis,
264
 
                                               &mapvals.firstaxis);
265
 
 
266
 
      if (gimp_vector3_inner_product (&cross_prod, normal) < 0.0)
267
 
        *u = 1.0 - *u;
268
 
    }
269
 
}
270
 
 
271
 
/***************************************************/
272
 
/* Compute intersection point with sphere (if any) */
273
 
/***************************************************/
274
 
 
275
 
static gint
276
 
sphere_intersect (GimpVector3 *dir,
277
 
                  GimpVector3 *viewp,
278
 
                  GimpVector3 *spos1,
279
 
                  GimpVector3 *spos2)
280
 
{
281
 
  static gdouble      alpha, beta, tau, s1, s2, tmp;
282
 
  static GimpVector3  t;
283
 
 
284
 
  gimp_vector3_sub (&t, &mapvals.position, viewp);
285
 
 
286
 
  alpha = gimp_vector3_inner_product (dir, &t);
287
 
  beta  = gimp_vector3_inner_product (&t, &t);
288
 
 
289
 
  tau = alpha * alpha - beta + mapvals.radius * mapvals.radius;
290
 
 
291
 
  if (tau >= 0.0)
292
 
    {
293
 
      tau = sqrt (tau);
294
 
      s1 = alpha + tau;
295
 
      s2 = alpha - tau;
296
 
 
297
 
      if (s2 < s1)
298
 
        {
299
 
          tmp = s1;
300
 
          s1 = s2;
301
 
          s2 = tmp;
302
 
        }
303
 
 
304
 
      spos1->x = viewp->x + s1 * dir->x;
305
 
      spos1->y = viewp->y + s1 * dir->y;
306
 
      spos1->z = viewp->z + s1 * dir->z;
307
 
      spos2->x = viewp->x + s2 * dir->x;
308
 
      spos2->y = viewp->y + s2 * dir->y;
309
 
      spos2->z = viewp->z + s2 * dir->z;
310
 
 
311
 
      return TRUE;
312
 
    }
313
 
 
314
 
  return FALSE;
315
 
}
316
 
 
317
 
/*****************************************************************************
318
 
 * These routines computes the color of the surface
319
 
 * of the sphere at a given point
320
 
 *****************************************************************************/
321
 
 
322
 
GimpRGB
323
 
get_ray_color_sphere (GimpVector3 *pos)
324
 
{
325
 
  GimpRGB color = background;
326
 
 
327
 
  static GimpRGB      color2;
328
 
  static gint         inside = FALSE;
329
 
  static GimpVector3  normal, ray, spos1, spos2;
330
 
  static gdouble      vx, vy;
331
 
 
332
 
  /* Check if ray is within the bounding box */
333
 
  /* ======================================= */
334
 
 
335
 
  if (pos->x<bx1 || pos->x>bx2 || pos->y<by1 || pos->y>by2)
336
 
    return color;
337
 
 
338
 
  /* Construct a line from our VP to the point */
339
 
  /* ========================================= */
340
 
 
341
 
  gimp_vector3_sub (&ray, pos, &mapvals.viewpoint);
342
 
  gimp_vector3_normalize (&ray);
343
 
 
344
 
  /* Check for intersection. This is a quasi ray-tracer. */
345
 
  /* =================================================== */
346
 
 
347
 
  if (sphere_intersect (&ray, &mapvals.viewpoint, &spos1, &spos2) == TRUE)
348
 
    {
349
 
      /* Compute spherical to rectangular mapping */
350
 
      /* ======================================== */
351
 
 
352
 
      gimp_vector3_sub (&normal, &spos1, &mapvals.position);
353
 
      gimp_vector3_normalize (&normal);
354
 
      sphere_to_image (&normal, &vx, &vy);
355
 
      color = get_image_color (vx, vy, &inside);
356
 
 
357
 
      /* Check for total transparency... */
358
 
      /* =============================== */
359
 
 
360
 
      if (color.a < 1.0)
361
 
        {
362
 
          /* Hey, we can see  through here!      */
363
 
          /* Lets see what's on the other side.. */
364
 
          /* =================================== */
365
 
 
366
 
          color = phong_shade (&spos1,
367
 
                               &mapvals.viewpoint,
368
 
                               &normal,
369
 
                               &mapvals.lightsource.position,
370
 
                               &color,
371
 
                               &mapvals.lightsource.color,
372
 
                               mapvals.lightsource.type);
373
 
 
374
 
          gimp_rgb_clamp (&color);
375
 
 
376
 
          gimp_vector3_sub (&normal, &spos2, &mapvals.position);
377
 
          gimp_vector3_normalize (&normal);
378
 
          sphere_to_image (&normal, &vx, &vy);
379
 
          color2 = get_image_color (vx, vy, &inside);
380
 
 
381
 
          /* Make the normal point inwards */
382
 
          /* ============================= */
383
 
 
384
 
          gimp_vector3_mul (&normal, -1.0);
385
 
 
386
 
          color2 = phong_shade (&spos2,
387
 
                                &mapvals.viewpoint,
388
 
                                &normal,
389
 
                                &mapvals.lightsource.position,
390
 
                                &color2,
391
 
                                &mapvals.lightsource.color,
392
 
                                mapvals.lightsource.type);
393
 
 
394
 
          gimp_rgb_clamp (&color2);
395
 
 
396
 
          /* Compute a mix of the first and second colors */
397
 
          /* ============================================ */
398
 
 
399
 
          gimp_rgb_composite (&color, &color2, GIMP_RGB_COMPOSITE_NORMAL);
400
 
          gimp_rgb_clamp (&color);
401
 
        }
402
 
      else if (color.a != 0.0 &&
403
 
               inside == TRUE &&
404
 
               mapvals.lightsource.type != NO_LIGHT)
405
 
        {
406
 
          /* Compute shading at this point */
407
 
          /* ============================= */
408
 
 
409
 
          color = phong_shade (&spos1,
410
 
                               &mapvals.viewpoint,
411
 
                               &normal,
412
 
                               &mapvals.lightsource.position,
413
 
                               &color,
414
 
                               &mapvals.lightsource.color,
415
 
                               mapvals.lightsource.type);
416
 
 
417
 
          gimp_rgb_clamp (&color);
418
 
        }
419
 
    }
420
 
 
421
 
  if (mapvals.transparent_background == FALSE && color.a < 1.0)
422
 
    {
423
 
      gimp_rgb_composite (&color, &background,
424
 
                          GIMP_RGB_COMPOSITE_BEHIND);
425
 
    }
426
 
 
427
 
  return color;
428
 
}
429
 
 
430
 
/***************************************************/
431
 
/* Transform the corners of the bounding box to 2D */
432
 
/***************************************************/
433
 
 
434
 
void
435
 
compute_bounding_box (void)
436
 
{
437
 
  GimpVector3  p1, p2;
438
 
  gdouble      t;
439
 
  GimpVector3  dir;
440
 
 
441
 
  p1 = mapvals.position;
442
 
  p1.x -= (mapvals.radius + 0.01);
443
 
  p1.y -= (mapvals.radius + 0.01);
444
 
 
445
 
  p2 = mapvals.position;
446
 
  p2.x += (mapvals.radius + 0.01);
447
 
  p2.y += (mapvals.radius + 0.01);
448
 
 
449
 
  gimp_vector3_sub (&dir, &p1, &mapvals.viewpoint);
450
 
  gimp_vector3_normalize (&dir);
451
 
 
452
 
  if (dir.z != 0.0)
453
 
    {
454
 
      t = (-1.0 * mapvals.viewpoint.z) / dir.z;
455
 
      p1.x = (mapvals.viewpoint.x + t * dir.x);
456
 
      p1.y = (mapvals.viewpoint.y + t * dir.y);
457
 
    }
458
 
 
459
 
  gimp_vector3_sub (&dir, &p2, &mapvals.viewpoint);
460
 
  gimp_vector3_normalize (&dir);
461
 
 
462
 
  if (dir.z != 0.0)
463
 
    {
464
 
      t = (-1.0 * mapvals.viewpoint.z) / dir.z;
465
 
      p2.x = (mapvals.viewpoint.x + t * dir.x);
466
 
      p2.y = (mapvals.viewpoint.y + t * dir.y);
467
 
    }
468
 
 
469
 
  bx1 = p1.x;
470
 
  by1 = p1.y;
471
 
  bx2 = p2.x;
472
 
  by2 = p2.y;
473
 
}
474
 
 
475
 
/* These two were taken from the Mesa source. Mesa is written   */
476
 
/* and is (C) by Brian Paul. vecmulmat() performs a post-mul by */
477
 
/* a 4x4 matrix to a 1x4(3) vector. rotmat() creates a matrix   */
478
 
/* that by post-mul will rotate a 1x4(3) vector the given angle */
479
 
/* about the given axis.                                        */
480
 
/* ============================================================ */
481
 
 
482
 
void
483
 
vecmulmat (GimpVector3 *u,
484
 
           GimpVector3 *v,
485
 
           gfloat       m[16])
486
 
{
487
 
  gfloat v0=v->x, v1=v->y, v2=v->z;
488
 
#define M(row,col)  m[col*4+row]
489
 
  u->x = v0 * M(0,0) + v1 * M(1,0) + v2 * M(2,0) + M(3,0);
490
 
  u->y = v0 * M(0,1) + v1 * M(1,1) + v2 * M(2,1) + M(3,1);
491
 
  u->z = v0 * M(0,2) + v1 * M(1,2) + v2 * M(2,2) + M(3,2);
492
 
#undef M
493
 
}
494
 
 
495
 
void
496
 
rotatemat (gfloat       angle,
497
 
           GimpVector3 *v,
498
 
           gfloat       m[16])
499
 
{
500
 
  /* This function contributed by Erich Boleyn (erich@uruk.org) */
501
 
  gfloat mag, s, c;
502
 
  gfloat xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c;
503
 
  gfloat IdentityMat[16];
504
 
  gint   cnt;
505
 
 
506
 
  s = sin (angle * (G_PI / 180.0));
507
 
  c = cos (angle * (G_PI / 180.0));
508
 
 
509
 
  mag = sqrt (v->x*v->x + v->y*v->y + v->z*v->z);
510
 
 
511
 
  if (mag == 0.0)
512
 
    {
513
 
      /* generate an identity matrix and return */
514
 
 
515
 
      for (cnt = 0; cnt < 16; cnt++)
516
 
        IdentityMat[cnt] = 0.0;
517
 
 
518
 
      IdentityMat[0]  = 1.0;
519
 
      IdentityMat[5]  = 1.0;
520
 
      IdentityMat[10] = 1.0;
521
 
      IdentityMat[15] = 1.0;
522
 
 
523
 
      memcpy (m, IdentityMat, sizeof (gfloat) * 16);
524
 
      return;
525
 
   }
526
 
 
527
 
  v->x /= mag;
528
 
  v->y /= mag;
529
 
  v->z /= mag;
530
 
 
531
 
#define M(row,col)  m[col*4+row]
532
 
 
533
 
  xx = v->x * v->x;
534
 
  yy = v->y * v->y;
535
 
  zz = v->z * v->z;
536
 
  xy = v->x * v->y;
537
 
  yz = v->y * v->z;
538
 
  zx = v->z * v->x;
539
 
  xs = v->x * s;
540
 
  ys = v->y * s;
541
 
  zs = v->z * s;
542
 
  one_c = 1.0F - c;
543
 
 
544
 
  M(0,0) = (one_c * xx) + c;
545
 
  M(0,1) = (one_c * xy) - zs;
546
 
  M(0,2) = (one_c * zx) + ys;
547
 
  M(0,3) = 0.0F;
548
 
 
549
 
  M(1,0) = (one_c * xy) + zs;
550
 
  M(1,1) = (one_c * yy) + c;
551
 
  M(1,2) = (one_c * yz) - xs;
552
 
  M(1,3) = 0.0F;
553
 
 
554
 
  M(2,0) = (one_c * zx) - ys;
555
 
  M(2,1) = (one_c * yz) + xs;
556
 
  M(2,2) = (one_c * zz) + c;
557
 
  M(2,3) = 0.0F;
558
 
 
559
 
  M(3,0) = 0.0F;
560
 
  M(3,1) = 0.0F;
561
 
  M(3,2) = 0.0F;
562
 
  M(3,3) = 1.0F;
563
 
 
564
 
#undef M
565
 
}
566
 
 
567
 
/* Transpose the matrix m. If m is orthogonal (like a rotation matrix), */
568
 
/* this is equal to the inverse of the matrix.                          */
569
 
/* ==================================================================== */
570
 
 
571
 
void
572
 
transpose_mat (gfloat m[16])
573
 
{
574
 
  gint    i, j;
575
 
  gfloat  t;
576
 
 
577
 
  for (i = 0; i < 4; i++)
578
 
    {
579
 
      for (j = 0; j < i; j++)
580
 
        {
581
 
          t = m[j*4+i];
582
 
          m[j*4+i] = m[i*4+j];
583
 
          m[i*4+j] = t;
584
 
        }
585
 
    }
586
 
}
587
 
 
588
 
/* Compute the matrix product c=a*b */
589
 
/* ================================ */
590
 
 
591
 
void
592
 
matmul (gfloat a[16],
593
 
        gfloat b[16],
594
 
        gfloat c[16])
595
 
{
596
 
  gint   i, j, k;
597
 
  gfloat value;
598
 
 
599
 
#define A(row,col)  a[col*4+row]
600
 
#define B(row,col)  b[col*4+row]
601
 
#define C(row,col)  c[col*4+row]
602
 
 
603
 
  for (i = 0; i < 4; i++)
604
 
    {
605
 
      for (j = 0; j < 4; j++)
606
 
        {
607
 
          value = 0.0;
608
 
 
609
 
          for (k = 0; k < 4; k++)
610
 
            value += A(i,k) * B(k,j);
611
 
 
612
 
          C(i,j) = value;
613
 
        }
614
 
    }
615
 
 
616
 
#undef A
617
 
#undef B
618
 
#undef C
619
 
}
620
 
 
621
 
void
622
 
ident_mat (gfloat m[16])
623
 
{
624
 
  gint  i, j;
625
 
 
626
 
#define M(row,col)  m[col*4+row]
627
 
 
628
 
  for (i = 0; i < 4; i++)
629
 
    {
630
 
      for (j = 0; j < 4; j++)
631
 
        {
632
 
          if (i == j)
633
 
            M(i,j) = 1.0;
634
 
          else
635
 
            M(i,j) = 0.0;
636
 
        }
637
 
    }
638
 
 
639
 
#undef M
640
 
}
641
 
 
642
 
static gboolean
643
 
intersect_rect (gdouble            u,
644
 
                gdouble            v,
645
 
                gdouble            w,
646
 
                GimpVector3        viewp,
647
 
                GimpVector3        dir,
648
 
                FaceIntersectInfo *face_info)
649
 
{
650
 
  gboolean result = FALSE;
651
 
  gdouble  u2, v2;
652
 
 
653
 
  if (dir.z!=0.0)
654
 
    {
655
 
      u2 = u / 2.0;
656
 
      v2 = v / 2.0;
657
 
 
658
 
      face_info->t = (w-viewp.z) / dir.z;
659
 
      face_info->s.x = viewp.x + face_info->t * dir.x;
660
 
      face_info->s.y = viewp.y + face_info->t * dir.y;
661
 
      face_info->s.z = w;
662
 
 
663
 
      if (face_info->s.x >= -u2 && face_info->s.x <= u2 &&
664
 
          face_info->s.y >= -v2 && face_info->s.y <= v2)
665
 
        {
666
 
          face_info->u = (face_info->s.x + u2) / u;
667
 
          face_info->v = (face_info->s.y + v2) / v;
668
 
          result = TRUE;
669
 
        }
670
 
    }
671
 
 
672
 
  return result;
673
 
}
674
 
 
675
 
static gboolean
676
 
intersect_box (GimpVector3        scale,
677
 
               GimpVector3        viewp,
678
 
               GimpVector3        dir,
679
 
               FaceIntersectInfo *face_intersect)
680
 
{
681
 
  GimpVector3        v, d, tmp, axis[3];
682
 
  FaceIntersectInfo  face_tmp;
683
 
  gboolean           result = FALSE;
684
 
  gfloat             m[16];
685
 
  gint               i = 0;
686
 
 
687
 
  gimp_vector3_set (&axis[0], 1.0, 0.0, 0.0);
688
 
  gimp_vector3_set (&axis[1], 0.0, 1.0, 0.0);
689
 
  gimp_vector3_set (&axis[2], 0.0, 0.0, 1.0);
690
 
 
691
 
  /* Front side */
692
 
  /* ========== */
693
 
 
694
 
  if (intersect_rect (scale.x, scale.y, scale.z / 2.0,
695
 
                      viewp, dir, &face_intersect[i]) == TRUE)
696
 
    {
697
 
      face_intersect[i].face = 0;
698
 
      gimp_vector3_set (&face_intersect[i++].n, 0.0, 0.0, 1.0);
699
 
      result = TRUE;
700
 
    }
701
 
 
702
 
  /* Back side */
703
 
  /* ========= */
704
 
 
705
 
  if (intersect_rect (scale.x, scale.y, -scale.z / 2.0,
706
 
                      viewp, dir, &face_intersect[i]) == TRUE)
707
 
    {
708
 
      face_intersect[i].face = 1;
709
 
      face_intersect[i].u = 1.0 - face_intersect[i].u;
710
 
      gimp_vector3_set (&face_intersect[i++].n, 0.0, 0.0, -1.0);
711
 
      result = TRUE;
712
 
    }
713
 
 
714
 
  /* Check if we've found the two possible intersection points */
715
 
  /* ========================================================= */
716
 
 
717
 
  if (i < 2)
718
 
    {
719
 
      /* Top: Rotate viewpoint and direction into rectangle's local coordinate system */
720
 
      /* ============================================================================ */
721
 
 
722
 
      rotatemat (90, &axis[0], m);
723
 
      vecmulmat (&v, &viewp, m);
724
 
      vecmulmat (&d, &dir, m);
725
 
 
726
 
      if (intersect_rect (scale.x, scale.z, scale.y / 2.0,
727
 
                          v, d, &face_intersect[i]) == TRUE)
728
 
        {
729
 
          face_intersect[i].face = 2;
730
 
 
731
 
          transpose_mat (m);
732
 
          vecmulmat(&tmp, &face_intersect[i].s, m);
733
 
          face_intersect[i].s = tmp;
734
 
 
735
 
          gimp_vector3_set (&face_intersect[i++].n, 0.0, -1.0, 0.0);
736
 
          result = TRUE;
737
 
        }
738
 
    }
739
 
 
740
 
  /* Check if we've found the two possible intersection points */
741
 
  /* ========================================================= */
742
 
 
743
 
  if (i < 2)
744
 
    {
745
 
      /* Bottom: Rotate viewpoint and direction into rectangle's local coordinate system */
746
 
      /* =============================================================================== */
747
 
 
748
 
      rotatemat (90, &axis[0], m);
749
 
      vecmulmat (&v, &viewp, m);
750
 
      vecmulmat (&d, &dir, m);
751
 
 
752
 
      if (intersect_rect (scale.x, scale.z, -scale.y / 2.0,
753
 
                          v, d, &face_intersect[i]) == TRUE)
754
 
        {
755
 
          face_intersect[i].face = 3;
756
 
 
757
 
          transpose_mat (m);
758
 
 
759
 
          vecmulmat (&tmp, &face_intersect[i].s, m);
760
 
          face_intersect[i].s = tmp;
761
 
 
762
 
          face_intersect[i].v = 1.0 - face_intersect[i].v;
763
 
 
764
 
          gimp_vector3_set (&face_intersect[i++].n, 0.0, 1.0, 0.0);
765
 
 
766
 
          result = TRUE;
767
 
        }
768
 
    }
769
 
 
770
 
  /* Check if we've found the two possible intersection points */
771
 
  /* ========================================================= */
772
 
 
773
 
  if (i < 2)
774
 
    {
775
 
      /* Left side: Rotate viewpoint and direction into rectangle's local coordinate system */
776
 
      /* ================================================================================== */
777
 
 
778
 
      rotatemat (90, &axis[1], m);
779
 
      vecmulmat (&v, &viewp, m);
780
 
      vecmulmat (&d, &dir, m);
781
 
 
782
 
      if (intersect_rect (scale.z, scale.y, scale.x / 2.0,
783
 
                          v, d, &face_intersect[i]) == TRUE)
784
 
        {
785
 
          face_intersect[i].face = 4;
786
 
 
787
 
          transpose_mat (m);
788
 
          vecmulmat (&tmp, &face_intersect[i].s, m);
789
 
          face_intersect[i].s = tmp;
790
 
 
791
 
          gimp_vector3_set (&face_intersect[i++].n, 1.0, 0.0, 0.0);
792
 
          result = TRUE;
793
 
        }
794
 
    }
795
 
 
796
 
  /* Check if we've found the two possible intersection points */
797
 
  /* ========================================================= */
798
 
 
799
 
  if (i < 2)
800
 
    {
801
 
      /* Right side: Rotate viewpoint and direction into rectangle's local coordinate system */
802
 
      /* =================================================================================== */
803
 
 
804
 
      rotatemat (90, &axis[1], m);
805
 
      vecmulmat (&v, &viewp, m);
806
 
      vecmulmat (&d, &dir, m);
807
 
 
808
 
      if (intersect_rect (scale.z, scale.y, -scale.x / 2.0,
809
 
                          v, d, &face_intersect[i]) == TRUE)
810
 
        {
811
 
          face_intersect[i].face = 5;
812
 
 
813
 
          transpose_mat (m);
814
 
          vecmulmat (&tmp, &face_intersect[i].s, m);
815
 
 
816
 
          face_intersect[i].u = 1.0 - face_intersect[i].u;
817
 
 
818
 
          gimp_vector3_set (&face_intersect[i++].n, -1.0, 0.0, 0.0);
819
 
          result = TRUE;
820
 
        }
821
 
    }
822
 
 
823
 
  /* Sort intersection points */
824
 
  /* ======================== */
825
 
 
826
 
  if (face_intersect[0].t > face_intersect[1].t)
827
 
    {
828
 
      face_tmp = face_intersect[0];
829
 
      face_intersect[0] = face_intersect[1];
830
 
      face_intersect[1] = face_tmp;
831
 
    }
832
 
 
833
 
  return result;
834
 
}
835
 
 
836
 
GimpRGB
837
 
get_ray_color_box (GimpVector3 *pos)
838
 
{
839
 
  GimpVector3        lvp, ldir, vp, p, dir, ns, nn;
840
 
  GimpRGB             color, color2;
841
 
  gfloat             m[16];
842
 
  gint               i;
843
 
  FaceIntersectInfo  face_intersect[2];
844
 
 
845
 
  color = background;
846
 
  vp = mapvals.viewpoint;
847
 
  p = *pos;
848
 
 
849
 
  /* Translate viewpoint so that the box has its origin */
850
 
  /* at its lower left corner.                          */
851
 
  /* ================================================== */
852
 
 
853
 
  vp.x = vp.x - mapvals.position.x;
854
 
  vp.y = vp.y - mapvals.position.y;
855
 
  vp.z = vp.z - mapvals.position.z;
856
 
 
857
 
  p.x = p.x - mapvals.position.x;
858
 
  p.y = p.y - mapvals.position.y;
859
 
  p.z = p.z - mapvals.position.z;
860
 
 
861
 
  /* Compute direction */
862
 
  /* ================= */
863
 
 
864
 
  gimp_vector3_sub (&dir, &p, &vp);
865
 
  gimp_vector3_normalize (&dir);
866
 
 
867
 
  /* Compute inverse of rotation matrix and apply it to   */
868
 
  /* the viewpoint and direction. This transforms the     */
869
 
  /* observer into the local coordinate system of the box */
870
 
  /* ==================================================== */
871
 
 
872
 
  memcpy (m, rotmat, sizeof (gfloat) * 16);
873
 
 
874
 
  transpose_mat (m);
875
 
 
876
 
  vecmulmat (&lvp, &vp, m);
877
 
  vecmulmat (&ldir, &dir, m);
878
 
 
879
 
  /* Ok. Now the observer is in the space where the box is located */
880
 
  /* with its lower left corner at the origin and its axis aligned */
881
 
  /* to the cartesian basis. Check if the transformed ray hits it. */
882
 
  /* ============================================================= */
883
 
 
884
 
  face_intersect[0].t = 1000000.0;
885
 
  face_intersect[1].t = 1000000.0;
886
 
 
887
 
  if (intersect_box (mapvals.scale, lvp, ldir, face_intersect) == TRUE)
888
 
    {
889
 
      /* We've hit the box. Transform the hit points and */
890
 
      /* normals back into the world coordinate system   */
891
 
      /* =============================================== */
892
 
 
893
 
      for (i = 0; i < 2; i++)
894
 
        {
895
 
          vecmulmat (&ns, &face_intersect[i].s, rotmat);
896
 
          vecmulmat (&nn, &face_intersect[i].n, rotmat);
897
 
 
898
 
          ns.x = ns.x + mapvals.position.x;
899
 
          ns.y = ns.y + mapvals.position.y;
900
 
          ns.z = ns.z + mapvals.position.z;
901
 
 
902
 
          face_intersect[i].s = ns;
903
 
          face_intersect[i].n = nn;
904
 
        }
905
 
 
906
 
      color = get_box_image_color (face_intersect[0].face,
907
 
                                   face_intersect[0].u,
908
 
                                   face_intersect[0].v);
909
 
 
910
 
      /* Check for total transparency... */
911
 
      /* =============================== */
912
 
 
913
 
      if (color.a < 1.0)
914
 
        {
915
 
          /* Hey, we can see  through here!      */
916
 
          /* Lets see what's on the other side.. */
917
 
          /* =================================== */
918
 
 
919
 
          color = phong_shade (&face_intersect[0].s,
920
 
                               &mapvals.viewpoint,
921
 
                               &face_intersect[0].n,
922
 
                               &mapvals.lightsource.position,
923
 
                               &color,
924
 
                               &mapvals.lightsource.color,
925
 
                               mapvals.lightsource.type);
926
 
 
927
 
          gimp_rgb_clamp (&color);
928
 
 
929
 
          color2 = get_box_image_color (face_intersect[1].face,
930
 
                                        face_intersect[1].u,
931
 
                                        face_intersect[1].v);
932
 
 
933
 
          /* Make the normal point inwards */
934
 
          /* ============================= */
935
 
 
936
 
          gimp_vector3_mul (&face_intersect[1].n, -1.0);
937
 
 
938
 
          color2 = phong_shade (&face_intersect[1].s,
939
 
                                &mapvals.viewpoint,
940
 
                                &face_intersect[1].n,
941
 
                                &mapvals.lightsource.position,
942
 
                                &color2,
943
 
                                &mapvals.lightsource.color,
944
 
                                mapvals.lightsource.type);
945
 
 
946
 
          gimp_rgb_clamp (&color2);
947
 
 
948
 
          if (mapvals.transparent_background == FALSE && color2.a < 1.0)
949
 
            {
950
 
              gimp_rgb_composite (&color2, &background,
951
 
                                  GIMP_RGB_COMPOSITE_BEHIND);
952
 
            }
953
 
 
954
 
          /* Compute a mix of the first and second colors */
955
 
          /* ============================================ */
956
 
 
957
 
          gimp_rgb_composite (&color, &color2, GIMP_RGB_COMPOSITE_NORMAL);
958
 
          gimp_rgb_clamp (&color);
959
 
        }
960
 
      else if (color.a != 0.0 && mapvals.lightsource.type != NO_LIGHT)
961
 
        {
962
 
          color = phong_shade (&face_intersect[0].s,
963
 
                               &mapvals.viewpoint,
964
 
                               &face_intersect[0].n,
965
 
                               &mapvals.lightsource.position,
966
 
                               &color,
967
 
                               &mapvals.lightsource.color,
968
 
                               mapvals.lightsource.type);
969
 
 
970
 
          gimp_rgb_clamp (&color);
971
 
        }
972
 
    }
973
 
  else
974
 
    {
975
 
      if (mapvals.transparent_background == TRUE)
976
 
        gimp_rgb_set_alpha (&color, 0.0);
977
 
    }
978
 
 
979
 
  return color;
980
 
}
981
 
 
982
 
static gboolean
983
 
intersect_circle (GimpVector3        vp,
984
 
                  GimpVector3        dir,
985
 
                  gdouble            w,
986
 
                  FaceIntersectInfo *face_info)
987
 
{
988
 
  gboolean result = FALSE;
989
 
  gdouble  r, d;
990
 
 
991
 
#define sqr(a) (a*a)
992
 
 
993
 
  if (dir.y != 0.0)
994
 
    {
995
 
      face_info->t = (w-vp.y)/dir.y;
996
 
      face_info->s.x = vp.x + face_info->t*dir.x;
997
 
      face_info->s.y = w;
998
 
      face_info->s.z = vp.z + face_info->t*dir.z;
999
 
 
1000
 
      r = sqrt (sqr (face_info->s.x) + sqr (face_info->s.z));
1001
 
 
1002
 
      if (r <= mapvals.cylinder_radius)
1003
 
        {
1004
 
          d = 2.0 * mapvals.cylinder_radius;
1005
 
          face_info->u = (face_info->s.x + mapvals.cylinder_radius) / d;
1006
 
          face_info->v = (face_info->s.z + mapvals.cylinder_radius) / d;
1007
 
          result = TRUE;
1008
 
        }
1009
 
    }
1010
 
 
1011
 
#undef sqr
1012
 
 
1013
 
  return result;
1014
 
}
1015
 
 
1016
 
static gboolean
1017
 
intersect_cylinder (GimpVector3        vp,
1018
 
                    GimpVector3        dir,
1019
 
                    FaceIntersectInfo *face_intersect)
1020
 
{
1021
 
  gdouble  a, b, c, d, e, f, tmp, l;
1022
 
  gboolean result = FALSE;
1023
 
  gint     i;
1024
 
 
1025
 
#define sqr(a) (a*a)
1026
 
 
1027
 
  a = sqr (dir.x) + sqr (dir.z);
1028
 
  b = 2.0 * (vp.x * dir.x + vp.z * dir.z);
1029
 
  c = sqr (vp.x) + sqr (vp.z) - sqr (mapvals.cylinder_radius);
1030
 
 
1031
 
  d = sqr (b) - 4.0 * a * c;
1032
 
 
1033
 
  if (d >= 0.0)
1034
 
    {
1035
 
      e = sqrt (d);
1036
 
      f = 2.0 * a;
1037
 
 
1038
 
      if (f != 0.0)
1039
 
        {
1040
 
          result = TRUE;
1041
 
 
1042
 
          face_intersect[0].t = (-b+e)/f;
1043
 
          face_intersect[1].t = (-b-e)/f;
1044
 
 
1045
 
          if (face_intersect[0].t>face_intersect[1].t)
1046
 
            {
1047
 
              tmp = face_intersect[0].t;
1048
 
              face_intersect[0].t = face_intersect[1].t;
1049
 
              face_intersect[1].t = tmp;
1050
 
            }
1051
 
 
1052
 
          for (i = 0; i < 2; i++)
1053
 
            {
1054
 
              face_intersect[i].s.x = vp.x + face_intersect[i].t * dir.x;
1055
 
              face_intersect[i].s.y = vp.y + face_intersect[i].t * dir.y;
1056
 
              face_intersect[i].s.z = vp.z + face_intersect[i].t * dir.z;
1057
 
 
1058
 
              face_intersect[i].n = face_intersect[i].s;
1059
 
              face_intersect[i].n.y = 0.0;
1060
 
              gimp_vector3_normalize(&face_intersect[i].n);
1061
 
 
1062
 
              l = mapvals.cylinder_length/2.0;
1063
 
 
1064
 
              face_intersect[i].u = (atan2(face_intersect[i].s.x,face_intersect[i].s.z)+G_PI)/(2.0*G_PI);
1065
 
              face_intersect[i].v = (face_intersect[i].s.y+l)/mapvals.cylinder_length;
1066
 
 
1067
 
              /* Mark hitpoint as on the cylinder hull */
1068
 
              /* ===================================== */
1069
 
 
1070
 
              face_intersect[i].face = 0;
1071
 
 
1072
 
              /* Check if we're completely off the cylinder axis */
1073
 
              /* =============================================== */
1074
 
 
1075
 
              if (face_intersect[i].s.y>l || face_intersect[i].s.y<-l)
1076
 
                {
1077
 
                  /* Check if we've hit a cap */
1078
 
                  /* ======================== */
1079
 
 
1080
 
                  if (face_intersect[i].s.y>l)
1081
 
                    {
1082
 
                      if (intersect_circle(vp,dir,l,&face_intersect[i])==FALSE)
1083
 
                        result = FALSE;
1084
 
                      else
1085
 
                        {
1086
 
                          face_intersect[i].face = 2;
1087
 
                          face_intersect[i].v = 1 - face_intersect[i].v;
1088
 
                          gimp_vector3_set(&face_intersect[i].n, 0.0, 1.0, 0.0);
1089
 
                        }
1090
 
                    }
1091
 
                  else
1092
 
                    {
1093
 
                      if (intersect_circle(vp,dir,-l,&face_intersect[i])==FALSE)
1094
 
                        result = FALSE;
1095
 
                      else
1096
 
                        {
1097
 
                          face_intersect[i].face = 1;
1098
 
                          gimp_vector3_set(&face_intersect[i].n, 0.0, -1.0, 0.0);
1099
 
                        }
1100
 
                    }
1101
 
                }
1102
 
            }
1103
 
        }
1104
 
    }
1105
 
 
1106
 
#undef sqr
1107
 
 
1108
 
  return result;
1109
 
}
1110
 
 
1111
 
static GimpRGB
1112
 
get_cylinder_color (gint    face,
1113
 
                    gdouble u,
1114
 
                    gdouble v)
1115
 
{
1116
 
  GimpRGB  color;
1117
 
  gint    inside;
1118
 
 
1119
 
  if (face == 0)
1120
 
    color = get_image_color (u, v, &inside);
1121
 
  else
1122
 
    color = get_cylinder_image_color (face - 1, u, v);
1123
 
 
1124
 
  return color;
1125
 
}
1126
 
 
1127
 
GimpRGB
1128
 
get_ray_color_cylinder (GimpVector3 *pos)
1129
 
{
1130
 
  GimpVector3       lvp, ldir, vp, p, dir, ns, nn;
1131
 
  GimpRGB            color, color2;
1132
 
  gfloat            m[16];
1133
 
  gint              i;
1134
 
  FaceIntersectInfo face_intersect[2];
1135
 
 
1136
 
  color = background;
1137
 
  vp = mapvals.viewpoint;
1138
 
  p = *pos;
1139
 
 
1140
 
  vp.x = vp.x - mapvals.position.x;
1141
 
  vp.y = vp.y - mapvals.position.y;
1142
 
  vp.z = vp.z - mapvals.position.z;
1143
 
 
1144
 
  p.x = p.x - mapvals.position.x;
1145
 
  p.y = p.y - mapvals.position.y;
1146
 
  p.z = p.z - mapvals.position.z;
1147
 
 
1148
 
  /* Compute direction */
1149
 
  /* ================= */
1150
 
 
1151
 
  gimp_vector3_sub (&dir, &p, &vp);
1152
 
  gimp_vector3_normalize (&dir);
1153
 
 
1154
 
  /* Compute inverse of rotation matrix and apply it to   */
1155
 
  /* the viewpoint and direction. This transforms the     */
1156
 
  /* observer into the local coordinate system of the box */
1157
 
  /* ==================================================== */
1158
 
 
1159
 
  memcpy (m, rotmat, sizeof (gfloat) * 16);
1160
 
 
1161
 
  transpose_mat (m);
1162
 
 
1163
 
  vecmulmat (&lvp, &vp, m);
1164
 
  vecmulmat (&ldir, &dir, m);
1165
 
 
1166
 
  if (intersect_cylinder (lvp, ldir, face_intersect) == TRUE)
1167
 
    {
1168
 
      /* We've hit the cylinder. Transform the hit points and */
1169
 
      /* normals back into the world coordinate system        */
1170
 
      /* ==================================================== */
1171
 
 
1172
 
      for (i = 0; i < 2; i++)
1173
 
        {
1174
 
          vecmulmat (&ns, &face_intersect[i].s, rotmat);
1175
 
          vecmulmat (&nn, &face_intersect[i].n, rotmat);
1176
 
 
1177
 
          ns.x = ns.x + mapvals.position.x;
1178
 
          ns.y = ns.y + mapvals.position.y;
1179
 
          ns.z = ns.z + mapvals.position.z;
1180
 
 
1181
 
          face_intersect[i].s = ns;
1182
 
          face_intersect[i].n = nn;
1183
 
        }
1184
 
 
1185
 
      color = get_cylinder_color (face_intersect[0].face,
1186
 
                                  face_intersect[0].u,
1187
 
                                  face_intersect[0].v);
1188
 
 
1189
 
      /* Check for transparency... */
1190
 
      /* ========================= */
1191
 
 
1192
 
      if (color.a < 1.0)
1193
 
        {
1194
 
          /* Hey, we can see  through here!      */
1195
 
          /* Lets see what's on the other side.. */
1196
 
          /* =================================== */
1197
 
 
1198
 
          color = phong_shade (&face_intersect[0].s,
1199
 
                               &mapvals.viewpoint,
1200
 
                               &face_intersect[0].n,
1201
 
                               &mapvals.lightsource.position,
1202
 
                               &color,
1203
 
                               &mapvals.lightsource.color,
1204
 
                               mapvals.lightsource.type);
1205
 
 
1206
 
          gimp_rgb_clamp (&color);
1207
 
 
1208
 
          color2 = get_cylinder_color (face_intersect[1].face,
1209
 
                                       face_intersect[1].u,
1210
 
                                       face_intersect[1].v);
1211
 
 
1212
 
          /* Make the normal point inwards */
1213
 
          /* ============================= */
1214
 
 
1215
 
          gimp_vector3_mul (&face_intersect[1].n, -1.0);
1216
 
 
1217
 
          color2 = phong_shade (&face_intersect[1].s,
1218
 
                                &mapvals.viewpoint,
1219
 
                                &face_intersect[1].n,
1220
 
                                &mapvals.lightsource.position,
1221
 
                                &color2,
1222
 
                                &mapvals.lightsource.color,
1223
 
                                mapvals.lightsource.type);
1224
 
 
1225
 
          gimp_rgb_clamp (&color2);
1226
 
 
1227
 
          if (mapvals.transparent_background == FALSE && color2.a < 1.0)
1228
 
            {
1229
 
              gimp_rgb_composite (&color2, &background,
1230
 
                                  GIMP_RGB_COMPOSITE_BEHIND);
1231
 
            }
1232
 
 
1233
 
          /* Compute a mix of the first and second colors */
1234
 
          /* ============================================ */
1235
 
 
1236
 
          gimp_rgb_composite (&color, &color2, GIMP_RGB_COMPOSITE_NORMAL);
1237
 
          gimp_rgb_clamp (&color);
1238
 
        }
1239
 
      else if (color.a != 0.0 && mapvals.lightsource.type != NO_LIGHT)
1240
 
        {
1241
 
          color = phong_shade (&face_intersect[0].s,
1242
 
                               &mapvals.viewpoint,
1243
 
                               &face_intersect[0].n,
1244
 
                               &mapvals.lightsource.position,
1245
 
                               &color,
1246
 
                               &mapvals.lightsource.color,
1247
 
                               mapvals.lightsource.type);
1248
 
 
1249
 
          gimp_rgb_clamp (&color);
1250
 
        }
1251
 
    }
1252
 
  else
1253
 
    {
1254
 
      if (mapvals.transparent_background == TRUE)
1255
 
        gimp_rgb_set_alpha (&color, 0.0);
1256
 
    }
1257
 
 
1258
 
  return color;
1259
 
}