]> git.mxchange.org Git - flightgear.git/blob - src/Objects/newmat.cxx
Substantial rewrite of FGNewMat, the material class. Most of the
[flightgear.git] / src / Objects / newmat.cxx
1 // newmat.cxx -- class to handle material properties
2 //
3 // Written by Curtis Olson, started May 1998.
4 //
5 // Copyright (C) 1998 - 2000  Curtis L. Olson  - curt@flightgear.org
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 #include <simgear/compiler.h>
29
30 #ifdef SG_MATH_EXCEPTION_CLASH
31 #  include <math.h>
32 #endif
33
34 #include <simgear/debug/logstream.hxx>
35 #include <simgear/misc/sg_path.hxx>
36 #include <simgear/misc/sgstream.hxx>
37
38 #include <Main/globals.hxx>
39 #include <Main/fg_props.hxx>
40
41 #include "newmat.hxx"
42
43
44 static bool
45 local_file_exists( const string& path ) {
46     sg_gzifstream in( path );
47     if ( ! in.is_open() ) {
48         return false;
49     } else {
50         return true;
51     }
52 }
53
54
55 // Constructor
56
57 FGNewMat::FGNewMat ()
58   : texture_path(""),
59     state(0),
60     textured(0),
61     nontextured(0),
62     alpha(false),
63     xsize(0),
64     ysize(0),
65     wrapu(true),
66     wrapv(true),
67     mipmap(true),
68     texture_loaded(false),
69     refcount(0)
70 {
71     for (int i = 0; i < 4; i++)
72       ambient[i] = diffuse[i] = specular[i] = emission[i] = 0.0;
73 }
74
75 FGNewMat::FGNewMat (const SGPropertyNode * props)
76 {
77     FGNewMat();
78     read_properties(props);
79     build_ssg_state(false);
80 }
81
82 FGNewMat::FGNewMat (const string &texture_path)
83 {
84     FGNewMat();
85     build_ssg_state(true);
86 }
87
88 FGNewMat::FGNewMat (ssgSimpleState * s)
89 {
90     FGNewMat();
91     set_ssg_state(s);
92 }
93
94
95 bool
96 FGNewMat::load_texture ()
97 {
98   if (texture_loaded) {
99     return false;
100   } else {
101     SG_LOG( SG_GENERAL, SG_INFO, "Loading deferred texture " << texture_path );
102 #ifdef PLIB_1_2_X
103     textured->setTexture((char *)texture_path.c_str(), wrapu, wrapv );
104 #else
105     textured->setTexture((char *)texture_path.c_str(), wrapu, wrapv, mipmap );
106 #endif
107     texture_loaded = true;
108     return true;
109   }
110 }
111
112
113 void FGNewMat::build_ssg_state( bool defer_tex_load )
114 {
115     GLenum shade_model =
116       (fgGetBool("/sim/rendering/shading") ? GL_SMOOTH : GL_FLAT);
117     bool texture_default = fgGetBool("/sim/rendering/textures");
118
119     state = new ssgStateSelector(2);
120     state->ref();
121
122     textured = new ssgSimpleState();
123     textured->ref();
124
125     nontextured = new ssgSimpleState();
126     nontextured->ref();
127
128     // Set up the textured state
129     textured->setShadeModel( shade_model );
130     textured->enable( GL_LIGHTING );
131     textured->enable ( GL_CULL_FACE ) ;
132     textured->enable( GL_TEXTURE_2D );
133     textured->disable( GL_BLEND );
134     textured->disable( GL_ALPHA_TEST );
135     if ( !defer_tex_load ) {
136         textured->setTexture( (char *)texture_path.c_str(), wrapu, wrapv );
137         texture_loaded = true;
138     } else {
139         texture_loaded = false;
140     }
141     textured->enable( GL_COLOR_MATERIAL );
142     textured->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
143     textured->setMaterial( GL_EMISSION, 0, 0, 0, 1 );
144     textured->setMaterial( GL_SPECULAR, 0, 0, 0, 1 );
145
146     // Set up the coloured state
147     nontextured->enable( GL_LIGHTING );
148     nontextured->setShadeModel( shade_model );
149     nontextured->enable ( GL_CULL_FACE      ) ;
150     nontextured->disable( GL_TEXTURE_2D );
151     nontextured->disable( GL_BLEND );
152     nontextured->disable( GL_ALPHA_TEST );
153     nontextured->disable( GL_COLOR_MATERIAL );
154
155     nontextured->setMaterial ( GL_AMBIENT, 
156                                ambient[0], ambient[1], 
157                                ambient[2], ambient[3] ) ;
158     nontextured->setMaterial ( GL_DIFFUSE, 
159                                diffuse[0], diffuse[1], 
160                                diffuse[2], diffuse[3] ) ;
161     nontextured->setMaterial ( GL_SPECULAR, 
162                                specular[0], specular[1], 
163                                specular[2], specular[3] ) ;
164     nontextured->setMaterial ( GL_EMISSION, 
165                                emission[0], emission[1], 
166                                emission[2], emission[3] ) ;
167
168     state->setStep( 0, textured );    // textured
169     state->setStep( 1, nontextured ); // untextured
170
171     // Choose the appropriate starting state.
172     if ( texture_default ) {
173         state->selectStep(0);
174     } else {
175         state->selectStep(1);
176     }
177 }
178
179
180 void FGNewMat::set_ssg_state( ssgSimpleState *s ) {
181     state = new ssgStateSelector(2);
182     state->ref();
183
184     textured = s;
185
186     nontextured = new ssgSimpleState();
187     nontextured->ref();
188
189     // Set up the coloured state
190     nontextured->enable( GL_LIGHTING );
191     nontextured->setShadeModel( GL_FLAT );
192     nontextured->enable ( GL_CULL_FACE      ) ;
193     nontextured->disable( GL_TEXTURE_2D );
194     nontextured->disable( GL_BLEND );
195     nontextured->disable( GL_ALPHA_TEST );
196     nontextured->disable( GL_COLOR_MATERIAL );
197
198     /* cout << "ambient = " << ambient[0] << "," << ambient[1] 
199        << "," << ambient[2] << endl; */
200     nontextured->setMaterial ( GL_AMBIENT, 
201                                ambient[0], ambient[1], 
202                                ambient[2], ambient[3] ) ;
203     nontextured->setMaterial ( GL_DIFFUSE, 
204                                diffuse[0], diffuse[1], 
205                                diffuse[2], diffuse[3] ) ;
206     nontextured->setMaterial ( GL_SPECULAR, 
207                                specular[0], specular[1], 
208                                specular[2], specular[3] ) ;
209     nontextured->setMaterial ( GL_EMISSION, 
210                                emission[0], emission[1], 
211                                emission[2], emission[3] ) ;
212
213     state->setStep( 0, textured );    // textured
214     state->setStep( 1, nontextured ); // untextured
215
216     // Choose the appropriate starting state.
217     state->selectStep(0);
218 }
219
220
221 // Destructor
222 FGNewMat::~FGNewMat ( void ) {
223 }
224
225
226 void
227 FGNewMat::read_properties (const SGPropertyNode * props)
228 {
229                                 // Get the path to the texture
230   string tname = props->getStringValue("texture", "unknown.rgb");
231   SGPath tpath(globals->get_fg_root());
232   tpath.append("Textures.high");
233   tpath.append(tname);
234   if (!local_file_exists(tpath.str())) {
235     tpath = SGPath(globals->get_fg_root());
236     tpath.append("Textures");
237     tpath.append(tname);
238   }
239   texture_path = tpath.str();
240
241   xsize = props->getDoubleValue("xsize", 0.0);
242   ysize = props->getDoubleValue("ysize", 0.0);
243   wrapu = props->getBoolValue("wrapu", true);
244   wrapv = props->getBoolValue("wrapv", true);
245   mipmap = props->getBoolValue("mipmap", true);
246   light_coverage = props->getDoubleValue("light-coverage");
247
248   ambient[0] = props->getDoubleValue("ambient/r", 0.0);
249   ambient[1] = props->getDoubleValue("ambient/g", 0.0);
250   ambient[2] = props->getDoubleValue("ambient/b", 0.0);
251   ambient[3] = props->getDoubleValue("ambient/a", 0.0);
252
253   diffuse[0] = props->getDoubleValue("diffuse/r", 0.0);
254   diffuse[1] = props->getDoubleValue("diffuse/g", 0.0);
255   diffuse[2] = props->getDoubleValue("diffuse/b", 0.0);
256   diffuse[3] = props->getDoubleValue("diffuse/a", 0.0);
257
258   specular[0] = props->getDoubleValue("specular/r", 0.0);
259   specular[1] = props->getDoubleValue("specular/g", 0.0);
260   specular[2] = props->getDoubleValue("specular/b", 0.0);
261   specular[3] = props->getDoubleValue("specular/a", 0.0);
262
263   emission[0] = props->getDoubleValue("emissive/r", 0.0);
264   emission[1] = props->getDoubleValue("emissive/g", 0.0);
265   emission[2] = props->getDoubleValue("emissive/b", 0.0);
266   emission[3] = props->getDoubleValue("emissive/a", 0.0);
267 }