]> git.mxchange.org Git - flightgear.git/blob - Objects/material.cxx
f19499a1e9a53e4df442683632170bcf2ad49236
[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 <Include/compiler.h>
37
38 #include <string.h>
39 #include STL_STRING
40
41 #include <Debug/logstream.hxx>
42 #include <Misc/fgstream.hxx>
43 #include <Main/options.hxx>
44 #include <Main/views.hxx>
45 #include <Scenery/tile.hxx>
46
47 #include "material.hxx"
48 #include "fragment.hxx"
49 #include "texload.h"
50
51 FG_USING_STD(string);
52 #ifdef FG_HAVE_NATIVE_SGI_COMPILERS
53 FG_USING_NAMESPACE(std);
54 #endif
55
56
57
58 // global material management class
59 fgMATERIAL_MGR material_mgr;
60
61
62 // Constructor
63 fgMATERIAL::fgMATERIAL ( void )
64     : texture_name(""),
65       alpha(0)
66       // , list_size(0)
67 {
68     ambient[0]  = ambient[1]  = ambient[2]  = ambient[3]  = 0.0;
69     diffuse[0]  = diffuse[1]  = diffuse[2]  = diffuse[3]  = 0.0;
70     specular[0] = specular[1] = specular[2] = specular[3] = 0.0;
71     emissive[0] = emissive[1] = emissive[2] = emissive[3] = 0.0;
72 }
73
74 /*
75 int
76 fgMATERIAL::append_sort_list( fgFRAGMENT *object )
77 {
78     if ( list_size < FG_MAX_MATERIAL_FRAGS ) {
79         list[ list_size++ ] = object;
80         return 1;
81     } else {
82         return 0;
83     }
84 }
85 */
86
87 istream&
88 operator >> ( istream& in, fgMATERIAL& m )
89 {
90     string token;
91
92     for (;;) {
93         in >> token;
94         if ( token == "texture" )
95         {
96             in >> token >> m.texture_name;
97         }
98         else if ( token == "ambient" )
99         {
100             in >> token >> m.ambient[0] >> m.ambient[1]
101                         >> m.ambient[2] >> m.ambient[3];
102         }
103         else if ( token == "diffuse" )
104         {
105             in >> token >> m.diffuse[0] >> m.diffuse[1]
106                         >> m.diffuse[2] >> m.diffuse[3];
107         }
108         else if ( token == "specular" )
109         {
110             in >> token >> m.specular[0] >> m.specular[1]
111                         >> m.specular[2] >> m.specular[3];
112         }
113         else if ( token == "emissive" )
114         {
115             in >> token >> m.emissive[0] >> m.emissive[1]
116                         >> m.emissive[2] >> m.emissive[3];
117         }
118         else if ( token == "alpha" )
119         {
120             in >> token >> token;
121             if ( token == "yes" )
122                 m.alpha = 1;
123             else if ( token == "no" )
124                 m.alpha = 0;
125             else
126             {
127                 FG_LOG( FG_TERRAIN, FG_INFO, "Bad alpha value " << token );
128             }
129         }
130         else if ( token[0] == '}' )
131         {
132             break;
133         }
134     }
135
136     return in;
137 }
138
139 void
140 fgMATERIAL::load_texture()
141 {
142         GLubyte *texbuf;
143         int width, height;
144
145         // create the texture object and bind it
146 #ifdef GL_VERSION_1_1
147         xglGenTextures(1, &texture_id );
148         xglBindTexture(GL_TEXTURE_2D, texture_id );
149 #elif GL_EXT_texture_object
150         xglGenTexturesEXT(1, &texture_id );
151         xglBindTextureEXT(GL_TEXTURE_2D, texture_id );
152 #else
153 #  error port me
154 #endif
155
156         // set the texture parameters for this texture
157         xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ) ;
158         xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ) ;
159         xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
160                           GL_LINEAR );
161         // xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
162         //                   GL_NEAREST_MIPMAP_NEAREST );
163         xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
164                           /* GL_LINEAR */ 
165                           /* GL_NEAREST_MIPMAP_LINEAR */
166                           GL_LINEAR_MIPMAP_LINEAR ) ;
167
168         /* load in the texture data */
169         string tpath = current_options.get_fg_root() + "/Textures/" + 
170             texture_name + ".rgb";
171         string fg_tpath = tpath + ".gz";
172
173         if ( alpha == 0 ) {
174             // load rgb texture
175
176             // Try uncompressed
177             if ( (texbuf = 
178                   read_rgb_texture(tpath.c_str(), &width, &height)) == 
179                  NULL )
180             {
181                 // Try compressed
182                 if ( (texbuf = 
183                       read_rgb_texture(fg_tpath.c_str(), &width, &height)) 
184                      == NULL )
185                 {
186                     FG_LOG( FG_GENERAL, FG_ALERT, 
187                             "Error in loading texture " << tpath );
188                     exit(-1);
189                 } 
190             } 
191
192             /* xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
193                GL_RGB, GL_UNSIGNED_BYTE, texbuf); */
194
195             gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGB, width, height, 
196                                GL_RGB, GL_UNSIGNED_BYTE, texbuf );
197         } else if ( alpha == 1 ) {
198             // load rgba (alpha) texture
199
200             // Try uncompressed
201             if ( (texbuf = 
202                   read_alpha_texture(tpath.c_str(), &width, &height))
203                  == NULL )
204             {
205                 // Try compressed
206                 if ((texbuf = 
207                      read_alpha_texture(fg_tpath.c_str(), &width, &height))
208                     == NULL )
209                 {
210                     FG_LOG( FG_GENERAL, FG_ALERT, 
211                             "Error in loading texture " << tpath );
212                     exit(-1);
213                 } 
214             } 
215
216             xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
217                           GL_RGBA, GL_UNSIGNED_BYTE, texbuf);
218         }
219 }
220
221
222 // Destructor
223 fgMATERIAL::~fgMATERIAL ( void ) {
224 }
225
226
227 // Constructor
228 fgMATERIAL_MGR::fgMATERIAL_MGR ( void ) {
229     textures_loaded = false;
230 }
231
232
233 void
234 fgMATERIAL::render_fragments()
235 {
236     int tris_rendered = current_view.get_tris_rendered();
237
238     // cout << "rendering " + texture_name + " = " << list_size << "\n";
239
240     if ( empty() )
241         return;
242
243     if ( current_options.get_textures() )
244     {
245 #ifdef GL_VERSION_1_1
246         xglBindTexture(GL_TEXTURE_2D, texture_id);
247 #elif GL_EXT_texture_object
248         xglBindTextureEXT(GL_TEXTURE_2D, texture_id);
249 #else
250 #  error port me
251 #endif
252     } else {
253         xglMaterialfv (GL_FRONT, GL_AMBIENT, ambient);
254         xglMaterialfv (GL_FRONT, GL_DIFFUSE, diffuse);
255     }
256
257     fgTILE* last_tile_ptr = NULL;
258     frag_list_iterator current = list.begin();
259     frag_list_iterator last = list.end();
260
261     for ( ; current != last; ++current ) {
262         fgFRAGMENT* frag_ptr = *current;
263         tris_rendered += frag_ptr->num_faces();
264         if ( frag_ptr->tile_ptr != last_tile_ptr )
265         {
266             // new tile, new translate
267             last_tile_ptr = frag_ptr->tile_ptr;
268             xglLoadMatrixd( frag_ptr->tile_ptr->model_view );
269         }
270
271         // Woohoo!!!  We finally get to draw something!
272         // printf("  display_list = %d\n", frag_ptr->display_list);
273         xglCallList( frag_ptr->display_list );
274     }
275
276     current_view.set_tris_rendered( tris_rendered );
277 }
278
279
280 // Load a library of material properties
281 int
282 fgMATERIAL_MGR::load_lib ( void )
283 {
284     string material_name;
285
286     // build the path name to the material db
287     string mpath = current_options.get_fg_root() + "/materials";
288     fg_gzifstream in( mpath );
289     if ( ! in ) {
290         FG_LOG( FG_GENERAL, FG_ALERT, "Cannot open file: " << mpath );
291         exit(-1);
292     }
293
294     while ( ! in.eof() ) {
295         // printf("%s", line);
296
297         // strip leading white space and comments
298         in >> skipcomment;
299
300         // set to zero to prevent its value accidently being '{'
301         // after a failed >> operation.
302         char token = 0;
303
304         in >> material_name >> token;
305
306         if ( token == '{' ) {
307             FG_LOG( FG_TERRAIN, FG_INFO,
308                     "  Loading material " << material_name );
309             fgMATERIAL m;
310             in >> m;
311
312             if ( current_options.get_textures() ) {
313                 m.load_texture();
314             }
315
316             material_mgr.material_map[material_name] = m;
317         }
318     }
319
320     if ( current_options.get_textures() ) {
321         textures_loaded = true;
322     }
323
324     return(1);
325 }
326
327
328 // Initialize the transient list of fragments for each material property
329 void
330 fgMATERIAL_MGR::init_transient_material_lists( void )
331 {
332     iterator last = end();
333     for ( iterator it = begin(); it != last; ++it )
334     {
335         (*it).second.init_sort_list();
336     }
337 }
338
339
340 bool
341 fgMATERIAL_MGR::find( const string& material, fgMATERIAL*& mtl_ptr )
342 {
343     iterator it = material_map.find( material );
344     if ( it != end() )
345     {
346         mtl_ptr = &((*it).second);
347         return true;
348     }
349
350     return false;
351 }
352
353
354 // Destructor
355 fgMATERIAL_MGR::~fgMATERIAL_MGR ( void ) {
356 }
357
358
359 void
360 fgMATERIAL_MGR::render_fragments()
361 {
362     current_view.set_tris_rendered( 0 );
363
364     iterator last = end();
365     for ( iterator current = begin(); current != last; ++current )
366         (*current).second.render_fragments();
367 }
368
369
370 // $Log$
371 // Revision 1.13  1999/02/26 22:09:58  curt
372 // Added initial support for native SGI compilers.
373 //
374 // Revision 1.12  1998/12/09 18:50:30  curt
375 // Converted "class fgVIEW" to "class FGView" and updated to make data
376 // members private and make required accessor functions.
377 //
378 // Revision 1.11  1998/11/07 19:07:12  curt
379 // Enable release builds using the --without-logging option to the configure
380 // script.  Also a couple log message cleanups, plus some C to C++ comment
381 // conversion.
382 //
383 // Revision 1.10  1998/11/06 21:18:17  curt
384 // Converted to new logstream debugging facility.  This allows release
385 // builds with no messages at all (and no performance impact) by using
386 // the -DFG_NDEBUG flag.
387 //
388 // Revision 1.9  1998/11/06 14:47:05  curt
389 // Changes to track Bernie's updates to fgstream.
390 //
391 // Revision 1.8  1998/10/12 23:49:17  curt
392 // Changes from NHV to make the code more dynamic with fewer hard coded limits.
393 //
394 // Revision 1.7  1998/09/17 18:35:52  curt
395 // Tweaks and optimizations by Norman Vine.
396 //
397 // Revision 1.6  1998/09/15 01:35:05  curt
398 // cleaned up my fragment.num_faces hack :-) to use the STL (no need in
399 // duplicating work.)
400 // Tweaked fgTileMgrRender() do not calc tile matrix unless necessary.
401 // removed some unneeded stuff from fgTileMgrCurElev()
402 //
403 // Revision 1.5  1998/09/10 19:07:11  curt
404 // /Simulator/Objects/fragment.hxx
405 //   Nested fgFACE inside fgFRAGMENT since its not used anywhere else.
406 //
407 // ./Simulator/Objects/material.cxx
408 // ./Simulator/Objects/material.hxx
409 //   Made fgMATERIAL and fgMATERIAL_MGR bona fide classes with private
410 //   data members - that should keep the rabble happy :)
411 //
412 // ./Simulator/Scenery/tilemgr.cxx
413 //   In viewable() delay evaluation of eye[0] and eye[1] in until they're
414 //   actually needed.
415 //   Change to fgTileMgrRender() to call fgMATERIAL_MGR::render_fragments()
416 //   method.
417 //
418 // ./Include/fg_stl_config.h
419 // ./Include/auto_ptr.hxx
420 //   Added support for g++ 2.7.
421 //   Further changes to other files are forthcoming.
422 //
423 // Brief summary of changes required for g++ 2.7.
424 //   operator->() not supported by iterators: use (*i).x instead of i->x
425 //   default template arguments not supported,
426 //   <functional> doesn't have mem_fun_ref() needed by callbacks.
427 //   some std include files have different names.
428 //   template member functions not supported.
429 //
430 // Revision 1.4  1998/09/01 19:03:08  curt
431 // Changes contributed by Bernie Bright <bbright@c031.aone.net.au>
432 //  - The new classes in libmisc.tgz define a stream interface into zlib.
433 //    I've put these in a new directory, Lib/Misc.  Feel free to rename it
434 //    to something more appropriate.  However you'll have to change the
435 //    include directives in all the other files.  Additionally you'll have
436 //    add the library to Lib/Makefile.am and Simulator/Main/Makefile.am.
437 //
438 //    The StopWatch class in Lib/Misc requires a HAVE_GETRUSAGE autoconf
439 //    test so I've included the required changes in config.tgz.
440 //
441 //    There are a fair few changes to Simulator/Objects as I've moved
442 //    things around.  Loading tiles is quicker but thats not where the delay
443 //    is.  Tile loading takes a few tenths of a second per file on a P200
444 //    but it seems to be the post-processing that leads to a noticeable
445 //    blip in framerate.  I suppose its time to start profiling to see where
446 //    the delays are.
447 //
448 //    I've included a brief description of each archives contents.
449 //
450 // Lib/Misc/
451 //   zfstream.cxx
452 //   zfstream.hxx
453 //     C++ stream interface into zlib.
454 //     Taken from zlib-1.1.3/contrib/iostream/.
455 //     Minor mods for STL compatibility.
456 //     There's no copyright associated with these so I assume they're
457 //     covered by zlib's.
458 //
459 //   fgstream.cxx
460 //   fgstream.hxx
461 //     FlightGear input stream using gz_ifstream.  Tries to open the
462 //     given filename.  If that fails then filename is examined and a
463 //     ".gz" suffix is removed or appended and that file is opened.
464 //
465 //   stopwatch.hxx
466 //     A simple timer for benchmarking.  Not used in production code.
467 //     Taken from the Blitz++ project.  Covered by GPL.
468 //
469 //   strutils.cxx
470 //   strutils.hxx
471 //     Some simple string manipulation routines.
472 //
473 // Simulator/Airports/
474 //   Load airports database using fgstream.
475 //   Changed fgAIRPORTS to use set<> instead of map<>.
476 //   Added bool fgAIRPORTS::search() as a neater way doing the lookup.
477 //   Returns true if found.
478 //
479 // Simulator/Astro/
480 //   Modified fgStarsInit() to load stars database using fgstream.
481 //
482 // Simulator/Objects/
483 //   Modified fgObjLoad() to use fgstream.
484 //   Modified fgMATERIAL_MGR::load_lib() to use fgstream.
485 //   Many changes to fgMATERIAL.
486 //   Some changes to fgFRAGMENT but I forget what!
487 //
488 // Revision 1.3  1998/08/27 17:02:09  curt
489 // Contributions from Bernie Bright <bbright@c031.aone.net.au>
490 // - use strings for fg_root and airport_id and added methods to return
491 //   them as strings,
492 // - inlined all access methods,
493 // - made the parsing functions private methods,
494 // - deleted some unused functions.
495 // - propogated some of these changes out a bit further.
496 //
497 // Revision 1.2  1998/08/25 20:53:33  curt
498 // Shuffled $FG_ROOT file layout.
499 //
500 // Revision 1.1  1998/08/25 16:51:24  curt
501 // Moved from ../Scenery
502 //
503 // Revision 1.13  1998/08/24 20:11:39  curt
504 // Tweaks ...
505 //
506 // Revision 1.12  1998/08/12 21:41:27  curt
507 // Need to negate the test for textures so that textures aren't loaded when
508 // they are disabled rather than visa versa ... :-)
509 //
510 // Revision 1.11  1998/08/12 21:13:03  curt
511 // material.cxx: don't load textures if they are disabled
512 // obj.cxx: optimizations from Norman Vine
513 // tile.cxx: minor tweaks
514 // tile.hxx: addition of num_faces
515 // tilemgr.cxx: minor tweaks
516 //
517 // Revision 1.10  1998/07/24 21:42:06  curt
518 // material.cxx: whups, double method declaration with no definition.
519 // obj.cxx: tweaks to avoid errors in SGI's CC.
520 // tile.cxx: optimizations by Norman Vine.
521 // tilemgr.cxx: optimizations by Norman Vine.
522 //
523 // Revision 1.9  1998/07/13 21:01:57  curt
524 // Wrote access functions for current fgOPTIONS.
525 //
526 // Revision 1.8  1998/07/08 14:47:20  curt
527 // Fix GL_MODULATE vs. GL_DECAL problem introduced by splash screen.
528 // polare3d.h renamed to polar3d.hxx
529 // fg{Cartesian,Polar}Point3d consolodated.
530 // Added some initial support for calculating local current ground elevation.
531 //
532 // Revision 1.7  1998/07/04 00:54:28  curt
533 // Added automatic mipmap generation.
534 //
535 // When rendering fragments, use saved model view matrix from associated tile
536 // rather than recalculating it with push() translate() pop().
537 //
538 // Revision 1.6  1998/06/27 16:54:59  curt
539 // Check for GL_VERSION_1_1 or GL_EXT_texture_object to decide whether to use
540 //   "EXT" versions of texture management routines.
541 //
542 // Revision 1.5  1998/06/17 21:36:39  curt
543 // Load and manage multiple textures defined in the Materials library.
544 // Boost max material fagments for each material property to 800.
545 // Multiple texture support when rendering.
546 //
547 // Revision 1.4  1998/06/12 00:58:04  curt
548 // Build only static libraries.
549 // Declare memmove/memset for Sloaris.
550 //
551 // Revision 1.3  1998/06/05 22:39:53  curt
552 // Working on sorting by, and rendering by material properties.
553 //
554 // Revision 1.2  1998/06/01 17:56:20  curt
555 // Incremental additions to material.cxx (not fully functional)
556 // Tweaked vfc_ratio math to avoid divide by zero.
557 //
558 // Revision 1.1  1998/05/30 01:56:45  curt
559 // Added material.cxx material.hxx
560 //