Moved some low level scene graph construction code over to simgear/scene/tgdb/
This commit is contained in:
@@ -0,0 +1,17 @@
|
|||||||
|
includedir = @includedir@/scene/tgdb
|
||||||
|
|
||||||
|
lib_LIBRARIES = libsgtgdb.a
|
||||||
|
|
||||||
|
noinst_HEADERS =
|
||||||
|
|
||||||
|
include_HEADERS = \
|
||||||
|
apt_signs.hxx \
|
||||||
|
leaf.hxx \
|
||||||
|
pt_lights.hxx
|
||||||
|
|
||||||
|
libsgtgdb_a_SOURCES = \
|
||||||
|
apt_signs.cxx \
|
||||||
|
leaf.cxx \
|
||||||
|
pt_lights.cxx
|
||||||
|
|
||||||
|
INCLUDES = -I$(top_srcdir)
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
// apt_signs.cxx -- build airport signs on the fly
|
||||||
|
//
|
||||||
|
// Written by Curtis Olson, started July 2001.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001 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$
|
||||||
|
|
||||||
|
|
||||||
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
#include <simgear/math/sg_types.hxx>
|
||||||
|
#include <simgear/scene/tgdb/leaf.hxx>
|
||||||
|
|
||||||
|
#include "apt_signs.hxx"
|
||||||
|
|
||||||
|
|
||||||
|
ssgBranch *gen_taxi_sign( SGMaterialLib *matlib,
|
||||||
|
const string path, const string content )
|
||||||
|
{
|
||||||
|
// for demo purposes we assume each element (letter) is 1x1 meter.
|
||||||
|
// Sign is placed 0.25 meters above the ground
|
||||||
|
|
||||||
|
ssgBranch *object = new ssgBranch();
|
||||||
|
object->setName( (char *)content.c_str() );
|
||||||
|
|
||||||
|
double offset = content.length() / 2.0;
|
||||||
|
|
||||||
|
for ( unsigned int i = 0; i < content.length(); ++i ) {
|
||||||
|
string material;
|
||||||
|
|
||||||
|
char item = content[i];
|
||||||
|
if ( item == '<' ) {
|
||||||
|
material = "ArrowL.rgb";
|
||||||
|
} else if ( item == '>' ) {
|
||||||
|
material = "ArrowR.rgb";
|
||||||
|
} else if ( item >= 'A' && item <= 'Z' ) {
|
||||||
|
material = "Letter";
|
||||||
|
material += item;
|
||||||
|
material += ".rgb";
|
||||||
|
} else if ( item >= 'a' && item <= 'z' ) {
|
||||||
|
int tmp = item - 'a';
|
||||||
|
char c = 'A' + tmp;
|
||||||
|
material = "Black";
|
||||||
|
material += c;
|
||||||
|
material += ".rgb";
|
||||||
|
} else {
|
||||||
|
SG_LOG( SG_TERRAIN, SG_ALERT,
|
||||||
|
"Unknown taxi sign code = '" << item << "' !!!!" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
point_list nodes; nodes.clear();
|
||||||
|
point_list normals; normals.clear();
|
||||||
|
point_list texcoords; texcoords.clear();
|
||||||
|
int_list vertex_index; vertex_index.clear();
|
||||||
|
int_list normal_index; normal_index.clear();
|
||||||
|
int_list tex_index; tex_index.clear();
|
||||||
|
|
||||||
|
nodes.push_back( Point3D( -offset + i, 0, 0.25 ) );
|
||||||
|
nodes.push_back( Point3D( -offset + i + 1, 0, 0.25 ) );
|
||||||
|
nodes.push_back( Point3D( -offset + i, 0, 1.25 ) );
|
||||||
|
nodes.push_back( Point3D( -offset + i + 1, 0, 1.25 ) );
|
||||||
|
|
||||||
|
normals.push_back( Point3D( 0, -1, 0 ) );
|
||||||
|
|
||||||
|
texcoords.push_back( Point3D( 0, 0, 0 ) );
|
||||||
|
texcoords.push_back( Point3D( 1, 0, 0 ) );
|
||||||
|
texcoords.push_back( Point3D( 0, 1, 0 ) );
|
||||||
|
texcoords.push_back( Point3D( 1, 1, 0 ) );
|
||||||
|
|
||||||
|
vertex_index.push_back( 0 );
|
||||||
|
vertex_index.push_back( 1 );
|
||||||
|
vertex_index.push_back( 2 );
|
||||||
|
vertex_index.push_back( 3 );
|
||||||
|
|
||||||
|
normal_index.push_back( 0 );
|
||||||
|
normal_index.push_back( 0 );
|
||||||
|
normal_index.push_back( 0 );
|
||||||
|
normal_index.push_back( 0 );
|
||||||
|
|
||||||
|
tex_index.push_back( 0 );
|
||||||
|
tex_index.push_back( 1 );
|
||||||
|
tex_index.push_back( 2 );
|
||||||
|
tex_index.push_back( 3 );
|
||||||
|
|
||||||
|
ssgLeaf *leaf = sgMakeLeaf( path, GL_TRIANGLE_STRIP, matlib, material,
|
||||||
|
nodes, normals, texcoords,
|
||||||
|
vertex_index, normal_index, tex_index,
|
||||||
|
false, NULL );
|
||||||
|
|
||||||
|
object->addKid( leaf );
|
||||||
|
}
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssgBranch *gen_runway_sign( SGMaterialLib *matlib,
|
||||||
|
const string path, const string name )
|
||||||
|
{
|
||||||
|
// for demo purposes we assume each element (letter) is 1x1 meter.
|
||||||
|
// Sign is placed 0.25 meters above the ground
|
||||||
|
|
||||||
|
ssgBranch *object = new ssgBranch();
|
||||||
|
object->setName( (char *)name.c_str() );
|
||||||
|
|
||||||
|
double width = name.length() / 3.0;
|
||||||
|
|
||||||
|
string material = name + ".rgb";
|
||||||
|
|
||||||
|
point_list nodes; nodes.clear();
|
||||||
|
point_list normals; normals.clear();
|
||||||
|
point_list texcoords; texcoords.clear();
|
||||||
|
int_list vertex_index; vertex_index.clear();
|
||||||
|
int_list normal_index; normal_index.clear();
|
||||||
|
int_list tex_index; tex_index.clear();
|
||||||
|
|
||||||
|
nodes.push_back( Point3D( -width, 0, 0.25 ) );
|
||||||
|
nodes.push_back( Point3D( width + 1, 0, 0.25 ) );
|
||||||
|
nodes.push_back( Point3D( -width, 0, 1.25 ) );
|
||||||
|
nodes.push_back( Point3D( width + 1, 0, 1.25 ) );
|
||||||
|
|
||||||
|
normals.push_back( Point3D( 0, -1, 0 ) );
|
||||||
|
|
||||||
|
texcoords.push_back( Point3D( 0, 0, 0 ) );
|
||||||
|
texcoords.push_back( Point3D( 1, 0, 0 ) );
|
||||||
|
texcoords.push_back( Point3D( 0, 1, 0 ) );
|
||||||
|
texcoords.push_back( Point3D( 1, 1, 0 ) );
|
||||||
|
|
||||||
|
vertex_index.push_back( 0 );
|
||||||
|
vertex_index.push_back( 1 );
|
||||||
|
vertex_index.push_back( 2 );
|
||||||
|
vertex_index.push_back( 3 );
|
||||||
|
|
||||||
|
normal_index.push_back( 0 );
|
||||||
|
normal_index.push_back( 0 );
|
||||||
|
normal_index.push_back( 0 );
|
||||||
|
normal_index.push_back( 0 );
|
||||||
|
|
||||||
|
tex_index.push_back( 0 );
|
||||||
|
tex_index.push_back( 1 );
|
||||||
|
tex_index.push_back( 2 );
|
||||||
|
tex_index.push_back( 3 );
|
||||||
|
|
||||||
|
ssgLeaf *leaf = sgMakeLeaf( path, GL_TRIANGLE_STRIP, matlib, material,
|
||||||
|
nodes, normals, texcoords,
|
||||||
|
vertex_index, normal_index, tex_index,
|
||||||
|
false, NULL );
|
||||||
|
|
||||||
|
object->addKid( leaf );
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
// apt_signs.hxx -- build airport signs on the fly
|
||||||
|
//
|
||||||
|
// Written by Curtis Olson, started July 2001.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2001 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 _APT_SIGNS_HXX
|
||||||
|
#define _APT_SIGNS_HXX
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
# error This library requires C++
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <simgear/compiler.h>
|
||||||
|
|
||||||
|
#include STL_STRING
|
||||||
|
|
||||||
|
#include <plib/ssg.h> // plib include
|
||||||
|
|
||||||
|
class SGMaterialLib; // forward declaration
|
||||||
|
|
||||||
|
SG_USING_STD(string);
|
||||||
|
|
||||||
|
|
||||||
|
// Generate a taxi sign
|
||||||
|
ssgBranch *gen_taxi_sign( SGMaterialLib *matlib,
|
||||||
|
const string path, const string content );
|
||||||
|
|
||||||
|
|
||||||
|
// Generate a runway sign
|
||||||
|
ssgBranch *gen_runway_sign( SGMaterialLib *matlib,
|
||||||
|
const string path, const string name );
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _APT_SIGNS_HXX
|
||||||
@@ -0,0 +1,259 @@
|
|||||||
|
// leaf.cxx -- function to build and ssg leaf from higher level data.
|
||||||
|
//
|
||||||
|
// Written by Curtis Olson, started October 1997.
|
||||||
|
//
|
||||||
|
// Copyright (C) 1997 - 2003 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 <simgear_config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <simgear/compiler.h>
|
||||||
|
|
||||||
|
#ifdef SG_MATH_EXCEPTION_CLASH
|
||||||
|
# include <math.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include STL_STRING
|
||||||
|
|
||||||
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
#include <simgear/math/sg_random.h>
|
||||||
|
#include <simgear/scene/material/mat.hxx>
|
||||||
|
#include <simgear/scene/material/matlib.hxx>
|
||||||
|
|
||||||
|
#include "leaf.hxx"
|
||||||
|
|
||||||
|
SG_USING_STD(string);
|
||||||
|
SG_USING_STD(vector);
|
||||||
|
|
||||||
|
|
||||||
|
typedef vector < int > int_list;
|
||||||
|
typedef int_list::iterator int_list_iterator;
|
||||||
|
typedef int_list::const_iterator int_point_list_iterator;
|
||||||
|
|
||||||
|
|
||||||
|
static void random_pt_inside_tri( float *res,
|
||||||
|
float *n1, float *n2, float *n3 )
|
||||||
|
{
|
||||||
|
double a = sg_random();
|
||||||
|
double b = sg_random();
|
||||||
|
if ( a + b > 1.0 ) {
|
||||||
|
a = 1.0 - a;
|
||||||
|
b = 1.0 - b;
|
||||||
|
}
|
||||||
|
double c = 1 - a - b;
|
||||||
|
|
||||||
|
res[0] = n1[0]*a + n2[0]*b + n3[0]*c;
|
||||||
|
res[1] = n1[1]*a + n2[1]*b + n3[1]*c;
|
||||||
|
res[2] = n1[2]*a + n2[2]*b + n3[2]*c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void gen_random_surface_points( ssgLeaf *leaf, ssgVertexArray *lights,
|
||||||
|
double factor ) {
|
||||||
|
int tris = leaf->getNumTriangles();
|
||||||
|
if ( tris > 0 ) {
|
||||||
|
short int n1, n2, n3;
|
||||||
|
float *p1, *p2, *p3;
|
||||||
|
sgVec3 result;
|
||||||
|
|
||||||
|
// generate a repeatable random seed
|
||||||
|
p1 = leaf->getVertex( 0 );
|
||||||
|
unsigned int seed = (unsigned int)(fabs(p1[0]*100));
|
||||||
|
sg_srandom( seed );
|
||||||
|
|
||||||
|
for ( int i = 0; i < tris; ++i ) {
|
||||||
|
leaf->getTriangle( i, &n1, &n2, &n3 );
|
||||||
|
p1 = leaf->getVertex(n1);
|
||||||
|
p2 = leaf->getVertex(n2);
|
||||||
|
p3 = leaf->getVertex(n3);
|
||||||
|
double area = sgTriArea( p1, p2, p3 );
|
||||||
|
double num = area / factor;
|
||||||
|
|
||||||
|
// generate a light point for each unit of area
|
||||||
|
while ( num > 1.0 ) {
|
||||||
|
random_pt_inside_tri( result, p1, p2, p3 );
|
||||||
|
lights->add( result );
|
||||||
|
num -= 1.0;
|
||||||
|
}
|
||||||
|
// for partial units of area, use a zombie door method to
|
||||||
|
// create the proper random chance of a light being created
|
||||||
|
// for this triangle
|
||||||
|
if ( num > 0.0 ) {
|
||||||
|
if ( sg_random() <= num ) {
|
||||||
|
// a zombie made it through our door
|
||||||
|
random_pt_inside_tri( result, p1, p2, p3 );
|
||||||
|
lights->add( result );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// Scenery loaders.
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ssgLeaf *sgMakeLeaf( const string& path,
|
||||||
|
const GLenum ty,
|
||||||
|
SGMaterialLib *matlib, const string& material,
|
||||||
|
const point_list& nodes, const point_list& normals,
|
||||||
|
const point_list& texcoords,
|
||||||
|
const int_list& node_index,
|
||||||
|
const int_list& normal_index,
|
||||||
|
const int_list& tex_index,
|
||||||
|
const bool calc_lights, ssgVertexArray *lights )
|
||||||
|
{
|
||||||
|
double tex_width = 1000.0, tex_height = 1000.0;
|
||||||
|
ssgSimpleState *state = NULL;
|
||||||
|
float coverage = -1;
|
||||||
|
|
||||||
|
SGMaterial *mat = matlib->find( material );
|
||||||
|
if ( mat == NULL ) {
|
||||||
|
// see if this is an on the fly texture
|
||||||
|
string file = path;
|
||||||
|
string::size_type pos = file.rfind( "/" );
|
||||||
|
file = file.substr( 0, pos );
|
||||||
|
// cout << "current file = " << file << endl;
|
||||||
|
file += "/";
|
||||||
|
file += material;
|
||||||
|
// cout << "current file = " << file << endl;
|
||||||
|
if ( ! matlib->add_item( file ) ) {
|
||||||
|
SG_LOG( SG_TERRAIN, SG_ALERT,
|
||||||
|
"Ack! unknown usemtl name = " << material
|
||||||
|
<< " in " << path );
|
||||||
|
} else {
|
||||||
|
// locate our newly created material
|
||||||
|
mat = matlib->find( material );
|
||||||
|
if ( mat == NULL ) {
|
||||||
|
SG_LOG( SG_TERRAIN, SG_ALERT,
|
||||||
|
"Ack! bad on the fly material create = "
|
||||||
|
<< material << " in " << path );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( mat != NULL ) {
|
||||||
|
// set the texture width and height values for this
|
||||||
|
// material
|
||||||
|
tex_width = mat->get_xsize();
|
||||||
|
tex_height = mat->get_ysize();
|
||||||
|
state = mat->get_state();
|
||||||
|
coverage = mat->get_light_coverage();
|
||||||
|
// cout << "(w) = " << tex_width << " (h) = "
|
||||||
|
// << tex_width << endl;
|
||||||
|
} else {
|
||||||
|
coverage = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sgVec2 tmp2;
|
||||||
|
sgVec3 tmp3;
|
||||||
|
sgVec4 tmp4;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// vertices
|
||||||
|
int size = node_index.size();
|
||||||
|
if ( size < 1 ) {
|
||||||
|
SG_LOG( SG_TERRAIN, SG_ALERT, "Woh! node list size < 1" );
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
ssgVertexArray *vl = new ssgVertexArray( size );
|
||||||
|
Point3D node;
|
||||||
|
for ( i = 0; i < size; ++i ) {
|
||||||
|
node = nodes[ node_index[i] ];
|
||||||
|
sgSetVec3( tmp3, node[0], node[1], node[2] );
|
||||||
|
vl -> add( tmp3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// normals
|
||||||
|
Point3D normal;
|
||||||
|
ssgNormalArray *nl = new ssgNormalArray( size );
|
||||||
|
if ( normal_index.size() ) {
|
||||||
|
// object file specifies normal indices (i.e. normal indices
|
||||||
|
// aren't 'implied'
|
||||||
|
for ( i = 0; i < size; ++i ) {
|
||||||
|
normal = normals[ normal_index[i] ];
|
||||||
|
sgSetVec3( tmp3, normal[0], normal[1], normal[2] );
|
||||||
|
nl -> add( tmp3 );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// use implied normal indices. normal index = vertex index.
|
||||||
|
for ( i = 0; i < size; ++i ) {
|
||||||
|
normal = normals[ node_index[i] ];
|
||||||
|
sgSetVec3( tmp3, normal[0], normal[1], normal[2] );
|
||||||
|
nl -> add( tmp3 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// colors
|
||||||
|
ssgColourArray *cl = new ssgColourArray( 1 );
|
||||||
|
sgSetVec4( tmp4, 1.0, 1.0, 1.0, 1.0 );
|
||||||
|
cl->add( tmp4 );
|
||||||
|
|
||||||
|
// texture coordinates
|
||||||
|
size = tex_index.size();
|
||||||
|
Point3D texcoord;
|
||||||
|
ssgTexCoordArray *tl = new ssgTexCoordArray( size );
|
||||||
|
if ( size == 1 ) {
|
||||||
|
texcoord = texcoords[ tex_index[0] ];
|
||||||
|
sgSetVec2( tmp2, texcoord[0], texcoord[1] );
|
||||||
|
sgSetVec2( tmp2, texcoord[0], texcoord[1] );
|
||||||
|
if ( tex_width > 0 ) {
|
||||||
|
tmp2[0] *= (1000.0 / tex_width);
|
||||||
|
}
|
||||||
|
if ( tex_height > 0 ) {
|
||||||
|
tmp2[1] *= (1000.0 / tex_height);
|
||||||
|
}
|
||||||
|
tl -> add( tmp2 );
|
||||||
|
} else if ( size > 1 ) {
|
||||||
|
for ( i = 0; i < size; ++i ) {
|
||||||
|
texcoord = texcoords[ tex_index[i] ];
|
||||||
|
sgSetVec2( tmp2, texcoord[0], texcoord[1] );
|
||||||
|
if ( tex_width > 0 ) {
|
||||||
|
tmp2[0] *= (1000.0 / tex_width);
|
||||||
|
}
|
||||||
|
if ( tex_height > 0 ) {
|
||||||
|
tmp2[1] *= (1000.0 / tex_height);
|
||||||
|
}
|
||||||
|
tl -> add( tmp2 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ssgLeaf *leaf = new ssgVtxTable ( ty, vl, nl, tl, cl );
|
||||||
|
|
||||||
|
// lookup the state record
|
||||||
|
|
||||||
|
leaf->setState( state );
|
||||||
|
|
||||||
|
if ( calc_lights ) {
|
||||||
|
if ( coverage > 0.0 ) {
|
||||||
|
if ( coverage < 10000.0 ) {
|
||||||
|
SG_LOG(SG_INPUT, SG_ALERT, "Light coverage is "
|
||||||
|
<< coverage << ", pushing up to 10000");
|
||||||
|
coverage = 10000;
|
||||||
|
}
|
||||||
|
gen_random_surface_points(leaf, lights, coverage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return leaf;
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
// leaf.hxx -- function to build and ssg leaf from higher level data.
|
||||||
|
//
|
||||||
|
// Written by Curtis Olson, started October 1997.
|
||||||
|
//
|
||||||
|
// Copyright (C) 1997 - 2003 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 _SG_LEAF_HXX
|
||||||
|
#define _SG_LEAF_HXX
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
# error This library requires C++
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <simgear/compiler.h>
|
||||||
|
|
||||||
|
#include STL_STRING
|
||||||
|
|
||||||
|
#include <plib/ssg.h> // plib include
|
||||||
|
|
||||||
|
#include <simgear/math/sg_types.hxx>
|
||||||
|
|
||||||
|
SG_USING_STD(string);
|
||||||
|
|
||||||
|
|
||||||
|
class SGMaterialLib; // forward declaration.
|
||||||
|
|
||||||
|
|
||||||
|
// Create a ssg leaf
|
||||||
|
ssgLeaf *sgMakeLeaf( const string& path,
|
||||||
|
const GLenum ty,
|
||||||
|
SGMaterialLib *matlib, const string& material,
|
||||||
|
const point_list& nodes, const point_list& normals,
|
||||||
|
const point_list& texcoords,
|
||||||
|
const int_list& node_index,
|
||||||
|
const int_list& normal_index,
|
||||||
|
const int_list& tex_index,
|
||||||
|
const bool calc_lights, ssgVertexArray *lights );
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _SG_LEAF_HXX
|
||||||
@@ -0,0 +1,619 @@
|
|||||||
|
// pt_lights.cxx -- build a 'directional' light on the fly
|
||||||
|
//
|
||||||
|
// Written by Curtis Olson, started March 2002.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2002 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$
|
||||||
|
|
||||||
|
|
||||||
|
#include <plib/sg.h>
|
||||||
|
|
||||||
|
#include <simgear/scene/material/mat.hxx>
|
||||||
|
#include <simgear/scene/material/matlib.hxx>
|
||||||
|
|
||||||
|
#include "pt_lights.hxx"
|
||||||
|
|
||||||
|
|
||||||
|
// strobe pre-draw (we want a larger point size)
|
||||||
|
static int StrobePreDraw( ssgEntity *e ) {
|
||||||
|
glPushAttrib( GL_POINT_BIT );
|
||||||
|
glPointSize(4.0);
|
||||||
|
glEnable(GL_POINT_SMOOTH);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// strobe post-draw (we want a larger point size)
|
||||||
|
static int StrobePostDraw( ssgEntity *e ) {
|
||||||
|
glPopAttrib();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Generate a directional light
|
||||||
|
ssgLeaf *gen_directional_light( sgVec3 pt, sgVec3 dir, sgVec3 up,
|
||||||
|
const SGMaterial *mat ) {
|
||||||
|
|
||||||
|
// calculate a vector perpendicular to dir and up
|
||||||
|
sgVec3 perp;
|
||||||
|
sgVectorProductVec3( perp, dir, up );
|
||||||
|
|
||||||
|
ssgVertexArray *vl = new ssgVertexArray( 3 );
|
||||||
|
ssgNormalArray *nl = new ssgNormalArray( 3 );
|
||||||
|
ssgColourArray *cl = new ssgColourArray( 3 );
|
||||||
|
|
||||||
|
// front face
|
||||||
|
sgVec3 tmp3;
|
||||||
|
sgCopyVec3( tmp3, pt );
|
||||||
|
vl->add( tmp3 );
|
||||||
|
sgAddVec3( tmp3, up );
|
||||||
|
vl->add( tmp3 );
|
||||||
|
sgAddVec3( tmp3, perp );
|
||||||
|
vl->add( tmp3 );
|
||||||
|
// sgSubVec3( tmp3, up );
|
||||||
|
// vl->add( tmp3 );
|
||||||
|
|
||||||
|
nl->add( dir );
|
||||||
|
nl->add( dir );
|
||||||
|
nl->add( dir );
|
||||||
|
// nl->add( dir );
|
||||||
|
|
||||||
|
sgVec4 color;
|
||||||
|
sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 );
|
||||||
|
cl->add( color );
|
||||||
|
sgSetVec4( color, 1.0, 1.0, 1.0, 0.0 );
|
||||||
|
cl->add( color );
|
||||||
|
cl->add( color );
|
||||||
|
// cl->add( color );
|
||||||
|
|
||||||
|
/*
|
||||||
|
// temporarily do back face
|
||||||
|
sgCopyVec3( tmp3, pt );
|
||||||
|
vl->add( tmp3 );
|
||||||
|
sgAddVec3( tmp3, up );
|
||||||
|
vl->add( tmp3 );
|
||||||
|
sgAddVec3( tmp3, perp );
|
||||||
|
vl->add( tmp3 );
|
||||||
|
|
||||||
|
sgNegateVec3( dir );
|
||||||
|
nl->add( dir );
|
||||||
|
nl->add( dir );
|
||||||
|
nl->add( dir );
|
||||||
|
|
||||||
|
sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 );
|
||||||
|
cl->add( color );
|
||||||
|
sgSetVec4( color, 1.0, 1.0, 1.0, 0.0 );
|
||||||
|
cl->add( color );
|
||||||
|
cl->add( color );
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ssgTexCoordArray *tl = new ssgTexCoordArray( 4 );
|
||||||
|
sgVec2 tmp2;
|
||||||
|
sgSetVec2( tmp2, 0.0, 0.0 );
|
||||||
|
tl->add( tmp2 );
|
||||||
|
sgSetVec2( tmp2, 1.0, 0.0 );
|
||||||
|
tl->add( tmp2 );
|
||||||
|
sgSetVec2( tmp2, 1.0, 1.0 );
|
||||||
|
tl->add( tmp2 );
|
||||||
|
sgSetVec2( tmp2, 0.0, 1.0 );
|
||||||
|
tl->add( tmp2 ); */
|
||||||
|
|
||||||
|
ssgLeaf *leaf =
|
||||||
|
new ssgVtxTable ( GL_TRIANGLES, vl, nl, NULL, cl );
|
||||||
|
|
||||||
|
if ( mat != NULL ) {
|
||||||
|
leaf->setState( mat->get_state() );
|
||||||
|
} else {
|
||||||
|
SG_LOG( SG_TERRAIN, SG_ALERT, "Warning: mat = NULL" );
|
||||||
|
}
|
||||||
|
|
||||||
|
return leaf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void calc_center_point( const point_list &nodes,
|
||||||
|
const int_list &pnt_i,
|
||||||
|
sgVec3 result ) {
|
||||||
|
sgVec3 pt;
|
||||||
|
sgSetVec3( pt, nodes[pnt_i[0]][0], nodes[pnt_i[0]][1], nodes[pnt_i[0]][2] );
|
||||||
|
|
||||||
|
double minx = pt[0];
|
||||||
|
double maxx = pt[0];
|
||||||
|
double miny = pt[1];
|
||||||
|
double maxy = pt[1];
|
||||||
|
double minz = pt[2];
|
||||||
|
double maxz = pt[2];
|
||||||
|
|
||||||
|
for ( unsigned int i = 0; i < pnt_i.size(); ++i ) {
|
||||||
|
sgSetVec3( pt, nodes[pnt_i[i]][0], nodes[pnt_i[i]][1],
|
||||||
|
nodes[pnt_i[i]][2] );
|
||||||
|
if ( pt[0] < minx ) { minx = pt[0]; }
|
||||||
|
if ( pt[0] > maxx ) { minx = pt[0]; }
|
||||||
|
if ( pt[1] < miny ) { miny = pt[1]; }
|
||||||
|
if ( pt[1] > maxy ) { miny = pt[1]; }
|
||||||
|
if ( pt[2] < minz ) { minz = pt[2]; }
|
||||||
|
if ( pt[2] > maxz ) { minz = pt[2]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
sgSetVec3( result, (minx + maxx) / 2.0, (miny + maxy) / 2.0,
|
||||||
|
(minz + maxz) / 2.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ssgTransform *gen_dir_light_group( const point_list &nodes,
|
||||||
|
const point_list &normals,
|
||||||
|
const int_list &pnt_i,
|
||||||
|
const int_list &nml_i,
|
||||||
|
const SGMaterial *mat,
|
||||||
|
sgVec3 up, bool vertical = false )
|
||||||
|
{
|
||||||
|
sgVec3 center;
|
||||||
|
calc_center_point( nodes, pnt_i, center );
|
||||||
|
// cout << center[0] << "," << center[1] << "," << center[2] << endl;
|
||||||
|
|
||||||
|
|
||||||
|
// find a vector perpendicular to the normal.
|
||||||
|
sgVec3 perp1;
|
||||||
|
if ( !vertical ) {
|
||||||
|
// normal isn't vertical so we can use up as our first vector
|
||||||
|
sgNormalizeVec3( perp1, up );
|
||||||
|
} else {
|
||||||
|
// normal is vertical so we have to work a bit harder to
|
||||||
|
// determine our first vector
|
||||||
|
sgVec3 pt1, pt2;
|
||||||
|
sgSetVec3( pt1, nodes[pnt_i[0]][0], nodes[pnt_i[0]][1],
|
||||||
|
nodes[pnt_i[0]][2] );
|
||||||
|
sgSetVec3( pt2, nodes[pnt_i[1]][0], nodes[pnt_i[1]][1],
|
||||||
|
nodes[pnt_i[1]][2] );
|
||||||
|
|
||||||
|
sgSubVec3( perp1, pt2, pt1 );
|
||||||
|
sgNormalizeVec3( perp1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
ssgVertexArray *vl = new ssgVertexArray( 3 * pnt_i.size() );
|
||||||
|
ssgNormalArray *nl = new ssgNormalArray( 3 * pnt_i.size() );
|
||||||
|
ssgColourArray *cl = new ssgColourArray( 3 * pnt_i.size() );
|
||||||
|
|
||||||
|
unsigned int i;
|
||||||
|
sgVec3 pt, normal;
|
||||||
|
for ( i = 0; i < pnt_i.size(); ++i ) {
|
||||||
|
sgSetVec3( pt, nodes[pnt_i[i]][0], nodes[pnt_i[i]][1],
|
||||||
|
nodes[pnt_i[i]][2] );
|
||||||
|
sgSubVec3( pt, center );
|
||||||
|
sgSetVec3( normal, normals[nml_i[i]][0], normals[nml_i[i]][1],
|
||||||
|
normals[nml_i[i]][2] );
|
||||||
|
|
||||||
|
// calculate a vector perpendicular to dir and up
|
||||||
|
sgVec3 perp2;
|
||||||
|
sgVectorProductVec3( perp2, normal, perp1 );
|
||||||
|
|
||||||
|
// front face
|
||||||
|
sgVec3 tmp3;
|
||||||
|
sgCopyVec3( tmp3, pt );
|
||||||
|
vl->add( tmp3 );
|
||||||
|
sgAddVec3( tmp3, perp1 );
|
||||||
|
vl->add( tmp3 );
|
||||||
|
sgAddVec3( tmp3, perp2 );
|
||||||
|
vl->add( tmp3 );
|
||||||
|
// sgSubVec3( tmp3, perp1 );
|
||||||
|
// vl->add( tmp3 );
|
||||||
|
|
||||||
|
nl->add( normal );
|
||||||
|
nl->add( normal );
|
||||||
|
nl->add( normal );
|
||||||
|
// nl->add( normal );
|
||||||
|
|
||||||
|
sgVec4 color;
|
||||||
|
sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 );
|
||||||
|
cl->add( color );
|
||||||
|
sgSetVec4( color, 1.0, 1.0, 1.0, 0.0 );
|
||||||
|
cl->add( color );
|
||||||
|
cl->add( color );
|
||||||
|
// cl->add( color );
|
||||||
|
}
|
||||||
|
|
||||||
|
ssgLeaf *leaf =
|
||||||
|
new ssgVtxTable ( GL_TRIANGLES, vl, nl, NULL, cl );
|
||||||
|
|
||||||
|
if ( mat != NULL ) {
|
||||||
|
leaf->setState( mat->get_state() );
|
||||||
|
} else {
|
||||||
|
SG_LOG( SG_TERRAIN, SG_ALERT, "Warning: material = NULL" );
|
||||||
|
}
|
||||||
|
|
||||||
|
// put an LOD on each lighting component
|
||||||
|
ssgRangeSelector *lod = new ssgRangeSelector;
|
||||||
|
lod->setRange( 0, SG_ZERO );
|
||||||
|
lod->setRange( 1, 20000 );
|
||||||
|
lod->addKid( leaf );
|
||||||
|
|
||||||
|
// create the transformation.
|
||||||
|
sgCoord coord;
|
||||||
|
sgSetCoord( &coord, center[0], center[1], center[2], 0.0, 0.0, 0.0 );
|
||||||
|
ssgTransform *trans = new ssgTransform;
|
||||||
|
trans->setTransform( &coord );
|
||||||
|
trans->addKid( lod );
|
||||||
|
|
||||||
|
return trans;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ssgTransform *gen_reil_lights( const point_list &nodes,
|
||||||
|
const point_list &normals,
|
||||||
|
const int_list &pnt_i,
|
||||||
|
const int_list &nml_i,
|
||||||
|
SGMaterialLib *matlib,
|
||||||
|
sgVec3 up )
|
||||||
|
{
|
||||||
|
sgVec3 center;
|
||||||
|
calc_center_point( nodes, pnt_i, center );
|
||||||
|
// cout << center[0] << "," << center[1] << "," << center[2] << endl;
|
||||||
|
|
||||||
|
sgVec3 nup;
|
||||||
|
sgNormalizeVec3( nup, up );
|
||||||
|
|
||||||
|
ssgVertexArray *vl = new ssgVertexArray( 3 * pnt_i.size() );
|
||||||
|
ssgNormalArray *nl = new ssgNormalArray( 3 * pnt_i.size() );
|
||||||
|
ssgColourArray *cl = new ssgColourArray( 3 * pnt_i.size() );
|
||||||
|
|
||||||
|
unsigned int i;
|
||||||
|
sgVec3 pt, normal;
|
||||||
|
for ( i = 0; i < pnt_i.size(); ++i ) {
|
||||||
|
sgSetVec3( pt, nodes[pnt_i[i]][0], nodes[pnt_i[i]][1],
|
||||||
|
nodes[pnt_i[i]][2] );
|
||||||
|
sgSubVec3( pt, center );
|
||||||
|
sgSetVec3( normal, normals[nml_i[i]][0], normals[nml_i[i]][1],
|
||||||
|
normals[nml_i[i]][2] );
|
||||||
|
|
||||||
|
// calculate a vector perpendicular to dir and up
|
||||||
|
sgVec3 perp;
|
||||||
|
sgVectorProductVec3( perp, normal, nup );
|
||||||
|
|
||||||
|
// front face
|
||||||
|
sgVec3 tmp3;
|
||||||
|
sgCopyVec3( tmp3, pt );
|
||||||
|
vl->add( tmp3 );
|
||||||
|
sgAddVec3( tmp3, nup );
|
||||||
|
vl->add( tmp3 );
|
||||||
|
sgAddVec3( tmp3, perp );
|
||||||
|
vl->add( tmp3 );
|
||||||
|
// sgSubVec3( tmp3, nup );
|
||||||
|
// vl->add( tmp3 );
|
||||||
|
|
||||||
|
nl->add( normal );
|
||||||
|
nl->add( normal );
|
||||||
|
nl->add( normal );
|
||||||
|
// nl->add( normal );
|
||||||
|
|
||||||
|
sgVec4 color;
|
||||||
|
sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 );
|
||||||
|
cl->add( color );
|
||||||
|
sgSetVec4( color, 1.0, 1.0, 1.0, 0.0 );
|
||||||
|
cl->add( color );
|
||||||
|
cl->add( color );
|
||||||
|
// cl->add( color );
|
||||||
|
}
|
||||||
|
|
||||||
|
ssgLeaf *leaf =
|
||||||
|
new ssgVtxTable ( GL_TRIANGLES, vl, nl, NULL, cl );
|
||||||
|
|
||||||
|
SGMaterial *mat = matlib->find( "RWY_WHITE_LIGHTS" );
|
||||||
|
|
||||||
|
if ( mat != NULL ) {
|
||||||
|
leaf->setState( mat->get_state() );
|
||||||
|
} else {
|
||||||
|
SG_LOG( SG_TERRAIN, SG_ALERT,
|
||||||
|
"Warning: can't find material = RWY_WHITE_LIGHTS" );
|
||||||
|
}
|
||||||
|
|
||||||
|
leaf->setCallback( SSG_CALLBACK_PREDRAW, StrobePreDraw );
|
||||||
|
leaf->setCallback( SSG_CALLBACK_POSTDRAW, StrobePostDraw );
|
||||||
|
|
||||||
|
ssgTimedSelector *reil = new ssgTimedSelector;
|
||||||
|
|
||||||
|
// need to add this twice to work around an ssg bug
|
||||||
|
reil->addKid( leaf );
|
||||||
|
reil->addKid( leaf );
|
||||||
|
|
||||||
|
reil->setDuration( 60 );
|
||||||
|
reil->setLimits( 0, 2 );
|
||||||
|
reil->setMode( SSG_ANIM_SHUTTLE );
|
||||||
|
reil->control( SSG_ANIM_START );
|
||||||
|
|
||||||
|
// put an LOD on each lighting component
|
||||||
|
ssgRangeSelector *lod = new ssgRangeSelector;
|
||||||
|
lod->setRange( 0, SG_ZERO );
|
||||||
|
lod->setRange( 1, 12000 );
|
||||||
|
lod->addKid( reil );
|
||||||
|
|
||||||
|
// create the transformation.
|
||||||
|
sgCoord coord;
|
||||||
|
sgSetCoord( &coord, center[0], center[1], center[2], 0.0, 0.0, 0.0 );
|
||||||
|
ssgTransform *trans = new ssgTransform;
|
||||||
|
trans->setTransform( &coord );
|
||||||
|
trans->addKid( lod );
|
||||||
|
|
||||||
|
return trans;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ssgTransform *gen_odals_lights( const point_list &nodes,
|
||||||
|
const point_list &normals,
|
||||||
|
const int_list &pnt_i,
|
||||||
|
const int_list &nml_i,
|
||||||
|
SGMaterialLib *matlib,
|
||||||
|
sgVec3 up )
|
||||||
|
{
|
||||||
|
sgVec3 center;
|
||||||
|
calc_center_point( nodes, pnt_i, center );
|
||||||
|
// cout << center[0] << "," << center[1] << "," << center[2] << endl;
|
||||||
|
|
||||||
|
ssgTimedSelector *odals = new ssgTimedSelector;
|
||||||
|
|
||||||
|
sgVec4 color;
|
||||||
|
sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 );
|
||||||
|
|
||||||
|
// we don't want directional lights here
|
||||||
|
SGMaterial *mat = matlib->find( "GROUND_LIGHTS" );
|
||||||
|
if ( mat == NULL ) {
|
||||||
|
SG_LOG( SG_TERRAIN, SG_ALERT,
|
||||||
|
"Warning: can't material = GROUND_LIGHTS" );
|
||||||
|
}
|
||||||
|
|
||||||
|
// center line strobes
|
||||||
|
int i;
|
||||||
|
sgVec3 pt;
|
||||||
|
for ( i = (int)pnt_i.size() - 1; i >= 2; --i ) {
|
||||||
|
ssgVertexArray *vl = new ssgVertexArray( 1 );
|
||||||
|
ssgColourArray *cl = new ssgColourArray( 1 );
|
||||||
|
|
||||||
|
sgSetVec3( pt, nodes[pnt_i[i]][0], nodes[pnt_i[i]][1],
|
||||||
|
nodes[pnt_i[i]][2] );
|
||||||
|
sgSubVec3( pt, center );
|
||||||
|
vl->add( pt );
|
||||||
|
|
||||||
|
cl->add( color );
|
||||||
|
|
||||||
|
ssgLeaf *leaf =
|
||||||
|
new ssgVtxTable ( GL_POINTS, vl, NULL, NULL, cl );
|
||||||
|
|
||||||
|
leaf->setState( mat->get_state() );
|
||||||
|
leaf->setCallback( SSG_CALLBACK_PREDRAW, StrobePreDraw );
|
||||||
|
leaf->setCallback( SSG_CALLBACK_POSTDRAW, StrobePostDraw );
|
||||||
|
|
||||||
|
odals->addKid( leaf );
|
||||||
|
}
|
||||||
|
|
||||||
|
// runway end strobes
|
||||||
|
ssgVertexArray *vl = new ssgVertexArray( 2 );
|
||||||
|
ssgColourArray *cl = new ssgColourArray( 2 );
|
||||||
|
|
||||||
|
sgSetVec3( pt, nodes[pnt_i[0]][0], nodes[pnt_i[0]][1],
|
||||||
|
nodes[pnt_i[0]][2] );
|
||||||
|
sgSubVec3( pt, center );
|
||||||
|
vl->add( pt );
|
||||||
|
cl->add( color );
|
||||||
|
|
||||||
|
sgSetVec3( pt, nodes[pnt_i[1]][0], nodes[pnt_i[1]][1],
|
||||||
|
nodes[pnt_i[1]][2] );
|
||||||
|
sgSubVec3( pt, center );
|
||||||
|
vl->add( pt );
|
||||||
|
cl->add( color );
|
||||||
|
|
||||||
|
ssgLeaf *leaf =
|
||||||
|
new ssgVtxTable ( GL_POINTS, vl, NULL, NULL, cl );
|
||||||
|
|
||||||
|
leaf->setState( mat->get_state() );
|
||||||
|
leaf->setCallback( SSG_CALLBACK_PREDRAW, StrobePreDraw );
|
||||||
|
leaf->setCallback( SSG_CALLBACK_POSTDRAW, StrobePostDraw );
|
||||||
|
|
||||||
|
odals->addKid( leaf );
|
||||||
|
|
||||||
|
// setup animition
|
||||||
|
|
||||||
|
odals->setDuration( 10 );
|
||||||
|
odals->setLimits( 0, pnt_i.size() - 1 );
|
||||||
|
odals->setMode( SSG_ANIM_SHUTTLE );
|
||||||
|
odals->control( SSG_ANIM_START );
|
||||||
|
|
||||||
|
// put an LOD on each lighting component
|
||||||
|
ssgRangeSelector *lod = new ssgRangeSelector;
|
||||||
|
lod->setRange( 0, SG_ZERO );
|
||||||
|
lod->setRange( 1, 12000 );
|
||||||
|
lod->addKid( odals );
|
||||||
|
|
||||||
|
// create the transformation.
|
||||||
|
sgCoord coord;
|
||||||
|
sgSetCoord( &coord, center[0], center[1], center[2], 0.0, 0.0, 0.0 );
|
||||||
|
ssgTransform *trans = new ssgTransform;
|
||||||
|
trans->setTransform( &coord );
|
||||||
|
trans->addKid( lod );
|
||||||
|
|
||||||
|
return trans;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ssgTransform *gen_rabbit_lights( const point_list &nodes,
|
||||||
|
const point_list &normals,
|
||||||
|
const int_list &pnt_i,
|
||||||
|
const int_list &nml_i,
|
||||||
|
SGMaterialLib *matlib,
|
||||||
|
sgVec3 up )
|
||||||
|
{
|
||||||
|
sgVec3 center;
|
||||||
|
calc_center_point( nodes, pnt_i, center );
|
||||||
|
// cout << center[0] << "," << center[1] << "," << center[2] << endl;
|
||||||
|
|
||||||
|
sgVec3 nup;
|
||||||
|
sgNormalizeVec3( nup, up );
|
||||||
|
|
||||||
|
ssgTimedSelector *rabbit = new ssgTimedSelector;
|
||||||
|
|
||||||
|
SGMaterial *mat = matlib->find( "RWY_WHITE_LIGHTS" );
|
||||||
|
if ( mat == NULL ) {
|
||||||
|
SG_LOG( SG_TERRAIN, SG_ALERT,
|
||||||
|
"Warning: can't material = RWY_WHITE_LIGHTS" );
|
||||||
|
}
|
||||||
|
|
||||||
|
int i;
|
||||||
|
sgVec3 pt, normal;
|
||||||
|
for ( i = (int)pnt_i.size() - 1; i >= 0; --i ) {
|
||||||
|
ssgVertexArray *vl = new ssgVertexArray( 3 );
|
||||||
|
ssgNormalArray *nl = new ssgNormalArray( 3 );
|
||||||
|
ssgColourArray *cl = new ssgColourArray( 3 );
|
||||||
|
|
||||||
|
sgSetVec3( pt, nodes[pnt_i[i]][0], nodes[pnt_i[i]][1],
|
||||||
|
nodes[pnt_i[i]][2] );
|
||||||
|
sgSubVec3( pt, center );
|
||||||
|
|
||||||
|
sgSetVec3( normal, normals[nml_i[i]][0], normals[nml_i[i]][1],
|
||||||
|
normals[nml_i[i]][2] );
|
||||||
|
|
||||||
|
// calculate a vector perpendicular to dir and up
|
||||||
|
sgVec3 perp;
|
||||||
|
sgVectorProductVec3( perp, normal, nup );
|
||||||
|
|
||||||
|
// front face
|
||||||
|
sgVec3 tmp3;
|
||||||
|
sgCopyVec3( tmp3, pt );
|
||||||
|
vl->add( tmp3 );
|
||||||
|
sgAddVec3( tmp3, nup );
|
||||||
|
vl->add( tmp3 );
|
||||||
|
sgAddVec3( tmp3, perp );
|
||||||
|
vl->add( tmp3 );
|
||||||
|
// sgSubVec3( tmp3, nup );
|
||||||
|
// vl->add( tmp3 );
|
||||||
|
|
||||||
|
nl->add( normal );
|
||||||
|
nl->add( normal );
|
||||||
|
nl->add( normal );
|
||||||
|
// nl->add( normal );
|
||||||
|
|
||||||
|
sgVec4 color;
|
||||||
|
sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 );
|
||||||
|
cl->add( color );
|
||||||
|
sgSetVec4( color, 1.0, 1.0, 1.0, 0.0 );
|
||||||
|
cl->add( color );
|
||||||
|
cl->add( color );
|
||||||
|
// cl->add( color );
|
||||||
|
|
||||||
|
ssgLeaf *leaf =
|
||||||
|
new ssgVtxTable ( GL_TRIANGLES, vl, nl, NULL, cl );
|
||||||
|
|
||||||
|
leaf->setState( mat->get_state() );
|
||||||
|
leaf->setCallback( SSG_CALLBACK_PREDRAW, StrobePreDraw );
|
||||||
|
leaf->setCallback( SSG_CALLBACK_POSTDRAW, StrobePostDraw );
|
||||||
|
|
||||||
|
rabbit->addKid( leaf );
|
||||||
|
}
|
||||||
|
|
||||||
|
rabbit->setDuration( 10 );
|
||||||
|
rabbit->setLimits( 0, pnt_i.size() - 1 );
|
||||||
|
rabbit->setMode( SSG_ANIM_SHUTTLE );
|
||||||
|
rabbit->control( SSG_ANIM_START );
|
||||||
|
|
||||||
|
// put an LOD on each lighting component
|
||||||
|
ssgRangeSelector *lod = new ssgRangeSelector;
|
||||||
|
lod->setRange( 0, SG_ZERO );
|
||||||
|
lod->setRange( 1, 12000 );
|
||||||
|
lod->addKid( rabbit );
|
||||||
|
|
||||||
|
// create the transformation.
|
||||||
|
sgCoord coord;
|
||||||
|
sgSetCoord( &coord, center[0], center[1], center[2], 0.0, 0.0, 0.0 );
|
||||||
|
ssgTransform *trans = new ssgTransform;
|
||||||
|
trans->setTransform( &coord );
|
||||||
|
trans->addKid( lod );
|
||||||
|
|
||||||
|
return trans;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0 // debugging infrastructure
|
||||||
|
// Generate a normal line
|
||||||
|
static ssgLeaf *gen_normal_line( SGMaterialLib *matlib,
|
||||||
|
sgVec3 pt, sgVec3 dir, sgVec3 up ) {
|
||||||
|
|
||||||
|
ssgVertexArray *vl = new ssgVertexArray( 3 );
|
||||||
|
ssgColourArray *cl = new ssgColourArray( 3 );
|
||||||
|
|
||||||
|
sgVec3 tmp3;
|
||||||
|
sgCopyVec3( tmp3, pt );
|
||||||
|
vl->add( tmp3 );
|
||||||
|
sgAddVec3( tmp3, dir );
|
||||||
|
vl->add( tmp3 );
|
||||||
|
|
||||||
|
sgVec4 color;
|
||||||
|
sgSetVec4( color, 1.0, 0.0, 0.0, 1.0 );
|
||||||
|
cl->add( color );
|
||||||
|
cl->add( color );
|
||||||
|
|
||||||
|
ssgLeaf *leaf =
|
||||||
|
new ssgVtxTable ( GL_LINES, vl, NULL, NULL, cl );
|
||||||
|
|
||||||
|
SGMaterial *mat = matlib->find( "GROUND_LIGHTS" );
|
||||||
|
leaf->setState( mat->get_state() );
|
||||||
|
|
||||||
|
return leaf;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
ssgBranch *gen_directional_lights( const point_list &nodes,
|
||||||
|
const point_list &normals,
|
||||||
|
const int_list &pnt_i,
|
||||||
|
const int_list &nml_i,
|
||||||
|
SGMaterialLib *matlib,
|
||||||
|
const string &material,
|
||||||
|
sgVec3 up )
|
||||||
|
{
|
||||||
|
sgVec3 nup;
|
||||||
|
sgNormalizeVec3( nup, up );
|
||||||
|
|
||||||
|
SGMaterial *mat = matlib->find( material );
|
||||||
|
|
||||||
|
if ( material == "RWY_REIL_LIGHTS" ) {
|
||||||
|
// cout << "found a reil" << endl;
|
||||||
|
ssgTransform *reil = gen_reil_lights( nodes, normals, pnt_i, nml_i,
|
||||||
|
matlib, up );
|
||||||
|
return reil;
|
||||||
|
} else if ( material == "RWY_ODALS_LIGHTS" ) {
|
||||||
|
// cout << "found a odals" << endl;
|
||||||
|
ssgTransform *odals = gen_odals_lights( nodes, normals, pnt_i, nml_i,
|
||||||
|
matlib, up );
|
||||||
|
return odals;
|
||||||
|
} else if ( material == "RWY_SEQUENCED_LIGHTS" ) {
|
||||||
|
// cout << "found a rabbit" << endl;
|
||||||
|
ssgTransform *rabbit = gen_rabbit_lights( nodes, normals,
|
||||||
|
pnt_i, nml_i,
|
||||||
|
matlib, up );
|
||||||
|
return rabbit;
|
||||||
|
} else if ( material == "RWY_BLUE_TAXIWAY_LIGHTS" ) {
|
||||||
|
ssgTransform *light_group = gen_dir_light_group( nodes, normals, pnt_i,
|
||||||
|
nml_i, mat, up,
|
||||||
|
true );
|
||||||
|
return light_group;
|
||||||
|
} else {
|
||||||
|
ssgTransform *light_group = gen_dir_light_group( nodes, normals, pnt_i,
|
||||||
|
nml_i, mat, up );
|
||||||
|
return light_group;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
// pt_lights.hxx -- build a 'directional' light on the fly
|
||||||
|
//
|
||||||
|
// Written by Curtis Olson, started March 2002.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2002 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 _PT_LIGHTS_HXX
|
||||||
|
#define _PT_LIGHTS_HXX
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
# error This library requires C++
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <simgear/compiler.h>
|
||||||
|
|
||||||
|
#include STL_STRING
|
||||||
|
#include <vector> // STL
|
||||||
|
|
||||||
|
#include <plib/sg.h>
|
||||||
|
#include <plib/ssg.h> // plib include
|
||||||
|
|
||||||
|
#include <simgear/math/sg_types.hxx>
|
||||||
|
|
||||||
|
SG_USING_STD(string);
|
||||||
|
SG_USING_STD(vector);
|
||||||
|
|
||||||
|
|
||||||
|
typedef vector < int > int_list;
|
||||||
|
typedef int_list::iterator int_list_iterator;
|
||||||
|
typedef int_list::const_iterator int_point_list_iterator;
|
||||||
|
|
||||||
|
|
||||||
|
// Define the various supported light types
|
||||||
|
typedef enum {
|
||||||
|
FG_RWYLIGHT_TAXI = 0,
|
||||||
|
FG_RWYLIGHT_VASI,
|
||||||
|
FG_RWYLIGHT_EDGE,
|
||||||
|
FG_RWYLIGHT_TOUCHDOWN,
|
||||||
|
FG_RWYLIGHT_THRESHOLD,
|
||||||
|
FG_RWYLIGHT_WHITE,
|
||||||
|
FG_RWYLIGHT_RED,
|
||||||
|
FG_RWYLIGHT_GREEN,
|
||||||
|
FG_RWYLIGHT_YELLOW
|
||||||
|
} fgRunwayLightType;
|
||||||
|
|
||||||
|
|
||||||
|
// Generate a directional light. This routines creates a
|
||||||
|
// 'directional' light that can only be viewed from within 90 degrees
|
||||||
|
// of the specified dir vector.
|
||||||
|
|
||||||
|
// To accomplish this, he routine creates a triangle with the 1st
|
||||||
|
// point coincident with the specified pt and the 2nd and 3rd points
|
||||||
|
// extending upward. The 1st point is created with an 'alpha' value
|
||||||
|
// of 1 while the 2nd and 3rd points are created with an 'alpha' of
|
||||||
|
// 0.0.
|
||||||
|
|
||||||
|
// If the triangle is drawn in glPolygonMode(GL_FRONT, GL_POINT) mode,
|
||||||
|
// then two important things happen:
|
||||||
|
|
||||||
|
// 1) Only the 3 vertex points are drawn, the 2nd two with an alpha of
|
||||||
|
// 0 so actually only the desired point is rendered.
|
||||||
|
|
||||||
|
// 2) since we are drawing a triangle, back face culling takes care of
|
||||||
|
// eliminating this poing when the view angle relative to dir is
|
||||||
|
// greater than 90 degrees.
|
||||||
|
|
||||||
|
// The final piece of this puzzle is that if we now use environment
|
||||||
|
// mapping on this point, via an appropriate texture we can then
|
||||||
|
// control the intensity and color of the point based on the view
|
||||||
|
// angle relative to 'dir' the optimal view direction of the light
|
||||||
|
// (i.e. the direction the light is pointing.)
|
||||||
|
|
||||||
|
// Yes this get's to be long and convoluted. If you can suggest a
|
||||||
|
// simpler way, please do! :-)
|
||||||
|
|
||||||
|
ssgLeaf *gen_directional_light( sgVec3 pt, sgVec3 dir, sgVec3 up );
|
||||||
|
|
||||||
|
|
||||||
|
ssgBranch *gen_directional_lights( const point_list &nodes,
|
||||||
|
const point_list &normals,
|
||||||
|
const int_list &pnt_i,
|
||||||
|
const int_list &nml_i,
|
||||||
|
SGMaterialLib *matlib,
|
||||||
|
const string &material,
|
||||||
|
sgVec3 up );
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _PT_LIGHTS_HXX
|
||||||
Reference in New Issue
Block a user