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