+++ /dev/null
-// materialmgr.cxx -- class to handle material properties
-//
-// Written by Curtis Olson, started May 1998.
-//
-// Copyright (C) 1998 Curtis L. Olson - curt@me.umn.edu
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-//
-// $Id$
-
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifdef SG_MATH_EXCEPTION_CLASH
-# include <math.h>
-#endif
-
-#ifdef HAVE_WINDOWS_H
-# include <windows.h>
-#endif
-
-#include GLUT_H
-
-#include <simgear/compiler.h>
-#include <simgear/constants.h>
-#include <simgear/misc/exception.hxx>
-
-#include <string.h>
-#include STL_STRING
-
-#include <simgear/debug/logstream.hxx>
-#include <simgear/misc/sg_path.hxx>
-#include <simgear/misc/sgstream.hxx>
-
-#include <Include/general.hxx>
-#include <Main/globals.hxx>
-#include <Main/fg_props.hxx>
-#include <Scenery/tileentry.hxx>
-
-#include "newmat.hxx"
-#include "matlib.hxx"
-
-SG_USING_NAMESPACE(std);
-SG_USING_STD(string);
-
-
-// global material management class
-FGMaterialLib material_lib;
-
-
-// Constructor
-FGMaterialLib::FGMaterialLib ( void ) {
- set_step(0);
-}
-
-
-static int gen_test_light_map() {
- static const int env_tex_res = 32;
- int half_res = env_tex_res / 2;
- unsigned char env_map[env_tex_res][env_tex_res][4];
- GLuint tex_name;
-
- for ( int i = 0; i < env_tex_res; ++i ) {
- for ( int j = 0; j < env_tex_res; ++j ) {
- double x = (i - half_res) / (double)half_res;
- double y = (j - half_res) / (double)half_res;
- double dist = sqrt(x*x + y*y);
- if ( dist > 1.0 ) { dist = 1.0; }
-
- // cout << x << "," << y << " " << (int)(dist * 255) << ","
- // << (int)((1.0 - dist) * 255) << endl;
- env_map[i][j][0] = (int)(dist * 255);
- env_map[i][j][1] = (int)((1.0 - dist) * 255);
- env_map[i][j][2] = 0;
- env_map[i][j][3] = 255;
- }
- }
-
- glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
- glGenTextures( 1, &tex_name );
- glBindTexture( GL_TEXTURE_2D, tex_name );
-
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, env_tex_res, env_tex_res, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, env_map);
-
- return tex_name;
-}
-
-
-// generate standard colored directional light environment texture map
-static int gen_standard_dir_light_map( int r, int g, int b, int alpha ) {
- const int env_tex_res = 32;
- int half_res = env_tex_res / 2;
- unsigned char env_map[env_tex_res][env_tex_res][4];
- GLuint tex_name;
-
- for ( int i = 0; i < env_tex_res; ++i ) {
- for ( int j = 0; j < env_tex_res; ++j ) {
- double x = (i - half_res) / (double)half_res;
- double y = (j - half_res) / (double)half_res;
- double dist = sqrt(x*x + y*y);
- if ( dist > 1.0 ) { dist = 1.0; }
- double bright = cos( dist * SGD_PI_2 );
- if ( bright < 0.3 ) { bright = 0.3; }
- env_map[i][j][0] = r;
- env_map[i][j][1] = g;
- env_map[i][j][2] = b;
- env_map[i][j][3] = (int)(bright * alpha);
- }
- }
-
- glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
- glGenTextures( 1, &tex_name );
- glBindTexture( GL_TEXTURE_2D, tex_name );
-
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, env_tex_res, env_tex_res, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, env_map);
-
- return tex_name;
-}
-
-
-// generate standard colored directional light environment texture map
-static int gen_taxiway_dir_light_map( int r, int g, int b, int alpha ) {
- const int env_tex_res = 32;
- int half_res = env_tex_res / 2;
- unsigned char env_map[env_tex_res][env_tex_res][4];
- GLuint tex_name;
-
- for ( int i = 0; i < env_tex_res; ++i ) {
- for ( int j = 0; j < env_tex_res; ++j ) {
- double x = (i - half_res) / (double)half_res;
- double y = (j - half_res) / (double)half_res;
- double tmp = sqrt(x*x + y*y);
- double dist = tmp * tmp;
- if ( dist > 1.0 ) { dist = 1.0; }
- double bright = sin( dist * SGD_PI_2 );
- if ( bright < 0.2 ) { bright = 0.2; }
- env_map[i][j][0] = r;
- env_map[i][j][1] = g;
- env_map[i][j][2] = b;
- env_map[i][j][3] = (int)(bright * alpha);
- }
- }
-
- glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
- glGenTextures( 1, &tex_name );
- glBindTexture( GL_TEXTURE_2D, tex_name );
-
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, env_tex_res, env_tex_res, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, env_map);
-
- return tex_name;
-}
-
-
-// generate the directional vasi light environment texture map
-static int gen_vasi_light_map() {
- const int env_tex_res = 256;
- int half_res = env_tex_res / 2;
- unsigned char env_map[env_tex_res][env_tex_res][4];
- GLuint tex_name;
-
- for ( int i = 0; i < env_tex_res; ++i ) {
- for ( int j = 0; j < env_tex_res; ++j ) {
- double x = (i - half_res) / (double)half_res;
- double y = (j - half_res) / (double)half_res;
- double dist = sqrt(x*x + y*y);
- if ( dist > 1.0 ) { dist = 1.0; }
- double bright = cos( dist * SGD_PI_2 );
-
- // top half white, bottom half red
- env_map[i][j][0] = 255;
- if ( i > half_res ) {
- // white
- env_map[i][j][1] = 255;
- env_map[i][j][2] = 255;
- } else if ( i == half_res - 1 || i == half_res ) {
- // pink
- env_map[i][j][1] = 127;
- env_map[i][j][2] = 127;
- } else {
- // red
- env_map[i][j][1] = 0;
- env_map[i][j][2] = 0;
- }
- env_map[i][j][3] = (int)(bright * 255);
- }
- }
-
- glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
- glGenTextures( 1, &tex_name );
- glBindTexture( GL_TEXTURE_2D, tex_name );
-
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, env_tex_res, env_tex_res, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, env_map);
-
- return tex_name;
-}
-
-
-// Load a library of material properties
-bool FGMaterialLib::load( const string& mpath ) {
-
- SGPropertyNode materials;
-
- SG_LOG( SG_INPUT, SG_INFO, "Reading materials from " << mpath );
- try {
- readProperties( mpath, &materials );
- } catch (const sg_exception &ex) {
- SG_LOG( SG_INPUT, SG_ALERT, "Error reading materials: "
- << ex.getMessage() );
- throw ex;
- }
-
- int nMaterials = materials.nChildren();
- for (int i = 0; i < nMaterials; i++) {
- const SGPropertyNode * node = materials.getChild(i);
- if (!strcmp(node->getName(), "material")) {
- FGNewMat * m = new FGNewMat(node);
-
- vector<SGPropertyNode_ptr>names = node->getChildren("name");
- for ( unsigned int j = 0; j < names.size(); j++ ) {
- string name = names[j]->getStringValue();
- m->ref();
- // cerr << "Material " << name << endl;
- matlib[name] = m;
- SG_LOG( SG_TERRAIN, SG_INFO, " Loading material "
- << names[j]->getStringValue() );
- }
- } else {
- SG_LOG(SG_INPUT, SG_ALERT,
- "Skipping bad material entry " << node->getName());
- }
- }
-
- // hard coded ground light state
- ssgSimpleState *gnd_lights = new ssgSimpleState;
- gnd_lights->ref();
- gnd_lights->disable( GL_TEXTURE_2D );
- gnd_lights->enable( GL_CULL_FACE );
- gnd_lights->enable( GL_COLOR_MATERIAL );
- gnd_lights->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
- gnd_lights->setMaterial( GL_EMISSION, 0, 0, 0, 1 );
- gnd_lights->setMaterial( GL_SPECULAR, 0, 0, 0, 1 );
- gnd_lights->enable( GL_BLEND );
- gnd_lights->disable( GL_ALPHA_TEST );
- gnd_lights->disable( GL_LIGHTING );
- matlib["GROUND_LIGHTS"] = new FGNewMat(gnd_lights);
-
- GLuint tex_name;
-
- // hard coded runway white light state
- tex_name = gen_standard_dir_light_map( 235, 235, 195, 255 );
- ssgSimpleState *rwy_white_lights = new ssgSimpleState();
- rwy_white_lights->ref();
- rwy_white_lights->disable( GL_LIGHTING );
- rwy_white_lights->enable ( GL_CULL_FACE ) ;
- rwy_white_lights->enable( GL_TEXTURE_2D );
- rwy_white_lights->enable( GL_BLEND );
- rwy_white_lights->enable( GL_ALPHA_TEST );
- rwy_white_lights->enable( GL_COLOR_MATERIAL );
- rwy_white_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
- rwy_white_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
- rwy_white_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
- rwy_white_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
- rwy_white_lights->setTexture( tex_name );
- matlib["RWY_WHITE_LIGHTS"] = new FGNewMat(rwy_white_lights);
- // For backwards compatibility ... remove someday
- matlib["RUNWAY_LIGHTS"] = new FGNewMat(rwy_white_lights);
- matlib["RWY_LIGHTS"] = new FGNewMat(rwy_white_lights);
- // end of backwards compatitibilty
-
- // hard coded runway medium intensity white light state
- tex_name = gen_standard_dir_light_map( 235, 235, 195, 205 );
- ssgSimpleState *rwy_white_medium_lights = new ssgSimpleState();
- rwy_white_medium_lights->ref();
- rwy_white_medium_lights->disable( GL_LIGHTING );
- rwy_white_medium_lights->enable ( GL_CULL_FACE ) ;
- rwy_white_medium_lights->enable( GL_TEXTURE_2D );
- rwy_white_medium_lights->enable( GL_BLEND );
- rwy_white_medium_lights->enable( GL_ALPHA_TEST );
- rwy_white_medium_lights->enable( GL_COLOR_MATERIAL );
- rwy_white_medium_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
- rwy_white_medium_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
- rwy_white_medium_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
- rwy_white_medium_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
- rwy_white_medium_lights->setTexture( tex_name );
- matlib["RWY_WHITE_MEDIUM_LIGHTS"] = new FGNewMat(rwy_white_medium_lights);
-
- // hard coded runway low intensity white light state
- tex_name = gen_standard_dir_light_map( 235, 235, 195, 155 );
- ssgSimpleState *rwy_white_low_lights = new ssgSimpleState();
- rwy_white_low_lights->ref();
- rwy_white_low_lights->disable( GL_LIGHTING );
- rwy_white_low_lights->enable ( GL_CULL_FACE ) ;
- rwy_white_low_lights->enable( GL_TEXTURE_2D );
- rwy_white_low_lights->enable( GL_BLEND );
- rwy_white_low_lights->enable( GL_ALPHA_TEST );
- rwy_white_low_lights->enable( GL_COLOR_MATERIAL );
- rwy_white_low_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
- rwy_white_low_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
- rwy_white_low_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
- rwy_white_low_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
- rwy_white_low_lights->setTexture( tex_name );
- matlib["RWY_WHITE_LOW_LIGHTS"] = new FGNewMat(rwy_white_low_lights);
-
- // hard coded runway yellow light state
- tex_name = gen_standard_dir_light_map( 235, 215, 20, 255 );
- ssgSimpleState *rwy_yellow_lights = new ssgSimpleState();
- rwy_yellow_lights->ref();
- rwy_yellow_lights->disable( GL_LIGHTING );
- rwy_yellow_lights->enable ( GL_CULL_FACE ) ;
- rwy_yellow_lights->enable( GL_TEXTURE_2D );
- rwy_yellow_lights->enable( GL_BLEND );
- rwy_yellow_lights->enable( GL_ALPHA_TEST );
- rwy_yellow_lights->enable( GL_COLOR_MATERIAL );
- rwy_yellow_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
- rwy_yellow_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
- rwy_yellow_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
- rwy_yellow_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
- rwy_yellow_lights->setTexture( tex_name );
- matlib["RWY_YELLOW_LIGHTS"] = new FGNewMat(rwy_yellow_lights);
-
- // hard coded runway medium intensity yellow light state
- tex_name = gen_standard_dir_light_map( 235, 215, 20, 205 );
- ssgSimpleState *rwy_yellow_medium_lights = new ssgSimpleState();
- rwy_yellow_medium_lights->ref();
- rwy_yellow_medium_lights->disable( GL_LIGHTING );
- rwy_yellow_medium_lights->enable ( GL_CULL_FACE ) ;
- rwy_yellow_medium_lights->enable( GL_TEXTURE_2D );
- rwy_yellow_medium_lights->enable( GL_BLEND );
- rwy_yellow_medium_lights->enable( GL_ALPHA_TEST );
- rwy_yellow_medium_lights->enable( GL_COLOR_MATERIAL );
- rwy_yellow_medium_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
- rwy_yellow_medium_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
- rwy_yellow_medium_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
- rwy_yellow_medium_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
- rwy_yellow_medium_lights->setTexture( tex_name );
- matlib["RWY_YELLOW_MEDIUM_LIGHTS"] = new FGNewMat(rwy_yellow_medium_lights);
-
- // hard coded runway low intensity yellow light state
- tex_name = gen_standard_dir_light_map( 235, 215, 20, 155 );
- ssgSimpleState *rwy_yellow_low_lights = new ssgSimpleState();
- rwy_yellow_low_lights->ref();
- rwy_yellow_low_lights->disable( GL_LIGHTING );
- rwy_yellow_low_lights->enable ( GL_CULL_FACE ) ;
- rwy_yellow_low_lights->enable( GL_TEXTURE_2D );
- rwy_yellow_low_lights->enable( GL_BLEND );
- rwy_yellow_low_lights->enable( GL_ALPHA_TEST );
- rwy_yellow_low_lights->enable( GL_COLOR_MATERIAL );
- rwy_yellow_low_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
- rwy_yellow_low_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
- rwy_yellow_low_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
- rwy_yellow_low_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
- rwy_yellow_low_lights->setTexture( tex_name );
- matlib["RWY_YELLOW_LOW_LIGHTS"] = new FGNewMat(rwy_yellow_low_lights);
-
- // hard coded runway red light state
- tex_name = gen_standard_dir_light_map( 235, 90, 90, 255 );
- ssgSimpleState *rwy_red_lights = new ssgSimpleState();
- rwy_red_lights->ref();
- rwy_red_lights->disable( GL_LIGHTING );
- rwy_red_lights->enable ( GL_CULL_FACE ) ;
- rwy_red_lights->enable( GL_TEXTURE_2D );
- rwy_red_lights->enable( GL_BLEND );
- rwy_red_lights->enable( GL_ALPHA_TEST );
- rwy_red_lights->enable( GL_COLOR_MATERIAL );
- rwy_red_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
- rwy_red_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
- rwy_red_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
- rwy_red_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
- rwy_red_lights->setTexture( tex_name );
- matlib["RWY_RED_LIGHTS"] = new FGNewMat(rwy_red_lights);
-
- // hard coded medium intensity runway red light state
- tex_name = gen_standard_dir_light_map( 235, 90, 90, 205 );
- ssgSimpleState *rwy_red_medium_lights = new ssgSimpleState();
- rwy_red_medium_lights->ref();
- rwy_red_medium_lights->disable( GL_LIGHTING );
- rwy_red_medium_lights->enable ( GL_CULL_FACE ) ;
- rwy_red_medium_lights->enable( GL_TEXTURE_2D );
- rwy_red_medium_lights->enable( GL_BLEND );
- rwy_red_medium_lights->enable( GL_ALPHA_TEST );
- rwy_red_medium_lights->enable( GL_COLOR_MATERIAL );
- rwy_red_medium_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
- rwy_red_medium_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
- rwy_red_medium_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
- rwy_red_medium_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
- rwy_red_medium_lights->setTexture( tex_name );
- matlib["RWY_RED_MEDIUM_LIGHTS"] = new FGNewMat(rwy_red_medium_lights);
-
- // hard coded low intensity runway red light state
- tex_name = gen_standard_dir_light_map( 235, 90, 90, 205 );
- ssgSimpleState *rwy_red_low_lights = new ssgSimpleState();
- rwy_red_low_lights->ref();
- rwy_red_low_lights->disable( GL_LIGHTING );
- rwy_red_low_lights->enable ( GL_CULL_FACE ) ;
- rwy_red_low_lights->enable( GL_TEXTURE_2D );
- rwy_red_low_lights->enable( GL_BLEND );
- rwy_red_low_lights->enable( GL_ALPHA_TEST );
- rwy_red_low_lights->enable( GL_COLOR_MATERIAL );
- rwy_red_low_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
- rwy_red_low_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
- rwy_red_low_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
- rwy_red_low_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
- rwy_red_low_lights->setTexture( tex_name );
- matlib["RWY_RED_LOW_LIGHTS"] = new FGNewMat(rwy_red_low_lights);
-
- // hard coded runway green light state
- tex_name = gen_standard_dir_light_map( 20, 235, 20, 255 );
- ssgSimpleState *rwy_green_lights = new ssgSimpleState();
- rwy_green_lights->ref();
- rwy_green_lights->disable( GL_LIGHTING );
- rwy_green_lights->enable ( GL_CULL_FACE ) ;
- rwy_green_lights->enable( GL_TEXTURE_2D );
- rwy_green_lights->enable( GL_BLEND );
- rwy_green_lights->enable( GL_ALPHA_TEST );
- rwy_green_lights->enable( GL_COLOR_MATERIAL );
- rwy_green_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
- rwy_green_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
- rwy_green_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
- rwy_green_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
- rwy_green_lights->setTexture( tex_name );
- matlib["RWY_GREEN_LIGHTS"] = new FGNewMat(rwy_green_lights);
-
- // hard coded medium intensity runway green light state
- tex_name = gen_standard_dir_light_map( 20, 235, 20, 205 );
- ssgSimpleState *rwy_green_medium_lights = new ssgSimpleState();
- rwy_green_medium_lights->ref();
- rwy_green_medium_lights->disable( GL_LIGHTING );
- rwy_green_medium_lights->enable ( GL_CULL_FACE ) ;
- rwy_green_medium_lights->enable( GL_TEXTURE_2D );
- rwy_green_medium_lights->enable( GL_BLEND );
- rwy_green_medium_lights->enable( GL_ALPHA_TEST );
- rwy_green_medium_lights->enable( GL_COLOR_MATERIAL );
- rwy_green_medium_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
- rwy_green_medium_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
- rwy_green_medium_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
- rwy_green_medium_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
- rwy_green_medium_lights->setTexture( tex_name );
- matlib["RWY_GREEN_MEDIUM_LIGHTS"] = new FGNewMat(rwy_green_medium_lights);
-
- // hard coded low intensity runway green light state
- tex_name = gen_standard_dir_light_map( 20, 235, 20, 205 );
- ssgSimpleState *rwy_green_low_lights = new ssgSimpleState();
- rwy_green_low_lights->ref();
- rwy_green_low_lights->disable( GL_LIGHTING );
- rwy_green_low_lights->enable ( GL_CULL_FACE ) ;
- rwy_green_low_lights->enable( GL_TEXTURE_2D );
- rwy_green_low_lights->enable( GL_BLEND );
- rwy_green_low_lights->enable( GL_ALPHA_TEST );
- rwy_green_low_lights->enable( GL_COLOR_MATERIAL );
- rwy_green_low_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
- rwy_green_low_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
- rwy_green_low_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
- rwy_green_low_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
- rwy_green_low_lights->setTexture( tex_name );
- matlib["RWY_GREEN_LOW_LIGHTS"] = new FGNewMat(rwy_green_low_lights);
-
- // hard coded low intensity taxiway blue light state
- tex_name = gen_taxiway_dir_light_map( 90, 90, 235, 205 );
- ssgSimpleState *taxiway_blue_low_lights = new ssgSimpleState();
- taxiway_blue_low_lights->ref();
- taxiway_blue_low_lights->disable( GL_LIGHTING );
- taxiway_blue_low_lights->enable ( GL_CULL_FACE ) ;
- taxiway_blue_low_lights->enable( GL_TEXTURE_2D );
- taxiway_blue_low_lights->enable( GL_BLEND );
- taxiway_blue_low_lights->enable( GL_ALPHA_TEST );
- taxiway_blue_low_lights->enable( GL_COLOR_MATERIAL );
- taxiway_blue_low_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
- taxiway_blue_low_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
- taxiway_blue_low_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
- taxiway_blue_low_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
- taxiway_blue_low_lights->setTexture( tex_name );
- matlib["RWY_BLUE_TAXIWAY_LIGHTS"]
- = new FGNewMat(taxiway_blue_low_lights);
-
- // hard coded runway vasi light state
- ssgSimpleState *rwy_vasi_lights = new ssgSimpleState();
- rwy_vasi_lights->ref();
- rwy_vasi_lights->disable( GL_LIGHTING );
- rwy_vasi_lights->enable ( GL_CULL_FACE ) ;
- rwy_vasi_lights->enable( GL_TEXTURE_2D );
- rwy_vasi_lights->enable( GL_BLEND );
- rwy_vasi_lights->enable( GL_ALPHA_TEST );
- rwy_vasi_lights->enable( GL_COLOR_MATERIAL );
- rwy_vasi_lights->setMaterial ( GL_AMBIENT, 1.0, 1.0, 1.0, 1.0 );
- rwy_vasi_lights->setMaterial ( GL_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
- rwy_vasi_lights->setMaterial ( GL_SPECULAR, 0.0, 0.0, 0.0, 0.0 );
- rwy_vasi_lights->setMaterial ( GL_EMISSION, 0.0, 0.0, 0.0, 0.0 );
- rwy_vasi_lights->setTexture( gen_vasi_light_map() );
- matlib["RWY_VASI_LIGHTS"] = new FGNewMat(rwy_vasi_lights);
-
- return true;
-}
-
-
-// Load a library of material properties
-bool FGMaterialLib::add_item ( const string &tex_path )
-{
- string material_name = tex_path;
- int pos = tex_path.rfind( "/" );
- material_name = material_name.substr( pos + 1 );
-
- return add_item( material_name, tex_path );
-}
-
-
-// Load a library of material properties
-bool FGMaterialLib::add_item ( const string &mat_name, const string &full_path )
-{
- int pos = full_path.rfind( "/" );
- string tex_name = full_path.substr( pos + 1 );
- string tex_path = full_path.substr( 0, pos );
-
- SG_LOG( SG_TERRAIN, SG_INFO, " Loading material "
- << mat_name << " (" << full_path << ")");
-
- material_lib.matlib[mat_name] = new FGNewMat(full_path);
-
- return true;
-}
-
-
-// Load a library of material properties
-bool FGMaterialLib::add_item ( const string &mat_name, ssgSimpleState *state )
-{
- FGNewMat *m = new FGNewMat(state);
-
- SG_LOG( SG_TERRAIN, SG_INFO, " Loading material given a premade "
- << "ssgSimpleState = " << mat_name );
-
- material_lib.matlib[mat_name] = m;
-
- return true;
-}
-
-
-// find a material record by material name
-FGNewMat *FGMaterialLib::find( const string& material ) {
- FGNewMat *result = NULL;
- material_map_iterator it = matlib.find( material );
- if ( it != end() ) {
- result = it->second;
- return result;
- }
-
- return NULL;
-}
-
-
-// Destructor
-FGMaterialLib::~FGMaterialLib ( void ) {
- // Free up all the material entries first
- for ( material_map_iterator it = begin(); it != end(); it++ ) {
- FGNewMat *slot = it->second;
- slot->deRef();
- if ( slot->getRef() <= 0 ) {
- delete slot;
- }
- }
-}
-
-
-// Set the step for all of the state selectors in the material slots
-void FGMaterialLib::set_step ( int step )
-{
- // container::iterator it = begin();
- for ( material_map_iterator it = begin(); it != end(); it++ ) {
- const string &key = it->first;
- SG_LOG( SG_GENERAL, SG_INFO,
- "Updating material " << key << " to step " << step );
- FGNewMat *slot = it->second;
- slot->get_state()->selectStep(step);
- }
-}
-
-
-// Get the step for the state selectors
-int FGMaterialLib::get_step ()
-{
- material_map_iterator it = begin();
- return it->second->get_state()->getSelectStep();
-}
-
-
-// Load one pending "deferred" texture. Return true if a texture
-// loaded successfully, false if no pending, or error.
-void FGMaterialLib::load_next_deferred() {
- // container::iterator it = begin();
- for ( material_map_iterator it = begin(); it != end(); it++ ) {
- /* we don't need the key, but here's how we'd get it if we wanted it. */
- // const string &key = it->first;
- FGNewMat *slot = it->second;
- if (slot->load_texture())
- return;
- }
-}
+++ /dev/null
-// newmat.cxx -- class to handle material properties
-//
-// Written by Curtis Olson, started May 1998.
-//
-// Copyright (C) 1998 - 2000 Curtis L. Olson - curt@flightgear.org
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-//
-// $Id$
-
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <simgear/compiler.h>
-
-#include <map>
-SG_USING_STD(map);
-
-#include <simgear/compiler.h>
-
-#ifdef SG_MATH_EXCEPTION_CLASH
-# include <math.h>
-#endif
-
-#include <simgear/debug/logstream.hxx>
-#include <simgear/math/sg_random.h>
-#include <simgear/misc/sg_path.hxx>
-#include <simgear/misc/sgstream.hxx>
-#include <simgear/scene/model/loader.hxx>
-
-#include <Main/globals.hxx>
-#include <Main/fg_props.hxx>
-
-#include "newmat.hxx"
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Local static functions.
-////////////////////////////////////////////////////////////////////////
-
-/**
- * Internal method to test whether a file exists.
- *
- * TODO: this should be moved to a SimGear library of local file
- * functions.
- */
-static inline bool
-local_file_exists( const string& path ) {
- sg_gzifstream in( path );
- if ( ! in.is_open() ) {
- return false;
- } else {
- return true;
- }
-}
-
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Implementation of FGNewMat::Object.
-////////////////////////////////////////////////////////////////////////
-
-FGNewMat::Object::Object (const SGPropertyNode * node, double range_m)
- : _models_loaded(false),
- _coverage_m2(node->getDoubleValue("coverage-m2", 1000000)),
- _range_m(range_m)
-{
- // Sanity check
- if (_coverage_m2 < 1000) {
- SG_LOG(SG_INPUT, SG_ALERT, "Random object coverage " << _coverage_m2
- << " is too small, forcing, to 1000");
- _coverage_m2 = 1000;
- }
-
- // Note all the model paths
- vector <SGPropertyNode_ptr> path_nodes = node->getChildren("path");
- for (unsigned int i = 0; i < path_nodes.size(); i++)
- _paths.push_back(path_nodes[i]->getStringValue());
-
- // Note the heading type
- string hdg = node->getStringValue("heading-type", "fixed");
- if (hdg == "fixed") {
- _heading_type = HEADING_FIXED;
- } else if (hdg == "billboard") {
- _heading_type = HEADING_BILLBOARD;
- } else if (hdg == "random") {
- _heading_type = HEADING_RANDOM;
- } else {
- _heading_type = HEADING_FIXED;
- SG_LOG(SG_INPUT, SG_ALERT, "Unknown heading type: " << hdg
- << "; using 'fixed' instead.");
- }
-
- // uncomment to preload models
- // load_models();
-}
-
-FGNewMat::Object::~Object ()
-{
- for (unsigned int i = 0; i < _models.size(); i++) {
- if (_models[i] != 0) {
- _models[i]->deRef();
- _models[i] = 0;
- }
- }
-}
-
-int
-FGNewMat::Object::get_model_count () const
-{
- load_models();
- return _models.size();
-}
-
-inline void
-FGNewMat::Object::load_models () const
-{
- // Load model only on demand
- if (!_models_loaded) {
- for (unsigned int i = 0; i < _paths.size(); i++) {
- ssgEntity * entity
- = globals->get_model_loader()->load_model( globals->get_fg_root(),
- _paths[i],
- globals->get_props(),
- globals->get_sim_time_sec());
- if (entity != 0) {
- // FIXME: this stuff can be handled
- // in the XML wrapper as well (at least,
- // the billboarding should be handled
- // there).
- float ranges[] = {0, _range_m};
- ssgRangeSelector * lod = new ssgRangeSelector;
- lod->ref();
- lod->setRanges(ranges, 2);
- if (_heading_type == HEADING_BILLBOARD) {
- ssgCutout * cutout = new ssgCutout(false);
- cutout->addKid(entity);
- lod->addKid(cutout);
- } else {
- lod->addKid(entity);
- }
- _models.push_back(lod);
- } else {
- SG_LOG(SG_INPUT, SG_ALERT, "Failed to load object " << _paths[i]);
- }
- }
- }
- _models_loaded = true;
-}
-
-ssgEntity *
-FGNewMat::Object::get_model (int index) const
-{
- load_models(); // comment this out if preloading models
- return _models[index];
-}
-
-ssgEntity *
-FGNewMat::Object::get_random_model () const
-{
- load_models(); // comment this out if preloading models
- int nModels = _models.size();
- int index = int(sg_random() * nModels);
- if (index >= nModels)
- index = 0;
- return _models[index];
-}
-
-double
-FGNewMat::Object::get_coverage_m2 () const
-{
- return _coverage_m2;
-}
-
-FGNewMat::Object::HeadingType
-FGNewMat::Object::get_heading_type () const
-{
- return _heading_type;
-}
-
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Implementation of FGNewMat::ObjectGroup.
-////////////////////////////////////////////////////////////////////////
-
-FGNewMat::ObjectGroup::ObjectGroup (SGPropertyNode * node)
- : _range_m(node->getDoubleValue("range-m", 2000))
-{
- // Load the object subnodes
- vector<SGPropertyNode_ptr> object_nodes =
- ((SGPropertyNode *)node)->getChildren("object");
- for (unsigned int i = 0; i < object_nodes.size(); i++) {
- const SGPropertyNode * object_node = object_nodes[i];
- if (object_node->hasChild("path"))
- _objects.push_back(new Object(object_node, _range_m));
- else
- SG_LOG(SG_INPUT, SG_ALERT, "No path supplied for object");
- }
-}
-
-FGNewMat::ObjectGroup::~ObjectGroup ()
-{
- for (unsigned int i = 0; i < _objects.size(); i++) {
- delete _objects[i];
- _objects[i] = 0;
- }
-}
-
-double
-FGNewMat::ObjectGroup::get_range_m () const
-{
- return _range_m;
-}
-
-int
-FGNewMat::ObjectGroup::get_object_count () const
-{
- return _objects.size();
-}
-
-FGNewMat::Object *
-FGNewMat::ObjectGroup::get_object (int index) const
-{
- return _objects[index];
-}
-
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Constructors and destructor.
-////////////////////////////////////////////////////////////////////////
-
-
-FGNewMat::FGNewMat (const SGPropertyNode * props)
-{
- init();
- read_properties(props);
- build_ssg_state(false);
-}
-
-FGNewMat::FGNewMat (const string &texpath)
-{
- init();
- texture_path = texpath;
- build_ssg_state(true);
-}
-
-FGNewMat::FGNewMat (ssgSimpleState *s)
-{
- init();
- set_ssg_state(s);
-}
-
-FGNewMat::~FGNewMat (void)
-{
- for (unsigned int i = 0; i < object_groups.size(); i++) {
- delete object_groups[i];
- object_groups[i] = 0;
- }
-}
-
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Public methods.
-////////////////////////////////////////////////////////////////////////
-
-void
-FGNewMat::read_properties (const SGPropertyNode * props)
-{
- // Get the path to the texture
- string tname = props->getStringValue("texture", "unknown.rgb");
- SGPath tpath(globals->get_fg_root());
- tpath.append("Textures.high");
- tpath.append(tname);
- if (!local_file_exists(tpath.str())) {
- tpath = SGPath(globals->get_fg_root());
- tpath.append("Textures");
- tpath.append(tname);
- }
- texture_path = tpath.str();
-
- xsize = props->getDoubleValue("xsize", 0.0);
- ysize = props->getDoubleValue("ysize", 0.0);
- wrapu = props->getBoolValue("wrapu", true);
- wrapv = props->getBoolValue("wrapv", true);
- mipmap = props->getBoolValue("mipmap", true);
- light_coverage = props->getDoubleValue("light-coverage", 0.0);
-
- ambient[0] = props->getDoubleValue("ambient/r", 0.0);
- ambient[1] = props->getDoubleValue("ambient/g", 0.0);
- ambient[2] = props->getDoubleValue("ambient/b", 0.0);
- ambient[3] = props->getDoubleValue("ambient/a", 0.0);
-
- diffuse[0] = props->getDoubleValue("diffuse/r", 0.0);
- diffuse[1] = props->getDoubleValue("diffuse/g", 0.0);
- diffuse[2] = props->getDoubleValue("diffuse/b", 0.0);
- diffuse[3] = props->getDoubleValue("diffuse/a", 0.0);
-
- specular[0] = props->getDoubleValue("specular/r", 0.0);
- specular[1] = props->getDoubleValue("specular/g", 0.0);
- specular[2] = props->getDoubleValue("specular/b", 0.0);
- specular[3] = props->getDoubleValue("specular/a", 0.0);
-
- emission[0] = props->getDoubleValue("emissive/r", 0.0);
- emission[1] = props->getDoubleValue("emissive/g", 0.0);
- emission[2] = props->getDoubleValue("emissive/b", 0.0);
- emission[3] = props->getDoubleValue("emissive/a", 0.0);
-
- shininess = props->getDoubleValue("shininess", 0.0);
-
- vector<SGPropertyNode_ptr> object_group_nodes =
- ((SGPropertyNode *)props)->getChildren("object-group");
- for (unsigned int i = 0; i < object_group_nodes.size(); i++)
- object_groups.push_back(new ObjectGroup(object_group_nodes[i]));
-}
-
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Private methods.
-////////////////////////////////////////////////////////////////////////
-
-void
-FGNewMat::init ()
-{
- texture_path = "";
- state = 0;
- textured = 0;
- nontextured = 0;
- xsize = 0;
- ysize = 0;
- wrapu = true;
- wrapv = true;
- mipmap = true;
- light_coverage = 0.0;
- texture_loaded = false;
- refcount = 0;
- shininess = 0.0;
- for (int i = 0; i < 4; i++) {
- ambient[i] = diffuse[i] = specular[i] = emission[i] = 0.0;
- }
-}
-
-bool
-FGNewMat::load_texture ()
-{
- if (texture_loaded) {
- return false;
- } else {
- SG_LOG( SG_GENERAL, SG_INFO, "Loading deferred texture "
- << texture_path );
- textured->setTexture( (char *)texture_path.c_str(),
- wrapu, wrapv, mipmap );
- texture_loaded = true;
- return true;
- }
-}
-
-
-void
-FGNewMat::build_ssg_state (bool defer_tex_load)
-{
- GLenum shade_model =
- (fgGetBool("/sim/rendering/shading") ? GL_SMOOTH : GL_FLAT);
- bool texture_default = fgGetBool("/sim/rendering/textures");
-
- state = new ssgStateSelector(2);
- state->ref();
-
- textured = new ssgSimpleState();
- textured->ref();
-
- nontextured = new ssgSimpleState();
- nontextured->ref();
-
- // Set up the textured state
- textured->setShadeModel( shade_model );
- textured->enable( GL_LIGHTING );
- textured->enable ( GL_CULL_FACE ) ;
- textured->enable( GL_TEXTURE_2D );
- textured->disable( GL_BLEND );
- textured->disable( GL_ALPHA_TEST );
- if ( !defer_tex_load ) {
- SG_LOG(SG_INPUT, SG_INFO, " " << texture_path );
- textured->setTexture( (char *)texture_path.c_str(), wrapu, wrapv );
- texture_loaded = true;
- } else {
- texture_loaded = false;
- }
- textured->enable( GL_COLOR_MATERIAL );
-#if 0
- textured->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
- textured->setMaterial( GL_EMISSION, 0, 0, 0, 1 );
- textured->setMaterial( GL_SPECULAR, 0, 0, 0, 1 );
-#else
- textured->setMaterial ( GL_AMBIENT,
- ambient[0], ambient[1],
- ambient[2], ambient[3] ) ;
- textured->setMaterial ( GL_DIFFUSE,
- diffuse[0], diffuse[1],
- diffuse[2], diffuse[3] ) ;
- textured->setMaterial ( GL_SPECULAR,
- specular[0], specular[1],
- specular[2], specular[3] ) ;
- textured->setMaterial ( GL_EMISSION,
- emission[0], emission[1],
- emission[2], emission[3] ) ;
- textured->setShininess ( shininess );
-#endif
-
- // Set up the coloured state
- nontextured->enable( GL_LIGHTING );
- nontextured->setShadeModel( shade_model );
- nontextured->enable ( GL_CULL_FACE ) ;
- nontextured->disable( GL_TEXTURE_2D );
- nontextured->disable( GL_BLEND );
- nontextured->disable( GL_ALPHA_TEST );
- nontextured->disable( GL_COLOR_MATERIAL );
-
- nontextured->setMaterial ( GL_AMBIENT,
- ambient[0], ambient[1],
- ambient[2], ambient[3] ) ;
- nontextured->setMaterial ( GL_DIFFUSE,
- diffuse[0], diffuse[1],
- diffuse[2], diffuse[3] ) ;
- nontextured->setMaterial ( GL_SPECULAR,
- specular[0], specular[1],
- specular[2], specular[3] ) ;
- nontextured->setMaterial ( GL_EMISSION,
- emission[0], emission[1],
- emission[2], emission[3] ) ;
- nontextured->setShininess ( shininess );
-
- state->setStep( 0, textured ); // textured
- state->setStep( 1, nontextured ); // untextured
-
- // Choose the appropriate starting state.
- if ( texture_default ) {
- state->selectStep(0);
- } else {
- state->selectStep(1);
- }
-}
-
-
-void FGNewMat::set_ssg_state( ssgSimpleState *s )
-{
- GLenum shade_model =
- (fgGetBool("/sim/rendering/shading") ? GL_SMOOTH : GL_FLAT);
- bool texture_default = fgGetBool("/sim/rendering/textures");
-
- state = new ssgStateSelector(2);
- state->ref();
-
- textured = s;
- texture_loaded = true;
-
- nontextured = new ssgSimpleState();
- nontextured->ref();
-
- // Set up the textured state
- textured->setShadeModel( shade_model );
-
- // Set up the coloured state
- nontextured->enable( GL_LIGHTING );
- nontextured->setShadeModel( shade_model );
- nontextured->enable ( GL_CULL_FACE ) ;
- nontextured->disable( GL_TEXTURE_2D );
- nontextured->disable( GL_BLEND );
- nontextured->disable( GL_ALPHA_TEST );
- nontextured->disable( GL_COLOR_MATERIAL );
-
- nontextured->setMaterial ( GL_AMBIENT,
- ambient[0], ambient[1],
- ambient[2], ambient[3] ) ;
- nontextured->setMaterial ( GL_DIFFUSE,
- diffuse[0], diffuse[1],
- diffuse[2], diffuse[3] ) ;
- nontextured->setMaterial ( GL_SPECULAR,
- specular[0], specular[1],
- specular[2], specular[3] ) ;
- nontextured->setMaterial ( GL_EMISSION,
- emission[0], emission[1],
- emission[2], emission[3] ) ;
- nontextured->setShininess ( shininess );
-
- state->setStep( 0, textured ); // textured
- state->setStep( 1, nontextured ); // untextured
-
- // Choose the appropriate starting state.
- if ( texture_default ) {
- state->selectStep(0);
- } else {
- state->selectStep(1);
- }
-}
-
-// end of newmat.cxx
+++ /dev/null
-// newmat.hxx -- a material in the scene graph.
-// TODO: this class needs to be renamed.
-//
-// Written by Curtis Olson, started May 1998.
-// Overhauled by David Megginson, December 2001
-//
-// Copyright (C) 1998 - 2000 Curtis L. Olson - curt@flightgear.org
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-//
-// $Id$
-
-
-#ifndef _NEWMAT_HXX
-#define _NEWMAT_HXX
-
-#ifndef __cplusplus
-# error This library requires C++
-#endif
-
-#include <simgear/compiler.h>
-
-#include STL_STRING // Standard C++ string library
-
-#include <plib/sg.h>
-#include <plib/ssg.h>
-
-#include <simgear/props/props.hxx>
-
-SG_USING_STD(string);
-
-
-/**
- * A material in the scene graph.
- *
- * A material represents information about a single surface type
- * in the 3D scene graph, including texture, colour, lighting,
- * tiling, and so on; most of the materials in FlightGear are
- * defined in the $FG_ROOT/materials.xml file, and can be changed
- * at runtime.
- */
-class FGNewMat {
-
-public:
-
-\f
- //////////////////////////////////////////////////////////////////////
- // Inner classes.
- //////////////////////////////////////////////////////////////////////
-
- class ObjectGroup;
-
- /**
- * A randomly-placeable object.
- *
- * FGNewMat uses this class to keep track of the model(s) and
- * parameters for a single instance of a randomly-placeable object.
- * The object can have more than one variant model (i.e. slightly
- * different shapes of trees), but they are considered equivalent
- * and interchangeable.
- */
- class Object
- {
- public:
-
- /**
- * The heading type for a randomly-placed object.
- */
- enum HeadingType {
- HEADING_FIXED,
- HEADING_BILLBOARD,
- HEADING_RANDOM
- };
-
-
- /**
- * Get the number of variant models available for the object.
- *
- * @return The number of variant models.
- */
- int get_model_count () const;
-
-
- /**
- * Get a specific variant model for the object.
- *
- * @param index The index of the model.
- * @return The model.
- */
- ssgEntity * get_model (int index) const;
-
-
- /**
- * Get a randomly-selected variant model for the object.
- *
- * @return A randomly select model from the variants.
- */
- ssgEntity * get_random_model () const;
-
-
- /**
- * Get the average number of meters^2 occupied by each instance.
- *
- * @return The coverage in meters^2.
- */
- double get_coverage_m2 () const;
-
-
- /**
- * Get the heading type for the object.
- *
- * @return The heading type.
- */
- HeadingType get_heading_type () const;
-
- protected:
-
- friend class ObjectGroup;
-
- Object (const SGPropertyNode * node, double range_m);
-
- virtual ~Object ();
-
- private:
-
- /**
- * Actually load the models.
- *
- * This class uses lazy loading so that models won't be held
- * in memory for materials that are never referenced.
- */
- void load_models () const;
-
- vector<string> _paths;
- mutable vector<ssgEntity *> _models;
- mutable bool _models_loaded;
- double _coverage_m2;
- double _range_m;
- HeadingType _heading_type;
- };
-
-
- /**
- * A collection of related objects with the same visual range.
- *
- * Grouping objects with the same range together significantly
- * reduces the memory requirements of randomly-placed objects.
- * Each FGNewMat instance keeps a (possibly-empty) list of
- * object groups for placing randomly on the scenery.
- */
- class ObjectGroup
- {
- public:
- virtual ~ObjectGroup ();
-
-
- /**
- * Get the visual range of the object in meters.
- *
- * @return The visual range.
- */
- double get_range_m () const;
-
-
- /**
- * Get the number of objects in the group.
- *
- * @return The number of objects.
- */
- int get_object_count () const;
-
-
- /**
- * Get a specific object.
- *
- * @param index The object's index, zero-based.
- * @return The object selected.
- */
- Object * get_object (int index) const;
-
- protected:
-
- friend class FGNewMat;
-
- ObjectGroup (SGPropertyNode * node);
-
- private:
-
- double _range_m;
- vector<Object *> _objects;
-
- };
-
-
-
-\f
- ////////////////////////////////////////////////////////////////////
- // Public Constructors.
- ////////////////////////////////////////////////////////////////////
-
- /**
- * Construct a material from a set of properties.
- *
- * @param props A property node containing subnodes with the
- * state information for the material. This node is usually
- * loaded from the $FG_ROOT/materials.xml file.
- */
- FGNewMat (const SGPropertyNode * props);
-
-
- /**
- * Construct a material from an absolute texture path.
- *
- * @param texture_path A string containing an absolute path
- * to a texture file (usually RGB).
- */
- FGNewMat (const string &texpath);
-
-
- /**
- * Construct a material around an existing SSG state.
- *
- * This constructor allows the application to create a custom,
- * low-level state for the scene graph and wrap a material around
- * it. Note: the pointer ownership is transferred to the material.
- *
- * @param s The SSG state for this material.
- */
- FGNewMat (ssgSimpleState * s);
-
- /**
- * Destructor.
- */
- virtual ~FGNewMat ( void );
-
-
-\f
- ////////////////////////////////////////////////////////////////////
- // Public methods.
- ////////////////////////////////////////////////////////////////////
-
- /**
- * Force the texture to load if it hasn't already.
- *
- * @return true if the texture loaded, false if it was loaded
- * already.
- */
- virtual bool load_texture ();
-
-
- /**
- * Get the textured state.
- */
- virtual inline ssgSimpleState *get_textured () { return textured; }
-
-
- /**
- * Get the xsize of the texture, in meters.
- */
- virtual inline double get_xsize() const { return xsize; }
-
-
- /**
- * Get the ysize of the texture, in meters.
- */
- virtual inline double get_ysize() const { return ysize; }
-
-
- /**
- * Get the light coverage.
- *
- * A smaller number means more generated night lighting.
- *
- * @return The area (m^2?) covered by each light.
- */
- virtual inline double get_light_coverage () const { return light_coverage; }
-
-
- /**
- * Get the number of randomly-placed objects defined for this material.
- */
- virtual int get_object_group_count () const { return object_groups.size(); }
-
-
- /**
- * Get a randomly-placed object for this material.
- */
- virtual ObjectGroup * get_object_group (int index) const {
- return object_groups[index];
- }
-
-
- /**
- * Get the current state.
- */
- virtual inline ssgStateSelector *get_state () const { return state; }
-
-
- /**
- * Increment the reference count for this material.
- *
- * A material with 0 references may be deleted by the
- * material library.
- */
- virtual inline void ref () { refcount++; }
-
-
- /**
- * Decrement the reference count for this material.
- */
- virtual inline void deRef () { refcount--; }
-
-
- /**
- * Get the reference count for this material.
- *
- * @return The number of references (0 if none).
- */
- virtual inline int getRef () const { return refcount; }
-
-protected:
-
-\f
- ////////////////////////////////////////////////////////////////////
- // Protected methods.
- ////////////////////////////////////////////////////////////////////
-
- /**
- * Initialization method, invoked by all public constructors.
- */
- virtual void init();
-
-
-private:
-
-\f
- ////////////////////////////////////////////////////////////////////
- // Internal state.
- ////////////////////////////////////////////////////////////////////
-
- // names
- string texture_path;
-
- // pointers to ssg states
- ssgStateSelector *state;
- ssgSimpleState *textured;
- ssgSimpleState *nontextured;
-
- // texture size
- double xsize, ysize;
-
- // wrap texture?
- bool wrapu, wrapv;
-
- // use mipmapping?
- int mipmap;
-
- // coverage of night lighting.
- double light_coverage;
-
- // material properties
- sgVec4 ambient, diffuse, specular, emission;
- double shininess;
-
- // true if texture loading deferred, and not yet loaded
- bool texture_loaded;
-
- vector<ObjectGroup *> object_groups;
-
- // ref count so we can properly delete if we have multiple
- // pointers to this record
- int refcount;
-
-
-\f
- ////////////////////////////////////////////////////////////////////
- // Internal constructors and methods.
- ////////////////////////////////////////////////////////////////////
-
- FGNewMat (const FGNewMat &mat); // unimplemented
-
- void read_properties (const SGPropertyNode * props);
- void build_ssg_state(bool defer_tex_load = false);
- void set_ssg_state( ssgSimpleState *s );
-
-
-};
-
-#endif // _NEWMAT_HXX