]> git.mxchange.org Git - flightgear.git/blob - src/Objects/matlib.cxx
Fix a bug with rabbit light creation.
[flightgear.git] / src / Objects / 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  - curt@me.umn.edu
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., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21 // $Id$
22
23
24 #ifdef HAVE_CONFIG_H
25 #  include <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 <GL/glut.h>
37 #include <GL/gl.h>
38
39 #include <simgear/compiler.h>
40 #include <simgear/constants.h>
41 #include <simgear/misc/exception.hxx>
42
43 #include <string.h>
44 #include STL_STRING
45
46 #include <simgear/debug/logstream.hxx>
47 #include <simgear/misc/sg_path.hxx>
48 #include <simgear/misc/sgstream.hxx>
49
50 #include <Include/general.hxx>
51 #include <Main/globals.hxx>
52 #include <Main/fg_props.hxx>
53 #include <Scenery/tileentry.hxx>
54
55 #include "newmat.hxx"
56 #include "matlib.hxx"
57
58 SG_USING_NAMESPACE(std);
59 SG_USING_STD(string);
60
61
62 // global material management class
63 FGMaterialLib material_lib;
64
65
66 // Constructor
67 FGMaterialLib::FGMaterialLib ( void ) {
68   set_step(0);
69 }
70
71
72 static int gen_test_light_map() {
73     static const int env_tex_res = 32;
74     int half_res = env_tex_res / 2;
75     unsigned char env_map[env_tex_res][env_tex_res][4];
76     GLuint tex_name;
77
78     for ( int i = 0; i < env_tex_res; ++i ) {
79         for ( int j = 0; j < env_tex_res; ++j ) {
80             double x = (i - half_res) / (double)half_res;
81             double y = (j - half_res) / (double)half_res;
82             double dist = sqrt(x*x + y*y);
83             if ( dist > 1.0 ) { dist = 1.0; }
84
85             // cout << x << "," << y << " " << (int)(dist * 255) << ","
86             //      << (int)((1.0 - dist) * 255) << endl;
87             env_map[i][j][0] = (int)(dist * 255);
88             env_map[i][j][1] = (int)((1.0 - dist) * 255);
89             env_map[i][j][2] = 0;
90             env_map[i][j][3] = 255;
91         }
92     }
93
94     glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
95     glGenTextures( 1, &tex_name );
96     glBindTexture( GL_TEXTURE_2D, tex_name );
97   
98     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
99     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
100     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
101     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
102     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, env_tex_res, env_tex_res, 0,
103                   GL_RGBA, GL_UNSIGNED_BYTE, env_map);
104
105     return tex_name;
106 }
107
108
109 // generate standard colored directional light environment texture map
110 static int gen_standard_dir_light_map( 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.3 ) { bright = 0.3; }
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
131     glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
132     glGenTextures( 1, &tex_name );
133     glBindTexture( GL_TEXTURE_2D, tex_name );
134   
135     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
136     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
137     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
138     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
139     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, env_tex_res, env_tex_res, 0,
140                   GL_RGBA, GL_UNSIGNED_BYTE, env_map);
141
142     return tex_name;
143 }
144
145
146 // generate the directional vasi light environment texture map
147 static int gen_vasi_light_map() {
148     const int env_tex_res = 256;
149     int half_res = env_tex_res / 2;
150     unsigned char env_map[env_tex_res][env_tex_res][4];
151     GLuint tex_name;
152
153     for ( int i = 0; i < env_tex_res; ++i ) {
154         for ( int j = 0; j < env_tex_res; ++j ) {
155             double x = (i - half_res) / (double)half_res;
156             double y = (j - half_res) / (double)half_res;
157             double dist = sqrt(x*x + y*y);
158             if ( dist > 1.0 ) { dist = 1.0; }
159             double bright = cos( dist * SGD_PI_2 );
160
161             // top half white, bottom half red
162             env_map[i][j][0] = 255;
163             if ( i > half_res ) {
164                 // white
165                 env_map[i][j][1] = 255;
166                 env_map[i][j][2] = 255;
167             } else if ( i == half_res - 1 || i == half_res ) {
168                 // pink
169                 env_map[i][j][1] = 127;
170                 env_map[i][j][2] = 127;
171             } else {
172                 // red
173                 env_map[i][j][1] = 0;
174                 env_map[i][j][2] = 0;
175             }
176             env_map[i][j][3] = (int)(bright * 255);
177         }
178     }
179
180     glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
181     glGenTextures( 1, &tex_name );
182     glBindTexture( GL_TEXTURE_2D, tex_name );
183   
184     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
185     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
186     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
187     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
188     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, env_tex_res, env_tex_res, 0,
189                   GL_RGBA, GL_UNSIGNED_BYTE, env_map);
190
191     return tex_name;
192 }
193
194
195 // Load a library of material properties
196 bool FGMaterialLib::load( const string& mpath ) {
197
198     SGPropertyNode materials;
199
200     SG_LOG( SG_INPUT, SG_INFO, "Reading materials from " << mpath );
201     try {
202         readProperties( mpath, &materials );
203     } catch (const sg_exception &ex) {
204         SG_LOG( SG_INPUT, SG_ALERT, "Error reading materials: "
205                 << ex.getMessage() );
206         throw ex;
207     }
208
209     int nMaterials = materials.nChildren();
210     for (int i = 0; i < nMaterials; i++) {
211         const SGPropertyNode * node = materials.getChild(i);
212         if (!strcmp(node->getName(), "material")) {
213             FGNewMat * m = new FGNewMat(node);
214
215             vector<SGPropertyNode_ptr>names = node->getChildren("name");
216             for ( unsigned int j = 0; j < names.size(); j++ ) {
217                 string name = names[j]->getStringValue();
218                 m->ref();
219                 // cerr << "Material " << name << endl;
220                 matlib[name] = m;
221                 SG_LOG( SG_TERRAIN, SG_INFO, "  Loading material "
222                         << names[j]->getStringValue() );
223             }
224         } else {
225             SG_LOG(SG_INPUT, SG_ALERT,
226                    "Skipping bad material entry " << node->getName());
227         }
228     }
229
230     // hard coded ground light state
231     ssgSimpleState *gnd_lights = new ssgSimpleState;
232     gnd_lights->ref();
233     gnd_lights->disable( GL_TEXTURE_2D );
234     gnd_lights->enable( GL_CULL_FACE );
235     gnd_lights->enable( GL_COLOR_MATERIAL );
236     gnd_lights->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
237     gnd_lights->setMaterial( GL_EMISSION, 0, 0, 0, 1 );
238     gnd_lights->setMaterial( GL_SPECULAR, 0, 0, 0, 1 );
239     gnd_lights->enable( GL_BLEND );
240     gnd_lights->disable( GL_ALPHA_TEST );
241     gnd_lights->disable( GL_LIGHTING );
242     matlib["GROUND_LIGHTS"] = new FGNewMat(gnd_lights);
243
244     GLuint tex_name;
245
246     // hard coded runway white light state
247     tex_name = gen_standard_dir_light_map( 235, 235, 215, 255 );
248     ssgSimpleState *rwy_white_lights = new ssgSimpleState();
249     rwy_white_lights->ref();
250     rwy_white_lights->disable( GL_LIGHTING );
251     rwy_white_lights->enable ( GL_CULL_FACE ) ;
252     rwy_white_lights->enable( GL_TEXTURE_2D );
253     rwy_white_lights->enable( GL_BLEND );
254     rwy_white_lights->enable( GL_ALPHA_TEST );
255     rwy_white_lights->enable( GL_COLOR_MATERIAL );
256     rwy_white_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
257     rwy_white_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
258     rwy_white_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
259     rwy_white_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
260     rwy_white_lights->setTexture( tex_name );
261     matlib["RWY_WHITE_LIGHTS"] = new FGNewMat(rwy_white_lights);
262     // For backwards compatibility ... remove someday
263     matlib["RUNWAY_LIGHTS"] = new FGNewMat(rwy_white_lights);
264     matlib["RWY_LIGHTS"] = new FGNewMat(rwy_white_lights);
265     // end of backwards compatitibilty
266
267     // hard coded runway medium intensity white light state
268     tex_name = gen_standard_dir_light_map( 235, 235, 215, 205 );
269     ssgSimpleState *rwy_white_medium_lights = new ssgSimpleState();
270     rwy_white_medium_lights->ref();
271     rwy_white_medium_lights->disable( GL_LIGHTING );
272     rwy_white_medium_lights->enable ( GL_CULL_FACE ) ;
273     rwy_white_medium_lights->enable( GL_TEXTURE_2D );
274     rwy_white_medium_lights->enable( GL_BLEND );
275     rwy_white_medium_lights->enable( GL_ALPHA_TEST );
276     rwy_white_medium_lights->enable( GL_COLOR_MATERIAL );
277     rwy_white_medium_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
278     rwy_white_medium_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
279     rwy_white_medium_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
280     rwy_white_medium_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
281     rwy_white_medium_lights->setTexture( tex_name );
282     matlib["RWY_WHITE_MEDIUM_LIGHTS"] = new FGNewMat(rwy_white_medium_lights);
283
284     // hard coded runway low intensity white light state
285     tex_name = gen_standard_dir_light_map( 235, 235, 215, 155 );
286     ssgSimpleState *rwy_white_low_lights = new ssgSimpleState();
287     rwy_white_low_lights->ref();
288     rwy_white_low_lights->disable( GL_LIGHTING );
289     rwy_white_low_lights->enable ( GL_CULL_FACE ) ;
290     rwy_white_low_lights->enable( GL_TEXTURE_2D );
291     rwy_white_low_lights->enable( GL_BLEND );
292     rwy_white_low_lights->enable( GL_ALPHA_TEST );
293     rwy_white_low_lights->enable( GL_COLOR_MATERIAL );
294     rwy_white_low_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
295     rwy_white_low_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
296     rwy_white_low_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
297     rwy_white_low_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
298     rwy_white_low_lights->setTexture( tex_name );
299     matlib["RWY_WHITE_LOW_LIGHTS"] = new FGNewMat(rwy_white_low_lights);
300
301     // hard coded runway yellow light state
302     tex_name = gen_standard_dir_light_map( 235, 235, 20, 255 );
303     ssgSimpleState *rwy_yellow_lights = new ssgSimpleState();
304     rwy_yellow_lights->ref();
305     rwy_yellow_lights->disable( GL_LIGHTING );
306     rwy_yellow_lights->enable ( GL_CULL_FACE ) ;
307     rwy_yellow_lights->enable( GL_TEXTURE_2D );
308     rwy_yellow_lights->enable( GL_BLEND );
309     rwy_yellow_lights->enable( GL_ALPHA_TEST );
310     rwy_yellow_lights->enable( GL_COLOR_MATERIAL );
311     rwy_yellow_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
312     rwy_yellow_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
313     rwy_yellow_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
314     rwy_yellow_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
315     rwy_yellow_lights->setTexture( tex_name );
316     matlib["RWY_YELLOW_LIGHTS"] = new FGNewMat(rwy_yellow_lights);
317
318     // hard coded runway medium intensity yellow light state
319     tex_name = gen_standard_dir_light_map( 235, 235, 20, 205 );
320     ssgSimpleState *rwy_yellow_medium_lights = new ssgSimpleState();
321     rwy_yellow_medium_lights->ref();
322     rwy_yellow_medium_lights->disable( GL_LIGHTING );
323     rwy_yellow_medium_lights->enable ( GL_CULL_FACE ) ;
324     rwy_yellow_medium_lights->enable( GL_TEXTURE_2D );
325     rwy_yellow_medium_lights->enable( GL_BLEND );
326     rwy_yellow_medium_lights->enable( GL_ALPHA_TEST );
327     rwy_yellow_medium_lights->enable( GL_COLOR_MATERIAL );
328     rwy_yellow_medium_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
329     rwy_yellow_medium_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
330     rwy_yellow_medium_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
331     rwy_yellow_medium_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
332     rwy_yellow_medium_lights->setTexture( tex_name );
333     matlib["RWY_YELLOW_MEDIUM_LIGHTS"] = new FGNewMat(rwy_yellow_medium_lights);
334
335     // hard coded runway low intensity yellow light state
336     tex_name = gen_standard_dir_light_map( 235, 235, 20, 155 );
337     ssgSimpleState *rwy_yellow_low_lights = new ssgSimpleState();
338     rwy_yellow_low_lights->ref();
339     rwy_yellow_low_lights->disable( GL_LIGHTING );
340     rwy_yellow_low_lights->enable ( GL_CULL_FACE ) ;
341     rwy_yellow_low_lights->enable( GL_TEXTURE_2D );
342     rwy_yellow_low_lights->enable( GL_BLEND );
343     rwy_yellow_low_lights->enable( GL_ALPHA_TEST );
344     rwy_yellow_low_lights->enable( GL_COLOR_MATERIAL );
345     rwy_yellow_low_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
346     rwy_yellow_low_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
347     rwy_yellow_low_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
348     rwy_yellow_low_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
349     rwy_yellow_low_lights->setTexture( tex_name );
350     matlib["RWY_YELLOW_LOW_LIGHTS"] = new FGNewMat(rwy_yellow_low_lights);
351
352     // hard coded runway red light state
353     tex_name = gen_standard_dir_light_map( 235, 20, 20, 255 );
354     ssgSimpleState *rwy_red_lights = new ssgSimpleState();
355     rwy_red_lights->ref();
356     rwy_red_lights->disable( GL_LIGHTING );
357     rwy_red_lights->enable ( GL_CULL_FACE ) ;
358     rwy_red_lights->enable( GL_TEXTURE_2D );
359     rwy_red_lights->enable( GL_BLEND );
360     rwy_red_lights->enable( GL_ALPHA_TEST );
361     rwy_red_lights->enable( GL_COLOR_MATERIAL );
362     rwy_red_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
363     rwy_red_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
364     rwy_red_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
365     rwy_red_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
366     rwy_red_lights->setTexture( tex_name );
367     matlib["RWY_RED_LIGHTS"] = new FGNewMat(rwy_red_lights);
368
369     // hard coded medium intensity runway red light state
370     tex_name = gen_standard_dir_light_map( 235, 20, 20, 205 );
371     ssgSimpleState *rwy_red_medium_lights = new ssgSimpleState();
372     rwy_red_medium_lights->ref();
373     rwy_red_medium_lights->disable( GL_LIGHTING );
374     rwy_red_medium_lights->enable ( GL_CULL_FACE ) ;
375     rwy_red_medium_lights->enable( GL_TEXTURE_2D );
376     rwy_red_medium_lights->enable( GL_BLEND );
377     rwy_red_medium_lights->enable( GL_ALPHA_TEST );
378     rwy_red_medium_lights->enable( GL_COLOR_MATERIAL );
379     rwy_red_medium_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
380     rwy_red_medium_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
381     rwy_red_medium_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
382     rwy_red_medium_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
383     rwy_red_medium_lights->setTexture( tex_name );
384     matlib["RWY_RED_MEDIUM_LIGHTS"] = new FGNewMat(rwy_red_medium_lights);
385
386     // hard coded low intensity runway red light state
387     tex_name = gen_standard_dir_light_map( 235, 20, 20, 205 );
388     ssgSimpleState *rwy_red_low_lights = new ssgSimpleState();
389     rwy_red_low_lights->ref();
390     rwy_red_low_lights->disable( GL_LIGHTING );
391     rwy_red_low_lights->enable ( GL_CULL_FACE ) ;
392     rwy_red_low_lights->enable( GL_TEXTURE_2D );
393     rwy_red_low_lights->enable( GL_BLEND );
394     rwy_red_low_lights->enable( GL_ALPHA_TEST );
395     rwy_red_low_lights->enable( GL_COLOR_MATERIAL );
396     rwy_red_low_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
397     rwy_red_low_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
398     rwy_red_low_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
399     rwy_red_low_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
400     rwy_red_low_lights->setTexture( tex_name );
401     matlib["RWY_RED_LOW_LIGHTS"] = new FGNewMat(rwy_red_low_lights);
402
403     // hard coded runway green light state
404     tex_name = gen_standard_dir_light_map( 20, 235, 20, 255 );
405     ssgSimpleState *rwy_green_lights = new ssgSimpleState();
406     rwy_green_lights->ref();
407     rwy_green_lights->disable( GL_LIGHTING );
408     rwy_green_lights->enable ( GL_CULL_FACE ) ;
409     rwy_green_lights->enable( GL_TEXTURE_2D );
410     rwy_green_lights->enable( GL_BLEND );
411     rwy_green_lights->enable( GL_ALPHA_TEST );
412     rwy_green_lights->enable( GL_COLOR_MATERIAL );
413     rwy_green_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
414     rwy_green_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
415     rwy_green_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
416     rwy_green_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
417     rwy_green_lights->setTexture( tex_name );
418     matlib["RWY_GREEN_LIGHTS"] = new FGNewMat(rwy_green_lights);
419
420     // hard coded medium intensity runway green light state
421     tex_name = gen_standard_dir_light_map( 20, 235, 20, 205 );
422     ssgSimpleState *rwy_green_medium_lights = new ssgSimpleState();
423     rwy_green_medium_lights->ref();
424     rwy_green_medium_lights->disable( GL_LIGHTING );
425     rwy_green_medium_lights->enable ( GL_CULL_FACE ) ;
426     rwy_green_medium_lights->enable( GL_TEXTURE_2D );
427     rwy_green_medium_lights->enable( GL_BLEND );
428     rwy_green_medium_lights->enable( GL_ALPHA_TEST );
429     rwy_green_medium_lights->enable( GL_COLOR_MATERIAL );
430     rwy_green_medium_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
431     rwy_green_medium_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
432     rwy_green_medium_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
433     rwy_green_medium_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
434     rwy_green_medium_lights->setTexture( tex_name );
435     matlib["RWY_GREEN_MEDIUM_LIGHTS"] = new FGNewMat(rwy_green_medium_lights);
436
437     // hard coded low intensity runway green light state
438     tex_name = gen_standard_dir_light_map( 20, 235, 20, 205 );
439     ssgSimpleState *rwy_green_low_lights = new ssgSimpleState();
440     rwy_green_low_lights->ref();
441     rwy_green_low_lights->disable( GL_LIGHTING );
442     rwy_green_low_lights->enable ( GL_CULL_FACE ) ;
443     rwy_green_low_lights->enable( GL_TEXTURE_2D );
444     rwy_green_low_lights->enable( GL_BLEND );
445     rwy_green_low_lights->enable( GL_ALPHA_TEST );
446     rwy_green_low_lights->enable( GL_COLOR_MATERIAL );
447     rwy_green_low_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
448     rwy_green_low_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
449     rwy_green_low_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
450     rwy_green_low_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
451     rwy_green_low_lights->setTexture( tex_name );
452     matlib["RWY_GREEN_LOW_LIGHTS"] = new FGNewMat(rwy_green_low_lights);
453
454     // hard coded runway vasi light state
455     ssgSimpleState *rwy_vasi_lights = new ssgSimpleState();
456     rwy_vasi_lights->ref();
457     rwy_vasi_lights->disable( GL_LIGHTING );
458     rwy_vasi_lights->enable ( GL_CULL_FACE ) ;
459     rwy_vasi_lights->enable( GL_TEXTURE_2D );
460     rwy_vasi_lights->enable( GL_BLEND );
461     rwy_vasi_lights->enable( GL_ALPHA_TEST );
462     rwy_vasi_lights->enable( GL_COLOR_MATERIAL );
463     rwy_vasi_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
464     rwy_vasi_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
465     rwy_vasi_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
466     rwy_vasi_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
467     rwy_vasi_lights->setTexture( gen_vasi_light_map() );
468     matlib["RWY_VASI_LIGHTS"] = new FGNewMat(rwy_vasi_lights);
469
470     return true;
471 }
472
473
474 // Load a library of material properties
475 bool FGMaterialLib::add_item ( const string &tex_path )
476 {
477     string material_name = tex_path;
478     int pos = tex_path.rfind( "/" );
479     material_name = material_name.substr( pos + 1 );
480
481     return add_item( material_name, tex_path );
482 }
483
484
485 // Load a library of material properties
486 bool FGMaterialLib::add_item ( const string &mat_name, const string &full_path )
487 {
488     int pos = full_path.rfind( "/" );
489     string tex_name = full_path.substr( pos + 1 );
490     string tex_path = full_path.substr( 0, pos );
491
492     SG_LOG( SG_TERRAIN, SG_INFO, "  Loading material " 
493             << mat_name << " (" << full_path << ")");
494
495     material_lib.matlib[mat_name] = new FGNewMat(full_path);
496
497     return true;
498 }
499
500
501 // Load a library of material properties
502 bool FGMaterialLib::add_item ( const string &mat_name, ssgSimpleState *state )
503 {
504     FGNewMat *m = new FGNewMat(state);
505
506     SG_LOG( SG_TERRAIN, SG_INFO, "  Loading material given a premade "
507             << "ssgSimpleState = " << mat_name );
508
509     material_lib.matlib[mat_name] = m;
510
511     return true;
512 }
513
514
515 // find a material record by material name
516 FGNewMat *FGMaterialLib::find( const string& material ) {
517     FGNewMat *result = NULL;
518     material_map_iterator it = matlib.find( material );
519     if ( it != end() ) {
520         result = it->second;
521         return result;
522     }
523
524     return NULL;
525 }
526
527
528 // Destructor
529 FGMaterialLib::~FGMaterialLib ( void ) {
530     // Free up all the material entries first
531     for ( material_map_iterator it = begin(); it != end(); it++ ) {
532         FGNewMat *slot = it->second;
533         slot->deRef();
534         if ( slot->getRef() <= 0 ) {
535             delete slot;
536         }
537     }
538 }
539
540
541 // Set the step for all of the state selectors in the material slots
542 void FGMaterialLib::set_step ( int step )
543 {
544     // container::iterator it = begin();
545     for ( material_map_iterator it = begin(); it != end(); it++ ) {
546         const string &key = it->first;
547         SG_LOG( SG_GENERAL, SG_INFO,
548                 "Updating material " << key << " to step " << step );
549         FGNewMat *slot = it->second;
550         slot->get_state()->selectStep(step);
551     }
552 }
553
554
555 // Get the step for the state selectors
556 int FGMaterialLib::get_step ()
557 {
558   material_map_iterator it = begin();
559   return it->second->get_state()->getSelectStep();
560 }
561
562
563 // Load one pending "deferred" texture.  Return true if a texture
564 // loaded successfully, false if no pending, or error.
565 void FGMaterialLib::load_next_deferred() {
566     // container::iterator it = begin();
567     for ( material_map_iterator it = begin(); it != end(); it++ ) {
568         /* we don't need the key, but here's how we'd get it if we wanted it. */
569         // const string &key = it->first;
570         FGNewMat *slot = it->second;
571         if (slot->load_texture())
572           return;
573     }
574 }