1 /* Copyright (C) 1992-1998 The Geometry Center
2  * Copyright (C) 1998-2000 Stuart Levy, Tamara Munzner, Mark Phillips
3  * Copyright (C) 2007 Claus-Justus Heine
4  *
5  * This file is part of Geomview.
6  *
7  * Geomview is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published
9  * by the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * Geomview is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with Geomview; see the file COPYING.  If not, write
19  * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
20  * USA, or visit http://www.gnu.org.
21  */
22 
23 #if HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26 
27 #if 0
28 static char copyright[] = "Copyright (C) 1992-1998 The Geometry Center\n\
29 Copyright (C) 1998-2000 Stuart Levy, Tamara Munzner, Mark Phillips";
30 #endif
31 
32 #include "mgP.h"
33 #include "mgribP.h"
34 #include "mgribshade.h"
35 #include "mgribtoken.h"
36 
37 /*
38  * Notes:	Tossed mgrib_material, just use mgrib_appearance
39  *		since shaders depend on both appearance and material
40  *		settings. (4/1/93 TMM)
41  */
42 void
mgrib_appearance(struct mgastk * astk,int ap_mask,int mat_mask)43 mgrib_appearance( struct mgastk *astk, int ap_mask, int mat_mask)
44 {
45     Appearance *ap = &(astk->ap);
46     Material *mat = &astk->mat;
47 
48     mrti(mr_section, "Interpreting Material", mr_NULL);
49 
50     if (mat_mask & MTF_DIFFUSE)
51         mrti(mr_color, mr_parray, 3, &mat->diffuse, mr_NULL);
52 
53     if ((ap_mask & APF_TRANSP || mat_mask & MTF_ALPHA) &&
54 	 ap->valid & APF_TRANSP && ap->flag & APF_TRANSP) {
55         /* presumably, we want this here as well as per vertex opacity
56          * specification
57 	 *
58 	 * Actually, if the material alpha override bit is set, we
59 	 * don't output the per vertex opacity information, which
60 	 * would take precedence. 4/16/93 TMM
61          */
62         float alpha = astk->mat.diffuse.a;
63 	mrti(mr_opacity, mr_array, 3, alpha, alpha, alpha, mr_NULL);
64     }
65 
66     if (     (ap_mask & (APF_SHADING|APF_TEXTURE))
67 	 ||  (mat_mask & (MTF_SPECULAR|MTF_SHININESS|MTF_Kd|MTF_Ka|MTF_Ks))
68          ||  (    (ap->tex != NULL)
69                && (ap->flag & APF_TEXTURE)
70                && (ap->tex != astk->next->ap.tex) )
71        ) {
72 #if 1 /* cH: I'm not so sure 'bout the following anymore */
73 	    /* NOTE: the factor "8.0" is to compensate for some of the
74 	     * usual rib shaders, i.e. BMRT, aqsis etc.. Don't know
75 	     * why they started this affair, but without the output
76 	     * from rendrib or aqsis is just _very_ different from
77 	     * that what is displayed on the screen -- cH.
78 	     *
79 	     */
80         float roughness = (mat->shininess)? 8.0/mat->shininess : 8.0/1.0;
81 #else
82         float roughness = (mat->shininess)? 1.0/mat->shininess : 1.0/1.0;
83 #endif
84 	enum tokentype shader = mr_plastic;
85 
86         if (ap->shading == APF_CONSTANT || ap->shading == APF_CSMOOTH) {
87 	    if (_mgribc->shader == MG_RIBSTDSHADE) {
88 		shader = mr_constant;
89 	    } else if ((ap->flag & APF_TEXTURE) && ap->tex != NULL) {
90 		switch (ap->tex->apply) {
91 		case TXF_MODULATE: shader = mr_GVmodulateconstant; break;
92 		case TXF_DECAL: shader = mr_GVdecalconstant; break;
93 		case TXF_BLEND: shader = mr_GVblendconstant; break;
94 		case TXF_REPLACE: shader = mr_GVreplaceconstant; break;
95 		}
96 	    }
97 	    mrti(mr_shadinginterpolation,
98 		 mr_string, ap->shading == APF_CONSTANT ? "constant" : "smooth",
99 		 mr_surface, shader, mr_NULL);
100 	} else {
101 	    /* determine shader */
102 	    if (_mgribc->shader == MG_RIBSTDSHADE) {
103 		if ((ap->flag & APF_TEXTURE) && ap->tex != NULL) {
104 		    shader = mr_paintedplastic;
105 		} else {
106 		    shader = mr_plastic;
107 		}
108 	    } else {
109 	        if (_mgc->space & TM_HYPERBOLIC) {
110 		    shader = mr_hplastic;
111 		} else if ((ap->flag & APF_TEXTURE) && ap->tex != NULL) {
112 		    switch (ap->tex->apply) {
113 		    case TXF_MODULATE: shader = mr_GVmodulateplastic; break;
114 		    case TXF_DECAL: shader = mr_GVdecalplastic; break;
115 		    case TXF_BLEND: shader = mr_GVblendplastic; break;
116 		    case TXF_REPLACE: shader = mr_GVreplaceplastic; break;
117 		    }
118 		} else {
119 		    shader = mr_plastic;
120 		}
121 	    }
122 
123 	    /* define surface */
124 	    if (!IS_SMOOTH(ap->shading)) {
125 		mrti(mr_shadinginterpolation, mr_constant,
126 		     mr_surface, shader, mr_Ka, mr_float, mat->ka,
127 		     mr_Kd, mr_float, mat->kd, mr_Ks, mr_float, mat->ks,
128 		     mr_specularcolor, mr_parray, 3, &(mat->specular),
129 		     mr_roughness, mr_float, roughness, mr_NULL);
130 	    } else {
131 		mrti(mr_shadinginterpolation, mr_string, "smooth",
132 		     mr_surface, shader, mr_Ka, mr_float, mat->ka,
133 		     mr_Kd, mr_float, mat->kd, mr_Ks, mr_float, mat->ks,
134 		     mr_specularcolor, mr_parray, 3, &(mat->specular),
135 		     mr_roughness, mr_float, roughness, mr_NULL);
136 	    }
137 	}
138 
139 	/* define texture if appropriate */
140 	if ((ap->flag & APF_TEXTURE) &&
141 	    ap->tex != NULL && ap->tex->image != NULL) {
142 	    char txtxname[PATH_MAX];
143 	    char tifftxname[PATH_MAX];
144 	    char filter[PATH_MAX];
145 	    int i;
146 	    unsigned chmask = 0;
147 
148 	    if (_mgribc->shader == MG_RIBSTDSHADE) {
149 		static bool was_here = false;
150 
151 		if (!was_here) {
152 		    OOGLWarn("textures with apply != modulate will not work "
153 			     "when using the standard shaders.\n");
154 		    was_here = true;
155 		}
156 	    }
157 
158 	    for (i = 0; i < _mgribc->n_tximg; i++) {
159 		if (_mgribc->tx[i]->image == ap->tex->image &&
160 		    (_mgribc->tx[i]->flags & (TXF_SCLAMP|TXF_TCLAMP))
161 		    ==
162 		    (ap->tex->flags & (TXF_SCLAMP|TXF_TCLAMP))) {
163 		    break;
164 		}
165 	    }
166 
167 	    mgrib_mktexname(txtxname, i, _mgribc->tmppath, "tiff.tx");
168 
169 	    if (i == _mgribc->n_tximg) {
170 		if (_mgribc->n_tximg % 10 == 0) {
171 		    _mgribc->tx = OOGLRenewNE(Texture *,
172 					      _mgribc->tx,
173 					      _mgribc->n_tximg + 10,
174 					      "New RIB texture images");
175 		}
176 		_mgribc->tx[i] = ap->tex;
177 		_mgribc->n_tximg++;
178 		/* try to dump the image to disk */
179 		mgrib_mktexname(tifftxname, i, _mgribc->displaypath, "tiff");
180 #ifdef HAVE_PAMTOTIFF
181 		chmask = (1 << ap->tex->image->channels) - 1;
182 		sprintf(filter, "pamtotiff -lzw -truecolor > %s 2> /dev/null",
183 			tifftxname);
184 #else
185 		chmask = ap->tex->image->channels > 2 ? 0x7 : 0x1;
186 		sprintf(filter, "pnmtotiff -lzw -truecolor > %s 2> /dev/null",
187 			tifftxname);
188 #endif
189 		if (!ImgWriteFilter(ap->tex->image, chmask, filter)) {
190 		    _mgribc->tx[i] = NULL;
191 		    --_mgribc->n_tximg;
192 		}
193 		mgrib_mktexname(tifftxname, i, NULL, "tiff");
194 		mrti_makecurrent(&_mgribc->txbuf);
195 		mrti(mr_maketexture, mr_string, tifftxname, mr_string, txtxname,
196 		     mr_string,
197 		     ap->tex->flags & TXF_SCLAMP ? "clamp" : "periodic",
198 		     mr_string,
199 		     ap->tex->flags & TXF_TCLAMP ? "clamp" : "periodic",
200 		     mr_string, "gaussian", mr_float, 2.0, mr_float, 2.0,
201 		     mr_NULL);
202 		mrti_makecurrent(&_mgribc->worldbuf);
203 	    }
204 	    if (i < _mgribc->n_tximg) {
205 		mrti(mr_texturename, mr_string, txtxname, mr_NULL);
206 	    }
207 	    if (ap->tex->apply == TXF_BLEND) {
208 		mrti(mr_string, "bgcolor",
209 		     mr_parray, 3, &(ap->tex->background), mr_NULL);
210 	    }
211 	    if (ap->tex->apply != TXF_DECAL) {
212 		mrti(mr_string, "At",
213 		     mr_float, (ap->flag & APF_TRANSP) ? 1.0 : 0.0, mr_NULL);
214 	    }
215 	}
216     }
217 }
218 
219 void
mgrib_lighting(struct mgastk * astk,int mask)220 mgrib_lighting(struct mgastk *astk, int mask)
221 {
222   LmLighting *lm = &astk->lighting;
223 
224   if (lm->valid & mask & LMF_AMBIENT) {
225       mrti(mr_section, "Interpreting Lights", mr_NULL);
226       /* output the ambient light */
227       mrti(mr_comment, "Ambient Light", mr_NULL);
228       mrti(mr_lightsource, mr_ambientlight, mr_int, 0,
229 	   mr_lightcolor, mr_parray, 3, &(lm->ambient), mr_NULL);
230     }
231   /* We must be in global coordinate space to place lights correctly. */
232   mrti(mr_transformbegin, mr_identity, mr_NULL);
233   mgrib_lights( lm, astk );
234   mrti(mr_transformend, mr_NULL);
235 }
236 
237 /* In GL, we want unique light numbers. In RenderMan we want to re-use
238 light numbers, so we always start with light "1".  In GL, we define
239 then bind lights. Defining is expensive and we avoid it as much as
240 possible. In RenderMan, it's a one-step process. Also, once a light is
241 defined it cannot be deleted. Thus we might need to explicitly turn
242 off lights if we are replacing more lights with less lights. So we
243 keep track of how many lights we've used so far, and turn off the
244 extras when we need to.
245 1/13/92 TMM */
246 
mgrib_lights(LmLighting * lm,struct mgastk * astk)247 void mgrib_lights( LmLighting *lm, struct mgastk *astk )
248 {
249   int i, lightsused;
250   LtLight *light, **lp;
251   static int prevused = 0;
252 
253   lightsused = 0;
254   LM_FOR_ALL_LIGHTS(lm, i,lp) {
255     light = *lp;
256     ++lightsused;
257 
258     if (light->Private == 0) {
259       /* this is a new light */
260       light->Private = lightsused;
261       light->changed = 1;
262     }
263     if (light->changed) {
264       if (light->position.w == 0.0) {
265 	/* directional light */
266 	/* We used to output the lights as "to" instead of as "from".
267 	   This is like negating them, which is why we then did
268 	   explicitly negate them to get the right result!
269 	   So, leave the lights alone now. Do NOT negate them.
270 	   It's NOT about handedness of coordinate systems.
271          */
272 	mrti(mr_comment, "Directional Light",
273 	     mr_lightsource, mr_distantlight, mr_int, light->Private,
274 	     mr_intensity, mr_float, light->intensity,
275 	     mr_lightcolor, mr_parray, 3, &(light->color),
276 	     mr_string, "from", mr_parray, 3, &(light->globalposition),
277 	     mr_string, "to", mr_array, 3, 0.,0.,0., /* aim at origin */
278 	     mr_NULL);
279       } else {
280 	/* point light */
281 	mrti(mr_lightsource, mr_string, "pointlight", mr_int, light->Private,
282 	     mr_intensity, mr_float, light->intensity,
283 	     mr_lightcolor, mr_parray, 3, &(light->color),
284 	     mr_string, "from", mr_parray, 3, &(light->globalposition),
285 	     mr_NULL);
286       }
287       light->changed = 0;
288     }
289   }
290   for (i = lightsused +1; i <= prevused; i++)
291     mrti(mr_illuminate, mr_int, i, mr_int, 0, mr_NULL);
292   if (prevused < lightsused) prevused = lightsused;
293 }
294 
295 /*
296  * Local Variables: ***
297  * mode: c ***
298  * c-basic-offset: 4 ***
299  * End: ***
300  */
301