]> git.mxchange.org Git - simgear.git/blob - simgear/scene/material/matlib.cxx
b3f702cc9cb1500c1a7b985073cd6a124e27e290
[simgear.git] / simgear / scene / material / matlib.cxx
1 // materialmgr.cxx -- class to handle material properties
2 //
3 // Written by Curtis Olson, started May 1998.
4 //
5 // Copyright (C) 1998  Curtis L. Olson  - http://www.flightgear.org/~curt
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program 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 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 //
21 // $Id$
22
23
24 #ifdef HAVE_CONFIG_H
25 #  include <simgear_config.h>
26 #endif
27
28 #ifdef SG_MATH_EXCEPTION_CLASH
29 #  include <math.h>
30 #endif
31
32 #ifdef HAVE_WINDOWS_H
33 #  include <windows.h>
34 #endif
35
36 #include <plib/ssg.h>
37
38 #include <simgear/compiler.h>
39 #include <simgear/constants.h>
40 #include <simgear/structure/exception.hxx>
41
42 #include SG_GL_H
43
44 #include <string.h>
45 #include STL_STRING
46
47 #include <simgear/debug/logstream.hxx>
48 #include <simgear/misc/sg_path.hxx>
49 #include <simgear/misc/sgstream.hxx>
50 #include <simgear/props/props_io.hxx>
51 #include <simgear/scene/tgdb/userdata.hxx>
52
53 #include "mat.hxx"
54
55 #include "matlib.hxx"
56
57 SG_USING_NAMESPACE(std);
58 SG_USING_STD(string);
59
60
61 // FIXME: should make this configurable
62 static const bool sprite_lighting = true;
63
64
65 // Constructor
66 SGMaterialLib::SGMaterialLib ( void ) {
67 }
68
69
70 #if 0 // debugging infrastructure
71 static int gen_test_light_map() {
72     static const int env_tex_res = 32;
73     int half_res = env_tex_res / 2;
74     unsigned char env_map[env_tex_res][env_tex_res][4];
75     GLuint tex_name;
76
77     for ( int i = 0; i < env_tex_res; ++i ) {
78         for ( int j = 0; j < env_tex_res; ++j ) {
79             double x = (i - half_res) / (double)half_res;
80             double y = (j - half_res) / (double)half_res;
81             double dist = sqrt(x*x + y*y);
82             if ( dist > 1.0 ) { dist = 1.0; }
83
84             // cout << x << "," << y << " " << (int)(dist * 255) << ","
85             //      << (int)((1.0 - dist) * 255) << endl;
86             env_map[i][j][0] = (int)(dist * 255);
87             env_map[i][j][1] = (int)((1.0 - dist) * 255);
88             env_map[i][j][2] = 0;
89             env_map[i][j][3] = 255;
90         }
91     }
92
93     glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
94     glGenTextures( 1, &tex_name );
95     glBindTexture( GL_TEXTURE_2D, tex_name );
96   
97     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
98     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
99     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
100     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
101     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, env_tex_res, env_tex_res, 0,
102                   GL_RGBA, GL_UNSIGNED_BYTE, env_map);
103
104     return tex_name;
105 }
106 #endif
107
108
109 // generate a light sprite texture map
110 static int gen_standard_light_sprite( int r, int g, int b, int alpha ) {
111     const int env_tex_res = 32;
112     int half_res = env_tex_res / 2;
113     unsigned char env_map[env_tex_res][env_tex_res][4];
114     GLuint tex_name;
115
116     for ( int i = 0; i < env_tex_res; ++i ) {
117         for ( int j = 0; j < env_tex_res; ++j ) {
118             double x = (i - half_res) / (double)half_res;
119             double y = (j - half_res) / (double)half_res;
120             double dist = sqrt(x*x + y*y);
121             if ( dist > 1.0 ) { dist = 1.0; }
122             double bright = cos( dist * SGD_PI_2 );
123             if ( bright < 0.01 ) { bright = 0.0; }
124             env_map[i][j][0] = r;
125             env_map[i][j][1] = g;
126             env_map[i][j][2] = b;
127             env_map[i][j][3] = (int)(bright * alpha);
128         }
129     }
130     glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
131     glGenTextures( 1, &tex_name );
132     glBindTexture( GL_TEXTURE_2D, tex_name );
133   
134     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
135     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
136     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
137     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
138     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, env_tex_res, env_tex_res, 0,
139                   GL_RGBA, GL_UNSIGNED_BYTE, env_map);
140
141     return tex_name;
142 }
143
144
145 // generate standard colored directional light environment texture map
146 static int gen_standard_dir_light_map( int r, int g, int b, int alpha ) {
147     const int env_tex_res = 32;
148     int half_res = env_tex_res / 2;
149     unsigned char env_map[env_tex_res][env_tex_res][4];
150     GLuint tex_name;
151
152     for ( int i = 0; i < env_tex_res; ++i ) {
153         for ( int j = 0; j < env_tex_res; ++j ) {
154             double x = (i - half_res) / (double)half_res;
155             double y = (j - half_res) / (double)half_res;
156             double dist = sqrt(x*x + y*y);
157             if ( dist > 1.0 ) { dist = 1.0; }
158             double bright = cos( dist * SGD_PI_2 );
159             if ( bright < 0.3 ) { bright = 0.3; }
160             env_map[i][j][0] = r;
161             env_map[i][j][1] = g;
162             env_map[i][j][2] = b;
163             env_map[i][j][3] = (int)(bright * alpha);
164         }
165     }
166
167     glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
168     glGenTextures( 1, &tex_name );
169     glBindTexture( GL_TEXTURE_2D, tex_name );
170   
171     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
172     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
173     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
174     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
175     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, env_tex_res, env_tex_res, 0,
176                   GL_RGBA, GL_UNSIGNED_BYTE, env_map);
177
178     return tex_name;
179 }
180
181
182 // generate standard colored directional light environment texture map
183 static int gen_taxiway_dir_light_map( int r, int g, int b, int alpha ) {
184     const int env_tex_res = 32;
185     int half_res = env_tex_res / 2;
186     unsigned char env_map[env_tex_res][env_tex_res][4];
187     GLuint tex_name;
188
189     for ( int i = 0; i < env_tex_res; ++i ) {
190         for ( int j = 0; j < env_tex_res; ++j ) {
191             double x = (i - half_res) / (double)half_res;
192             double y = (j - half_res) / (double)half_res;
193             double tmp = sqrt(x*x + y*y);
194             double dist = tmp * tmp;
195             if ( dist > 1.0 ) { dist = 1.0; }
196             double bright = sin( dist * SGD_PI_2 );
197             if ( bright < 0.2 ) { bright = 0.2; }
198             env_map[i][j][0] = r;
199             env_map[i][j][1] = g;
200             env_map[i][j][2] = b;
201             env_map[i][j][3] = (int)(bright * alpha);
202         }
203     }
204
205     glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
206     glGenTextures( 1, &tex_name );
207     glBindTexture( GL_TEXTURE_2D, tex_name );
208   
209     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
210     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
211     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
212     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
213     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, env_tex_res, env_tex_res, 0,
214                   GL_RGBA, GL_UNSIGNED_BYTE, env_map);
215
216     return tex_name;
217 }
218
219
220 // Load a library of material properties
221 bool SGMaterialLib::load( const string &fg_root, const string& mpath, const char *season ) {
222
223     SGPropertyNode materials;
224
225     SG_LOG( SG_INPUT, SG_INFO, "Reading materials from " << mpath );
226     try {
227         readProperties( mpath, &materials );
228     } catch (const sg_exception &ex) {
229         SG_LOG( SG_INPUT, SG_ALERT, "Error reading materials: "
230                 << ex.getMessage() );
231         throw;
232     }
233
234     SGSharedPtr<SGMaterial> m;
235
236     int nMaterials = materials.nChildren();
237     for (int i = 0; i < nMaterials; i++) {
238         const SGPropertyNode * node = materials.getChild(i);
239         if (!strcmp(node->getName(), "material")) {
240             m = new SGMaterial( fg_root, node, season );
241
242             vector<SGPropertyNode_ptr>names = node->getChildren("name");
243             for ( unsigned int j = 0; j < names.size(); j++ ) {
244                 string name = names[j]->getStringValue();
245                 // cerr << "Material " << name << endl;
246                 matlib[name] = m;
247                 m->add_name(name);
248                 SG_LOG( SG_TERRAIN, SG_INFO, "  Loading material "
249                         << names[j]->getStringValue() );
250             }
251         } else {
252             SG_LOG(SG_INPUT, SG_WARN,
253                    "Skipping bad material entry " << node->getName());
254         }
255     }
256
257     // hard coded ground light state
258     ssgSimpleState *gnd_lights = new ssgSimpleState;
259     gnd_lights->disable( GL_TEXTURE_2D );
260     gnd_lights->enable( GL_CULL_FACE );
261     gnd_lights->enable( GL_COLOR_MATERIAL );
262     gnd_lights->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
263     gnd_lights->setMaterial( GL_EMISSION, 0, 0, 0, 1 );
264     gnd_lights->setMaterial( GL_SPECULAR, 0, 0, 0, 1 );
265     gnd_lights->enable( GL_BLEND );
266     gnd_lights->disable( GL_ALPHA_TEST );
267     gnd_lights->disable( GL_LIGHTING );
268     m = new SGMaterial( gnd_lights );
269     m->add_name("GROUND_LIGHTS");
270     matlib["GROUND_LIGHTS"] = m;
271
272     GLuint tex_name;
273
274     // hard coded runway white light state
275     if ( sprite_lighting ) {
276         tex_name = gen_standard_light_sprite( 235, 235, 195, 255 );
277     } else {
278         tex_name = gen_standard_dir_light_map( 235, 235, 195, 255 );
279     }
280     ssgSimpleState *rwy_white_lights = new ssgSimpleState();
281     rwy_white_lights->disable( GL_LIGHTING );
282     rwy_white_lights->enable ( GL_CULL_FACE ) ;
283     rwy_white_lights->enable( GL_TEXTURE_2D );
284     rwy_white_lights->enable( GL_BLEND );
285     rwy_white_lights->enable( GL_ALPHA_TEST );
286     rwy_white_lights->enable( GL_COLOR_MATERIAL );
287     rwy_white_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
288     rwy_white_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
289     rwy_white_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
290     rwy_white_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
291     rwy_white_lights->setTexture( tex_name );
292     m = new SGMaterial( rwy_white_lights );
293     m->add_name("RWY_WHITE_LIGHTS");
294     matlib["RWY_WHITE_LIGHTS"] = m;
295     // For backwards compatibility ... remove someday
296     m->add_name("RUNWAY_LIGHTS");
297     matlib["RUNWAY_LIGHTS"] = m;
298     m->add_name("RWY_LIGHTS");
299     matlib["RWY_LIGHTS"] = m;
300     // end of backwards compatitibilty
301
302     // hard coded runway medium intensity white light state
303     if ( sprite_lighting ) {
304         tex_name = gen_standard_light_sprite( 235, 235, 195, 205 );
305     } else {
306         tex_name = gen_standard_dir_light_map( 235, 235, 195, 205 );
307     }
308     ssgSimpleState *rwy_white_medium_lights = new ssgSimpleState();
309     rwy_white_medium_lights->disable( GL_LIGHTING );
310     rwy_white_medium_lights->enable ( GL_CULL_FACE ) ;
311     rwy_white_medium_lights->enable( GL_TEXTURE_2D );
312     rwy_white_medium_lights->enable( GL_BLEND );
313     rwy_white_medium_lights->enable( GL_ALPHA_TEST );
314     rwy_white_medium_lights->enable( GL_COLOR_MATERIAL );
315     rwy_white_medium_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
316     rwy_white_medium_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
317     rwy_white_medium_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
318     rwy_white_medium_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
319     rwy_white_medium_lights->setTexture( tex_name );
320     m = new SGMaterial( rwy_white_medium_lights );
321     m->add_name("RWY_WHITE_MEDIUM_LIGHTS");
322     matlib["RWY_WHITE_MEDIUM_LIGHTS"] = m;
323
324     // hard coded runway low intensity white light state
325     if ( sprite_lighting ) {
326         tex_name = gen_standard_light_sprite( 235, 235, 195, 155 );
327     } else {
328         tex_name = gen_standard_dir_light_map( 235, 235, 195, 155 );
329     }
330     ssgSimpleState *rwy_white_low_lights = new ssgSimpleState();
331     rwy_white_low_lights->disable( GL_LIGHTING );
332     rwy_white_low_lights->enable ( GL_CULL_FACE ) ;
333     rwy_white_low_lights->enable( GL_TEXTURE_2D );
334     rwy_white_low_lights->enable( GL_BLEND );
335     rwy_white_low_lights->enable( GL_ALPHA_TEST );
336     rwy_white_low_lights->enable( GL_COLOR_MATERIAL );
337     rwy_white_low_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
338     rwy_white_low_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
339     rwy_white_low_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
340     rwy_white_low_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
341     rwy_white_low_lights->setTexture( tex_name );
342     m = new SGMaterial( rwy_white_low_lights );
343     m->add_name("RWY_WHITE_LOW_LIGHTS");
344     matlib["RWY_WHITE_LOW_LIGHTS"] = m;
345
346     // hard coded runway yellow light state
347     if ( sprite_lighting ) {
348         tex_name = gen_standard_light_sprite( 235, 215, 20, 255 );
349     } else {
350         tex_name = gen_standard_dir_light_map( 235, 215, 20, 255 );
351     }
352     ssgSimpleState *rwy_yellow_lights = new ssgSimpleState();
353     rwy_yellow_lights->disable( GL_LIGHTING );
354     rwy_yellow_lights->enable ( GL_CULL_FACE ) ;
355     rwy_yellow_lights->enable( GL_TEXTURE_2D );
356     rwy_yellow_lights->enable( GL_BLEND );
357     rwy_yellow_lights->enable( GL_ALPHA_TEST );
358     rwy_yellow_lights->enable( GL_COLOR_MATERIAL );
359     rwy_yellow_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
360     rwy_yellow_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
361     rwy_yellow_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
362     rwy_yellow_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
363     rwy_yellow_lights->setTexture( tex_name );
364     m = new SGMaterial( rwy_yellow_lights );
365     m->add_name("RWY_YELLOW_LIGHTS");
366     matlib["RWY_YELLOW_LIGHTS"] = m;
367
368     // hard coded runway medium intensity yellow light state
369     if ( sprite_lighting ) {
370         tex_name = gen_standard_light_sprite( 235, 215, 20, 205 );
371     } else {
372         tex_name = gen_standard_dir_light_map( 235, 215, 20, 205 );
373     }
374     ssgSimpleState *rwy_yellow_medium_lights = new ssgSimpleState();
375     rwy_yellow_medium_lights->disable( GL_LIGHTING );
376     rwy_yellow_medium_lights->enable ( GL_CULL_FACE ) ;
377     rwy_yellow_medium_lights->enable( GL_TEXTURE_2D );
378     rwy_yellow_medium_lights->enable( GL_BLEND );
379     rwy_yellow_medium_lights->enable( GL_ALPHA_TEST );
380     rwy_yellow_medium_lights->enable( GL_COLOR_MATERIAL );
381     rwy_yellow_medium_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
382     rwy_yellow_medium_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
383     rwy_yellow_medium_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
384     rwy_yellow_medium_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
385     rwy_yellow_medium_lights->setTexture( tex_name );
386     m = new SGMaterial( rwy_yellow_medium_lights );
387     m->add_name("RWY_YELLOW_MEDIUM_LIGHTS");
388     matlib["RWY_YELLOW_MEDIUM_LIGHTS"] = m;
389
390     // hard coded runway low intensity yellow light state
391     if ( sprite_lighting ) {
392         tex_name = gen_standard_light_sprite( 235, 215, 20, 155 );
393     } else {
394         tex_name = gen_standard_dir_light_map( 235, 215, 20, 155 );
395     }
396     ssgSimpleState *rwy_yellow_low_lights = new ssgSimpleState();
397     rwy_yellow_low_lights->disable( GL_LIGHTING );
398     rwy_yellow_low_lights->enable ( GL_CULL_FACE ) ;
399     rwy_yellow_low_lights->enable( GL_TEXTURE_2D );
400     rwy_yellow_low_lights->enable( GL_BLEND );
401     rwy_yellow_low_lights->enable( GL_ALPHA_TEST );
402     rwy_yellow_low_lights->enable( GL_COLOR_MATERIAL );
403     rwy_yellow_low_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
404     rwy_yellow_low_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
405     rwy_yellow_low_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
406     rwy_yellow_low_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
407     rwy_yellow_low_lights->setTexture( tex_name );
408     m = new SGMaterial( rwy_yellow_low_lights );
409     m->add_name("RWY_YELLOW_LOW_LIGHTS");
410     matlib["RWY_YELLOW_LOW_LIGHTS"] = m;
411
412     // hard coded runway red light state
413     if ( sprite_lighting ) {
414         tex_name = gen_standard_light_sprite( 235, 90, 90, 255 );
415     } else {
416         tex_name = gen_standard_dir_light_map( 235, 90, 90, 255 );
417     }
418     ssgSimpleState *rwy_red_lights = new ssgSimpleState();
419     rwy_red_lights->disable( GL_LIGHTING );
420     rwy_red_lights->enable ( GL_CULL_FACE ) ;
421     rwy_red_lights->enable( GL_TEXTURE_2D );
422     rwy_red_lights->enable( GL_BLEND );
423     rwy_red_lights->enable( GL_ALPHA_TEST );
424     rwy_red_lights->enable( GL_COLOR_MATERIAL );
425     rwy_red_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
426     rwy_red_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
427     rwy_red_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
428     rwy_red_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
429     rwy_red_lights->setTexture( tex_name );
430     m = new SGMaterial( rwy_red_lights );
431     m->add_name("RWY_RED_LIGHTS");
432     matlib["RWY_RED_LIGHTS"] = m;
433
434     // hard coded medium intensity runway red light state
435     if ( sprite_lighting ) {
436         tex_name = gen_standard_light_sprite( 235, 90, 90, 205 );
437     } else {
438         tex_name = gen_standard_dir_light_map( 235, 90, 90, 205 );
439     }
440     ssgSimpleState *rwy_red_medium_lights = new ssgSimpleState();
441     rwy_red_medium_lights->disable( GL_LIGHTING );
442     rwy_red_medium_lights->enable ( GL_CULL_FACE ) ;
443     rwy_red_medium_lights->enable( GL_TEXTURE_2D );
444     rwy_red_medium_lights->enable( GL_BLEND );
445     rwy_red_medium_lights->enable( GL_ALPHA_TEST );
446     rwy_red_medium_lights->enable( GL_COLOR_MATERIAL );
447     rwy_red_medium_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
448     rwy_red_medium_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
449     rwy_red_medium_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
450     rwy_red_medium_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
451     rwy_red_medium_lights->setTexture( tex_name );
452     m = new SGMaterial( rwy_red_medium_lights );
453     m->add_name("RWY_RED_MEDIUM_LIGHTS");
454     matlib["RWY_RED_MEDIUM_LIGHTS"] = m;
455
456     // hard coded low intensity runway red light state
457     if ( sprite_lighting ) {
458         tex_name = gen_standard_light_sprite( 235, 90, 90, 155 );
459     } else {
460         tex_name = gen_standard_dir_light_map( 235, 90, 90, 155 );
461     }
462     ssgSimpleState *rwy_red_low_lights = new ssgSimpleState();
463     rwy_red_low_lights->disable( GL_LIGHTING );
464     rwy_red_low_lights->enable ( GL_CULL_FACE ) ;
465     rwy_red_low_lights->enable( GL_TEXTURE_2D );
466     rwy_red_low_lights->enable( GL_BLEND );
467     rwy_red_low_lights->enable( GL_ALPHA_TEST );
468     rwy_red_low_lights->enable( GL_COLOR_MATERIAL );
469     rwy_red_low_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
470     rwy_red_low_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
471     rwy_red_low_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
472     rwy_red_low_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
473     rwy_red_low_lights->setTexture( tex_name );
474     m = new SGMaterial( rwy_red_low_lights );
475     m->add_name("RWY_RED_LOW_LIGHTS");
476     matlib["RWY_RED_LOW_LIGHTS"] = m;
477
478     // hard coded runway green light state
479     if ( sprite_lighting ) {
480         tex_name = gen_standard_light_sprite( 20, 235, 20, 255 );
481     } else {
482         tex_name = gen_standard_dir_light_map( 20, 235, 20, 255 );
483     }
484     ssgSimpleState *rwy_green_lights = new ssgSimpleState();
485     rwy_green_lights->disable( GL_LIGHTING );
486     rwy_green_lights->enable ( GL_CULL_FACE ) ;
487     rwy_green_lights->enable( GL_TEXTURE_2D );
488     rwy_green_lights->enable( GL_BLEND );
489     rwy_green_lights->enable( GL_ALPHA_TEST );
490     rwy_green_lights->enable( GL_COLOR_MATERIAL );
491     rwy_green_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
492     rwy_green_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
493     rwy_green_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
494     rwy_green_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
495     rwy_green_lights->setTexture( tex_name );
496     m = new SGMaterial( rwy_green_lights );
497     m->add_name("RWY_GREEN_LIGHTS");
498     matlib["RWY_GREEN_LIGHTS"] = m;
499
500     // hard coded medium intensity runway green light state
501     if ( sprite_lighting ) {
502         tex_name = gen_standard_light_sprite( 20, 235, 20, 205 );
503     } else {
504         tex_name = gen_standard_dir_light_map( 20, 235, 20, 205 );
505     }
506     ssgSimpleState *rwy_green_medium_lights = new ssgSimpleState();
507     rwy_green_medium_lights->disable( GL_LIGHTING );
508     rwy_green_medium_lights->enable ( GL_CULL_FACE ) ;
509     rwy_green_medium_lights->enable( GL_TEXTURE_2D );
510     rwy_green_medium_lights->enable( GL_BLEND );
511     rwy_green_medium_lights->enable( GL_ALPHA_TEST );
512     rwy_green_medium_lights->enable( GL_COLOR_MATERIAL );
513     rwy_green_medium_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
514     rwy_green_medium_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
515     rwy_green_medium_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
516     rwy_green_medium_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
517     rwy_green_medium_lights->setTexture( tex_name );
518     m = new SGMaterial( rwy_green_medium_lights );
519     m->add_name("RWY_GREEN_MEDIUM_LIGHTS");
520     matlib["RWY_GREEN_MEDIUM_LIGHTS"] = m;
521
522     // hard coded low intensity runway green light state
523     if ( sprite_lighting ) {
524         tex_name = gen_standard_light_sprite( 20, 235, 20, 155 );
525     } else {
526         tex_name = gen_standard_dir_light_map( 20, 235, 20, 155 );
527     }
528     ssgSimpleState *rwy_green_low_lights = new ssgSimpleState();
529     rwy_green_low_lights->disable( GL_LIGHTING );
530     rwy_green_low_lights->enable ( GL_CULL_FACE ) ;
531     rwy_green_low_lights->enable( GL_TEXTURE_2D );
532     rwy_green_low_lights->enable( GL_BLEND );
533     rwy_green_low_lights->enable( GL_ALPHA_TEST );
534     rwy_green_low_lights->enable( GL_COLOR_MATERIAL );
535     rwy_green_low_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
536     rwy_green_low_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
537     rwy_green_low_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
538     rwy_green_low_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
539     rwy_green_low_lights->setTexture( tex_name );
540     m = new SGMaterial( rwy_green_low_lights );
541     m->add_name("RWY_GREEN_LOW_LIGHTS");
542     matlib["RWY_GREEN_LOW_LIGHTS"] = m;
543     m->add_name("RWY_GREEN_TAXIWAY_LIGHTS");
544     matlib["RWY_GREEN_TAXIWAY_LIGHTS"] = m;
545
546     // hard coded low intensity taxiway blue light state
547     if ( sprite_lighting ) {
548         tex_name = gen_standard_light_sprite( 90, 90, 235, 205 );
549     } else {
550         tex_name = gen_taxiway_dir_light_map( 90, 90, 235, 205 );
551     }
552     ssgSimpleState *taxiway_blue_low_lights = new ssgSimpleState();
553     taxiway_blue_low_lights->disable( GL_LIGHTING );
554     taxiway_blue_low_lights->enable ( GL_CULL_FACE ) ;
555     taxiway_blue_low_lights->enable( GL_TEXTURE_2D );
556     taxiway_blue_low_lights->enable( GL_BLEND );
557     taxiway_blue_low_lights->enable( GL_ALPHA_TEST );
558     taxiway_blue_low_lights->enable( GL_COLOR_MATERIAL );
559     taxiway_blue_low_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
560     taxiway_blue_low_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
561     taxiway_blue_low_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
562     taxiway_blue_low_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
563     taxiway_blue_low_lights->setTexture( tex_name );
564     m = new SGMaterial( taxiway_blue_low_lights );
565     m->add_name("RWY_BLUE_TAXIWAY_LIGHTS");
566     matlib["RWY_BLUE_TAXIWAY_LIGHTS"] = m;
567
568     // hard coded runway vasi light state
569     if ( sprite_lighting ) {
570         tex_name = gen_standard_light_sprite( 235, 235, 195, 255 );
571     } else {
572         tex_name = gen_standard_dir_light_map( 235, 235, 195, 255 );
573     }
574     ssgSimpleState *rwy_vasi_lights = new ssgSimpleState();
575     rwy_vasi_lights->disable( GL_LIGHTING );
576     rwy_vasi_lights->enable ( GL_CULL_FACE ) ;
577     rwy_vasi_lights->enable( GL_TEXTURE_2D );
578     rwy_vasi_lights->enable( GL_BLEND );
579     rwy_vasi_lights->enable( GL_ALPHA_TEST );
580     rwy_vasi_lights->enable( GL_COLOR_MATERIAL );
581     rwy_vasi_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
582     rwy_vasi_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
583     rwy_vasi_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
584     rwy_vasi_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
585     // rwy_vasi_lights->setTexture( gen_vasi_light_map_old() );
586     rwy_vasi_lights->setTexture( tex_name );
587     m = new SGMaterial( rwy_vasi_lights );
588     m->add_name("RWY_VASI_LIGHTS");
589     matlib["RWY_VASI_LIGHTS"] = m;
590
591     return true;
592 }
593
594
595 // Load a library of material properties
596 bool SGMaterialLib::add_item ( const string &tex_path )
597 {
598     string material_name = tex_path;
599     int pos = tex_path.rfind( "/" );
600     material_name = material_name.substr( pos + 1 );
601
602     return add_item( material_name, tex_path );
603 }
604
605
606 // Load a library of material properties
607 bool SGMaterialLib::add_item ( const string &mat_name, const string &full_path )
608 {
609     int pos = full_path.rfind( "/" );
610     string tex_name = full_path.substr( pos + 1 );
611     string tex_path = full_path.substr( 0, pos );
612
613     SG_LOG( SG_TERRAIN, SG_INFO, "  Loading material " 
614             << mat_name << " (" << full_path << ")");
615
616     matlib[mat_name] = new SGMaterial( full_path );
617     matlib[mat_name]->add_name(mat_name);
618
619     return true;
620 }
621
622
623 // Load a library of material properties
624 bool SGMaterialLib::add_item ( const string &mat_name, ssgSimpleState *state )
625 {
626     matlib[mat_name] = new SGMaterial( state );
627     matlib[mat_name]->add_name(mat_name);
628
629     SG_LOG( SG_TERRAIN, SG_INFO, "  Loading material given a premade "
630             << "ssgSimpleState = " << mat_name );
631
632     return true;
633 }
634
635
636 // find a material record by material name
637 SGMaterial *SGMaterialLib::find( const string& material ) {
638     SGMaterial *result = NULL;
639     material_map_iterator it = matlib.find( material );
640     if ( it != end() ) {
641         result = it->second;
642         return result;
643     }
644
645     return NULL;
646 }
647
648
649 // Destructor
650 SGMaterialLib::~SGMaterialLib ( void ) {
651 }
652
653
654 // Load one pending "deferred" texture.  Return true if a texture
655 // loaded successfully, false if no pending, or error.
656 void SGMaterialLib::load_next_deferred() {
657     // container::iterator it = begin();
658     for ( material_map_iterator it = begin(); it != end(); it++ ) {
659         /* we don't need the key, but here's how we'd get it if we wanted it. */
660         // const string &key = it->first;
661         SGMaterial *slot = it->second;
662         if (slot->load_texture())
663           return;
664     }
665 }
666
667 // Return the material from that given leaf
668 const SGMaterial* SGMaterialLib::findMaterial(/*const*/ssgLeaf* leaf) const
669 {
670   if (!leaf)
671     return 0;
672   
673   ssgBase* base = leaf->getUserData();
674   if (!base)
675     return 0;
676
677   SGMaterialUserData* matUserData = dynamic_cast<SGMaterialUserData*>(base);
678   if (!matUserData)
679     return 0;
680
681   return matUserData->getMaterial();
682 }