Modified Files:

simgear/bucket/newbucket.hxx simgear/scene/material/mat.cxx
	simgear/scene/material/matlib.cxx
	simgear/scene/material/matlib.hxx
	simgear/scene/model/location.cxx
	simgear/scene/tgdb/apt_signs.cxx simgear/scene/tgdb/leaf.cxx
	simgear/scene/tgdb/leaf.hxx simgear/scene/tgdb/obj.cxx
	simgear/scene/tgdb/obj.hxx
	simgear/scene/util/SGUpdateVisitor.hxx: Reorganize scenegraph to
	simplify top level structure.
This commit is contained in:
frohlich
2007-05-08 06:11:15 +00:00
parent a85da04601
commit 834eab9457
11 changed files with 439 additions and 236 deletions

View File

@@ -31,6 +31,7 @@
#include <simgear/compiler.h>
#include <simgear/constants.h>
#include <simgear/math/SGMath.hxx>
#ifdef SG_HAVE_STD_INCLUDES
# include <cmath>
@@ -252,7 +253,24 @@ public:
* @return the height of the tile in meters.
*/
double get_height_m() const;
/**
* @return the center of the bucket in geodetic coordinates.
*/
SGGeod get_center() const
{ return SGGeod::fromDeg(get_center_lon(), get_center_lat()); }
/**
* @return the center of the bucket in geodetic coordinates.
*/
SGGeod get_corner(unsigned num) const
{
double lonFac = ((num + 1) & 2) ? 0.5 : -0.5;
double latFac = ((num ) & 2) ? 0.5 : -0.5;
return SGGeod::fromDeg(get_center_lon() + lonFac*get_width(),
get_center_lat() + latFac*get_height());
}
// Informational methods.
/**

View File

@@ -266,6 +266,7 @@ SGMaterial::build_state( bool defer_tex_load )
for (unsigned int i = 0; i < _status.size(); i++)
{
osg::StateSet *stateSet = new osg::StateSet;
stateSet->setUserData(new SGMaterialUserData(this));
// Set up the textured state
osg::ShadeModel* shadeModel = new osg::ShadeModel;

View File

@@ -216,7 +216,7 @@ bool SGMaterialLib::load( const string &fg_root, const string& mpath, const char
osg::ref_ptr<osg::StateSet> lightStateSet = new osg::StateSet;
{
lightStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
lightStateSet->setRenderBinDetails(9, "DepthSortedBin");
lightStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
// lightStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
@@ -552,13 +552,13 @@ void SGMaterialLib::load_next_deferred() {
}
}
// Return the material from that given leaf
const SGMaterial* SGMaterialLib::findMaterial(const osg::Node* leaf) const
const SGMaterial*
SGMaterialLib::findMaterial(const osg::StateSet* stateSet) const
{
if (!leaf)
if (!stateSet)
return 0;
const osg::Referenced* base = leaf->getUserData();
const osg::Referenced* base = stateSet->getUserData();
if (!base)
return 0;

View File

@@ -86,7 +86,7 @@ public:
material_map_iterator end() { return matlib.end(); }
const_material_map_iterator end() const { return matlib.end(); }
const SGMaterial* findMaterial(const osg::Node* leaf) const;
const SGMaterial* findMaterial(const osg::StateSet* stateSet) const;
// Destructor
~SGMaterialLib ( void );

View File

@@ -33,7 +33,6 @@
#include <simgear/math/point3d.hxx>
#include <simgear/math/polar3d.hxx>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/math/vector.hxx>
#include "location.hxx"

View File

@@ -33,7 +33,6 @@
#include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_types.hxx>
#include <simgear/scene/tgdb/leaf.hxx>
#include <simgear/scene/material/mat.hxx>
#include <simgear/scene/material/matlib.hxx>
@@ -355,63 +354,27 @@ SGMakeSign(SGMaterialLib *matlib, const string& path, const string& content)
return object;
}
osg::Node*
SGMakeRunwaySign(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
osg::Group *object = new osg::Group;
object->setName(name);
float width = name.length() / 3.0;
double width = name.length() / 3.0;
osg::Vec3 corner(-width, 0, 0.25f);
osg::Vec3 widthVec(2*width + 1, 0, 0);
osg::Vec3 heightVec(0, 0, 1);
osg::Geometry* geometry;
geometry = osg::createTexturedQuadGeometry(corner, widthVec, heightVec);
string material = name;
SGMaterial *mat = matlib->find(name);
if (mat)
geometry->setStateSet(mat->get_state());
point_list nodes;
point_list normals;
point_list texcoords;
int_list vertex_index;
int_list normal_index;
int_list tex_index;
osg::Geode* geode = new osg::Geode;
geode->setName(name);
geode->addDrawable(geometry);
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 );
osg::Node* leaf = SGMakeLeaf( path, GL_TRIANGLE_STRIP, matlib, material,
nodes, normals, texcoords,
vertex_index, normal_index, tex_index,
false, NULL );
object->addChild(leaf);
return object;
return geode;
}

View File

@@ -54,22 +54,6 @@ typedef vector < int > int_list;
typedef int_list::iterator int_list_iterator;
typedef int_list::const_iterator int_point_list_iterator;
static inline
osg::Vec3 random_pt_inside_tri(const osg::Vec3& n1, const osg::Vec3& n2,
const osg::Vec3& 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;
return n1*a + n2*b + n3*c;
}
/// class to implement the TrinagleFunctor class
struct SGRandomSurfacePointsFill {
osg::Vec3Array* lights;
@@ -97,6 +81,20 @@ struct SGRandomSurfacePointsFill {
}
}
}
osg::Vec3 random_pt_inside_tri(const osg::Vec3& n1, const osg::Vec3& n2,
const osg::Vec3& n3)
{
double a = sg_random();
double b = sg_random();
if ( a + b > 1.0 ) {
a = 1 - a;
b = 1 - b;
}
double c = 1 - a - b;
return n1*a + n2*b + n3*c;
}
};
static void SGGenRandomSurfacePoints( osg::Geometry *leaf, double factor,
@@ -109,13 +107,13 @@ static void SGGenRandomSurfacePoints( osg::Geometry *leaf, double factor,
}
////////////////////////////////////////////////////////////////////////
// Scenery loaders.
////////////////////////////////////////////////////////////////////////
osg::Node* SGMakeLeaf( const string& path,
const GLenum ty,
SGMaterialLib *matlib, const string& material,
osg::Drawable* SGMakeLeaf( const string& path,
const GLenum ty, SGMaterial *mat,
const point_list& nodes, const point_list& normals,
const point_list& texcoords,
const int_list& node_index,
@@ -127,31 +125,6 @@ osg::Node* SGMakeLeaf( const string& path,
osg::StateSet *state = 0;
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
@@ -159,10 +132,6 @@ osg::Node* SGMakeLeaf( const string& path,
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;
}
int i;
@@ -240,12 +209,9 @@ osg::Node* SGMakeLeaf( const string& path,
geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
geometry->setTexCoordArray(0, tl);
geometry->addPrimitiveSet(new osg::DrawArrays(ty, 0, vl->size()));
osg::Geode* geode = new osg::Geode;
geode->addDrawable(geometry);
// lookup the state record
geode->setStateSet(state);
geode->setUserData( new SGMaterialUserData(mat) );
geometry->setStateSet(state);
if ( calc_lights ) {
if ( coverage > 0.0 ) {
@@ -254,9 +220,10 @@ osg::Node* SGMakeLeaf( const string& path,
<< coverage << ", pushing up to 10000");
coverage = 10000;
}
SGGenRandomSurfacePoints(geometry, coverage, lights );
SGGenRandomSurfacePoints(geometry, coverage, lights);
}
}
return geode;
return geometry;
}

View File

@@ -46,9 +46,8 @@ class SGMaterialLib; // forward declaration.
// Create a ssg leaf
osg::Node* SGMakeLeaf( const string& path,
const GLenum ty,
SGMaterialLib *matlib, const string& material,
osg::Drawable* SGMakeLeaf( const string& path,
const GLenum ty, SGMaterial *mat,
const point_list& nodes, const point_list& normals,
const point_list& texcoords,
const int_list& node_index,

View File

@@ -33,6 +33,7 @@
#include STL_STRING
#include <osg/Depth>
#include <osg/Fog>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
@@ -40,14 +41,19 @@
#include <osg/MatrixTransform>
#include <osg/StateSet>
#include <osgUtil/Optimizer>
#include <osgDB/WriteFile>
#include <simgear/bucket/newbucket.hxx>
#include <simgear/io/sg_binobj.hxx>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/math/sg_random.h>
#include <simgear/math/sg_types.hxx>
#include <simgear/misc/texcoord.hxx>
#include <simgear/scene/material/mat.hxx>
#include <simgear/scene/material/matlib.hxx>
#include <simgear/scene/util/SGUpdateVisitor.hxx>
#include <simgear/scene/util/SGNodeMasks.hxx>
#include <simgear/scene/tgdb/leaf.hxx>
#include <simgear/scene/tgdb/pt_lights.hxx>
#include <simgear/scene/tgdb/userdata.hxx>
@@ -64,14 +70,12 @@ struct Leaf {
// Generate an ocean tile
bool SGGenTile( const string& path, SGBucket b,
Point3D *center, double *bounding_radius,
bool SGGenTile( const string& path, const SGBucket& b,
SGMaterialLib *matlib, osg::Group* group )
{
osg::StateSet *state = 0;
double tex_width = 1000.0;
// double tex_height;
// find Ocean material in the properties list
SGMaterial *mat = matlib->find( "Ocean" );
@@ -79,7 +83,6 @@ bool SGGenTile( const string& path, SGBucket b,
// set the texture width and height values for this
// material
tex_width = mat->get_xsize();
// tex_height = newmat->get_ysize();
// set ssgState
state = mat->get_state();
@@ -90,16 +93,14 @@ bool SGGenTile( const string& path, SGBucket b,
}
// Calculate center point
SGVec3d cartCenter = SGVec3d::fromGeod(b.get_center());
Point3D center = Point3D(cartCenter[0], cartCenter[1], cartCenter[2]);
double clon = b.get_center_lon();
double clat = b.get_center_lat();
double height = b.get_height();
double width = b.get_width();
*center = sgGeodToCart( Point3D(clon*SGD_DEGREES_TO_RADIANS,
clat*SGD_DEGREES_TO_RADIANS,
0.0) );
// cout << "center = " << center << endl;;
// Caculate corner vertices
Point3D geod[4];
geod[0] = Point3D( clon - width/2.0, clat - height/2.0, 0.0 );
@@ -118,14 +119,10 @@ bool SGGenTile( const string& path, SGBucket b,
Point3D cart[4], rel[4];
for ( i = 0; i < 4; ++i ) {
cart[i] = sgGeodToCart(rad[i]);
rel[i] = cart[i] - *center;
rel[i] = cart[i] - center;
// cout << "corner " << i << " = " << cart[i] << endl;
}
// Calculate bounding radius
*bounding_radius = center->distance3D( cart[0] );
// cout << "bounding radius = " << t->bounding_radius << endl;
// Calculate normals
Point3D normals[4];
for ( i = 0; i < 4; ++i ) {
@@ -252,7 +249,7 @@ bool SGGenTile( const string& path, SGBucket b,
* @param material_name The name of the surface's material.
*/
static void
gen_random_surface_objects (osg::Node *leaf,
gen_random_surface_objects (osg::Drawable *leaf,
osg::Group *branch,
Point3D *center,
SGMaterial *mat )
@@ -320,7 +317,7 @@ class SGLightOffsetTransform : public osg::Transform {
public:
#define SCALE_FACTOR 0.94
virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,
osg::NodeVisitor* nv) const
osg::NodeVisitor* nv) const
{
if (nv && nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR) {
double scaleFactor = SCALE_FACTOR;
@@ -349,13 +346,44 @@ public:
transform(3,0) = center[0]*(1 - scaleFactor);
transform(3,1) = center[1]*(1 - scaleFactor);
transform(3,2) = center[2]*(1 - scaleFactor);
matrix.preMult(transform);
matrix.postMult(transform);
}
return true;
}
#undef SCALE_FACTOR
};
static SGMaterial* findMaterial(const std::string& material,
const std::string& path,
SGMaterialLib *matlib)
{
SGMaterial *mat = matlib->find( material );
if (mat)
return mat;
// 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 );
}
}
return mat;
}
////////////////////////////////////////////////////////////////////////
@@ -363,15 +391,14 @@ public:
////////////////////////////////////////////////////////////////////////
// Load an Binary obj file
bool SGBinObjLoad( const string& path, const bool is_base,
Point3D *center,
double *bounding_radius,
static bool SGBinObjLoad( const string& path, const bool is_base,
Point3D& center,
SGMaterialLib *matlib,
bool use_random_objects,
osg::Group *geometry,
osg::Group *_vasi_lights,
osg::Group *_rwy_lights,
osg::Group *_taxi_lights,
osg::Group *local_terrain,
osg::Group *vasi_lights,
osg::Group *rwy_lights,
osg::Group *taxi_lights,
osg::Vec3Array *ground_lights )
{
SGBinObject obj;
@@ -380,37 +407,10 @@ bool SGBinObjLoad( const string& path, const bool is_base,
return false;
}
// Ok, somehow polygon offset for lights ...
// Could never make the polygon offset for our lights get right.
// So, why not in this way ...
SGLightOffsetTransform* vasi_lights = 0;
if (_vasi_lights) {
vasi_lights = new SGLightOffsetTransform;
_vasi_lights->addChild(vasi_lights);
}
SGLightOffsetTransform *rwy_lights = 0;
if (_rwy_lights) {
rwy_lights = new SGLightOffsetTransform;
_rwy_lights->addChild(rwy_lights);
}
SGLightOffsetTransform *taxi_lights = 0;
if (_taxi_lights) {
taxi_lights = new SGLightOffsetTransform;
_taxi_lights->addChild(taxi_lights);
}
osg::Group *local_terrain = new osg::Group;
local_terrain->setName( "LocalTerrain" );
geometry->addChild( local_terrain );
geometry->setName(path);
// reference point (center offset/bounding sphere)
*center = obj.get_gbs_center();
*bounding_radius = obj.get_gbs_radius();
center = obj.get_gbs_center();
point_list const& nodes = obj.get_wgs84_nodes();
// point_list const& colors = obj.get_colors();
point_list const& normals = obj.get_normals();
point_list const& texcoords = obj.get_texcoords();
@@ -419,6 +419,9 @@ bool SGBinObjLoad( const string& path, const bool is_base,
group_list::size_type i;
osg::Geode* geode = new osg::Geode;
local_terrain->addChild( geode );
// generate points
string_list const& pt_materials = obj.get_pt_materials();
group_list const& pts_v = obj.get_pts_v();
@@ -427,7 +430,7 @@ bool SGBinObjLoad( const string& path, const bool is_base,
// cout << "pts_v.size() = " << pts_v.size() << endl;
if ( pt_materials[i].substr(0, 3) == "RWY" ) {
// airport environment lighting
SGVec3d up(center->x(), center->y(), center->z());
SGVec3d up(center.x(), center.y(), center.z());
// returns a transform -> lod -> leaf structure
osg::Node *branch = SGMakeDirectionalLights( nodes, normals,
pts_v[i], pts_n[i],
@@ -444,27 +447,30 @@ bool SGBinObjLoad( const string& path, const bool is_base,
}
} else {
// other geometry
material = pt_materials[i];
SGMaterial *mat = findMaterial( pt_materials[i], path, matlib );
tex_index.clear();
osg::Node *leaf = SGMakeLeaf( path, GL_POINTS, matlib, material,
osg::Drawable *leaf = SGMakeLeaf( path, GL_POINTS, mat,
nodes, normals, texcoords,
pts_v[i], pts_n[i], tex_index,
false, ground_lights );
local_terrain->addChild( leaf );
geode->addDrawable( leaf );
}
}
// Put all randomly-placed objects under a separate branch
// (actually an ssgRangeSelector) named "random-models".
osg::Group * random_object_branch = 0;
if (use_random_objects) {
osg::LOD* object_lod = new osg::LOD;
object_lod->setName("random-models");
geometry->addChild(object_lod);
random_object_branch = new osg::Group;
// Maximum 20km range for random objects
object_lod->addChild(random_object_branch, 0, 20000);
}
// if (use_random_objects) {
// osg::LOD* object_lod = new osg::LOD;
// object_lod->setName("random-models");
// geometry->addChild(object_lod);
// random_object_branch = new osg::Group;
// // Maximum 20km range for random objects
// object_lod->addChild(random_object_branch, 0, 20000);
// }
typedef map<string,list<Leaf> > LeafMap;
LeafMap leafMap;
@@ -499,65 +505,48 @@ bool SGBinObjLoad( const string& path, const bool is_base,
LeafMap::iterator lmi = leafMap.begin();
while ( lmi != leafMap.end() ) {
SGMaterial *mat = findMaterial( lmi->first, path, matlib );
list<Leaf> &leaf_list = lmi->second;
list<Leaf>::iterator li = leaf_list.begin();
while ( li != leaf_list.end() ) {
Leaf &leaf = *li;
int ind = leaf.index;
if ( leaf.type == GL_TRIANGLES ) {
osg::Node *leaf = SGMakeLeaf( path, GL_TRIANGLES, matlib,
tri_materials[ind],
osg::Drawable *leaf = SGMakeLeaf( path, GL_TRIANGLES, mat,
nodes, normals, texcoords,
tris_v[ind], tris_n[ind], tris_tc[ind],
is_base, ground_lights );
if ( use_random_objects ) {
SGMaterial *mat = matlib->find( tri_materials[ind] );
if ( mat == NULL ) {
SG_LOG( SG_INPUT, SG_ALERT,
"Unknown material for random surface objects = "
<< tri_materials[ind] );
} else {
if ( random_object_branch ) {
if ( mat ) {
gen_random_surface_objects( leaf, random_object_branch,
center, mat );
&center, mat );
}
}
local_terrain->addChild( leaf );
geode->addDrawable( leaf );
} else if ( leaf.type == GL_TRIANGLE_STRIP ) {
osg::Node *leaf = SGMakeLeaf( path, GL_TRIANGLE_STRIP,
matlib, strip_materials[ind],
osg::Drawable *leaf = SGMakeLeaf( path, GL_TRIANGLE_STRIP, mat,
nodes, normals, texcoords,
strips_v[ind], strips_n[ind], strips_tc[ind],
is_base, ground_lights );
if ( use_random_objects ) {
SGMaterial *mat = matlib->find( strip_materials[ind] );
if ( mat == NULL ) {
SG_LOG( SG_INPUT, SG_ALERT,
"Unknown material for random surface objects = "
<< strip_materials[ind] );
} else {
if ( random_object_branch ) {
if ( mat ) {
gen_random_surface_objects( leaf, random_object_branch,
center, mat );
&center, mat );
}
}
local_terrain->addChild( leaf );
geode->addDrawable( leaf );
} else {
osg::Node *leaf = SGMakeLeaf( path, GL_TRIANGLE_FAN,
matlib, fan_materials[ind],
osg::Drawable *leaf = SGMakeLeaf( path, GL_TRIANGLE_FAN, mat,
nodes, normals, texcoords,
fans_v[ind], fans_n[ind], fans_tc[ind],
is_base, ground_lights );
if ( use_random_objects ) {
SGMaterial *mat = matlib->find( fan_materials[ind] );
if ( mat == NULL ) {
SG_LOG( SG_INPUT, SG_ALERT,
"Unknown material for random surface objects = "
<< fan_materials[ind] );
} else {
if ( random_object_branch ) {
if ( mat ) {
gen_random_surface_objects( leaf, random_object_branch,
center, mat );
&center, mat );
}
}
local_terrain->addChild( leaf );
geode->addDrawable( leaf );
}
++li;
}
@@ -566,3 +555,236 @@ bool SGBinObjLoad( const string& path, const bool is_base,
return true;
}
static osg::Node*
gen_lights( SGMaterialLib *matlib, osg::Vec3Array *lights, int inc, float bright )
{
// generate a repeatable random seed
sg_srandom( (unsigned)(*lights)[0][0] );
// Allocate ssg structure
osg::Vec3Array *vl = new osg::Vec3Array;
osg::Vec4Array *cl = new osg::Vec4Array;
for ( unsigned i = 0; i < lights->size(); ++i ) {
// this loop is slightly less efficient than it otherwise
// could be, but we want a red light to always be red, and a
// yellow light to always be yellow, etc. so we are trying to
// preserve the random sequence.
float zombie = sg_random();
if ( i % inc == 0 ) {
vl->push_back( (*lights)[i] );
// factor = sg_random() ^ 2, range = 0 .. 1 concentrated towards 0
float factor = sg_random();
factor *= factor;
osg::Vec4 color;
if ( zombie > 0.5 ) {
// 50% chance of yellowish
color = osg::Vec4( 0.9, 0.9, 0.3, bright - factor * 0.2 );
} else if ( zombie > 0.15 ) {
// 35% chance of whitish
color = osg::Vec4( 0.9, 0.9, 0.8, bright - factor * 0.2 );
} else if ( zombie > 0.05 ) {
// 10% chance of orangish
color = osg::Vec4( 0.9, 0.6, 0.2, bright - factor * 0.2 );
} else {
// 5% chance of redish
color = osg::Vec4( 0.9, 0.2, 0.2, bright - factor * 0.2 );
}
cl->push_back( color );
}
}
// create ssg leaf
osg::Geometry* geometry = new osg::Geometry;
geometry->setVertexArray(vl);
geometry->setColorArray(cl);
geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
geometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, vl->size()));
osg::Geode* geode = new osg::Geode;
geode->addDrawable(geometry);
// assign state
SGMaterial *mat = matlib->find( "GROUND_LIGHTS" );
geometry->setStateSet(mat->get_state());
return geode;
}
class SGTileUpdateCallback : public osg::NodeCallback {
public:
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
assert(dynamic_cast<osg::Switch*>(node));
assert(dynamic_cast<SGUpdateVisitor*>(nv));
osg::Switch* lightSwitch = static_cast<osg::Switch*>(node);
SGUpdateVisitor* updateVisitor = static_cast<SGUpdateVisitor*>(nv);
// The current sun angle in degree
float sun_angle = updateVisitor->getSunAngleDeg();
// vasi is always on
lightSwitch->setValue(0, true);
if (sun_angle > 85 || updateVisitor->getVisibility() < 5000) {
// runway and taxi
lightSwitch->setValue(1, true);
lightSwitch->setValue(2, true);
} else {
// runway and taxi
lightSwitch->setValue(1, false);
lightSwitch->setValue(2, false);
}
// ground lights
if ( sun_angle > 95 )
lightSwitch->setValue(5, true);
else
lightSwitch->setValue(5, false);
if ( sun_angle > 92 )
lightSwitch->setValue(4, true);
else
lightSwitch->setValue(4, false);
if ( sun_angle > 89 )
lightSwitch->setValue(3, true);
else
lightSwitch->setValue(3, false);
traverse(node, nv);
}
};
class SGRunwayLightFogUpdateCallback : public osg::StateAttribute::Callback {
public:
virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
{
assert(dynamic_cast<SGUpdateVisitor*>(nv));
assert(dynamic_cast<osg::Fog*>(sa));
SGUpdateVisitor* updateVisitor = static_cast<SGUpdateVisitor*>(nv);
osg::Fog* fog = static_cast<osg::Fog*>(sa);
fog->setMode(osg::Fog::EXP2);
fog->setColor(updateVisitor->getFogColor().osg());
fog->setDensity(updateVisitor->getRunwayFogExp2Density());
}
};
class SGTaxiLightFogUpdateCallback : public osg::StateAttribute::Callback {
public:
virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
{
assert(dynamic_cast<SGUpdateVisitor*>(nv));
assert(dynamic_cast<osg::Fog*>(sa));
SGUpdateVisitor* updateVisitor = static_cast<SGUpdateVisitor*>(nv);
osg::Fog* fog = static_cast<osg::Fog*>(sa);
fog->setMode(osg::Fog::EXP2);
fog->setColor(updateVisitor->getFogColor().osg());
fog->setDensity(updateVisitor->getTaxiFogExp2Density());
}
};
class SGGroundLightFogUpdateCallback : public osg::StateAttribute::Callback {
public:
virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
{
assert(dynamic_cast<SGUpdateVisitor*>(nv));
assert(dynamic_cast<osg::Fog*>(sa));
SGUpdateVisitor* updateVisitor = static_cast<SGUpdateVisitor*>(nv);
osg::Fog* fog = static_cast<osg::Fog*>(sa);
fog->setMode(osg::Fog::EXP2);
fog->setColor(updateVisitor->getFogColor().osg());
fog->setDensity(updateVisitor->getGroundLightsFogExp2Density());
}
};
osg::Node*
SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects)
{
osg::Group* vasiLights = new osg::Group;
osg::StateSet* stateSet = vasiLights->getOrCreateStateSet();
osg::Fog* fog = new osg::Fog;
fog->setUpdateCallback(new SGRunwayLightFogUpdateCallback);
stateSet->setAttribute(fog);
osg::Group* rwyLights = new osg::Group;
stateSet = rwyLights->getOrCreateStateSet();
fog = new osg::Fog;
fog->setUpdateCallback(new SGRunwayLightFogUpdateCallback);
stateSet->setAttribute(fog);
osg::Group* taxiLights = new osg::Group;
stateSet = taxiLights->getOrCreateStateSet();
fog = new osg::Fog;
fog->setUpdateCallback(new SGTaxiLightFogUpdateCallback);
stateSet->setAttribute(fog);
osg::Group* groundLights0 = new osg::Group;
stateSet = groundLights0->getOrCreateStateSet();
fog = new osg::Fog;
fog->setUpdateCallback(new SGGroundLightFogUpdateCallback);
stateSet->setAttribute(fog);
osg::Group* groundLights1 = new osg::Group;
stateSet = groundLights1->getOrCreateStateSet();
fog = new osg::Fog;
fog->setUpdateCallback(new SGGroundLightFogUpdateCallback);
stateSet->setAttribute(fog);
osg::Group* groundLights2 = new osg::Group;
stateSet = groundLights2->getOrCreateStateSet();
fog = new osg::Fog;
fog->setUpdateCallback(new SGGroundLightFogUpdateCallback);
stateSet->setAttribute(fog);
osg::Switch* lightSwitch = new osg::Switch;
lightSwitch->setUpdateCallback(new SGTileUpdateCallback);
lightSwitch->addChild(vasiLights, true);
lightSwitch->addChild(rwyLights, true);
lightSwitch->addChild(taxiLights, true);
lightSwitch->addChild(groundLights0, true);
lightSwitch->addChild(groundLights1, true);
lightSwitch->addChild(groundLights2, true);
osg::Group* lightGroup = new SGLightOffsetTransform;
lightGroup->addChild(lightSwitch);
unsigned nodeMask = ~0u;
nodeMask &= ~SG_NODEMASK_CASTSHADOW_BIT;
nodeMask &= ~SG_NODEMASK_RECIEVESHADOW_BIT;
nodeMask &= ~SG_NODEMASK_PICK_BIT;
nodeMask &= ~SG_NODEMASK_TERRAIN_BIT;
lightGroup->setNodeMask(nodeMask);
osg::Group* terrainGroup = new osg::Group;
osg::ref_ptr<osg::Vec3Array> light_pts = new osg::Vec3Array;
Point3D center;
SGBinObjLoad(path, calc_lights, center, matlib, use_random_objects,
terrainGroup, vasiLights, rwyLights, taxiLights, light_pts.get());
if ( light_pts->size() ) {
osg::Node *lights;
lights = gen_lights( matlib, light_pts.get(), 4, 0.7 );
groundLights0->addChild( lights );
lights = gen_lights( matlib, light_pts.get(), 2, 0.85 );
groundLights1->addChild( lights );
lights = gen_lights( matlib, light_pts.get(), 1, 1.0 );
groundLights2->addChild( lights );
}
// The toplevel transform for that tile.
osg::MatrixTransform* transform = new osg::MatrixTransform;
transform->setName(path);
transform->setMatrix(osg::Matrix::translate(osg::Vec3d(center[0], center[1], center[2])));
transform->addChild(terrainGroup);
transform->addChild(lightGroup);
return transform;
}

View File

@@ -45,23 +45,12 @@ SG_USING_STD(string);
class SGBucket;
class SGMaterialLib;
// Load a Binary obj file
bool SGBinObjLoad( const string& path, const bool is_base,
Point3D *center,
double *bounding_radius,
SGMaterialLib *matlib,
bool use_random_objects,
osg::Group *geometry,
osg::Group *vasi_lights,
osg::Group *rwy_lights,
osg::Group *taxi_lights,
osg::Vec3Array *ground_lights );
// Generate an ocean tile
bool SGGenTile( const string& path, SGBucket b,
Point3D *center, double *bounding_radius,
bool SGGenTile( const string& path, const SGBucket& b,
SGMaterialLib *matlib, osg::Group *geometry );
osg::Node*
SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects);
#endif // _SG_OBJ_HXX

View File

@@ -29,12 +29,14 @@
class SGUpdateVisitor : public osgUtil::UpdateVisitor {
public:
SGUpdateVisitor()
SGUpdateVisitor() :
mVisibility(-1)
{
// Need to traverse all children, else some LOD nodes do not get updated
// Note that the broad number of updates is not done due to
// the update callback in the global position node.
setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN);
setVisibility(10000);
}
void setViewData(const SGVec3d& globalEyePos,
const SGQuatd& globalViewOrientation)
@@ -48,15 +50,32 @@ public:
mHorizLocalDown = mGlobalHorizLocalOr.backTransform(SGVec3d(0, 0, 1));
}
void setSceneryCenter(const SGVec3d& sceneryCenter)
{
mSceneryCenter = sceneryCenter;
}
void setVisibility(double visibility)
{
if (mVisibility == visibility)
return;
mVisibility = visibility;
mSqrVisibility = visibility*visibility;
double m_log01 = -log( 0.01 );
double sqrt_m_log01 = sqrt( m_log01 );
double fog_exp_density = m_log01 / visibility;
double fog_exp2_density = sqrt_m_log01 / visibility;
double ground_exp2_punch_through = sqrt_m_log01 / (visibility * 1.5);
double rwy_exp2_punch_through, taxi_exp2_punch_through;
if ( visibility < 8000 ) {
rwy_exp2_punch_through = sqrt_m_log01 / (visibility * 2.5);
taxi_exp2_punch_through = sqrt_m_log01 / (visibility * 1.5);
} else {
rwy_exp2_punch_through = sqrt_m_log01 / ( 8000 * 2.5 );
taxi_exp2_punch_through = sqrt_m_log01 / ( 8000 * 1.5 );
}
mFogExpDensity = fog_exp_density;
mFogExp2Density = fog_exp2_density;
mRunwayFogExp2Density = rwy_exp2_punch_through;
mTaxiFogExp2Density = taxi_exp2_punch_through;
mGroundLightsFogExp2Density = ground_exp2_punch_through;
}
double getVisibility() const
@@ -64,6 +83,17 @@ public:
double getSqrVisibility() const
{ return mSqrVisibility; }
double getFogExpDensity() const
{ return mFogExpDensity; }
double getFogExp2Density() const
{ return mFogExp2Density; }
double getRunwayFogExp2Density() const
{ return mRunwayFogExp2Density; }
double getTaxiFogExp2Density() const
{ return mTaxiFogExp2Density; }
double getGroundLightsFogExp2Density() const
{ return mGroundLightsFogExp2Density; }
const SGVec3d& getGlobalEyePos() const
{ return mGlobalEyePos; }
const SGGeod& getGeodEyePos() const
@@ -80,11 +110,15 @@ public:
{ return mHorizLocalDown; }
void setLight(const SGVec3f& direction, const SGVec4f& ambient,
const SGVec4f& diffuse, const SGVec4f& specular)
const SGVec4f& diffuse, const SGVec4f& specular,
const SGVec4f& fogColor, double sunAngleDeg)
{
mLightDirection = direction;
mAmbientLight = ambient;
mDiffuseLight = diffuse;
mSpecularLight = specular;
mFogColor = fogColor;
mSunAngleDeg = sunAngleDeg;
}
const SGVec3f& getLightDirection() const
@@ -95,6 +129,11 @@ public:
{ return mDiffuseLight; }
const SGVec4f& getSpecularLight() const
{ return mSpecularLight; }
const SGVec4f& getFogColor() const
{ return mFogColor; }
double getSunAngleDeg() const
{ return mSunAngleDeg; }
private:
SGGeod mGlobalGeodEyePos;
@@ -105,15 +144,21 @@ private:
SGVec3d mHorizLocalEast;
SGVec3d mHorizLocalDown;
SGVec3d mSceneryCenter;
double mVisibility;
double mSqrVisibility;
double mFogExpDensity;
double mFogExp2Density;
double mRunwayFogExp2Density;
double mTaxiFogExp2Density;
double mGroundLightsFogExp2Density;
SGVec3f mLightDirection;
SGVec4f mAmbientLight;
SGVec4f mDiffuseLight;
SGVec4f mSpecularLight;
SGVec4f mFogColor;
double mSunAngleDeg;
};
#endif