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