]> git.mxchange.org Git - flightgear.git/blob - Objects/material.cxx
Moved from ../Scenery
[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 <Include/fg_zlib.h>
40 #include <Main/options.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 }
52
53
54 // Sorting routines
55 void fgMATERIAL::init_sort_list( void ) {
56 }
57
58
59 int fgMATERIAL::append_sort_list( fgFRAGMENT *object ) {
60     return(0);
61 }
62
63
64 // Destructor
65 fgMATERIAL::~fgMATERIAL ( void ) {
66 }
67
68
69 // Constructor
70 fgMATERIAL_MGR::fgMATERIAL_MGR ( void ) {
71 }
72
73
74 // Load a library of material properties
75 int fgMATERIAL_MGR::load_lib ( void ) {
76     fgMATERIAL m;
77     char material_name[256];
78     char mpath[256], fg_mpath[256], tpath[256], fg_tpath[256];
79     char line[256], *line_ptr, value[256];
80     GLubyte *texbuf;
81     fgFile f;
82     int width, height;
83     int alpha;
84
85     // build the path name to the material db
86     current_options.get_fg_root(mpath);
87     strcat(mpath, "/Scenery/");
88     strcat(mpath, "Materials");
89     strcpy(fg_mpath, mpath);
90     strcat(fg_mpath, ".gz");
91
92     // first try "path.gz"
93     if ( (f = fgopen(fg_mpath, "rb")) == NULL ) {
94         // next try "path"    
95         if ( (f = fgopen(mpath, "rb")) == NULL ) {
96             fgPrintf(FG_GENERAL, FG_EXIT, "Cannot open file: %s\n", mpath);
97         }       
98     }
99
100     while ( fggets(f, line, 250) != NULL ) {
101         // printf("%s", line);
102
103         // strip leading white space
104         line_ptr = line;
105         while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') ) &&
106                 (line_ptr[0] != '\n') ) {
107             line_ptr++;
108             
109         }
110
111         if ( line_ptr[0] == '#' ) {
112             // ignore lines that start with '#'
113         } else if ( line_ptr[0] == '\n' ) {
114             // ignore blank lines
115         } else if ( strstr(line_ptr, "{") ) {
116             // start of record
117             alpha = 0;
118             m.ambient[0]  = m.ambient[1]  = m.ambient[2]  = m.ambient[3]  = 0.0;
119             m.diffuse[0]  = m.diffuse[1]  = m.diffuse[2]  = m.diffuse[3]  = 0.0;
120             m.specular[0] = m.specular[1] = m.specular[2] = m.specular[3] = 0.0;
121             m.emissive[0] = m.emissive[1] = m.emissive[2] = m.emissive[3] = 0.0;
122
123             material_name[0] = '\0';
124             sscanf(line_ptr, "%s", material_name);
125             if ( ! strlen(material_name) ) {
126                 fgPrintf( FG_TERRAIN, FG_INFO, "Bad material name in '%s'\n",
127                           line );
128             }
129             printf("  Loading material = %s\n", material_name);
130         } else if ( strncmp(line_ptr, "alpha", 5) == 0 ) {
131             line_ptr += 5;
132             while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') || 
133                       (line_ptr[0] == '=') ) &&
134                     (line_ptr[0] != '\n') ) {
135                 line_ptr++;
136             }
137             sscanf(line_ptr, "%s\n", value);
138             if ( strcmp(value, "no") == 0 ) {
139                 alpha = 0;
140             } else if ( strcmp(value, "yes") == 0 ) {
141                 alpha = 1;
142             } else {
143                 fgPrintf( FG_TERRAIN, FG_INFO, "Bad alpha value '%s'\n", line );
144             }
145         } else if ( (strncmp(line_ptr, "texture", 7) == 0) &&
146                     !current_options.get_textures() ) {
147             // do nothing
148         } else if ( strncmp(line_ptr, "texture", 7) == 0 ) {
149             line_ptr += 7;
150             while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') || 
151                       (line_ptr[0] == '=') ) &&
152                     (line_ptr[0] != '\n') ) {
153                 line_ptr++;
154             }
155             // printf("texture name = %s\n", line_ptr);
156             sscanf(line_ptr, "%s\n", m.texture_name);
157
158             // create the texture object and bind it
159 #ifdef GL_VERSION_1_1
160             xglGenTextures(1, &m.texture_id);
161             xglBindTexture(GL_TEXTURE_2D, m.texture_id);
162 #elif GL_EXT_texture_object
163             xglGenTexturesEXT(1, &m.texture_id);
164             xglBindTextureEXT(GL_TEXTURE_2D, m.texture_id);
165 #else
166 #  error port me
167 #endif
168
169             // set the texture parameters for this texture
170             xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ) ;
171             xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ) ;
172             xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
173                               GL_LINEAR );
174             // xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
175             //                   GL_NEAREST_MIPMAP_NEAREST );
176             xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
177                               /* GL_LINEAR */ 
178                               /* GL_NEAREST_MIPMAP_LINEAR */
179                               GL_LINEAR_MIPMAP_LINEAR ) ;
180
181             /* load in the texture data */
182             current_options.get_fg_root(tpath);
183             strcat(tpath, "/Textures/");
184             strcat(tpath, m.texture_name);
185             strcat(tpath, ".rgb");
186
187             if ( alpha == 0 ) {
188                 // load rgb texture
189
190                 // Try uncompressed
191                 if ( (texbuf = read_rgb_texture(tpath, &width, &height))
192                      == NULL ) {
193                     // Try compressed
194                     strcpy(fg_tpath, tpath);
195                     strcat(fg_tpath, ".gz");
196                     if ( (texbuf = read_rgb_texture(fg_tpath, &width, &height)) 
197                          == NULL ) {
198                         fgPrintf( FG_GENERAL, FG_EXIT, 
199                                   "Error in loading texture %s\n", tpath );
200                         return(0);
201                     } 
202                 } 
203
204                 /* xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
205                               GL_RGB, GL_UNSIGNED_BYTE, texbuf); */
206
207                 gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGB, width, height, 
208                                     GL_RGB, GL_UNSIGNED_BYTE, texbuf );
209             } else if ( alpha == 1 ) {
210                 // load rgba (alpha) texture
211
212                 // Try uncompressed
213                 if ( (texbuf = read_alpha_texture(tpath, &width, &height))
214                      == NULL ) {
215                     // Try compressed
216                     strcpy(fg_tpath, tpath);
217                     strcat(fg_tpath, ".gz");
218                     if ((texbuf = read_alpha_texture(fg_tpath, &width, &height))
219                         == NULL ) {
220                         fgPrintf( FG_GENERAL, FG_EXIT, 
221                                   "Error in loading texture %s\n", tpath );
222                         return(0);
223                     } 
224                 } 
225
226                 xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
227                               GL_RGBA, GL_UNSIGNED_BYTE, texbuf);
228             }
229
230         } else if ( strncmp(line_ptr, "ambient", 7) == 0 ) {
231             line_ptr += 7;
232             while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') || 
233                       (line_ptr[0] == '=') ) &&
234                     (line_ptr[0] != '\n') ) {
235                 line_ptr++;
236             }
237             sscanf( line_ptr, "%f %f %f %f", 
238                     &m.ambient[0], &m.ambient[1], &m.ambient[2], &m.ambient[3]);
239         } else if ( strncmp(line_ptr, "diffuse", 7) == 0 ) {
240             line_ptr += 7;
241             while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') || 
242                       (line_ptr[0] == '=') ) &&
243                     (line_ptr[0] != '\n') ) {
244                 line_ptr++;
245             }
246             sscanf( line_ptr, "%f %f %f %f", 
247                     &m.diffuse[0], &m.diffuse[1], &m.diffuse[2], &m.diffuse[3]);
248         } else if ( strncmp(line_ptr, "specular", 8) == 0 ) {
249             line_ptr += 8;
250             while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') || 
251                       (line_ptr[0] == '=') ) &&
252                     (line_ptr[0] != '\n') ) {
253                 line_ptr++;
254             }
255             sscanf( line_ptr, "%f %f %f %f", 
256                     &m.specular[0], &m.specular[1], 
257                     &m.specular[2], &m.specular[3]);
258         } else if ( strncmp(line_ptr, "emissive", 8) == 0 ) {
259             line_ptr += 8;
260             while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') || 
261                       (line_ptr[0] == '=') ) &&
262                     (line_ptr[0] != '\n') ) {
263                 line_ptr++;
264             }
265             sscanf( line_ptr, "%f %f %f %f", 
266                     &m.emissive[0], &m.emissive[1], 
267                     &m.emissive[2], &m.emissive[3]);
268         } else if ( line_ptr[0] == '}' ) {
269             // end of record, lets add this one to the list
270             material_mgr.material_map[material_name] = m;
271         } else {
272             fgPrintf(FG_TERRAIN, FG_INFO, 
273                      "Unknown line in material properties file\n");
274         }
275     }
276
277     fgclose(f);
278
279     return(1);
280 }
281
282
283 // Initialize the transient list of fragments for each material property
284 void fgMATERIAL_MGR::init_transient_material_lists( void ) {
285     map < string, fgMATERIAL, less<string> > :: iterator mapcurrent = 
286         material_mgr.material_map.begin();
287     map < string, fgMATERIAL, less<string> > :: iterator maplast = 
288         material_mgr.material_map.end();
289
290     while ( mapcurrent != maplast ) {
291         // (char *)key = (*mapcurrent).first;
292         // (fgMATERIAL)value = (*mapcurrent).second;
293         (*mapcurrent).second.list_size = 0;
294
295         *mapcurrent++;
296     }
297 }
298
299
300 // Destructor
301 fgMATERIAL_MGR::~fgMATERIAL_MGR ( void ) {
302 }
303
304
305 // $Log$
306 // Revision 1.1  1998/08/25 16:51:24  curt
307 // Moved from ../Scenery
308 //
309 // Revision 1.13  1998/08/24 20:11:39  curt
310 // Tweaks ...
311 //
312 // Revision 1.12  1998/08/12 21:41:27  curt
313 // Need to negate the test for textures so that textures aren't loaded when
314 // they are disabled rather than visa versa ... :-)
315 //
316 // Revision 1.11  1998/08/12 21:13:03  curt
317 // material.cxx: don't load textures if they are disabled
318 // obj.cxx: optimizations from Norman Vine
319 // tile.cxx: minor tweaks
320 // tile.hxx: addition of num_faces
321 // tilemgr.cxx: minor tweaks
322 //
323 // Revision 1.10  1998/07/24 21:42:06  curt
324 // material.cxx: whups, double method declaration with no definition.
325 // obj.cxx: tweaks to avoid errors in SGI's CC.
326 // tile.cxx: optimizations by Norman Vine.
327 // tilemgr.cxx: optimizations by Norman Vine.
328 //
329 // Revision 1.9  1998/07/13 21:01:57  curt
330 // Wrote access functions for current fgOPTIONS.
331 //
332 // Revision 1.8  1998/07/08 14:47:20  curt
333 // Fix GL_MODULATE vs. GL_DECAL problem introduced by splash screen.
334 // polare3d.h renamed to polar3d.hxx
335 // fg{Cartesian,Polar}Point3d consolodated.
336 // Added some initial support for calculating local current ground elevation.
337 //
338 // Revision 1.7  1998/07/04 00:54:28  curt
339 // Added automatic mipmap generation.
340 //
341 // When rendering fragments, use saved model view matrix from associated tile
342 // rather than recalculating it with push() translate() pop().
343 //
344 // Revision 1.6  1998/06/27 16:54:59  curt
345 // Check for GL_VERSION_1_1 or GL_EXT_texture_object to decide whether to use
346 //   "EXT" versions of texture management routines.
347 //
348 // Revision 1.5  1998/06/17 21:36:39  curt
349 // Load and manage multiple textures defined in the Materials library.
350 // Boost max material fagments for each material property to 800.
351 // Multiple texture support when rendering.
352 //
353 // Revision 1.4  1998/06/12 00:58:04  curt
354 // Build only static libraries.
355 // Declare memmove/memset for Sloaris.
356 //
357 // Revision 1.3  1998/06/05 22:39:53  curt
358 // Working on sorting by, and rendering by material properties.
359 //
360 // Revision 1.2  1998/06/01 17:56:20  curt
361 // Incremental additions to material.cxx (not fully functional)
362 // Tweaked vfc_ratio math to avoid divide by zero.
363 //
364 // Revision 1.1  1998/05/30 01:56:45  curt
365 // Added material.cxx material.hxx
366 //