1 /* Lighting Effects 0.2.2 -- image filter plug-in for GIMP
2  *
3  * Copyright (C) 1996-98 Tom Bech
4  * Copyright (C) 1996-98 Federico Mena Quintero
5  *
6  * E-mail: tomb@gimp.org (Tom) or quartic@gimp.org (Federico)
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include "config.h"
23 
24 #include <gtk/gtk.h>
25 
26 #include <libgimp/gimp.h>
27 
28 #include "lighting-apply.h"
29 #include "lighting-image.h"
30 #include "lighting-main.h"
31 #include "lighting-preview.h"
32 #include "lighting-shade.h"
33 #include "lighting-ui.h"
34 
35 #include "libgimp/stdplugins-intl.h"
36 
37 
38 LightingValues mapvals;
39 
40 /******************/
41 /* Implementation */
42 /******************/
43 
44 /*************************************/
45 /* Set parameters to standard values */
46 /*************************************/
47 
48 static void
set_default_settings(void)49 set_default_settings (void)
50 {
51   gint k;
52 
53   mapvals.update_enabled = TRUE;
54   mapvals.light_selected = 0;
55   mapvals.light_isolated = FALSE;
56 
57   gimp_vector3_set (&mapvals.viewpoint,   0.5, 0.5, 0.25);
58   gimp_vector3_set (&mapvals.planenormal, 0.0, 0.0, 1.0);
59 
60   gimp_vector3_set (&mapvals.lightsource[0].position,  -1.0, -1.0, 1.0);
61   gimp_vector3_set (&mapvals.lightsource[0].direction, -1.0, -1.0, 1.0);
62 
63   gimp_rgba_set (&mapvals.lightsource[0].color, 1.0, 1.0, 1.0, 1.0);
64   mapvals.lightsource[0].intensity = 1.0;
65   mapvals.lightsource[0].type      = POINT_LIGHT;
66   mapvals.lightsource[0].active    = TRUE;
67 
68   /* init lights 2 and 3 pos to upper left and below */
69   gimp_vector3_set (&mapvals.lightsource[1].position,   2.0, -1.0, 1.0);
70   gimp_vector3_set (&mapvals.lightsource[1].direction,  1.0, -1.0, 1.0);
71 
72   gimp_vector3_set (&mapvals.lightsource[2].position,   1.0,  2.0, 1.0);
73   gimp_vector3_set (&mapvals.lightsource[2].direction,  0.0,  1.0, 1.0);
74 
75   /* init any remaining lights to directly overhead */
76   for (k = 3; k < NUM_LIGHTS; k++)
77     {
78       gimp_vector3_set (&mapvals.lightsource[k].position,   0.0,  0.0, 1.0);
79       gimp_vector3_set (&mapvals.lightsource[k].direction,  0.0,  0.0, 1.0);
80     }
81 
82   for (k = 1; k < NUM_LIGHTS; k++)
83     {
84       gimp_rgba_set (&mapvals.lightsource[k].color, 1.0, 1.0, 1.0, 1.0);
85       mapvals.lightsource[k].intensity = 1.0;
86       mapvals.lightsource[k].type      = NO_LIGHT;
87       mapvals.lightsource[k].active    = TRUE;
88     }
89 
90   mapvals.material.ambient_int  =  0.2;
91   mapvals.material.diffuse_int  =  0.5;
92   mapvals.material.diffuse_ref  =  0.4;
93   mapvals.material.specular_ref =  0.5;
94   mapvals.material.highlight    = 27.0;
95   mapvals.material.metallic     = FALSE;
96 
97   mapvals.pixel_threshold     = 0.25;
98   mapvals.max_depth           =  3.0;
99   mapvals.preview_zoom_factor =  1.0;
100 
101   mapvals.bumpmaptype = 0;
102   mapvals.bumpmin     = 0.0;
103   mapvals.bumpmax     = 0.1;
104 
105   mapvals.antialiasing           = FALSE;
106   mapvals.create_new_image       = FALSE;
107   mapvals.transparent_background = FALSE;
108   mapvals.bump_mapped            = FALSE;
109   mapvals.env_mapped             = FALSE;
110   mapvals.ref_mapped             = FALSE;
111   mapvals.previewquality         = FALSE;
112   mapvals.interactive_preview    = TRUE;
113 
114   mapvals.bumpmap_id = -1;
115   mapvals.envmap_id  = -1;
116 }
117 
118 static void
check_drawables(void)119 check_drawables (void)
120 {
121   if (mapvals.bump_mapped)
122     {
123       if (mapvals.bumpmap_id != -1 &&
124           gimp_item_get_image (mapvals.bumpmap_id) == -1)
125         {
126           mapvals.bump_mapped = FALSE;
127           mapvals.bumpmap_id  = -1;
128         }
129 
130       if (gimp_drawable_is_indexed (mapvals.bumpmap_id) ||
131           (gimp_drawable_width (mapvals.drawable_id) !=
132            gimp_drawable_width (mapvals.bumpmap_id)) ||
133           (gimp_drawable_height (mapvals.drawable_id) !=
134            gimp_drawable_height (mapvals.bumpmap_id)))
135         {
136           mapvals.bump_mapped = FALSE;
137           mapvals.bumpmap_id  = -1;
138         }
139     }
140 
141   if (mapvals.env_mapped)
142     {
143       if (mapvals.envmap_id != -1 &&
144           gimp_item_get_image (mapvals.envmap_id) == -1)
145         {
146           mapvals.env_mapped = FALSE;
147           mapvals.envmap_id  = -1;
148         }
149 
150       if (gimp_drawable_is_gray (mapvals.envmap_id) ||
151           gimp_drawable_has_alpha (mapvals.envmap_id))
152         {
153           mapvals.env_mapped = FALSE;
154           mapvals.envmap_id  = -1;
155         }
156     }
157 }
158 
159 static void
query(void)160 query (void)
161 {
162   static const GimpParamDef args[] =
163   {
164     { GIMP_PDB_INT32,    "run-mode",              "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
165     { GIMP_PDB_IMAGE,    "image",                 "Input image" },
166     { GIMP_PDB_DRAWABLE, "drawable",              "Input drawable" },
167     { GIMP_PDB_DRAWABLE, "bumpdrawable",          "Bumpmap drawable (set to 0 if disabled)" },
168     { GIMP_PDB_DRAWABLE, "envdrawable",           "Environmentmap drawable (set to 0 if disabled)" },
169     { GIMP_PDB_INT32,    "dobumpmap",             "Enable bumpmapping (TRUE/FALSE)" },
170     { GIMP_PDB_INT32,    "doenvmap",              "Enable envmapping (TRUE/FALSE)" },
171     { GIMP_PDB_INT32,    "bumpmaptype",           "Type of mapping (0=linear,1=log, 2=sinusoidal, 3=spherical)" },
172     { GIMP_PDB_INT32,    "lighttype",             "Type of lightsource (0=point,1=directional,3=spot,4=none)" },
173     { GIMP_PDB_COLOR,    "lightcolor",            "Lightsource color (r,g,b)" },
174     { GIMP_PDB_FLOAT,    "lightposition-x",       "Lightsource position (x,y,z)" },
175     { GIMP_PDB_FLOAT,    "lightposition-y",       "Lightsource position (x,y,z)" },
176     { GIMP_PDB_FLOAT,    "lightposition-z",       "Lightsource position (x,y,z)" },
177     { GIMP_PDB_FLOAT,    "lightdirection-x",      "Lightsource direction [x,y,z]" },
178     { GIMP_PDB_FLOAT,    "lightdirection-y",      "Lightsource direction [x,y,z]" },
179     { GIMP_PDB_FLOAT,    "lightdirection-z",      "Lightsource direction [x,y,z]" },
180     { GIMP_PDB_FLOAT,    "ambient-intensity",     "Material ambient intensity (0..1)" },
181     { GIMP_PDB_FLOAT,    "diffuse-intensity",     "Material diffuse intensity (0..1)" },
182     { GIMP_PDB_FLOAT,    "diffuse-reflectivity",  "Material diffuse reflectivity (0..1)" },
183     { GIMP_PDB_FLOAT,    "specular-reflectivity", "Material specular reflectivity (0..1)" },
184     { GIMP_PDB_FLOAT,    "highlight",             "Material highlight (0..->), note: it's exponential" },
185     { GIMP_PDB_INT32,    "antialiasing",          "Apply antialiasing (TRUE/FALSE)" },
186     { GIMP_PDB_INT32,    "newimage",              "Create a new image (TRUE/FALSE)" },
187     { GIMP_PDB_INT32,    "transparentbackground", "Make background transparent (TRUE/FALSE)" }
188   };
189 
190   gimp_install_procedure (PLUG_IN_PROC,
191                           N_("Apply various lighting effects to an image"),
192                           "No help yet",
193                           "Tom Bech & Federico Mena Quintero",
194                           "Tom Bech & Federico Mena Quintero",
195                           "Version 0.2.0, March 15 1998",
196                           N_("_Lighting Effects..."),
197                           "RGB*",
198                           GIMP_PLUGIN,
199                           G_N_ELEMENTS (args), 0,
200                           args, NULL);
201 
202   gimp_plugin_menu_register (PLUG_IN_PROC,
203                              "<Image>/Filters/Light and Shadow/Light");
204 }
205 
206 static void
run(const gchar * name,gint nparams,const GimpParam * param,gint * nreturn_vals,GimpParam ** return_vals)207 run (const gchar      *name,
208      gint              nparams,
209      const GimpParam  *param,
210      gint             *nreturn_vals,
211      GimpParam       **return_vals)
212 {
213   static GimpParam   values[1];
214   GimpRunMode        run_mode;
215   gint32             drawable_id;
216   GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
217 
218   INIT_I18N ();
219   gegl_init (NULL, NULL);
220 
221   *nreturn_vals = 1;
222   *return_vals = values;
223 
224   values[0].type = GIMP_PDB_STATUS;
225   values[0].data.d_status = status;
226 
227   /* Set default values */
228   /* ================== */
229 
230   set_default_settings ();
231 
232   /* Possibly retrieve data */
233   /* ====================== */
234 
235   gimp_get_data (PLUG_IN_PROC, &mapvals);
236 
237   /* Get the specified drawable */
238   /* ========================== */
239 
240   run_mode    = param[0].data.d_int32;
241   drawable_id = param[2].data.d_drawable;
242 
243   mapvals.drawable_id = drawable_id;
244 
245   check_drawables ();
246 
247   if (status == GIMP_PDB_SUCCESS)
248     {
249       /* Make sure that the drawable is RGBA or RGB color */
250       /* ================================================ */
251 
252       if (gimp_drawable_is_rgb (drawable_id))
253         {
254           switch (run_mode)
255             {
256               case GIMP_RUN_INTERACTIVE:
257                 if (main_dialog (drawable_id))
258                   {
259                     compute_image ();
260 
261                     gimp_set_data (PLUG_IN_PROC,
262                                    &mapvals, sizeof (LightingValues));
263                     gimp_displays_flush ();
264                   }
265               break;
266 
267               case GIMP_RUN_WITH_LAST_VALS:
268                 if (image_setup (drawable_id, FALSE))
269                   compute_image ();
270                 gimp_displays_flush ();
271                 break;
272 
273               case GIMP_RUN_NONINTERACTIVE:
274                 if (nparams != 24)
275                   {
276                     status = GIMP_PDB_CALLING_ERROR;
277                   }
278                 else
279                   {
280                     mapvals.bumpmap_id                 = param[3].data.d_drawable;
281                     mapvals.envmap_id                  = param[4].data.d_drawable;
282                     mapvals.bump_mapped                = (gint) param[5].data.d_int32;
283                     mapvals.env_mapped                 = (gint) param[6].data.d_int32;
284                     mapvals.bumpmaptype                = (gint) param[7].data.d_int32;
285                     mapvals.lightsource[0].type        = (LightType) param[8].data.d_int32;
286                     mapvals.lightsource[0].color       = param[9].data.d_color;
287                     mapvals.lightsource[0].position.x  = param[10].data.d_float;
288                     mapvals.lightsource[0].position.y  = param[11].data.d_float;
289                     mapvals.lightsource[0].position.z  = param[12].data.d_float;
290                     mapvals.lightsource[0].direction.x = param[13].data.d_float;
291                     mapvals.lightsource[0].direction.y = param[14].data.d_float;
292                     mapvals.lightsource[0].direction.z = param[15].data.d_float;
293                     mapvals.material.ambient_int       = param[16].data.d_float;
294                     mapvals.material.diffuse_int       = param[17].data.d_float;
295                     mapvals.material.diffuse_ref       = param[18].data.d_float;
296                     mapvals.material.specular_ref      = param[19].data.d_float;
297                     mapvals.material.highlight         = param[20].data.d_float;
298                     mapvals.antialiasing               = (gint) param[21].data.d_int32;
299                     mapvals.create_new_image           = (gint) param[22].data.d_int32;
300                     mapvals.transparent_background     = (gint) param[23].data.d_int32;
301 
302                     check_drawables ();
303                     if (image_setup (drawable_id, FALSE))
304                       compute_image ();
305                   }
306               default:
307                 break;
308             }
309         }
310       else
311         {
312           status = GIMP_PDB_EXECUTION_ERROR;
313         }
314     }
315 
316   values[0].data.d_status = status;
317 
318   g_free (xpostab);
319   g_free (ypostab);
320 }
321 
322 const GimpPlugInInfo PLUG_IN_INFO =
323 {
324   NULL,  /* init_proc  */
325   NULL,  /* quit_proc  */
326   query, /* query_proc */
327   run,   /* run_proc   */
328 };
329 
330 MAIN ()
331