]> git.mxchange.org Git - flightgear.git/blob - Objects/material.cxx
Fixed a serious bug caused by not-quite-correct comment/white space eating
[flightgear.git] / Objects / material.cxx
1 // material.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 // (Log is kept at end of this file)
23
24
25 #ifdef HAVE_CONFIG_H
26 #  include <config.h>
27 #endif
28
29 #ifdef HAVE_WINDOWS_H
30 #  include <windows.h>
31 #endif
32
33 #include <GL/glut.h>
34 #include <XGL/xgl.h>
35
36 #include <string.h>
37
38 #include <Debug/fg_debug.h>
39 #include <Main/options.hxx>
40 #include <Misc/fgstream.hxx>
41
42 #include "material.hxx"
43 #include "texload.h"
44
45 // global material management class
46 fgMATERIAL_MGR material_mgr;
47
48
49 // Constructor
50 fgMATERIAL::fgMATERIAL ( void ) {
51     alpha = 0;
52     ambient[0]  = ambient[1]  = ambient[2]  = ambient[3]  = 0.0;
53     diffuse[0]  = diffuse[1]  = diffuse[2]  = diffuse[3]  = 0.0;
54     specular[0] = specular[1] = specular[2] = specular[3] = 0.0;
55     emissive[0] = emissive[1] = emissive[2] = emissive[3] = 0.0;
56 }
57
58
59 int fgMATERIAL::append_sort_list( fgFRAGMENT *object ) {
60     if ( list_size < FG_MAX_MATERIAL_FRAGS )
61     {
62         list[ list_size++ ] = object;
63         return 0;
64     }
65     else
66     {
67         return 1;
68     }
69 }
70
71 istream&
72 operator >> ( istream& in, fgMATERIAL& m )
73 {
74     string token;
75
76     for (;;)
77     {
78         in >> token;
79         if ( token == "texture" )
80         {
81             in >> token >> m.texture_name;
82         }
83         else if ( token == "ambient" )
84         {
85             in >> token >> m.ambient[0] >> m.ambient[1]
86                         >> m.ambient[2] >> m.ambient[3];
87         }
88         else if ( token == "diffuse" )
89         {
90             in >> token >> m.diffuse[0] >> m.diffuse[1]
91                         >> m.diffuse[2] >> m.diffuse[3];
92         }
93         else if ( token == "specular" )
94         {
95             in >> token >> m.specular[0] >> m.specular[1]
96                         >> m.specular[2] >> m.specular[3];
97         }
98         else if ( token == "emissive" )
99         {
100             in >> token >> m.emissive[0] >> m.emissive[1]
101                         >> m.emissive[2] >> m.emissive[3];
102         }
103         else if ( token == "alpha" )
104         {
105             in >> token >> token;
106             if ( token == "yes" )
107                 m.alpha = 1;
108             else if ( token == "no" )
109                 m.alpha = 0;
110             else
111             {
112                 fgPrintf( FG_TERRAIN, FG_INFO,
113                           "Bad alpha value '%s'\n", token.c_str() );
114             }
115         }
116         else if ( token[0] == '}' )
117         {
118             break;
119         }
120     }
121
122     return in;
123 }
124
125 void
126 fgMATERIAL::load_texture()
127 {
128     if ( current_options.get_textures() )
129     {
130         GLubyte *texbuf;
131         int width, height;
132
133         // create the texture object and bind it
134 #ifdef GL_VERSION_1_1
135         xglGenTextures(1, &texture_id );
136         xglBindTexture(GL_TEXTURE_2D, texture_id );
137 #elif GL_EXT_texture_object
138         xglGenTexturesEXT(1, &texture_id );
139         xglBindTextureEXT(GL_TEXTURE_2D, texture_id );
140 #else
141 #  error port me
142 #endif
143
144         // set the texture parameters for this texture
145         xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ) ;
146         xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ) ;
147         xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
148                           GL_LINEAR );
149         // xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
150         //                   GL_NEAREST_MIPMAP_NEAREST );
151         xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
152                           /* GL_LINEAR */ 
153                           /* GL_NEAREST_MIPMAP_LINEAR */
154                           GL_LINEAR_MIPMAP_LINEAR ) ;
155
156         /* load in the texture data */
157         string tpath = current_options.get_fg_root() + "/Textures/" + 
158             texture_name + ".rgb";
159         string fg_tpath = tpath + ".gz";
160
161         if ( alpha == 0 ) {
162             // load rgb texture
163
164             // Try uncompressed
165             if ( (texbuf = 
166                   read_rgb_texture(tpath.c_str(), &width, &height)) == 
167                  NULL )
168             {
169                 // Try compressed
170                 if ( (texbuf = 
171                       read_rgb_texture(fg_tpath.c_str(), &width, &height)) 
172                      == NULL )
173                 {
174                     fgPrintf( FG_GENERAL, FG_EXIT, 
175                               "Error in loading texture %s\n", 
176                               tpath.c_str() );
177                     return;
178                 } 
179             } 
180
181             /* xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
182                GL_RGB, GL_UNSIGNED_BYTE, texbuf); */
183
184             gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGB, width, height, 
185                                GL_RGB, GL_UNSIGNED_BYTE, texbuf );
186         } else if ( alpha == 1 ) {
187             // load rgba (alpha) texture
188
189             // Try uncompressed
190             if ( (texbuf = 
191                   read_alpha_texture(tpath.c_str(), &width, &height))
192                  == NULL )
193             {
194                 // Try compressed
195                 if ((texbuf = 
196                      read_alpha_texture(fg_tpath.c_str(), &width, &height))
197                     == NULL )
198                 {
199                     fgPrintf( FG_GENERAL, FG_EXIT, 
200                               "Error in loading texture %s\n",
201                               tpath.c_str() );
202                     return;
203                 } 
204             } 
205
206             xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
207                           GL_RGBA, GL_UNSIGNED_BYTE, texbuf);
208         }
209     }
210 }
211
212
213 // Destructor
214 fgMATERIAL::~fgMATERIAL ( void ) {
215 }
216
217
218 // Constructor
219 fgMATERIAL_MGR::fgMATERIAL_MGR ( void ) {
220 }
221
222
223 // Load a library of material properties
224 int fgMATERIAL_MGR::load_lib ( void ) {
225     string material_name;
226
227     // build the path name to the material db
228     string mpath = current_options.get_fg_root() + "/materials";
229     fg_gzifstream in( mpath );
230     if ( ! in )
231         fgPrintf( FG_GENERAL, FG_EXIT, "Cannot open file: %s\n", 
232                   mpath.c_str() );
233
234     while ( ! in.eof() ) {
235         // printf("%s", line);
236
237         // strip leading white space and comments
238         in.eat_comments();
239
240         // set to zero to prevent its value accidently being '{'
241         // after a failed >> operation.
242         char token = 0;
243
244         in.stream() >> material_name >> token;
245
246         if ( token == '{' ) {
247             cout << "Loading material " << material_name << endl;
248             fgMATERIAL m;
249             in.stream() >> m;
250             material_mgr.material_map[material_name] = m;
251         }
252     }
253
254     for ( iterator it = material_map.begin();
255           it != material_map.end(); ++it )
256     {
257         it->second.load_texture();
258     }
259
260     return(1);
261 }
262
263
264 // Initialize the transient list of fragments for each material property
265 void fgMATERIAL_MGR::init_transient_material_lists( void ) {
266     for ( iterator it = material_map.begin();
267           it != material_map.end(); ++it )
268     {
269         it->second.init_sort_list();
270     }
271 }
272
273 bool
274 fgMATERIAL_MGR::find( const string& material, fgMATERIAL*& mtl_ptr )
275 {
276     iterator it = material_map.find( material );
277     if ( it != material_map.end() )
278     {
279         mtl_ptr = &(it->second);
280         return true;
281     }
282
283     return false;
284 }
285
286
287 // Destructor
288 fgMATERIAL_MGR::~fgMATERIAL_MGR ( void ) {
289 }
290
291
292 // $Log$
293 // Revision 1.4  1998/09/01 19:03:08  curt
294 // Changes contributed by Bernie Bright <bbright@c031.aone.net.au>
295 //  - The new classes in libmisc.tgz define a stream interface into zlib.
296 //    I've put these in a new directory, Lib/Misc.  Feel free to rename it
297 //    to something more appropriate.  However you'll have to change the
298 //    include directives in all the other files.  Additionally you'll have
299 //    add the library to Lib/Makefile.am and Simulator/Main/Makefile.am.
300 //
301 //    The StopWatch class in Lib/Misc requires a HAVE_GETRUSAGE autoconf
302 //    test so I've included the required changes in config.tgz.
303 //
304 //    There are a fair few changes to Simulator/Objects as I've moved
305 //    things around.  Loading tiles is quicker but thats not where the delay
306 //    is.  Tile loading takes a few tenths of a second per file on a P200
307 //    but it seems to be the post-processing that leads to a noticeable
308 //    blip in framerate.  I suppose its time to start profiling to see where
309 //    the delays are.
310 //
311 //    I've included a brief description of each archives contents.
312 //
313 // Lib/Misc/
314 //   zfstream.cxx
315 //   zfstream.hxx
316 //     C++ stream interface into zlib.
317 //     Taken from zlib-1.1.3/contrib/iostream/.
318 //     Minor mods for STL compatibility.
319 //     There's no copyright associated with these so I assume they're
320 //     covered by zlib's.
321 //
322 //   fgstream.cxx
323 //   fgstream.hxx
324 //     FlightGear input stream using gz_ifstream.  Tries to open the
325 //     given filename.  If that fails then filename is examined and a
326 //     ".gz" suffix is removed or appended and that file is opened.
327 //
328 //   stopwatch.hxx
329 //     A simple timer for benchmarking.  Not used in production code.
330 //     Taken from the Blitz++ project.  Covered by GPL.
331 //
332 //   strutils.cxx
333 //   strutils.hxx
334 //     Some simple string manipulation routines.
335 //
336 // Simulator/Airports/
337 //   Load airports database using fgstream.
338 //   Changed fgAIRPORTS to use set<> instead of map<>.
339 //   Added bool fgAIRPORTS::search() as a neater way doing the lookup.
340 //   Returns true if found.
341 //
342 // Simulator/Astro/
343 //   Modified fgStarsInit() to load stars database using fgstream.
344 //
345 // Simulator/Objects/
346 //   Modified fgObjLoad() to use fgstream.
347 //   Modified fgMATERIAL_MGR::load_lib() to use fgstream.
348 //   Many changes to fgMATERIAL.
349 //   Some changes to fgFRAGMENT but I forget what!
350 //
351 // Revision 1.3  1998/08/27 17:02:09  curt
352 // Contributions from Bernie Bright <bbright@c031.aone.net.au>
353 // - use strings for fg_root and airport_id and added methods to return
354 //   them as strings,
355 // - inlined all access methods,
356 // - made the parsing functions private methods,
357 // - deleted some unused functions.
358 // - propogated some of these changes out a bit further.
359 //
360 // Revision 1.2  1998/08/25 20:53:33  curt
361 // Shuffled $FG_ROOT file layout.
362 //
363 // Revision 1.1  1998/08/25 16:51:24  curt
364 // Moved from ../Scenery
365 //
366 // Revision 1.13  1998/08/24 20:11:39  curt
367 // Tweaks ...
368 //
369 // Revision 1.12  1998/08/12 21:41:27  curt
370 // Need to negate the test for textures so that textures aren't loaded when
371 // they are disabled rather than visa versa ... :-)
372 //
373 // Revision 1.11  1998/08/12 21:13:03  curt
374 // material.cxx: don't load textures if they are disabled
375 // obj.cxx: optimizations from Norman Vine
376 // tile.cxx: minor tweaks
377 // tile.hxx: addition of num_faces
378 // tilemgr.cxx: minor tweaks
379 //
380 // Revision 1.10  1998/07/24 21:42:06  curt
381 // material.cxx: whups, double method declaration with no definition.
382 // obj.cxx: tweaks to avoid errors in SGI's CC.
383 // tile.cxx: optimizations by Norman Vine.
384 // tilemgr.cxx: optimizations by Norman Vine.
385 //
386 // Revision 1.9  1998/07/13 21:01:57  curt
387 // Wrote access functions for current fgOPTIONS.
388 //
389 // Revision 1.8  1998/07/08 14:47:20  curt
390 // Fix GL_MODULATE vs. GL_DECAL problem introduced by splash screen.
391 // polare3d.h renamed to polar3d.hxx
392 // fg{Cartesian,Polar}Point3d consolodated.
393 // Added some initial support for calculating local current ground elevation.
394 //
395 // Revision 1.7  1998/07/04 00:54:28  curt
396 // Added automatic mipmap generation.
397 //
398 // When rendering fragments, use saved model view matrix from associated tile
399 // rather than recalculating it with push() translate() pop().
400 //
401 // Revision 1.6  1998/06/27 16:54:59  curt
402 // Check for GL_VERSION_1_1 or GL_EXT_texture_object to decide whether to use
403 //   "EXT" versions of texture management routines.
404 //
405 // Revision 1.5  1998/06/17 21:36:39  curt
406 // Load and manage multiple textures defined in the Materials library.
407 // Boost max material fagments for each material property to 800.
408 // Multiple texture support when rendering.
409 //
410 // Revision 1.4  1998/06/12 00:58:04  curt
411 // Build only static libraries.
412 // Declare memmove/memset for Sloaris.
413 //
414 // Revision 1.3  1998/06/05 22:39:53  curt
415 // Working on sorting by, and rendering by material properties.
416 //
417 // Revision 1.2  1998/06/01 17:56:20  curt
418 // Incremental additions to material.cxx (not fully functional)
419 // Tweaked vfc_ratio math to avoid divide by zero.
420 //
421 // Revision 1.1  1998/05/30 01:56:45  curt
422 // Added material.cxx material.hxx
423 //